varnish-cache/lib/libvcc/vcc_backend.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 */
31
32
#include "config.h"
33
34
#include <stdlib.h>
35
#include <string.h>
36
#include <sys/stat.h>
37
38
#include "vcc_compile.h"
39
#include "vus.h"
40
41
const char *
42 25
vcc_default_probe(struct vcc *tl)
43
{
44
45 25
        if (tl->default_probe != NULL)
46 0
                return (tl->default_probe);
47 25
        VSB_cat(tl->sb, "No default probe defined\n");
48 25
        vcc_ErrToken(tl, tl->t);
49 25
        VSB_cat(tl->sb, " at\n");
50 25
        vcc_ErrWhere(tl, tl->t);
51 25
        return ("");
52 25
}
53
54
/*--------------------------------------------------------------------
55
 * Struct sockaddr is not really designed to be a compile time
56
 * initialized data structure, so we encode it as a byte-string
57
 * and put it in an official sockaddr when we load the VCL.
58
 */
59
60
static void
61 32700
Emit_Sockaddr(struct vcc *tl, struct vsb *vsb1, const struct token *t_host,
62
    const struct token *t_port)
63
{
64
        const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa;
65
        char buf[BUFSIZ];
66
67 32700
        AN(t_host->dec);
68
69 32700
        if (t_port != NULL)
70 24750
                bprintf(buf, "%s %s", t_host->dec, t_port->dec);
71
        else
72 7950
                bprintf(buf, "%s", t_host->dec);
73 65400
        Resolve_Sockaddr(tl, buf, "80",
74 32700
            &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host");
75 32700
        ERRCHK(tl);
76 32650
        if (ipv4 != NULL) {
77 65000
                VSB_printf(vsb1,
78
                    "\t.ipv4 = (const struct suckaddr *)%s,\n",
79 32500
                    ipv4);
80 32500
        }
81 32650
        if (ipv6 != NULL) {
82 650
                VSB_printf(vsb1,
83
                    "\t.ipv6 = (const struct suckaddr *)%s,\n",
84 325
                    ipv6);
85 325
        }
86 32650
        VSB_cat(vsb1, "\t.uds_path = (void *) 0,\n");
87 32700
}
88
89
/*
90
 * For UDS, we do not create a VSA. We run the VUS_resolver() checks and, if
91
 * it's a path, can be accessed, and is a socket. If so, just emit the path
92
 * field and set the IP suckaddrs to NULL.
93
 */
94
95
static int
96 800
uds_resolved(void *priv, const struct sockaddr_un *uds)
97
{
98 800
        (void) priv;
99 800
        (void) uds;
100 800
        return (42);
101
}
102
103
static void
104 775
emit_path(struct vsb *vsb1, char *path)
105
{
106 775
        VSB_printf(vsb1, "\t.uds_path = \"%s\",\n", path);
107 775
        VSB_cat(vsb1, "\t.ipv4 = (void *) 0,\n");
108 775
        VSB_cat(vsb1, "\t.ipv6 = (void *) 0,\n");
109 775
}
110
111
static void
112 850
Emit_UDS_Path(struct vcc *tl, struct vsb *vsb1,
113
    const struct token *t_path, const char *errid)
114
{
115
        struct stat st;
116
        const char *vus_err;
117
118 850
        AN(t_path);
119 850
        AN(t_path->dec);
120
121 850
        if (! VUS_is(t_path->dec)) {
122 50
                VSB_printf(tl->sb,
123
                           "%s: Must be a valid path or abstract socket:\n",
124 25
                           errid);
125 25
                vcc_ErrWhere(tl, t_path);
126 25
                return;
127
        }
128 825
        if (VUS_resolver(t_path->dec, uds_resolved, NULL, &vus_err) != 42) {
129 25
                VSB_printf(tl->sb, "%s: %s\n", errid, vus_err);
130 25
                vcc_ErrWhere(tl, t_path);
131 25
                return;
132
        }
133 800
        if (*t_path->dec == '@') {
134 0
                emit_path(vsb1, t_path->dec);
135 0
                return;
136
        }
137 800
        assert(*t_path->dec == '/');
138 800
        errno = 0;
139 800
        if (stat(t_path->dec, &st) != 0) {
140 25
                int err = errno;
141 50
                VSB_printf(tl->sb, "%s: Cannot stat: %s\n", errid,
142 25
                           strerror(errno));
143 25
                vcc_ErrWhere(tl, t_path);
144 25
                if (err == ENOENT || err == EACCES)
145 25
                        vcc_Warn(tl);
146
                else
147 0
                        return;
148 800
        } else if (!S_ISSOCK(st.st_mode)) {
149 25
                VSB_printf(tl->sb, "%s: Not a socket:\n", errid);
150 25
                vcc_ErrWhere(tl, t_path);
151 25
                return;
152
        }
153 775
        emit_path(vsb1, t_path->dec);
154 850
}
155
156
/*--------------------------------------------------------------------
157
 * Disallow mutually exclusive field definitions
158
 */
159
160
static void
161 34375
vcc_Redef(struct vcc *tl, const char *redef, const struct token **t_did,
162
    const struct token *t_field)
163
{
164 34375
        if (*t_did != NULL) {
165 75
                VSB_printf(tl->sb, "%s redefinition at:\n", redef);
166 75
                vcc_ErrWhere(tl, t_field);
167 75
                VSB_cat(tl->sb, "Previous definition:\n");
168 75
                vcc_ErrWhere(tl, *t_did);
169 75
                return;
170
        }
171 34300
        *t_did = t_field;
172 34375
}
173
174
/*--------------------------------------------------------------------
175
 * Parse a backend probe specification
176
 */
177
178
static void
179 1125
vcc_ParseProbeSpec(struct vcc *tl, const struct symbol *sym, char **namep)
180
{
181
        struct fld_spec *fs;
182
        const struct token *t_field;
183 1125
        const struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL;
184 1125
        struct token *t_initial = NULL;
185
        unsigned window, threshold, initial, status, exp_close;
186
        char buf[32];
187
        const char *name;
188
        double t;
189
190 1125
        fs = vcc_FldSpec(tl,
191
            "?url",
192
            "?request",
193
            "?expected_response",
194
            "?timeout",
195
            "?interval",
196
            "?window",
197
            "?threshold",
198
            "?initial",
199
            "?expect_close",
200
            NULL);
201
202 1125
        SkipToken(tl, '{');
203
204 1125
        if (sym != NULL) {
205 275
                name = sym->rname;
206 275
        } else {
207 850
                bprintf(buf, "vgc_probe__%d", tl->nprobe++);
208 850
                name = buf;
209
        }
210 1125
        Fh(tl, 0, "static const struct vrt_backend_probe %s[] = {{\n", name);
211 1125
        Fh(tl, 0, "\t.magic = VRT_BACKEND_PROBE_MAGIC,\n");
212 1125
        if (namep != NULL)
213 850
                *namep = TlDup(tl, name);
214
215 1125
        window = 0;
216 1125
        threshold = 0;
217 1125
        initial = 0;
218 1125
        status = 0;
219 1125
        exp_close = 1;
220 3625
        while (tl->t->tok != '}') {
221
222 2650
                vcc_IsField(tl, &t_field, fs);
223 2650
                ERRCHK(tl);
224 2650
                if (vcc_IdIs(t_field, "url")) {
225 275
                        vcc_Redef(tl, "Probe request", &t_did, t_field);
226 275
                        ERRCHK(tl);
227 250
                        ExpectErr(tl, CSTR);
228 250
                        Fh(tl, 0, "\t.url = ");
229 250
                        EncToken(tl->fh, tl->t);
230 250
                        Fh(tl, 0, ",\n");
231 250
                        vcc_NextToken(tl);
232 2625
                } else if (vcc_IdIs(t_field, "request")) {
233 125
                        vcc_Redef(tl, "Probe request", &t_did, t_field);
234 125
                        ERRCHK(tl);
235 100
                        ExpectErr(tl, CSTR);
236 100
                        Fh(tl, 0, "\t.request =\n");
237 400
                        while (tl->t->tok == CSTR) {
238 300
                                Fh(tl, 0, "\t\t");
239 300
                                EncToken(tl->fh, tl->t);
240 300
                                Fh(tl, 0, " \"\\r\\n\"\n");
241 300
                                vcc_NextToken(tl);
242
                        }
243 100
                        Fh(tl, 0, "\t\t\"\\r\\n\",\n");
244 2350
                } else if (vcc_IdIs(t_field, "timeout")) {
245 225
                        Fh(tl, 0, "\t.timeout = ");
246 225
                        vcc_Duration(tl, &t);
247 225
                        ERRCHK(tl);
248 200
                        Fh(tl, 0, "%g,\n", t);
249 2225
                } else if (vcc_IdIs(t_field, "interval")) {
250 600
                        Fh(tl, 0, "\t.interval = ");
251 600
                        vcc_Duration(tl, &t);
252 600
                        ERRCHK(tl);
253 600
                        Fh(tl, 0, "%g,\n", t);
254 2025
                } else if (vcc_IdIs(t_field, "window")) {
255 450
                        t_window = tl->t;
256 450
                        window = vcc_UintVal(tl);
257 450
                        ERRCHK(tl);
258 1425
                } else if (vcc_IdIs(t_field, "initial")) {
259 325
                        t_initial = tl->t;
260 325
                        initial = vcc_UintVal(tl);
261 325
                        ERRCHK(tl);
262 975
                } else if (vcc_IdIs(t_field, "expected_response")) {
263 50
                        status = vcc_UintVal(tl);
264 50
                        if (status < 100 || status > 999) {
265 25
                                VSB_cat(tl->sb,
266
                                    "Must specify .expected_response with "
267
                                    "exactly three digits "
268
                                    "(100 <= x <= 999)\n");
269 25
                                vcc_ErrWhere(tl, tl->t);
270 25
                                return;
271
                        }
272 25
                        ERRCHK(tl);
273 625
                } else if (vcc_IdIs(t_field, "threshold")) {
274 500
                        t_threshold = tl->t;
275 500
                        threshold = vcc_UintVal(tl);
276 500
                        ERRCHK(tl);
277 600
                } else if (vcc_IdIs(t_field, "expect_close")) {
278 100
                        exp_close = vcc_BoolVal(tl);
279 100
                        ERRCHK(tl);
280 50
                } else {
281 0
                        vcc_ErrToken(tl, t_field);
282 0
                        vcc_ErrWhere(tl, t_field);
283 0
                        ErrInternal(tl);
284 0
                        return;
285
                }
286
287 2500
                SkipToken(tl, ';');
288
        }
289 975
        free(fs);
290
291 975
        if (t_threshold != NULL || t_window != NULL) {
292 525
                if (t_threshold == NULL && t_window != NULL) {
293 25
                        VSB_cat(tl->sb,
294
                            "Must specify .threshold with .window\n");
295 25
                        vcc_ErrWhere(tl, t_window);
296 25
                        return;
297 500
                } else if (t_threshold != NULL && t_window == NULL) {
298 75
                        if (threshold > 64) {
299 25
                                VSB_cat(tl->sb,
300
                                    "Threshold must be 64 or less.\n");
301 25
                                vcc_ErrWhere(tl, t_threshold);
302 25
                                return;
303
                        }
304 50
                        window = threshold + 1;
305 475
                } else if (window > 64) {
306 25
                        AN(t_window);
307 25
                        VSB_cat(tl->sb, "Window must be 64 or less.\n");
308 25
                        vcc_ErrWhere(tl, t_window);
309 25
                        return;
310
                }
311 450
                if (threshold > window ) {
312 25
                        VSB_cat(tl->sb,
313
                            "Threshold can not be greater than window.\n");
314 25
                        AN(t_threshold);
315 25
                        vcc_ErrWhere(tl, t_threshold);
316 25
                        AN(t_window);
317 25
                        vcc_ErrWhere(tl, t_window);
318 25
                }
319 450
                Fh(tl, 0, "\t.window = %u,\n", window);
320 450
                Fh(tl, 0, "\t.threshold = %u,\n", threshold);
321 450
        }
322 900
        if (t_initial != NULL)
323 325
                Fh(tl, 0, "\t.initial = %u,\n", initial);
324
        else
325 575
                Fh(tl, 0, "\t.initial = ~0U,\n");
326 900
        if (status > 0)
327 25
                Fh(tl, 0, "\t.exp_status = %u,\n", status);
328 900
        Fh(tl, 0, "\t.exp_close = %u,\n", exp_close);
329 900
        Fh(tl, 0, "}};\n");
330 900
        SkipToken(tl, '}');
331 1125
}
332
333
/*--------------------------------------------------------------------
334
 * Parse and emit a probe definition
335
 */
336
337
void
338 500
vcc_ParseProbe(struct vcc *tl)
339
{
340
        struct symbol *sym;
341
        char *p;
342
343 500
        vcc_NextToken(tl);                      /* ID: probe */
344
345 500
        vcc_ExpectVid(tl, "backend probe");     /* ID: name */
346 500
        ERRCHK(tl);
347 500
        if (vcc_IdIs(tl->t, "default")) {
348 200
                vcc_NextToken(tl);
349 200
                vcc_ParseProbeSpec(tl, NULL, &p);
350 200
                tl->default_probe = p;
351 200
        } else {
352 300
                sym = VCC_HandleSymbol(tl, PROBE);
353 300
                ERRCHK(tl);
354 275
                AN(sym);
355 275
                vcc_ParseProbeSpec(tl, sym, NULL);
356
        }
357 500
}
358
359
/*--------------------------------------------------------------------
360
 * Parse and emit a backend host definition
361
 *
362
 * The struct vrt_backend is emitted to Fh().
363
 */
364
365
static void
366 39625
vcc_ParseHostDef(struct vcc *tl, struct symbol *sym,
367
    const struct token *t_be, const char *vgcname)
368
{
369
        const struct token *t_field;
370
        const struct token *t_val;
371 39625
        const struct token *t_host = NULL;
372 39625
        const struct token *t_port = NULL;
373 39625
        const struct token *t_path = NULL;
374 39625
        const struct token *t_hosthdr = NULL;
375 39625
        const struct token *t_authority = NULL;
376 39625
        const struct token *t_did = NULL;
377 39625
        const struct token *t_preamble = NULL;
378
        struct symbol *pb;
379
        struct fld_spec *fs;
380
        struct inifin *ifp;
381
        struct vsb *vsb1;
382 39625
        struct symbol *via = NULL;
383
        char *p;
384
        unsigned u;
385
        double t;
386
387 42225
        if (tl->t->tok == ID &&
388 5550
            (vcc_IdIs(tl->t, "none") || vcc_IdIs(tl->t, "None"))) {
389 5550
                vcc_NextToken(tl);
390 5550
                SkipToken(tl, ';');
391 5550
                ifp = New_IniFin(tl);
392 5550
                VSB_printf(ifp->ini, "\t(void)%s;", vgcname);
393 5550
                VSB_printf(ifp->fin, "\t\t(void)%s;", vgcname);
394 5550
                return;
395
        }
396
397 34075
        SkipToken(tl, '{');
398
399
        /* Check for old syntax */
400 34075
        if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) {
401 25
                VSB_cat(tl->sb,
402
                    "NB: Backend Syntax has changed:\n"
403
                    "Remove \"set\" and \"backend\" in front"
404
                    " of backend fields.\n" );
405 25
                vcc_ErrToken(tl, tl->t);
406 25
                VSB_cat(tl->sb, " at ");
407 25
                vcc_ErrWhere(tl, tl->t);
408 25
                return;
409
        }
410
411 34050
        fs = vcc_FldSpec(tl,
412
            "?host",
413
            "?port",
414
            "?path",
415
            "?host_header",
416
            "?connect_timeout",
417
            "?first_byte_timeout",
418
            "?between_bytes_timeout",
419
            "?probe",
420
            "?max_connections",
421
            "?proxy_header",
422
            "?preamble",
423
            "?via",
424
            "?authority",
425
            NULL);
426
427 34050
        tl->fb = VSB_new_auto();
428 34050
        AN(tl->fb);
429
430 68100
        Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n",
431 34050
            vgcname);
