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 4020
vca_tcp_config(void)
56
{
57
58 4020
        return (0);
59
}
60
61
static int
62 7620
vca_tcp_opensocket(struct listen_sock *ls)
63
{
64
        int fail;
65
66 7620
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
67
68 7620
        if (ls->sock > 0) {
69 3748
                MCH_Fd_Inherit(ls->sock, NULL);
70 3748
                closefd(&ls->sock);
71 3748
        }
72
73 7620
        ls->sock = VTCP_bind(ls->addr, NULL);
74 7620
        fail = errno;
75
76 7620
        if (ls->sock < 0) {
77 4
                AN(fail);
78 4
                return (fail);
79
        }
80
81 7616
        AZ(ls->perms);
82 7616
        MCH_Fd_Inherit(ls->sock, "sock");
83
84 7616
        return (0);
85 7620
}
86
87
static int v_matchproto_(vss_resolved_f)
88 3876
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 3876
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
97
98 3976
        VTAILQ_FOREACH(ls, &TCP_acceptor.socks, vcalist) {
99 104
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
100
101 104
                if (!VSA_Compare(sa, ls->addr))
102 4
                        ARGV_ERR("-a arguments %s and %s have same address\n",
103
                            ls->endpoint, la->endpoint);
104 100
        }
105
106 3872
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
107 3872
        AN(ls);
108
109 3872
        ls->sock = -1;
110 3872
        ls->vca = &TCP_acceptor;
111
112 3872
        ls->addr = VSA_Clone(sa);
113 3872
        AN(ls->addr);
114
115 3872
        REPLACE(ls->endpoint, la->endpoint);
116 3872
        ls->name = la->name;
117 3872
        ls->transport = la->transport;
118 3872
        ls->perms = la->perms;
119
120 3872
        VJ_master(JAIL_MASTER_PRIVPORT);
121 3872
        fail = vca_tcp_opensocket(ls);
122 3872
        VJ_master(JAIL_MASTER_LOW);
123
124 3872
        if (fail) {
125 4
                VSA_free(&ls->addr);
126 4
                free(ls->endpoint);
127 4
                FREE_OBJ(ls);
128 4
                if (fail != EAFNOSUPPORT)
129 4
                        ARGV_ERR("Could not get socket %s: %s\n",
130
                            la->endpoint, VAS_errtxt(fail));
131 0
                return (0);
132
        }
133
134 3868
        AZ(ls->uds);
135
136 3868
        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 3864
                VSA_free(&ls->addr);
143 3864
                ls->addr = VTCP_my_suckaddr(ls->sock);
144 7728
                VTCP_myname(ls->sock, abuf, sizeof abuf,
145 3864
                    pbuf, sizeof pbuf);
146 3864
                if (VSA_Get_Proto(sa) == AF_INET6)
147 100
                        bprintf(nbuf, "[%s]:%s", abuf, pbuf);
148
                else
149 3764
                        bprintf(nbuf, "%s:%s", abuf, pbuf);
150 3864
                REPLACE(ls->endpoint, nbuf);
151 3864
        }
152
153 3868
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
154 3868
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
155 3868
        VTAILQ_INSERT_TAIL(&TCP_acceptor.socks, ls, vcalist);
156
157 3868
        return (0);
158 3868
}
159
160
161
int
162 3804
vca_tcp_open(char **av, struct listen_arg *la, const char **err)
163
{
164 3804
        const struct transport *xp = NULL;
165
166 3804
        CHECK_OBJ_NOTNULL(la, LISTEN_ARG_MAGIC);
167 3804
        AN(av);
168 3804
        AN(err);
169 3804
        AZ(la->perms);
170
171 3804
        if (strchr(la->endpoint, '/') != NULL)
172 4
                ARGV_ERR("Unix domain socket addresses must be"
173
                    " absolute paths in -a (%s)\n", la->endpoint);
174
175 3872
        for (int i = 0; av[i] != NULL; i++) {
176 96
                if (strchr(av[i], '=') == NULL) {
177 84
                        if (xp != NULL)
178 8
                                ARGV_ERR("Too many protocol sub-args"
179
                                    " in -a (%s)\n", av[i]);
180 76
                        xp = XPORT_Find(av[i]);
181 76
                        if (xp == NULL)
182 4
                                ARGV_ERR("Unknown protocol '%s'\n", av[i]);
183 72
                        continue;
184
                }
185
186 12
                ARGV_ERR("Invalid sub-arg %s in -a\n", av[i]);
187 0
        }
188
189 3776
        if (xp == NULL)
190 3712
                xp = XPORT_Find("http");
191
192 3776
        AN(xp);
193 3776
        la->transport = xp;
194
195 3776
        return (VSS_resolver_range(la->endpoint, "80", vca_tcp_open_cb, la, err));
196
}
197
198
int
199 3808
vca_tcp_reopen(void)
200
{
201
        struct listen_sock *ls;
202 3808
        int err, fail = 0;
203
204 7556
        VTAILQ_FOREACH(ls, &TCP_acceptor.socks, vcalist) {
205 3748
                CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
206
207 3748
                VJ_master(JAIL_MASTER_PRIVPORT);
208 3748
                err = vca_tcp_opensocket(ls);
209 3748
                VJ_master(JAIL_MASTER_LOW);
210
211 3748
                if (err == 0)
212 3748
                        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 3808
        return (fail);
220
}