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 39840
vca_tcp_config(void)
56
{
57
58 39840
        return (0);
59
}
60
61
static int
62 75360
vca_tcp_opensocket(struct listen_sock *ls)
63
{
64
        int fail;
65
66 75360
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
67
68 75360
        if (ls->sock > 0) {
69 37000
                MCH_Fd_Inherit(ls->sock, NULL);
70 37000
                closefd(&ls->sock);
71 37000
        }
72
73 75360
        ls->sock = VTCP_bind(ls->addr, NULL);
74 75360
        fail = errno;
75
76 75360
        if (ls->sock < 0) {
77 40
                AN(fail);
78 40
                return (fail);
79
        }
80
81 75320
        AZ(ls->perms);
82 75320
        MCH_Fd_Inherit(ls->sock, "sock");
83
84 75320
        return (0);
85 75360
}
86
87
static int v_matchproto_(vss_resolved_f)
88 38400
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 38400
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
97
98 39400
        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 38360
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
107 38360
        AN(ls);
108
109 38360
        ls->sock = -1;
110 38360
        ls->vca = &TCP_acceptor;
111
112 38360
        ls->addr = VSA_Clone(sa);
113 38360
        AN(ls->addr);
114
115 38360
        REPLACE(ls->endpoint, la->endpoint);
116 38360
        ls->name = la->name;
117 38360
        ls->transport = la->transport;
118 38360
        ls->perms = la->perms;
119
120 38360
        VJ_master(JAIL_MASTER_PRIVPORT);
121 38360
        fail = vca_tcp_opensocket(ls);
122 38360
        VJ_master(JAIL_MASTER_LOW);
123
124 38360
        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 38320
        AZ(ls->uds);
135
136 38320
        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 38280
                VSA_free(&ls->addr);
143 38280
                ls->addr = VTCP_my_suckaddr(ls->sock);
144 76560
                VTCP_myname(ls->sock, abuf, sizeof abuf,
145 38280
                    pbuf, sizeof pbuf);
146 38280
                if (VSA_Get_Proto(sa) == AF_INET6)
147 1000
                        bprintf(nbuf, "[%s]:%s", abuf, pbuf);
148
                else
149 37280
                        bprintf(nbuf, "%s:%s", abuf, pbuf);
150 38280
                REPLACE(ls->endpoint, nbuf);
151 38280
        }
152
153 38320
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
154 38320
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
155 38320
        VTAILQ_INSERT_TAIL(&TCP_acceptor.socks, ls, vcalist);
156
157 38320
        return (0);
158 38320
}
159
160
161
int
162 37680
vca_tcp_open(char **av, struct listen_arg *la, const char **err)
163
{
164 37680
        const struct transport *xp = NULL;
165
166 37680
        CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC);
167 37680
        AN(av);
168 37680
        AN(err);
169 37680
        AZ(la->perms);
170
171 37680
        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 38320
        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 37400
        if (xp == NULL)
190 36800
                xp = XPORT_Find("http");
191
192 37400
        AN(xp);
193 37400
        la->transport = xp;
194
195 37400
        return (VSS_resolver_range(la->endpoint, "80", vca_tcp_open_cb, la, err));
196
}
197
198
int
199 37600
vca_tcp_reopen(void)
200
{
201
        struct listen_sock *ls;
202 37600
        int err, fail = 0;
203
204 74600
        VTAILQ_FOREACH(ls, &TCP_acceptor.socks, vcalist) {
205 37000
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
206
207 37000
                VJ_master(JAIL_MASTER_PRIVPORT);
208 37000
                err = vca_tcp_opensocket(ls);
209 37000
                VJ_master(JAIL_MASTER_LOW);
210
211 37000
                if (err == 0)
212 37000
                        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 37600
        return (fail);
220
}