varnish-cache/lib/libvcc/vcc_utils.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
30
#include "config.h"
31
32
#include <math.h>
33
#include <string.h>
34
#include <stdlib.h>
35
#include <sys/socket.h>
36
#include <sys/types.h>
37
#include <sys/stat.h>
38
#include <unistd.h>
39
#include <errno.h>
40
41
#include "vcc_compile.h"
42
43
#include "vre.h"
44
#include "vsa.h"
45
#include "vss.h"
46
#include "vtcp.h"
47
48
/*--------------------------------------------------------------------*/
49
50
void
51 8268
vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
52
{
53
        char buf[BUFSIZ];
54
        vre_t *t;
55
        const char *error;
56
        int erroroffset;
57
        struct inifin *ifp;
58
59 8268
        Expect(tl, CSTR);
60 8268
        if (tl->err)
61 3
                return;
62 8268
        t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
63 8268
        if (t == NULL) {
64 3
                VSB_printf(tl->sb,
65
                    "Regexp compilation error:\n\n%s\n\n", error);
66 3
                vcc_ErrWhere(tl, tl->t);
67 3
                return;
68
        }
69 8265
        VRE_free(&t);
70 8265
        bprintf(buf, "VGC_re_%u", tl->unique++);
71 8265
        if (vgc_name)
72 8265
                VSB_cat(vgc_name, buf);
73
74 8265
        Fh(tl, 0, "static void *%s;\n", buf);
75 8265
        ifp = New_IniFin(tl);
76 8265
        VSB_printf(ifp->ini, "\tVRT_re_init(&%s, ",buf);
77 8265
        EncToken(ifp->ini, tl->t);
78 8265
        VSB_printf(ifp->ini, ");");
79 8265
        VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf);
80 8265
        vcc_NextToken(tl);
81
}
82
83
/*
84
 * The IPv6 crew royally screwed up the entire idea behind
85
 * struct sockaddr, see libvarnish/vsa.c for blow-by-blow account.
86
 *
87
 * There is no sane or even remotely portable way to initialize
88
 * a sockaddr for random protocols at compile time.
89
 *
90
 * In our case it is slightly more tricky than that, because we don't
91
 * even want to #include the struct sockaddr* definitions.
92
 *
93
 * Instead we make sure the sockaddr is sane (for our values of
94
 * sane) and dump it as our own "struct suckaddr" type, in binary,
95
 * using the widest integertype, hoping that this will ensure sufficient
96
 * alignment.
97
 */
98
99
static void
100 3441
vcc_suckaddr(struct vcc *tl, const char *host, const struct suckaddr *vsa,
101
    const char **ip, const char **ip_ascii, const char **p_ascii)
102 3441
{
103
        char a[VTCP_ADDRBUFSIZE];
104
        char p[VTCP_PORTBUFSIZE];
105 3441
        const int sz = sizeof(unsigned long long);
106 3441
        const unsigned n = (vsa_suckaddr_len + sz - 1) / sz;
107 3441
        unsigned long long b[n];
108
        int len;
109
        char *q;
110
111 3441
        VTCP_name(vsa, a, sizeof a, p, sizeof p);
112 3441
        Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, a);
113 3441
        if (ip_ascii != NULL)
114 3366
                *ip_ascii = TlDup(tl, a);
115 3441
        if (p_ascii != NULL && *p_ascii == NULL)
116 3363
                *p_ascii = TlDup(tl, p);
117
118 3441
        Fh(tl, 0, "static const unsigned long long");
119 3441
        Fh(tl, 0, " suckaddr_%u[%d] = {\n", tl->unique, n);
120 3441
        memcpy(b, vsa, vsa_suckaddr_len);
121 17205
        for (len = 0; len < n; len++)
122 13764
                Fh(tl, 0, "%s    0x%0*llxULL",
123
                    len ? ",\n" : "", sz * 2, b[len]);
124 3441
        Fh(tl, 0, "\n};\n");
125
126 3441
        q = TlAlloc(tl, 40);
127 3441
        AN(q);
128 3441
        assert(snprintf(q, 40, "(const void*)suckaddr_%u", tl->unique) < 40);
129 3441
        *ip = q;
130 3441
        tl->unique++;
