varnish-cache/bin/varnishd/mgt/mgt_acceptor.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 * Acceptor socket management
30
 */
31
32
#include "config.h"
33
34
#include <sys/types.h>
35
#include <sys/socket.h>
36
#include <errno.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <unistd.h>
41
42
#include "mgt/mgt.h"
43
#include "common/heritage.h"
44
45
#include "vav.h"
46
#include "vcli_serve.h"
47
#include "vsa.h"
48
#include "vss.h"
49
#include "vtcp.h"
50
51
static VTAILQ_HEAD(,listen_arg) listen_args =
52
    VTAILQ_HEAD_INITIALIZER(listen_args);
53
54
static int
55 1271
mac_opensocket(struct listen_sock *ls)
56
{
57
        int fail;
58
59 1271
        CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
60 1271
        if (ls->sock > 0) {
61 616
                MCH_Fd_Inherit(ls->sock, NULL);
62 616
                closefd(&ls->sock);
63
        }
64 1271
        ls->sock = VTCP_bind(ls->addr, NULL);
65 1271
        fail = errno;
66 1271
        if (ls->sock < 0) {
67 1
                AN(fail);
68 1
                return (fail);
69
        }
70 1270
        MCH_Fd_Inherit(ls->sock, "sock");
71 1270
        return (0);
72
}
73
74
/*=====================================================================
75
 * Reopen the accept sockets to get rid of listen status.
76
 * returns the highest errno encountered, 0 for success
77
 */
78
79
int
80 615
MAC_reopen_sockets(void)
81
{
82
        struct listen_sock *ls;
83 615
        int err, fail = 0;
84
85 1231
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
86 616
                VJ_master(JAIL_MASTER_PRIVPORT);
87 616
                err = mac_opensocket(ls);
88 616
                VJ_master(JAIL_MASTER_LOW);
89 616
                if (err == 0)
90 616
                        continue;
91 0
                if (err > fail)
92 0
                        fail = err;
93 0
                MGT_Complain(C_ERR,
94
                    "Could not reopen listen socket %s: %s",
95
                    ls->endpoint, strerror(err));
96
        }
97 615
        return fail;
98
}
99
100
/*--------------------------------------------------------------------*/
101
102
static int v_matchproto_(vss_resolved_f)
103 656
mac_callback(void *priv, const struct suckaddr *sa)
104
{
105
        struct listen_arg *la;
106
        struct listen_sock *ls;
107
        char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
108
        char nbuf[VTCP_ADDRBUFSIZE+VTCP_PORTBUFSIZE+2];
109
        int fail;
110
111 656
        CAST_OBJ_NOTNULL(la, priv, LISTEN_ARG_MAGIC);
112
113 672
        VTAILQ_FOREACH(ls, &heritage.socks, list) {
114 17
                if (!VSA_Compare(sa, ls->addr))
115 1
                        ARGV_ERR("-a arguments %s and %s have same address\n",
116
                            ls->endpoint, la->endpoint);
117
        }
118 655
        ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
119 655
        AN(ls);
120 655
        ls->sock = -1;
121 655
        ls->addr = VSA_Clone(sa);
122 655
        AN(ls->addr);
123 655
        ls->endpoint = strdup(la->endpoint);
124 655
        AN(ls->endpoint);
125 655
        ls->name = la->name;
126 655
        ls->transport = la->transport;
127 655
        VJ_master(JAIL_MASTER_PRIVPORT);
128 655
        fail = mac_opensocket(ls);
129 655
        VJ_master(JAIL_MASTER_LOW);
130 655
        if (fail) {
131 1
                free(ls->addr);
132 1
                free(ls->endpoint);
133 1
                FREE_OBJ(ls);
134 1
                if (fail != EAFNOSUPPORT)
135 1
                        ARGV_ERR("Could not get socket %s: %s\n",
136
                            la->endpoint, strerror(fail));
137 0
                return(0);
138
        }
139 654
        if (VSA_Port(ls->addr) == 0) {
140
                /*
141
                 * If the argv port number is zero, we adopt whatever
142
                 * port number this VTCP_bind() found us, as if
143
                 * it was specified by the argv.
144
                 */
145 653
                free(ls->addr);
146 653
                ls->addr = VTCP_my_suckaddr(ls->sock);
147 653
                VTCP_myname(ls->sock, abuf, sizeof abuf,
148
                    pbuf, sizeof pbuf);
149 653
                bprintf(nbuf, "%s:%s", abuf, pbuf);
150 653
                REPLACE(ls->endpoint, nbuf);
151
        }
152 654
        VTAILQ_INSERT_TAIL(&la->socks, ls, arglist);
153 654
        VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
154 654
        return (0);
155
}
156
157
void
158 643
MAC_Arg(const char *spec)
159
{
160
        char **av;
161
        struct listen_arg *la;
162
        const char *err;
163
        int error;
164
        const struct transport *xp;
165
        const char *name;
166
        char name_buf[8];
167
        static unsigned seq = 0;
168
169 643
        av = MGT_NamedArg(spec, &name, "-a");
170 643
        AN(av);
171
172 643
        ALLOC_OBJ(la, LISTEN_ARG_MAGIC);
173 643
        AN(la);
174 643
        VTAILQ_INIT(&la->socks);
175 643
        VTAILQ_INSERT_TAIL(&listen_args, la, list);
176 643
        la->endpoint = av[1];
177
178 643
        if (name == NULL) {
179 642
                bprintf(name_buf, "a%u", seq++);
180 642
                name = strdup(name_buf);
181 642
                AN(name);
182
        }
183 643
        la->name = name;
184
185 643
        if (av[2] == NULL) {
186 632
                xp = XPORT_Find("http");
187
        } else {
188 11
                xp = XPORT_Find(av[2]);
189 11
                if (xp == NULL)
190 1
                        ARGV_ERR("Unknown protocol '%s'\n", av[2]);
191 10
                if (av[3] != NULL)
192 2
                        ARGV_ERR("Too many sub-arguments to -a(%s)\n", av[2]);
193
        }
194 640
        AN(xp);
195 640
        la->transport = xp;
196
197 640
        error = VSS_resolver(av[1], "80", mac_callback, la, &err);
198 638
        if (VTAILQ_EMPTY(&la->socks) || error)
199 0
                ARGV_ERR("Got no socket(s) for %s\n", av[1]);
200 638
        VAV_Free(av);
201 638
}