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 502446
vss_parse(char *str, char **addr, char **port)
66
{
67
        char *p;
68
69 502446
        *addr = *port = NULL;
70
71 502446
        if (str[0] == '[') {
72
                /* IPv6 address of the form [::1]:80 */
73 1800
                *addr = str + 1;
74 1800
                p = strchr(str, ']');
75 1800
                if (p == NULL)
76 40
                        return ("IPv6 address lacks ']'");
77 1760
                *p++ = '\0';
78 1760
                if (*p == '\0')
79 400
                        return (NULL);
80 1360
                if (*p != ' ' && *p != ':')
81 40
                        return ("IPv6 address has wrong port separator");
82 1320
        } else {
83
                /*
84
                 * IPv4 address of the form 127.0.0.1:80, IPv6 address
85
                 * without port or non-numeric.
86
                 */
87 500646
                *addr = str;
88 500646
                p = strchr(str, ' ');
89 500646
                if (p == NULL)
90 420247
                        p = strchr(str, ':');
91 500646
                if (p == NULL)
92 91048
                        return (NULL);
93 409598
                if (p[0] == ':' && strchr(&p[1], ':'))
94 1680
                        return (NULL);
95 407918
                if (p == str)
96 44520
                        *addr = NULL;
97
        }
98 409238
        *p++ = '\0';
99 409238
        *port = p;
100 409238
        return (NULL);
101 502446
}
102
103
static const char *
104 39280
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 39280
        errp = vss_parse(str, addr, port);
112 39280
        if (errp != NULL)
113 0
                return (errp);
114 39280
        if (*port == NULL || **port == '-')
115 520
                return (NULL);
116
117 38760
        l = strtoul(*port, &end, 10);
118 38760
        if (end[0] != '-' || end[1] == '\0')
119 37840
                return (NULL);
120 920
        if (strchr(end + 1, '-') != NULL)
121 80
                return (NULL);
122 840
        h = strtoul(end + 1, &end, 10);
123 840
        if (end[0] != '\0')
124 120
                return (NULL);
125
126
        /* Port range of the form 80-81 */
127 720
        if (l == 0)
128 40
                return ("Range start cannot be 0");
129 680
        if (h < l)
130 40
                return ("Range start higher than range end");
131 640
        if (h > 65535)
132 40
                return ("Range end higher than 65535");
133
134 600
        *lo = l;
135 600
        *hi = h;
136 600
        return (NULL);
137 39280
}
138
139
static int
140 463166
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 463166
        AN(addr);
148 463166
        AN(res);
149 463166
        AZ(*res);
150 463166
        AN(errp);
151 463166
        *errp = NULL;
152
153 463166
        memset(&hints, 0, sizeof hints);
154 463166
        hints.ai_family = family;
155 463166
        hints.ai_socktype = socktype;
156 463166
        hints.ai_flags = flags;
157
158 463166
        p = strdup(addr);
159 463166
        AN(p);
160 463166
        *errp = vss_parse(p, &hp, &pp);
161 463166
        if (*errp != NULL) {
162 80
                free(p);
163 80
                return (-1);
164
        }
165 463086
        if (pp != NULL)
166 370154
                def_port = pp;
167 463086
        ret = getaddrinfo(hp, def_port, &hints, res);
168 463086
        free(p);
169
170 463086
        if (ret == EAI_SYSTEM)
171 0
                *errp = VAS_errtxt(errno);
172 463086
        else if (ret != 0)
173 1760
                *errp = gai_strerror(ret);
174
175 463086
        return (ret);
176 463166
}
177
178
static const struct suckaddr *
179 85568
vss_alloc_suckaddr(void *dst, const struct addrinfo *ai)
180
{
181
182 85568
        AN(ai);
183 85568
        if (dst == NULL)
184 81040
                return (VSA_Malloc(ai->ai_addr, ai->ai_addrlen));
185
186 4528
        return (VSA_Build(dst, ai->ai_addr, ai->ai_addrlen));
187 85568
}
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 376589
VSS_resolver_socktype(const char *addr, const char *def_port,
198
    vss_resolved_f *func, void *priv, const char **errp, int socktype)