432
433 34050
        Fb(tl, 0, "\t.magic = VRT_BACKEND_MAGIC,\n");
434 34050
        Fb(tl, 0, "\t.endpoint = &vgc_dir_ep_%s,\n", vgcname);
435 34050
        Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be));
436 34050
        Fb(tl, 0, "\",\n");
437
438 94200
        while (tl->t->tok != '}') {
439
440 60600
                vcc_IsField(tl, &t_field, fs);
441 60600
                ERRCHK(tl);
442 60550
                if (vcc_IdIs(t_field, "host")) {
443 33075
                        vcc_Redef(tl, "Address", &t_did, t_field);
444 33075
                        ERRCHK(tl);
445 33075
                        ExpectErr(tl, CSTR);
446 33075
                        assert(tl->t->dec != NULL);
447 33075
                        t_host = tl->t;
448 33075
                        vcc_NextToken(tl);
449 33075
                        SkipToken(tl, ';');
450 60550
                } else if (vcc_IdIs(t_field, "port")) {
451 24800
                        ExpectErr(tl, CSTR);
452 24800
                        assert(tl->t->dec != NULL);
453 24800
                        t_port = tl->t;
454 24800
                        vcc_NextToken(tl);
455 24800
                        SkipToken(tl, ';');
456 27475
                } else if (vcc_IdIs(t_field, "path")) {
457 925
                        if (tl->syntax < VCL_41) {
458 25
                                VSB_cat(tl->sb,
459
                                    "Unix socket backends only supported"
460
                                    " in VCL4.1 and higher.\n");
461 25
                                vcc_ErrToken(tl, tl->t);
462 25
                                VSB_cat(tl->sb, " at ");
463 25
                                vcc_ErrWhere(tl, tl->t);
464 25
                                VSB_destroy(&tl->fb);
465 25
                                return;
466
                        }
467 900
                        vcc_Redef(tl, "Address", &t_did, t_field);
468 900
                        ERRCHK(tl);
469 875
                        ExpectErr(tl, CSTR);
470 875
                        assert(tl->t->dec != NULL);
471 875
                        t_path = tl->t;
472 875
                        vcc_NextToken(tl);
473 875
                        SkipToken(tl, ';');
474 2625
                } else if (vcc_IdIs(t_field, "host_header")) {
475 100
                        ExpectErr(tl, CSTR);
476 100
                        assert(tl->t->dec != NULL);
477 100
                        t_hosthdr = tl->t;
478 100
                        vcc_NextToken(tl);
479 100
                        SkipToken(tl, ';');
480 1750
                } else if (vcc_IdIs(t_field, "connect_timeout")) {
481 0
                        Fb(tl, 0, "\t.connect_timeout = ");
482 0
                        vcc_Duration(tl, &t);
483 0
                        ERRCHK(tl);
484 0
                        Fb(tl, 0, "%g,\n", t);
485 0
                        SkipToken(tl, ';');
486 1650
                } else if (vcc_IdIs(t_field, "first_byte_timeout")) {
487 75
                        Fb(tl, 0, "\t.first_byte_timeout = ");
488 75
                        vcc_Duration(tl, &t);
489 75
                        ERRCHK(tl);
490 75
                        Fb(tl, 0, "%g,\n", t);
491 75
                        SkipToken(tl, ';');
492 1650
                } else if (vcc_IdIs(t_field, "between_bytes_timeout")) {
493 25
                        Fb(tl, 0, "\t.between_bytes_timeout = ");
494 25
                        vcc_Duration(tl, &t);
495 25
                        ERRCHK(tl);
496 25
                        Fb(tl, 0, "%g,\n", t);
497 25
                        SkipToken(tl, ';');
498 1575
                } else if (vcc_IdIs(t_field, "max_connections")) {
499 125
                        u = vcc_UintVal(tl);
500 125
                        ERRCHK(tl);
501 125
                        SkipToken(tl, ';');
502 125
                        Fb(tl, 0, "\t.max_connections = %u,\n", u);
503 1550
                } else if (vcc_IdIs(t_field, "proxy_header")) {
504 150
                        t_val = tl->t;
505 150
                        u = vcc_UintVal(tl);
506 150
                        ERRCHK(tl);
507 150
                        if (u != 1 && u != 2) {
508 0
                                VSB_cat(tl->sb,
509
                                    ".proxy_header must be 1 or 2\n");
510 0
                                vcc_ErrWhere(tl, t_val);
511 0
                                VSB_destroy(&tl->fb);
512 0
                                return;
513
                        }
514 150
                        SkipToken(tl, ';');
515 150
                        Fb(tl, 0, "\t.proxy_header = %u,\n", u);
516 1425
                } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') {
517 650
                        vcc_ParseProbeSpec(tl, NULL, &p);
518 650
                        Fb(tl, 0, "\t.probe = %s,\n", p);
519 650
                        free(p);
520 650
                        ERRCHK(tl);
521 1025
                } else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) {
522 275
                        if (vcc_IdIs(tl->t, "default")) {
523 25
                                vcc_NextToken(tl);
524 25
                                (void)vcc_default_probe(tl);
525 25
                        } else {
526 250
                                pb = VCC_SymbolGet(tl, SYM_MAIN, SYM_PROBE,
527
                                    SYMTAB_EXISTING, XREF_REF);
528 250
                                ERRCHK(tl);
529 225
                                AN(pb);
530 225
                                Fb(tl, 0, "\t.probe = %s,\n", pb->rname);
531
                        }
532 250
                        SkipToken(tl, ';');
533 575
                } else if (vcc_IdIs(t_field, "probe")) {
534 25
                        VSB_cat(tl->sb, "Expected '{' or name of probe, got ");
535 25
                        vcc_ErrToken(tl, tl->t);
536 25
                        VSB_cat(tl->sb, " at\n");
537 25
                        vcc_ErrWhere(tl, tl->t);
538 25
                        VSB_destroy(&tl->fb);
539 25
                        return;
540 325
                } else if (vcc_IdIs(t_field, "preamble")) {
541 25
                        ExpectErr(tl, CBLOB);
542 25
                        t_preamble = tl->t;
543 25
                        vcc_NextToken(tl);
544 25
                        SkipToken(tl, ';');
545 325
                } else if (vcc_IdIs(t_field, "via")) {
546 225
                        via = VCC_SymbolGet(tl, SYM_MAIN, SYM_BACKEND,
547
                            SYMTAB_EXISTING, XREF_REF);
548 225
                        ERRCHK(tl);
549 225
                        AN(via);
550 225
                        AN(via->rname);
551
552 225
                        if (via->extra != NULL) {
553 25
                                AZ(strcmp(via->extra, "via"));
554 25
                                VSB_cat(tl->sb,
555
                                        "Can not stack .via backends at\n");
556 25
                                vcc_ErrWhere(tl, tl->t);
557 25
                                VSB_destroy(&tl->fb);
558 25
                                return;
559
                        }
560
561 200
                        AN(sym);
562 200
                        AZ(sym->extra);
563 200
                        sym->extra = "via";
564 200
                        SkipToken(tl, ';');
565 275
                } else if (vcc_IdIs(t_field, "authority")) {
566 75
                        ExpectErr(tl, CSTR);
567 75
                        assert(tl->t->dec != NULL);
568 75
                        t_authority = tl->t;
569 75
                        vcc_NextToken(tl);
570 75
                        SkipToken(tl, ';');
571 75
                } else {
572 0
                        ErrInternal(tl);
573 0
                        VSB_destroy(&tl->fb);
574 0
                        return;
575
                }
