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