199
{
200 376589
        struct addrinfo *res0 = NULL, *res;
201
        const struct suckaddr *vsa;
202
        int ret;
203
204 376589
        AN(addr);
205 376589
        AN(func);
206 376589
        AN(errp);
207
208 753178
        ret = vss_resolve(addr, def_port, AF_UNSPEC, socktype, AI_PASSIVE,
209 376589
            &res0, errp);
210 376589
        if (ret != 0)
211 920
                return (-1);
212
213 582749
        for (res = res0; res != NULL; res = res->ai_next) {
214 414789
                vsa = VSA_Malloc(res->ai_addr, res->ai_addrlen);
215 414789
                if (vsa != NULL) {
216 414789
                        ret = func(priv, vsa);
217 414789
                        VSA_free(&vsa);
218 414789
                        if (ret)
219 207709
                                break;
220 207080
                }
221 207080
        }
222 375669
        freeaddrinfo(res0);
223 375669
        return (ret);
224 376589
}
225
226
int
227 376640
VSS_resolver(const char *addr, const char *def_port, vss_resolved_f *func,
228
    void *priv, const char **errp)
229
{
230 376640
        return (VSS_resolver_socktype(
231 376640
            addr, def_port, func, priv, errp, SOCK_STREAM));
232
}
233
234
int
235 39280
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 39280
        unsigned long lo = 0, hi = 0, i;
240 39280
        int error = 0;
241
242 39280
        AN(addr);
243 39280
        AN(func);
244 39280
        AN(errp);
245
246 39280
        p = strdup(addr);
247 39280
        AN(p);
248 39280
        *errp = vss_parse_range(p, &hp, &pp, &lo, &hi);
249 39280
        if (*errp != NULL) {
250 120
                free(p);
251 120
                return (-1);
252
        }
253
254 39160
        if (lo == 0) {
255
                /* No port range (0 not allowed in range) */
256 38560
                free(p);
257 38560
                return (VSS_resolver(addr, def_port, func, priv, errp));
258
        }
259
260
        /* Undo vss_parse() string modifications */
261 600
        memcpy(p, addr, pp - p);
262
263 1760
        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 1160
                sprintf(pp, "%lu", i);
269 1160
                error = VSS_resolver(p, def_port, func, priv, errp);
270 1160
        }
271 600
        free(p);
272 600
        return (error);
273 39280
}
274
275
const struct suckaddr *
276 82968
VSS_ResolveOne(void *dst, const char *addr, const char *def_port,
277
    int family, int socktype, int flags)
278
{
279 82968
        struct addrinfo *res = NULL;
280 82968
        const struct suckaddr *retval = NULL;
281
        const char *err;
282
        int ret;
283
284 82968
        AN(addr);
285 82968
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res, &err);
286 82968
        if (ret == 0 && res != NULL && res->ai_next == NULL) {
287 82528
                AZ(err);
288 82528
                retval = vss_alloc_suckaddr(dst, res);
289 82528
        }
290 82968
        if (res != NULL)
291 82528
                freeaddrinfo(res);
292 82968
        return (retval);
293
}
294
295
const struct suckaddr *
296 3520
VSS_ResolveFirst(void *dst, const char *addr, const char *def_port,
297
    int family, int socktype, int flags)
298
{
299 3520
        struct addrinfo *res0 = NULL, *res;
300 3520
        const struct suckaddr *retval = NULL;
301
        const char *err;
302
        int ret;
303
304 3520
        AN(addr);
305 3520
        ret = vss_resolve(addr, def_port, family, socktype, flags, &res0, &err);
306 3520
        if (ret == 0)
307 3040
                AZ(err);
308
309 3560
        for (res = res0; res != NULL; res = res->ai_next) {
310 3040
                retval = vss_alloc_suckaddr(dst, res);
311 3040
                if (retval != NULL)
312 3000
                        break;
313 40
        }
314 3520
        if (res0 != NULL)
315 3040
                freeaddrinfo(res0);
316 3520
        return (retval);
317
}