576
577
        }
578
579 33600
        vcc_FieldsOk(tl, fs);
580 33600
        free(fs);
581 33600
        ERRCHK(tl);
582
583 33600
        ExpectErr(tl, '}');
584
585 33600
        if (t_host == NULL && t_path == NULL) {
586 25
                VSB_cat(tl->sb, "Expected .host or .path.\n");
587 25
                vcc_ErrWhere(tl, t_be);
588 25
                VSB_destroy(&tl->fb);
589 25
                return;
590
        }
591
592 33575
        if (via != NULL && t_path != NULL) {
593 25
                VSB_cat(tl->sb, "Cannot set both .via and .path.\n");
594 25
                vcc_ErrWhere(tl, t_be);
595 25
                return;
596
        }
597
598 33550
        if (via != NULL)
599 175
                AZ(via->extra);
600
601 33550
        vsb1 = VSB_new_auto();
602 33550
        AN(vsb1);
603 67100
        VSB_printf(vsb1,
604
            "\nstatic const struct vrt_endpoint vgc_dir_ep_%s = {\n",
605 33550
            vgcname);
606 33550
        VSB_cat(vsb1, "\t.magic = VRT_ENDPOINT_MAGIC,\n");
607
608 33550
        assert(t_host != NULL || t_path != NULL);
