varnish-cache/lib/libvarnish/vss.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2010 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Dag-Erling Smørgrav <des@des.no>
6
 * Author: Cecilie Fritzvold <cecilihf@linpro.no>
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
#include "config.h"
33
34
#include <sys/socket.h>
35
36
#include <netdb.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <stdio.h>
40
41
#include "vdef.h"
42
43
#include "vas.h"
44
#include "vsa.h"
45
#include "vss.h"
46
47
/*lint -esym(754, _storage) not ref */
48
49
/*
50
 * Take a string provided by the user and break it up into address and
51
 * port parts. The address and port separator may be either a colon or
52
 * a whitespace. Examples of acceptable input include:
53
 *
54
 * "localhost" - "localhost:80" - "localhost 80"
55
 * "127.0.0.1" - "127.0.0.1:80" - "127.0.0.1 80"
56
 * "0.0.0.0"   - "0.0.0.0:80"   - "0.0.0.0 80"
57
 * "[::1]"     - "[::1]:80"     - "[::1] 80"
58
 * "[::]"      - "[::]:80"      - "[::] 80"
59
 * "::1"       - "[::1]:80"     - "[::1] 80"
60
 *
61
 * See also RFC5952
62
 */
63
64
static const char *
65 50446
vss_parse(char *str, char **addr, char **port)
66
{
67
        char *p;
68
69 50446
        *addr = *port = NULL;
70
71 50446
        if (str[0] == '[') {
72
                /* IPv6 address of the form [::1]:80 */
73 180
                *addr = str + 1;
74 180
                p = strchr(str, ']');
75 180
                if (p == NULL)
76 4
                        return ("IPv6 address lacks ']'");
77 176
                *p++ = '\0';
78 176
                if (*p == '\0')
79 40
                        return (NULL);
80 136
                if (*p != ' ' && *p != ':')
81 4
                        return ("IPv6 address has wrong port separator");
82 132
        } else {
83
                /*
84
                 * IPv4 address of the form 127.0.0.1:80, IPv6 address
85
                 * without port or non-numeric.
86
                 */
87 50266
                *addr = str;
88 50266
                p = strchr(str, ' ');
89 50266
                if (p == NULL)
90 42190
                        p = strchr(str, ':');
91 50266
                if (p == NULL)
92 9130
                        return (NULL);
93 41136
                if (p[0] == ':' && strchr(&p[1], ':'))
94 168
                        return (NULL);
95 40968
                if (p == str)
96 4464
                        *addr = NULL;
97
        }
98 41100
        *p++ = '\0';
99 41100
        *port = p;
100 41100
        return (NULL);
101 50446
}
102
103
static const char *
104 3940
vss_parse_range(char *str, char **addr, char **port, unsigned long *lo,
105
    unsigned long *hi)
106
{
107
        const char *errp;
108
        char *end;
109
        unsigned long l, h;
110
111 3940
        errp = vss_parse(str, addr, port);
112 3940
        if (errp != NULL)
113 0
                return (errp);
114 3940
        if (*port == NULL || **port == '-')
115 52
                return (NULL);
116
117 3888
        l = strtoul(*port, &end, 10);
118 3888
        if (end[0] != '-' || end[1] == '\0')
119 3796
                return (NULL);
120 92
        if (strchr(end + 1, '-') != NULL)
121 8
                return (NULL);
122 84
        h = strtoul(end + 1, &end, 10);
123 84
        if (end[0] != '\0')
124 12
                return (NULL);
125
126
        /* Port range of the form 80-81 */
127 72
        if (l == 0)
128 4
                return ("Range start cannot be 0");
129 68
        if (h < l)
130 4
                return ("Range start higher than range end");
131 64
        if (h > 65535)
132 4
                return ("Range end higher than 65535");
133
134 60
        *lo = l;
135 60
        *hi = h;
136 60
        return (NULL);
137 3940
}
138
139
static int
140 46506
vss_resolve(const char *addr, const char *def_port, int family, int socktype,
141
    int flags, struct addrinfo **res, const char **errp)
142
{
143
        struct addrinfo hints;
144
        char *p, *hp, *pp;
145
        int ret;
146
147 46506
        AN(addr);
148 46506
        AN(res);
149 46506
        AZ(*res);
150 46506
        AN(errp);
151 46506
        *errp = NULL;
152
153 46506
        memset(&hints, 0, sizeof hints);
154 46506
        hints.ai_family = family;
155 46506
        hints.ai_socktype = socktype;
156 46506
        hints.ai_flags = flags;
157
158 46506
        p = strdup(addr);
159 46506
        AN(p);
160 46506
        *errp = vss_parse(p, &hp, &pp);
161 46506
        if (*errp != NULL) {
162 8
                free(p);
163 8
                return (-1);
164
        }
165 46498
        if (pp != NULL)
166 37180
                def_port = pp;
167 46498
        ret = getaddrinfo(hp, def_port, &hints, res);
168 46498
        free(p);
169
170 46498
        if (ret == EAI_SYSTEM)
171 0
                *errp = VAS_errtxt(errno);
172 46498
        else if (ret != 0)
173 176
                *errp = gai_strerror(ret);
174
175 46498
        return (ret);
176 46506
}
177
178
static const struct suckaddr *
179 8582
vss_alloc_suckaddr(void *dst, const struct addrinfo *ai)
180
{
181
182 8582
        AN(ai);
183 8582
        if (dst == NULL)
184 8128
                return (VSA_Malloc(ai->ai_addr, ai->ai_addrlen));
185
186 454
        return (VSA_Build(dst, ai->ai_addr, ai->ai_addrlen));
187 8582
}
188
189
/*
190
 * Look up an address, using a default port if provided, and call
191
 * the callback function with the suckaddrs we find.
192
 * If the callback function returns anything but zero, we terminate
193
 * and pass that value.
194
 */