131 3441
}
132
133
/*--------------------------------------------------------------------
134
 * This routine is a monster, but at least we only have one such monster.
135
 * Look up a IP number, and return IPv4/IPv6 address as VGC produced names
136
 * and optionally ascii strings.
137
 *
138
 * For IP compile time constants we only want one IP#, but it can be
139
 * IPv4 or IPv6.
140
 *
141
 * For backends, we accept up to one IPv4 and one IPv6.
142
 */
143
144
struct rss {
145
        unsigned                magic;
146
#define RSS_MAGIC               0x11e966ab
147
148
        struct suckaddr         *vsa4;
149
        struct suckaddr         *vsa6;
150
        struct vsb              *vsb;
151
        int                     retval;
152
        int                     wrong;
153
};
154
155
static int v_matchproto_(vss_resolved_f)
156 3441
rs_callback(void *priv, const struct suckaddr *vsa)
157
{
158
        struct rss *rss;
159
        int v;
160
        char a[VTCP_ADDRBUFSIZE];
161
        char p[VTCP_PORTBUFSIZE];
162
163 3441
        CAST_OBJ_NOTNULL(rss, priv, RSS_MAGIC);
164 3441
        assert(VSA_Sane(vsa));
165
166 3441
        v = VSA_Get_Proto(vsa);
167 3441
        assert(v != AF_UNIX);
168 3441
        VTCP_name(vsa, a, sizeof a, p, sizeof p);
169 3441
        VSB_printf(rss->vsb, "\t%s:%s\n", a, p);
170 3441
        if (v == AF_INET) {
171 3408
                if (rss->vsa4 == NULL)
172 3408
                        rss->vsa4 = VSA_Clone(vsa);
173 0
                else if (VSA_Compare(vsa, rss->vsa4))
174 0
                        rss->wrong++;
175 3408
                rss->retval++;
176 33
        } else if (v == AF_INET6) {
177 33
                if (rss->vsa6 == NULL)
178 33
                        rss->vsa6 = VSA_Clone(vsa);
179 0
                else if (VSA_Compare(vsa, rss->vsa6))
180 0
                        rss->wrong++;
181 33
                rss->retval++;
182
        }
183 3441
        return (0);
184
}
185
186
void
187 3447
Resolve_Sockaddr(struct vcc *tl,
188
    const char *host,
189
    const char *def_port,
190
    const char **ipv4,
191
    const char **ipv4_ascii,
192
    const char **ipv6,
193
    const char **ipv6_ascii,
194
    const char **p_ascii,
195
    int maxips,
196
    const struct token *t_err,
197
    const char *errid)
198
{
199
        int error;
200
        struct rss *rss;
201
        const char *err;
202
203 3447
        *ipv4 = NULL;
204 3447
        *ipv6 = NULL;
205 3447
        if (p_ascii != NULL)
206 3369
                *p_ascii = NULL;
207
208 3447
        ALLOC_OBJ(rss, RSS_MAGIC);
209 3447
        AN(rss);
210 3447
        rss->vsb = VSB_new_auto();
211 3447
        AN(rss->vsb);
212
213 3447
        error = VSS_resolver(host, def_port, rs_callback, rss, &err);
214 3447
        AZ(VSB_finish(rss->vsb));
215 3447
        if (err != NULL) {
216 24
                VSB_printf(tl->sb,
217
                    "%s '%.*s' could not be resolved to an IP address:\n"
218
                    "\t%s\n"
219
                    "(Sorry if that error message is gibberish.)\n",
220 12
                    errid, PF(t_err), err);
221 12
                vcc_ErrWhere(tl, t_err);
222 12
                free(rss->vsa4);
223 12
                free(rss->vsa6);
224 12
                VSB_destroy(&rss->vsb);
225 12
                FREE_OBJ(rss);
226 12
                return;
227
        }
228 3435
        AZ(error);
229 3435
        if (rss->vsa4 != NULL) {
230 3408
                vcc_suckaddr(tl, host, rss->vsa4, ipv4, ipv4_ascii, p_ascii);
231 3408
                free(rss->vsa4);
232
        }
233 3435
        if (rss->vsa6 != NULL) {
234 33
                vcc_suckaddr(tl, host, rss->vsa6, ipv6, ipv6_ascii, p_ascii);
235 33
                free(rss->vsa6);
236
        }
237 3435
        if (rss->retval == 0) {
238 0
                VSB_printf(tl->sb,
239
                    "%s '%.*s': resolves to "
240
                    "neither IPv4 nor IPv6 addresses.\n",
241 0
                    errid, PF(t_err) );
242 0
                vcc_ErrWhere(tl, t_err);
243
        }
244 3435
        if (rss->wrong || rss->retval > maxips) {
245 6
                VSB_printf(tl->sb,
246
                    "%s %.*s: resolves to too many addresses.\n"
247
                    "Only one IPv4 %s IPv6 are allowed.\n"
248
                    "Please specify which exact address "
249
                    "you want to use, we found all of these:\n%s",
250 3
                    errid, PF(t_err),
251
                    maxips > 1 ? "and one" :  "or",
252 3
                    VSB_data(rss->vsb));
253 3
                vcc_ErrWhere(tl, t_err);
254
        }
255 3435
        VSB_destroy(&rss->vsb);
256 3435
        FREE_OBJ(rss);
257
}
258
259
/*
260
 * For UDS, we do not create a VSA. Check if it's an absolute path, can
261
 * be accessed, and is a socket. If so, just emit the path field and set
262
 * the IP suckaddrs to NULL.
263
 */