609 33550
        if (t_host != NULL)
610
                /* Check that the hostname makes sense */
611 32700
                Emit_Sockaddr(tl, vsb1, t_host, t_port);
612
        else
613
                /* Check that the path can be a legal UDS */
614 850
                Emit_UDS_Path(tl, vsb1, t_path, "Backend path");
615 33550
        ERRCHK(tl);
616
617 33425
        if (t_preamble != NULL)
618 25
                VSB_printf(vsb1, "\t.preamble = %s,\n", t_preamble->dec);
619
620 33425
        VSB_cat(vsb1, "};\n");
621 33425
        AZ(VSB_finish(vsb1));
622 33425
        Fh(tl, 0, "%s", VSB_data(vsb1));
623 33425
        VSB_destroy(&vsb1);
624
625
        /* Emit the hosthdr field, fall back to .host if not specified */
626
        /* If .path is specified, set "0.0.0.0". */
627 33425
        Fb(tl, 0, "\t.hosthdr = ");
628 33425
        if (t_hosthdr != NULL)
629 100
                EncToken(tl->fb, t_hosthdr);
630 33325
        else if (t_host != NULL)
631 32600
                EncToken(tl->fb, t_host);
632
        else
633 725
                Fb(tl, 0, "\"0.0.0.0\"");