195
196
int
197 37824
VSS_resolver_socktype(const char *addr, const char *def_port,
198
    vss_resolved_f *func, void *priv, const char **errp, int socktype)
199
{
200 37824
        struct addrinfo *res0 = NULL, *res;
201
        const struct suckaddr *vsa;
202
        int ret;
203
204 37824
        AN(addr);
205 37824
        AN(func);
206 37824
        AN(errp);
207
208 75648
        ret = vss_resolve(addr, def_port, AF_UNSPEC, socktype, AI_PASSIVE,
209 37824
            &res0, errp);
210 37824
        if (ret != 0)
211 92
                return (-1);
212
213 58512
        for (res = res0; res != NULL; res = res->ai_next) {
214 41655
                vsa = VSA_Malloc(res->ai_addr, res->ai_addrlen);
215 41655
                if (vsa != NULL) {
216 41655
                        ret = func(priv, vsa);
217 41655
                        VSA_free(&vsa);
218 41655
                        if (ret)
219 20875
                                break;
220 20780
                }
221 20780
        }
222 37732
        freeaddrinfo(res0);
223 37732
        return (ret);
224 37824
}
225
226
int
227 37828
VSS_resolver(const char *addr, const char *def_port, vss_resolved_f *func,
228
    void *priv, const char **errp)
229
{
230 37828
        return (VSS_resolver_socktype(
231 37828
            addr, def_port, func, priv, errp, SOCK_STREAM));
232
}
233
234
int
235 3940
VSS_resolver_range(const char *addr, const char *def_port, vss_resolved_f *func,
236
    void *priv, const char **errp)
237
{
238
        char *p, *hp, *pp;
239 3940
        unsigned long lo = 0, hi = 0, i;
240 3940
        int error = 0;
241
242 3940
        AN(addr);
243 3940
        AN(func);
244 3940
        AN(errp);
245
246 3940
        p = strdup(addr);
247 3940
        AN(p);
248 3940
        *errp = vss_parse_range(p, &hp, &pp, &lo, &hi);
249 3940
        if (*errp != NULL) {
250 12
                free(p);
251 12
                return (-1);
252
        }
253
254 3928
        if (lo == 0) {
255
                /* No port range (0 not allowed in range) */
256 3868
                free(p);
257 3868
                return (VSS_resolver(addr, def_port, func, priv, errp));
258
        }
259
260
        /* Undo vss_parse() string modifications */
261 60
        memcpy(p, addr, pp - p);
262
263 176
        for (i = lo; i <= hi && !error; i++) {
264
                /* pp points to the first character of the range definition.
265
                 * The range definition includes the biggest port number, so the
266
                 * buffer must be big enough to fit each number individually.
267
                 */
268 116
                sprintf(pp, "%lu", i);
269 116
                error = VSS_resolver(p, def_port, func, priv, errp);
270 116
        }
271 60
        free(p);
272 60
        return (error);
273 3940
}
274
275
const struct suckaddr *
276 8322
VSS_ResolveOne(void *dst, const char *addr, const char *def_port,
277
    int family, int socktype, int flags)
278
{
279 8322
        struct addrinfo *res = NULL;
280 8322
        const struct suckaddr *retval = NULL;
281
        const char *err;
282
        int ret;
283
284 8322
        AN(addr);
285 8322
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res, &err);
286 8322
        if (ret == 0 && res != NULL && res->ai_next == NULL) {
287 8278
                AZ(err);
288 8278
                retval = vss_alloc_suckaddr(dst, res);
289 8278
        }
290 8322
        if (res != NULL)
291 8278
                freeaddrinfo(res);
292 8322
        return (retval);
293
}
294
295
const struct suckaddr *
296 352
VSS_ResolveFirst(void *dst, const char *addr, const char *def_port,
297
    int family, int socktype, int flags)
298
{
299 352
        struct addrinfo *res0 = NULL, *res;
300 352
        const struct suckaddr *retval = NULL;
301
        const char *err;
302
        int ret;
303
304 352
        AN(addr);
305 352
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res0, &err);
306 352
        if (ret == 0)
307 304
                AZ(err);
308
309 356
        for (res = res0; res != NULL; res = res->ai_next) {
310 304
                retval = vss_alloc_suckaddr(dst, res);
311 304
                if (retval != NULL)
312 300
                        break;
313 4
        }
314 352
        if (res0 != NULL)
315 304
                freeaddrinfo(res0);
316 352
        return (retval);
317
}