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 216139
vss_parse(char *str, char **addr, char **port)
66
{
67
        char *p;
68
69 216139
        *addr = *port = NULL;
70
71 216139
        if (str[0] == '[') {
72
                /* IPv6 address of the form [::1]:80 */
73 799
                *addr = str + 1;
74 799
                p = strchr(str, ']');
75 799
                if (p == NULL)
76 17
                        return ("IPv6 address lacks ']'");
77 782
                *p++ = '\0';
78 782
                if (*p == '\0')
79 170
                        return (NULL);
80 612
                if (*p != ' ' && *p != ':')
81 17
                        return ("IPv6 address has wrong port separator");
82 595
        } else {
83
                /*
84
                 * IPv4 address of the form 127.0.0.1:80, IPv6 address
85
                 * without port or non-numeric.
86
                 */
87 215340
                *addr = str;
88 215340
                p = strchr(str, ' ');
89 215340
                if (p == NULL)
90 180765
                        p = strchr(str, ':');
91 215340
                if (p == NULL)
92 39155
                        return (NULL);
93 176185
                if (p[0] == ':' && strchr(&p[1], ':'))
94 714
                        return (NULL);
95 175471
                if (p == str)
96 19074
                        *addr = NULL;
97
        }
98 176066
        *p++ = '\0';
99 176066
        *port = p;
100 176066
        return (NULL);
101 216139
}
102
103
static const char *
104 16847
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 16847
        errp = vss_parse(str, addr, port);
112 16847
        if (errp != NULL)
113 0
                return (errp);
114 16847
        if (*port == NULL || **port == '-')
115 221
                return (NULL);
116
117 16626
        l = strtoul(*port, &end, 10);
118 16626
        if (end[0] != '-' || end[1] == '\0')
119 16235
                return (NULL);
120 391
        if (strchr(end + 1, '-') != NULL)
121 34
                return (NULL);
122 357
        h = strtoul(end + 1, &end, 10);
123 357
        if (end[0] != '\0')
124 51
                return (NULL);
125
126
        /* Port range of the form 80-81 */
127 306
        if (l == 0)
128 17
                return ("Range start cannot be 0");
129 289
        if (h < l)
130 17
                return ("Range start higher than range end");
131 272
        if (h > 65535)
132 17
                return ("Range end higher than 65535");
133
134 255
        *lo = l;
135 255
        *hi = h;
136 255
        return (NULL);
137 16847
}
138
139
static int
140 199294
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 199294
        AN(addr);
148 199294
        AN(res);
149 199294
        AZ(*res);
150 199294
        AN(errp);
151 199294
        *errp = NULL;
152
153 199294
        memset(&hints, 0, sizeof hints);
154 199294
        hints.ai_family = family;
155 199294
        hints.ai_socktype = socktype;
156 199294
        hints.ai_flags = flags;
157
158 199294
        p = strdup(addr);
159 199294
        AN(p);
160 199294
        *errp = vss_parse(p, &hp, &pp);
161 199294
        if (*errp != NULL) {
162 34
                free(p);
163 34
                return (-1);
164
        }
165 199260
        if (pp != NULL)
166 159304
                def_port = pp;
167 199260
        ret = getaddrinfo(hp, def_port, &hints, res);
168 199260
        free(p);
169
170 199260
        if (ret == EAI_SYSTEM)
171 0
                *errp = VAS_errtxt(errno);
172 199260
        else if (ret != 0)
173 884
                *errp = gai_strerror(ret);
174
175 199260
        return (ret);
176 199294
}
177
178
static const struct suckaddr *
179 36775
vss_alloc_suckaddr(void *dst, const struct addrinfo *ai)
180
{
181
182 36775
        AN(ai);
183 36775
        if (dst == NULL)
184 34816
                return (VSA_Malloc(ai->ai_addr, ai->ai_addrlen));
185
186 1959
        return (VSA_Build(dst, ai->ai_addr, ai->ai_addrlen));
187 36775
}
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 161957
VSS_resolver_socktype(const char *addr, const char *def_port,
198
    vss_resolved_f *func, void *priv, const char **errp, int socktype)