634 33425
        Fb(tl, 0, ",\n");
635
636
        /*
637
         * Emit the authority field, falling back to hosthdr, then host.
638
         *
639
         * When authority is "", sending the TLV is disabled.
640
         *
641
         * Falling back to host may result in an IP address in authority,
642
         * which is an illegal SNI HostName (RFC 4366 ch. 3.1). But we
643
         * document the potential error, rather than try to find out
644
         * whether or not Emit_Sockaddr() had to look up a name.
645
         */
646 33425
        if (via != NULL) {
647 175
                AN(t_host);
648 175
                Fb(tl, 0, "\t.authority = ");
649 175
                if (t_authority != NULL)
650 75
                        EncToken(tl->fb, t_authority);
651 100
                else if (t_hosthdr != NULL)
652 25
                        EncToken(tl->fb, t_hosthdr);
653
                else
654 75
                        EncToken(tl->fb, t_host);
655 175
                Fb(tl, 0, ",\n");
656 175
        }
657
658
        /* Close the struct */
659 33425
        Fb(tl, 0, "};\n");
660
661 33425
        vcc_NextToken(tl);
662
663 33425
        AZ(VSB_finish(tl->fb));
664 33425
        Fh(tl, 0, "%s", VSB_data(tl->fb));
665 33425
        VSB_destroy(&tl->fb);