264
void
265 90
Emit_UDS_Path(struct vcc *tl, const struct token *t_path, const char *errid)
266
{
267
        struct stat st;
268
269 90
        AN(t_path);
270 90
        AN(t_path->dec);
271
272 90
        if (*t_path->dec != '/') {
273 3
                VSB_printf(tl->sb,
274
                           "%s: Must be an absolute path:\n", errid);
275 3
                vcc_ErrWhere(tl, t_path);
276 3
                return;
277
        }
278 87
        errno = 0;
279 87
        if (stat(t_path->dec, &st) != 0) {
280 3
                VSB_printf(tl->sb, "%s: Cannot stat: %s\n", errid,
281 3
                           strerror(errno));
282 3
                vcc_ErrWhere(tl, t_path);
283 3
                return;
284
        }
285 84
        if (!S_ISSOCK(st.st_mode)) {
286 3
                VSB_printf(tl->sb, "%s: Not a socket:\n", errid);
287 3
                vcc_ErrWhere(tl, t_path);
288 3
                return;
289
        }
290 81
        Fb(tl, 0, "\t.path = \"%s\",\n", t_path->dec);
291 81
        Fb(tl, 0, "\t.ipv4_suckaddr = (void *) 0,\n");
292 81
        Fb(tl, 0, "\t.ipv6_suckaddr = (void *) 0,\n");
293
}
294
295
/*--------------------------------------------------------------------
296
 * Recognize and convert units of time, return seconds.
297
 */
298
299
double
300 11277
vcc_TimeUnit(struct vcc *tl)
301
{
302 11277
        double sc = 1.0;
303
304 11277
        assert(tl->t->tok == ID);
305 11277
        if (vcc_IdIs(tl->t, "ms"))
306 21
                sc = 1e-3;
307 11256
        else if (vcc_IdIs(tl->t, "s"))
308 11142
                sc = 1.0;
309 114
        else if (vcc_IdIs(tl->t, "m"))
310 66
                sc = 60.0;
311 48
        else if (vcc_IdIs(tl->t, "h"))
312 21
                sc = 60.0 * 60.0;
313 27
        else if (vcc_IdIs(tl->t, "d"))
314 12
                sc = 60.0 * 60.0 * 24.0;
315 15
        else if (vcc_IdIs(tl->t, "w"))
316 3
                sc = 60.0 * 60.0 * 24.0 * 7.0;
317 12
        else if (vcc_IdIs(tl->t, "y"))
318 9
                sc = 60.0 * 60.0 * 24.0 * 365.0;
319
        else {
320 3
                VSB_printf(tl->sb, "Unknown time unit ");
321 3
                vcc_ErrToken(tl, tl->t);
322 3
                VSB_printf(tl->sb,
323
                    ".  Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'\n");
324 3
                vcc_ErrWhere(tl, tl->t);
325 3
                return (1.0);
326
        }
327 11274
        vcc_NextToken(tl);
328 11274
        return (sc);
329
}
330
331
/*--------------------------------------------------------------------
332
 * Recognize and convert { CNUM } to unsigned value
333
 * The tokenizer made sure we only get digits.
334
 */
