vinyl-cache/lib/libvinyl/vsa.c
0
/*-
1
 * Copyright (c) 2013-2015 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
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
 * Struct sockaddr_* is not even close to a convenient API.
30
 *
31
 * These functions try to mitigate the madness, at the cost of actually
32
 * knowing something about address families.
33
 */
34
35
#include "config.h"
36
37
#include <string.h>
38
#include <stdint.h>
39
#include <stdlib.h>
40
#include <sys/socket.h>
41
#include <sys/un.h>
42
#include <sys/types.h>
43
#include <netinet/in.h>
44
45
#include "vdef.h"
46
#include "vas.h"
47
#include "vsa.h"
48
#include "miniobj.h"
49
50
/*
51
 * Struct sockaddr{|_in|_in6|_storage} is absolutely the worst data
52
 * structure I have ever seen gold-plated in international standards.
53
 *
54
 * Network addresses have multiple different forms, many fewer today
55
 * than in last century, but imagine that in addition to IPv4 and IPv6
56
 * we had 40 other protocols.  Actually, you don't need to imagine that
57
 * just count the AF_* macros in /usr/include/sys/socket.h.
58
 *
59
 * So what do we pass the kernel API for an address to bind(2), connect(2) &
60
 * listen(2) etc. etc ?
61
 *
62
 * We could define a struct which is big enough to hold any and all
63
 * of these addresses.  That would make it a fixed size argument.
64
 * obviously the struct would have to be something like:
65
 *      struct bla {
66
 *              int family;
67
 *              char address[MAX_ADDR_LEN];
68
 *      }
69
 * and MAX_ADDR_LEN would have to be quite large, 128 byte or so.
70
 *
71
 * Back in last century that was TOTALLY unacceptable waste of space.
72
 *
73
 * The way which was chosen instead, was to make a "generic" address,
74
 * and have per protocol "specific" addresses, and pass the length
75
 * argument explicitly to the KPI functions.
76
 *
77
 * The generic address was called "struct sockaddr", and the specific
78
 * were called "struct sockaddr_${whatever}".  All of these must have
79
 * a "family" field as first element, so the kernel can figure out
80
 * which protocol it is.
81
 *
82
 * The generic struct sockaddr was made big enough for all protocols
83
 * supported in the kernel, so it would have different sizes depending
84
 * on your machine and kernel configuration.
85
 *
86
 * However, that allowed you to write protocol-agnostic programs, by
87
 * using "struct sockaddr" throughout, and relying on libray APIs for
88
 * things like name to address (and vice versa) resolution, and since
89
 * nobody were in the business of shipping random UNIX binaries around
90
 * the lack of binary portability didn't matter.
91
 *
92
 * Along the way the BSD people figured out that it was a bother
93
 * to carry the length argument separately, and added that to the
94
 * format of sockaddr, but other groups found this unclean, as
95
 * the length was already an explicit parameter.
96
 *
97
 * The net result of this is that your "portable" code, must take
98
 * care to handle the "sa_len" member on kernels which have it,
99
 * while still tracking the separate length argument for all other
100
 * kernels.
101
 *
102
 * Needless to say, there were no neat #define to tell you which
103
 * was which, so each programmer found a different heuristic to
104
 * decide, often not understanding it fully, which caused the kind
105
 * of portability issues which lead to the autocrap tools.
106
 *
107
 * Then all the other protocols died, we were left with IP and
108
 * life were good, the dot-com madness multiplied the IT-business
109
 * by a factor 1000, by making any high-school student who had
110
 * programmed PERL for 6 weeks a "senior web-programmer".
111
 *
112
 * Next IPv6 happened, in a rush even, (no seriously, I'm not kidding!),
113
 * and since IPv6 addresses were HUGE, like 16 bytes HUGE, the generic
114
 * struct sockaddr was not increased in size.
115
 *
116
 * At least "not yet", because it would break all the shitty code written
117
 * by the dot-com generation.
118
 *
119
 * Nobody used IPv6 anyway so that didn't matter that much.
120
 *
121
 * Then people actually started using IPv6 and its struct sockaddr_in6,
122
 * and realized that all the code which used "struct sockaddr" to allocate
123
 * space at compile time were broken.
124
 *
125
 * Some people took to using sockaddr_in6, since that was known to
126
 * be big enough for both IPv4 and IPv6, but "purist" found that
127
 * ugly and "prone to future trouble".
128
 *
129
 * So instead they came up with a "clean solution":  The added
130
 * "struct sockaddr_storage" which is defined to be "Large enough
131
 * to accommodate all supported protocol-specific address structures".
132
 *
133
 * Since we cannot possibly know what zany protocols will exist in
134
 * the future, and since some people think that we will add future
135
 * protocols, while retaining ABI compatibility, (totally overlooking
136
 * the fact that no code for name-resolution supports that) it is
137
 * usually defined so it can cope with 128 byte addresses.
138
 *
139
 * Does that ring a bell ?
140
 *
141
 * Only, not quite:  Remember that all APIs require you to track
142
 * the address and the length separately, so you only get the
143
 * size of the specific protocols sockaddr_${whatever} from API
144
 * functions, not a full sockaddr_storage, and besides the
145
 * prototype for the KPI is still "struct sockaddr *", so you
146
 * cannot gain C type-safety back by using sockaddr_storage
147
 * as the "generic network address" type.
148
 *
149
 * So we have come full circle, while causing maximum havoc along
150
 * the way and for the forseeable future.
151
 *
152
 * Do I need to tell you that static code analysis tools have a
153
 * really hard time coping with this, and that they give a lot of
154
 * false negatives which confuse people ?
155
 *
156
 * I have decided to try to contain this crap in this single
157
 * source-file, with only minimum leakage into the rest of Vinyl,
158
 * which will only know of pointers to "struct suckaddr", the naming
159
 * of which is my considered opinion of the historical narrative above.
160
 *
161
 * And you don't need to take my word for this, you can see it all
162
 * in various #include files on your own system.   If you are on
163
 * a Solaris derivative, don't miss the beautiful horror hidden in the
164
 * variant definition of IPv6 addresses between kernel and userland.
165
 *
166
 * Update (2026): Gosh, who could ever have foreseen that IPv4
167
 * mapped into IPv6 would become a mess ?   Now we normalize
168
 * all such VSAs to IPv4 at the VSA level.
169
 */
