varnish-cache/bin/varnishd/acceptor/mgt_acceptor_tcp.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2023 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Asad Sajjad Ahmed <asadsa@varnish-software.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 */
32
33
#include "config.h"
34
35
#include <sys/types.h>
36
#include <sys/socket.h>
37
#include <sys/stat.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
#include "mgt/mgt.h"
44
#include "common/heritage.h"
45
46
#include "acceptor/cache_acceptor.h"
47
#include "acceptor/acceptor_tcp.h"
48
#include "acceptor/mgt_acceptor.h"
49
50
#include "vsa.h"
51
#include "vss.h"
52
#include "vtcp.h"
53
54
int
55 39800
vca_tcp_config(void)
56
{
57
58 39800
        return (0);
59
}
60
61
static int
62 75280
vca_tcp_opensocket(struct listen_sock *ls)
63
{
64
        int fail;
65
66 75280
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
67
68 75280
        if (ls->sock > 0) {
69 36960
                MCH_Fd_Inherit(ls->sock, NULL);
70 36960
                closefd(&ls->sock);
71 36960
        }
72
73 75280
        ls->sock = VTCP_bind(ls->addr, NULL);
74 75280
        fail = errno;
75
76 75280
        if (ls->sock < 0) {
77 40
                AN(fail);
78 40
                return (fail);
79
        }
80
81 75240
        AZ(ls->perms);
82 75240
        MCH_Fd_Inherit(ls->sock, "sock");
83
84 75240
        return (0);
85 75280
}
86
87
static int v_matchproto_(vss_resolved_f)
88 38360
vca_tcp_open_cb(void *priv, const struct suckaddr *sa)
89
{
90
        struct listen_arg *la;
91
        struct listen_sock *ls;
92
        char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
93
        char nbuf[VTCP_ADDRBUFSIZE+VTCP_PORTBUFSIZE+2];
94
        int fail;
95
96 38360
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
97
98 39360
        VTAILQ_FOREACH(ls, &TCP_acceptor.socks, vcalist) {
99 1040
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
100
101 1040
                if (!VSA_Compare(sa, ls->addr))
102 40
                        ARGV_ERR("-a arguments %s and %s have same address\n",
103
                            ls->endpoint, la->endpoint);
104 1000
        }
105
106 38320
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
107 38320
        AN(ls);
108
109 38320
        ls->sock = -1;
110 38320
        ls->vca = &TCP_acceptor;
111
112 38320
        ls->addr = VSA_Clone(sa);
113 38320
        AN(ls->addr);
114
115 38320
        REPLACE(ls->endpoint, la->endpoint);
116 38320
        ls->name = la->name;
117 38320
        ls->transport = la->transport;
118 38320
        ls->perms = la->perms;
119
120 38320
        VJ_master(JAIL_MASTER_PRIVPORT);
121 38320
        fail = vca_tcp_opensocket(ls);
122 38320
        VJ_master(JAIL_MASTER_LOW);
123
124 38320
        if (fail) {
125 40
                VSA_free(&ls->addr);
126 40
                free(ls->endpoint);
127 40
                FREE_OBJ(ls);
128 40
                if (fail != EAFNOSUPPORT)
129 40
                        ARGV_ERR("Could not get socket %s: %s\n",
130
                            la->endpoint, VAS_errtxt(fail));
131 0
                return (0);
132
        }
133
134 38280
        AZ(ls->uds);
135
136 38280
        if (VSA_Port(ls->addr) == 0) {
137
                /*
138
                 * If the argv port number is zero, we adopt whatever
139
                 * port number this VTCP_bind() found us, as if
140
                 * it was specified by the argv.
141
                 */
142 38240
                VSA_free(&ls->addr);
143 38240
                ls->addr = VTCP_my_suckaddr(ls->sock);
144 76480
                VTCP_myname(ls->sock, abuf, sizeof abuf,
145 38240
                    pbuf, sizeof pbuf);
146 38240
                if (VSA_Get_Proto(sa) == AF_INET6)
147 1000
                        bprintf(nbuf, "[%s]:%s", abuf, pbuf);
148
                else
149 37240
                        bprintf(nbuf, "%s:%s", abuf, pbuf);
150 38240
                REPLACE(ls->endpoint, nbuf);
151 38240
        }
152
153 38280
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
154 38280
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
155 38280
        VTAILQ_INSERT_TAIL(&TCP_acceptor.socks, ls, vcalist);
156
157 38280
        return (0);
158 38280
}
159
160
161
int
162 37640
vca_tcp_open(char **av, struct listen_arg *la, const char **err)
163
{
164 37640
        const struct transport *xp = NULL;
165
166 37640
        CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC);
167 37640
        AN(av);
168 37640
        AN(err);
169 37640
        AZ(la->perms);
170
171 37640
        if (strchr(la->endpoint, '/') != NULL)
172 40
                ARGV_ERR("Unix domain socket addresses must be"
173
                    " absolute paths in -a (%s)\n", la->endpoint);
174
175 38280
        for (int i = 0; av[i] != NULL; i++) {
176 920
                if (strchr(av[i], '=') == NULL) {
177 800
                        if (xp != NULL)
178 80
                                ARGV_ERR("Too many protocol sub-args"
179
                                    " in -a (%s)\n", av[i]);
180 720
                        xp = XPORT_Find(av[i]);
181 720
                        if (xp == NULL)
182 40
                                ARGV_ERR("Unknown protocol '%s'\n", av[i]);
183 680
                        continue;
184
                }
185
186 120
                ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
187 0
        }
188
189 37360
        if (xp == NULL)
190 36760
                xp = XPORT_Find("http");
191
192 37360
        AN(xp);
193 37360
        la->transport = xp;
194
195 37360
        return (VSS_resolver_range(la->endpoint, "80", vca_tcp_open_cb, la, err));
196
}
197
198
int
199 37560
vca_tcp_reopen(void)
200
{
201
        struct listen_sock *ls;
202 37560
        int err, fail = 0;
203
204 74520
        VTAILQ_FOREACH(ls, &TCP_acceptor.socks, vcalist) {
205 36960
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
206
207 36960
                VJ_master(JAIL_MASTER_PRIVPORT);
208 36960
                err = vca_tcp_opensocket(ls);
209 36960
                VJ_master(JAIL_MASTER_LOW);
210
211 36960
                if (err == 0)
212 36960
                        continue;
213
214 0
                fail = vmax(fail, err);
215 0
                MGT_Complain(C_ERR, "Could not reopen listen socket %s: %s",
216 0
                    ls->endpoint, VAS_errtxt(err));
217 0
        }
218
219 37560
        return (fail);
220
}