335
336
unsigned
337 222
vcc_UintVal(struct vcc *tl)
338
{
339 222
        unsigned d = 0;
340
        const char *p;
341
342 222
        Expect(tl, CNUM);
343 537
        for (p = tl->t->b; p < tl->t->e; p++) {
344 315
                d *= 10;
345 315
                d += *p - '0';
346
        }
347 222
        vcc_NextToken(tl);
348 222
        return (d);
349
}
350
351
/*--------------------------------------------------------------------
352
 * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value
353
 * The tokenizer made sure we only get digits and a '.'
354
 */
355
356
void
357 24156
vcc_NumVal(struct vcc *tl, double *d, int *frac)
358
{
359 24156
        double e = 0.1;
360
        const char *p;
361
362 24156
        *frac = 0;
363 24156
        *d = 0.0;
364 24156
        Expect(tl, CNUM);
365 24156
        if (tl->err) {
366 0
                *d = NAN;
367 0
                return;
368
        }
369 72345
        for (p = tl->t->b; p < tl->t->e; p++) {
370 48189
                *d *= 10;
371 48189
                *d += *p - '0';
372
        }
373 24156
        vcc_NextToken(tl);
374 24156
        if (tl->t->tok != '.')
375 23853
                return;
376 303
        *frac = 1;
377 303
        vcc_NextToken(tl);
378 303
        if (tl->t->tok != CNUM)
379 3
                return;
380 639
        for (p = tl->t->b; p < tl->t->e; p++) {
381 339
                *d += (*p - '0') * e;
382 339
                e *= 0.1;
383
        }
384 300
        vcc_NextToken(tl);
385
}
386
387
static double
388 171
vcc_DoubleVal(struct vcc *tl)
389
{
390
        double d;
391
        int i;
392
393 171
        vcc_NumVal(tl, &d, &i);
394 171
        return (d);
395
}
396
397
/*--------------------------------------------------------------------*/
398
399
void
400 72
vcc_Duration(struct vcc *tl, double *d)
401
{
402
        double v, sc;
403
404 72
        v = vcc_DoubleVal(tl);
405 72
        ERRCHK(tl);
406 72
        ExpectErr(tl, ID);
407 72
        sc = vcc_TimeUnit(tl);
408 72
        *d = v * sc;
409
}
410
411
/*--------------------------------------------------------------------*/
412
413
void
414 99
vcc_ByteVal(struct vcc *tl, double *d)
415
{
416
        double v, sc;
417
418 99
        v = vcc_DoubleVal(tl);
419 99
        ERRCHK(tl);
420 99
        if (tl->t->tok != ID) {
421 3
                VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got ");
422 3
                vcc_ErrToken(tl, tl->t);
423 3
                VSB_printf(tl->sb, "\n");
424 3
                vcc_ErrWhere(tl, tl->t);
425 3
                return;
426
        }
427 96
        if (vcc_IdIs(tl->t, "B"))
428 66
                sc = 1.;
429 30
        else if (vcc_IdIs(tl->t, "KB"))
430 18
                sc = 1024.;
431 12
        else if (vcc_IdIs(tl->t, "MB"))
432 3
                sc = 1024. * 1024.;
433 9
        else if (vcc_IdIs(tl->t, "GB"))
434 3
                sc = 1024. * 1024. * 1024.;
435 6
        else if (vcc_IdIs(tl->t, "TB"))
436 3
                sc = 1024. * 1024. * 1024. * 1024.;
437
        else {
438 3
                VSB_printf(tl->sb, "Unknown BYTES unit ");
439 3
                vcc_ErrToken(tl, tl->t);
440 3
                VSB_printf(tl->sb,
441
                    ".  Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n");
442 3
                vcc_ErrWhere(tl, tl->t);
443 3
                return;
444
        }
445 93
        vcc_NextToken(tl);
446 93
        *d = v * sc;
447
}
448