199
{
200 161957
        struct addrinfo *res0 = NULL, *res;
201
        const struct suckaddr *vsa;
202
        int ret;
203
204 161957
        AN(addr);
205 161957
        AN(func);
206 161957
        AN(errp);
207
208 323914
        ret = vss_resolve(addr, def_port, AF_UNSPEC, socktype, AI_PASSIVE,
209 161957
            &res0, errp);
210 161957
        if (ret != 0)
211 391
                return (-1);
212
213 250442
        for (res = res0; res != NULL; res = res->ai_next) {
214 178345
                vsa = VSA_Malloc(res->ai_addr, res->ai_addrlen);
215 178345
                if (vsa != NULL) {
216 178345
                        ret = func(priv, vsa);
217 178345
                        VSA_free(&vsa);
218 178345
                        if (ret)
219 89469
                                break;
220 88876
                }
221 88876
        }
222 161566
        freeaddrinfo(res0);
223 161566
        return (ret);
224 161957
}
225
226
int
227 161976
VSS_resolver(const char *addr, const char *def_port, vss_resolved_f *func,
228
    void *priv, const char **errp)
229
{
230 161976
        return (VSS_resolver_socktype(
231 161976
            addr, def_port, func, priv, errp, SOCK_STREAM));
232
}
233
234
int
235 16847
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 16847
        unsigned long lo = 0, hi = 0, i;
240 16847
        int error = 0;
241
242 16847
        AN(addr);
243 16847
        AN(func);
244 16847
        AN(errp);
245
246 16847
        p = strdup(addr);
247 16847
        AN(p);
248 16847
        *errp = vss_parse_range(p, &hp, &pp, &lo, &hi);
249 16847
        if (*errp != NULL) {
250 51
                free(p);
251 51
                return (-1);
252
        }
253
254 16796
        if (lo == 0) {
255
                /* No port range (0 not allowed in range) */
256 16541
                free(p);
257 16541
                return (VSS_resolver(addr, def_port, func, priv, errp));
258
        }
259
260
        /* Undo vss_parse() string modifications */
261 255
        memcpy(p, addr, pp - p);
262
263 748
        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 493
                sprintf(pp, "%lu", i);
269 493
                error = VSS_resolver(p, def_port, func, priv, errp);
270 493
        }
271 255
        free(p);
272 255
        return (error);
273 16847
}
274
275
const struct suckaddr *
276 35806
VSS_ResolveOne(void *dst, const char *addr, const char *def_port,
277
    int family, int socktype, int flags)
278
{
279 35806
        struct addrinfo *res = NULL;
280 35806
        const struct suckaddr *retval = NULL;
281
        const char *err;
282
        int ret;
283
284 35806
        AN(addr);
285 35806
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res, &err);
286 35806
        if (ret == 0 && res != NULL && res->ai_next == NULL) {
287 35483
                AZ(err);
288 35483
                retval = vss_alloc_suckaddr(dst, res);
289 35483
        }
290 35806
        if (res != NULL)
291 35483
                freeaddrinfo(res);
292 35806
        return (retval);
293
}
294
295
const struct suckaddr *
296 1496
VSS_ResolveFirst(void *dst, const char *addr, const char *def_port,
297
    int family, int socktype, int flags)
298
{
299 1496
        struct addrinfo *res0 = NULL, *res;
300 1496
        const struct suckaddr *retval = NULL;
301
        const char *err;
302
        int ret;
303
304 1496
        AN(addr);
305 1496
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res0, &err);
306 1496
        if (ret == 0)
307 1292
                AZ(err);
308
309 1513
        for (res = res0; res != NULL; res = res->ai_next) {
310 1292
                retval = vss_alloc_suckaddr(dst, res);
311 1292
                if (retval != NULL)
312 1275
                        break;
313 17
        }
314 1496
        if (res0 != NULL)
315 1292
                freeaddrinfo(res0);
316 1496
        return (retval);
317
}