170
171
struct suckaddr {
172
        unsigned                        magic;
173
#define SUCKADDR_MAGIC                  0x4b1e9335
174
        union {
175
                struct sockaddr         sa;
176
                struct sockaddr_in      sa4;
177
                struct sockaddr_in6     sa6;
178
        } u;
179
};
180
181
const size_t vsa_suckaddr_len = sizeof(struct suckaddr);
182
183
/*
184
 * Bogus IPv4 address 0.0.0.0:0 to be used for VCL *.ip variables when the
185
 * "real" address is not IP (such as UDS addresses).
186
 */
187
static struct suckaddr bogo_ip_vsa;
188
const struct suckaddr *bogo_ip = &bogo_ip_vsa;
189
/* same in IPv6 */
190
static struct suckaddr bogo_ip6_vsa;
191
const struct suckaddr *bogo_ip6 = &bogo_ip6_vsa;
192
193
static const uint8_t map4_0_80[10] = {0,0,0,0,0,0,0,0,0,0};
194
static const uint8_t map4_0_104[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
195
static const uint8_t map4_0_96[12] = {0,0,0,0,0,0,0,0,0,0,0x00,0x00};
196
static const uint8_t map4_ffff_96[12] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
197
198
/*
199
 * Rewrite IPv4-in-IPv6 suckaddr's in place
200
 */
201
202
static void
203 163841
vsa_normalize(struct suckaddr *sua)
204
{
205 163841
        CHECK_OBJ_NOTNULL(sua, SUCKADDR_MAGIC);
206 163841
        if (sua->u.sa.sa_family != PF_INET6)
207 145805
                return;
208 18036
        uint8_t *p6 = (void*)&sua->u.sa6.sin6_addr;
209
210 18036
        if (vmemcmp(p6, map4_0_80, sizeof map4_0_80)) {
211
                // A "normal" IPv6 address.
212 188
                return;
213
        }
214
215 17848
        if (!vmemcmp(p6, map4_0_104, sizeof map4_0_104)) {
216
                // IPv6 loopback
217
                // IPv6 "any"
218
                // IPv4-compat-IPv6, but IPv4 is in 0/8 IPv4
219 17840
                return;
220
        }
221
222 8
        if (!vmemcmp(p6, map4_0_96, sizeof map4_0_96)) {
223
                // RFC3513 2.5.5 - convert
224 8
        } else if (!vmemcmp(p6, map4_ffff_96, sizeof map4_ffff_96)) {
225
                // RFC4291 2.5.5.2 - convert
226 4
        } else {
227 0
                return;
228
        }
229
230 8
        uint8_t *p4 = (void*)&sua->u.sa4.sin_addr;
231 8
        sua->u.sa.sa_family = PF_INET;
232 8
        vmemcpy(p4, p6 + 12, 4);
233
234
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
235 8
        sua->u.sa.sa_len = sizeof(sua->u.sa4);
236
#endif
237 163841
}
238
239
void
240 4268
VSA_Init(void)
241
{
242 4268
        AN(VSA_BuildFAP(&bogo_ip_vsa, PF_INET, NULL, 0, NULL, 0));
243 4268
        AN(VSA_BuildFAP(&bogo_ip6_vsa, PF_INET6, NULL, 0, NULL, 0));
244 4268
}
245
246
/*
247
 * This VRT interface is for the VCC generated ACL code, which needs
248
 * to know the address family and a pointer to the actual address.
249
 */
250
251
int
252 386452
VSA_GetPtr(const struct suckaddr *sua, const unsigned char ** dst)
253
{
254
255 386452
        AN(dst);
256 386452
        if (sua == NULL)
257 0
                return (-1);
258 386452
        CHECK_OBJ(sua, SUCKADDR_MAGIC);
259
260 386452
        switch (sua->u.sa.sa_family) {
261
        case PF_INET:
262 1000
                assert(sua->u.sa.sa_family == sua->u.sa4.sin_family);
263 1000
                *dst = (const unsigned char *)&sua->u.sa4.sin_addr;
264 1000
                return (sua->u.sa4.sin_family);
265
        case PF_INET6:
266 385452
                assert(sua->u.sa.sa_family == sua->u.sa6.sin6_family);
267 385452
                *dst = (const unsigned char *)&sua->u.sa6.sin6_addr;
268 385452
                return (sua->u.sa6.sin6_family);
269
        default:
270 0
                *dst = NULL;
271 0
                return (-1);
272
        }
273 386452
}
274
275
/*
276
 * Return the size of a struct sockaddr in a struck suckaddr
277
 * or 0 if unknown family
278
 */
279
static inline socklen_t
280 663949
sua_len(const struct sockaddr *sa)
281
{
282
283 663949
        switch (sa->sa_family) {
284
        case PF_INET:
285 251133
                return (sizeof(struct sockaddr_in));
286
        case PF_INET6:
287 412812
                return (sizeof(struct sockaddr_in6));
288
        case AF_UNIX:
289 4
                return (sizeof(struct sockaddr_un));
290
        default:
291 0
                return (0);
292
        }
293 663949
}
294
295
/*
296
 * Malloc a suckaddr from a sockaddr of some kind.
297
 */
298
299
const struct suckaddr *
300 48804
VSA_Malloc(const void *s, unsigned  sal)
301
{
302
303 48804
        return (VSA_Build(NULL, s, sal));
304
}
305
306
/*
307
 * 'd' SHALL point to vsa_suckaddr_len aligned bytes of storage
308
 *
309
 * fam: address family
310
 * a / al : address and length
311
 * p / pl : port and length
312
 *
313
 * NULL or 0 length argument are ignored.
314
 * argument of the wrong length are an error (NULL return value, EINVAL)
315
 */
316
const struct suckaddr *
317 8796
VSA_BuildFAP(void *d, sa_family_t fam, const void *a, unsigned al,
318
            const void *p, unsigned pl)
319
{
320
        struct sockaddr_in sin4;
321
        struct sockaddr_in6 sin6;
322
323 8796
        switch (fam) {
324
        case PF_INET:
325 4468
                memset(&sin4, 0, sizeof sin4);
326 4468
                sin4.sin_family = fam;
327 4468
                if (a != NULL && al > 0) {
328 200
                        if (al != sizeof(sin4.sin_addr))
329 0
                                break;
330 200
                        vmemcpy(&sin4.sin_addr, a, al);
331 200
                }
332 4468
                if (p != NULL && pl > 0) {
333 176
                        if (pl != sizeof(sin4.sin_port))
334 0
                                break;
335 176
                        vmemcpy(&sin4.sin_port, p, pl);
336 176
                }
337 4468
                return (VSA_Build(d, &sin4, sizeof sin4));
338
        case PF_INET6:
339 4328
                memset(&sin6, 0, sizeof sin6);
340 4328
                sin6.sin6_family = fam;
341 4328
                if (a != NULL && al > 0) {
342 60
                        if (al != sizeof(sin6.sin6_addr))
343 0
                                break;
344 60
                        vmemcpy(&sin6.sin6_addr, a, al);
345 60
                }
346 4328
                if (p != NULL && pl > 0) {
347 48
                        if (pl != sizeof(sin6.sin6_port))
348 0
                                break;
349 48
                        vmemcpy(&sin6.sin6_port, p, pl);
350 48
                }
351 4328
                return (VSA_Build(d, &sin6, sizeof sin6));
352
        default:
353 0
                errno = EAFNOSUPPORT;
354 0
                return (NULL);
355
        }
356 0
        errno = EINVAL;
357 0
        return (NULL);
358 8796
}
359
360
const struct suckaddr *
361 65895
VSA_Build(void *d, const void *s, unsigned sal)
362
{
363
        struct suckaddr *sua;
364 65895
        const struct sockaddr *sa = s;
365
        unsigned l;     // for flexelint
366
367 65895
        AN(s);
368 65895
        l = sua_len(sa);
369 65895
        if (l == 0 || l != sal)
370 5
                return (NULL);
371
372 65892
        if (d == NULL) {
373 48804
                d = malloc(vsa_suckaddr_len);
374 48804
                AN(d);
375 48804
        }
376
377 65892
        sua = d;
378
379 65892
        INIT_OBJ(sua, SUCKADDR_MAGIC);
380 65892
        switch (l) {
381
        case sizeof sua->u.sa4:
382 52504
                vmemcpy(&sua->u.sa4, s, l);
383 52504
                assert(sua->u.sa.sa_family == PF_INET);
384 52504
                break;
385
        case sizeof sua->u.sa6:
386 13388
                vmemcpy(&sua->u.sa6, s, l);
387 13388
                assert(sua->u.sa.sa_family == PF_INET6);
388 13388
                break;
389
        default:
390 0
                WRONG("VSA protocol vs. size");
391 0
        }
392
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
393 65892
        sua->u.sa.sa_len = (unsigned char)l;
394
#endif
395 65892
        vsa_normalize(sua);
396 65892
        return (sua);
397 65897
}
398
399
const void *
400 167546
VSA_Get_Sockaddr(const struct suckaddr *sua, socklen_t *slp)
401
{
402
        socklen_t sl;
403
404 167546
        CHECK_OBJ_NOTNULL(sua, SUCKADDR_MAGIC);
405 167546
        AN(slp);
406 167546
        sl = sua_len(&sua->u.sa);
407 167546
        if (sl == 0)
408 0
                return (NULL);
409 167546
        *slp = sl;
410 167546
        return (&sua->u.sa);
411 167546
}
412
413
int
414 57391
VSA_Get_Proto(const struct suckaddr *sua)
415
{
416
417 57391
        CHECK_OBJ_NOTNULL(sua, SUCKADDR_MAGIC);
418 57391
        return (sua->u.sa.sa_family);
419
}
420
421
int
422 430508
VSA_Sane(const struct suckaddr *sua)
423
{
424 430508
        return (VALID_OBJ(sua, SUCKADDR_MAGIC) && sua_len(&sua->u.sa) != 0);
425
}
426
427
int
428 851
VSA_Compare(const struct suckaddr *sua1, const struct suckaddr *sua2)
429
{
430
431 851
        CHECK_OBJ_NOTNULL(sua1, SUCKADDR_MAGIC);
432 851
        CHECK_OBJ_NOTNULL(sua2, SUCKADDR_MAGIC);
433 851
        return (vmemcmp(sua1, sua2, vsa_suckaddr_len));
434
}
435
436
int
437 92
VSA_Compare_IP(const struct suckaddr *sua1, const struct suckaddr *sua2)
438
{
439
440 92
        assert(VSA_Sane(sua1));
441 92
        assert(VSA_Sane(sua2));
442
443 92
        if (sua1->u.sa.sa_family != sua2->u.sa.sa_family)
444 0
                return (-1);
445
446 92
        switch (sua1->u.sa.sa_family) {
447
        case PF_INET:
448 92
                return (vmemcmp(&sua1->u.sa4.sin_addr,
449
                    &sua2->u.sa4.sin_addr, sizeof(struct in_addr)));
450
        case PF_INET6:
451 0
                return (vmemcmp(&sua1->u.sa6.sin6_addr,
452
                    &sua2->u.sa6.sin6_addr, sizeof(struct in6_addr)));
453
        default:
454 0
                WRONG("Just plain insane");
455 0
        }
456 0
        NEEDLESS(return (-1));
457 92
}
458
459
const struct suckaddr *
460 13912
VSA_Clone(const struct suckaddr *sua)
461
{
462
        struct suckaddr *sua2;
463
464 13912
        assert(VSA_Sane(sua));
465 13912
        sua2 = calloc(1, vsa_suckaddr_len);
466 13912
        XXXAN(sua2);
467 13912
        vmemcpy(sua2, sua, vsa_suckaddr_len);
468 13912
        return (sua2);
469
}
470
471
unsigned
472 4652
VSA_Port(const struct suckaddr *sua)
473
{
474
475 4652
        CHECK_OBJ_NOTNULL(sua, SUCKADDR_MAGIC);
476 4652
        switch (sua->u.sa.sa_family) {
477
        case PF_INET:
478 4448
                return (ntohs(sua->u.sa4.sin_port));
479
        case PF_INET6:
480 204
                return (ntohs(sua->u.sa6.sin6_port));
481
        default:
482 0
                return (0);
483
        }
484 4652
}
485
486
#define VSA_getname(which)                              \
487
const struct suckaddr *                                 \
488
VSA_get ## which ## name(int fd, void *d, size_t l)     \
489
{                                                       \
490
        struct suckaddr *sua;                           \
491
        socklen_t sl;                                   \
492
        int r;                                          \
493
                                                        \
494
        AN(d);                                          \
495
        if (l != vsa_suckaddr_len) {                    \
496
                errno = EINVAL;                         \
497
                return (NULL);                          \
498
        }                                               \
499
                                                        \
500
        sua = d;                                        \
501
                                                        \
502
        INIT_OBJ(sua, SUCKADDR_MAGIC);                  \
503
        sl = sizeof(sua->u);                            \
504
        r = get ## which ## name(fd, &sua->u.sa, &sl);  \
505
        if (r != 0)                                     \
506
                return (NULL);                          \
507
        vsa_normalize(sua);                             \
508
        return (sua);                                   \
509
}
510
511 65227
VSA_getname(sock)
512 32725
VSA_getname(peer)
513
#undef VSA_getname
514
515
void
516 58551
VSA_free(const struct suckaddr **vsap)
517
{
518
        const struct suckaddr *vsa;
519
520 58551
        TAKE_OBJ_NOTNULL(vsa, vsap, SUCKADDR_MAGIC);
521 58551
        free(TRUST_ME(vsa));
522 58551
}