666
667 33425
        ifp = New_IniFin(tl);
668 66850
        VSB_printf(ifp->ini,
669
            "\t%s =\n\t    VRT_new_backend_clustered(ctx, vsc_cluster,\n"
670
            "\t\t&vgc_dir_priv_%s, %s);\n",
671 33425
            vgcname, vgcname, via ? via->rname : "NULL");
672 66850
        VSB_printf(ifp->ini,
673 33425
            "\tif (%s)\n\t\tVRT_StaticDirector(%s);", vgcname, vgcname);
674 33425
        VSB_printf(ifp->fin, "\t\tVRT_delete_backend(ctx, &%s);", vgcname);
675 39625
}
676
677
/*--------------------------------------------------------------------
678
 * Parse directors and backends
679
 */
680
681
void
682 39750
vcc_ParseBackend(struct vcc *tl)
683
{
684
        struct token *t_first, *t_be;
685 39750
        struct symbol *sym = NULL;
686
        const char *dn;
687
688 39750
        tl->ndirector++;
689 39750
        t_first = tl->t;
690 39750
        SkipToken(tl, ID);              /* ID: backend */
691
692 39750
        vcc_ExpectVid(tl, "backend");   /* ID: name */
693 39750
        ERRCHK(tl);
694
695 39725
        t_be = tl->t;
696 39725
        if (vcc_IdIs(tl->t, "default")) {
697 1625
                if (tl->first_director != NULL) {
698 75
                        tl->first_director->noref = 0;
699 75
                        tl->first_director = NULL;
700 75
                        tl->default_director = NULL;
701 75
                }
702 1625
                if (tl->default_director != NULL) {
703 25
                        VSB_cat(tl->sb,
704
                            "Only one default director possible.\n");
705 25
                        vcc_ErrWhere(tl, t_first);
706 25
                        return;
707
                }
708 1600
                vcc_NextToken(tl);
709 1600
                dn = "vgc_backend_default";
710 1600
                tl->default_director = dn;
711 1600
        } else {
712 38100
                sym = VCC_HandleSymbol(tl, BACKEND);
713 38100
                ERRCHK(tl);
714 38025
                AN(sym);
715 38025
                dn = sym->rname;
716 38025
                if (tl->default_director == NULL) {
717 31475
                        tl->first_director = sym;
718 31475
                        tl->default_director = dn;
719 31475
                        sym->noref = 1;
720 31475
                }
721
        }
722 39625
        Fh(tl, 0, "\nstatic VCL_BACKEND %s;\n", dn);
723 39625
        vcc_ParseHostDef(tl, sym, t_be, dn);
724 39625
        if (tl->err) {
725 1300
                VSB_printf(tl->sb,
726 650
                    "\nIn %.*s specification starting at:\n", PF(t_first));
727 650
                vcc_ErrWhere(tl, t_first);
728 650
                return;
729
        }
730 39750
}
731
732
void
733 72975
vcc_Backend_Init(struct vcc *tl)
734
{
735
        struct inifin *ifp;
736
737 72975
        Fh(tl, 0, "\nstatic struct vsmw_cluster *vsc_cluster;\n");
738 72975
        ifp = New_IniFin(tl);
739 72975
        VSB_cat(ifp->ini, "\tvsc_cluster = VRT_VSM_Cluster_New(ctx,\n"
740
            "\t    ndirector * VRT_backend_vsm_need(ctx));\n");
741 72975
        VSB_cat(ifp->ini, "\tif (vsc_cluster == 0)\n\t\treturn(1);");
742 72975
        VSB_cat(ifp->fin, "\t\tVRT_VSM_Cluster_Destroy(ctx, &vsc_cluster);");
743 72975
}