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 * 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 * Runtime support for compiled VCL programs
32 */
33
34 #include "config.h"
35
36 #include <stdlib.h>
37
38 #include "cache_varnishd.h"
39
40 #include "cache_objhead.h"
41 #include "vav.h"
42 #include "vcl.h"
43 #include "vct.h"
44 #include "venc.h"
45 #include "vend.h"
46 #include "vrt_obj.h"
47 #include "vsa.h"
48 #include "vsha256.h"
49 #include "vtcp.h"
50 #include "vtim.h"
51 #include "vcc_interface.h"
52
53 #include "common/heritage.h"
54 #include "common/vsmw.h"
55 #include "proxy/cache_proxy.h"
56
57 const void * const vrt_magic_string_end = &vrt_magic_string_end;
58 const void * const vrt_magic_string_unset = &vrt_magic_string_unset;
59
60 /*--------------------------------------------------------------------*/
61
62 VCL_VOID
VRT_synth(VRT_CTX,VCL_INT code,VCL_STRING reason)63 VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
64 {
65 const char *ret;
66
67 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
68 assert(ctx->req != NULL || ctx->bo != NULL);
69
70 ret = ctx->req == NULL ? "error" : "synth";
71 if (code < 0) {
72 VRT_fail(ctx, "return(%s()) status code (%jd) is negative",
73 ret, (intmax_t)code);
74 return;
75 }
76 if (code > 65535) {
77 VRT_fail(ctx, "return(%s()) status code (%jd) > 65535",
78 ret, (intmax_t)code);
79 return;
80 }
81 if ((code % 1000) < 100) {
82 VRT_fail(ctx,
83 "illegal return(%s()) status code (%jd) (..0##)",
84 ret, (intmax_t)code);
85 return;
86 }
87
88 if (reason && !WS_Inside(ctx->ws, reason, NULL)) {
89 reason = WS_Copy(ctx->ws, reason, -1);
90 if (!reason) {
91 VRT_fail(ctx, "Workspace overflow");
92 return;
93 }
94 }
95
96 if (ctx->req == NULL) {
97 CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
98 ctx->bo->err_code = (uint16_t)code;
99 ctx->bo->err_reason = reason ? reason
100 : http_Status2Reason(ctx->bo->err_code % 1000, NULL);
101 return;
102 }
103
104 ctx->req->err_code = (uint16_t)code;
105 ctx->req->err_reason = reason ? reason
106 : http_Status2Reason(ctx->req->err_code % 1000, NULL);
107 }
108
109 /*--------------------------------------------------------------------*/
110
111 void
VPI_acl_log(VRT_CTX,const char * msg)112 VPI_acl_log(VRT_CTX, const char *msg)
113 {
114
115 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
116 AN(msg);
117 if (ctx->vsl != NULL)
118 VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
119 else
120 VSL(SLT_VCL_acl, 0, "%s", msg);
121 }
122
123 int
VRT_acl_match(VRT_CTX,VCL_ACL acl,VCL_IP ip)124 VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip)
125 {
126
127 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
128 CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC);
129 if (ip == NULL) {
130 VRT_fail(ctx, "Cannot match a null IP address");
131 return (0);
132 }
133 assert(VSA_Sane(ip));
134 return (acl->match(ctx, ip));
135 }
136
137 /*--------------------------------------------------------------------*/
138
139 VCL_VOID
VRT_hit_for_pass(VRT_CTX,VCL_DURATION d)140 VRT_hit_for_pass(VRT_CTX, VCL_DURATION d)
141 {
142 struct objcore *oc;
143
144 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
145 if (ctx->bo == NULL) {
146 VSLb(ctx->vsl, SLT_Error,
147 "Note: Ignoring DURATION argument to return(pass);");
148 return;
149 }
150 CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
151 oc = ctx->bo->fetch_objcore;
152 oc->ttl = d;
153 oc->grace = 0.0;
154 oc->keep = 0.0;
155 VSLb(ctx->vsl, SLT_TTL, "HFP %.0f %.0f %.0f %.0f uncacheable",
156 oc->ttl, oc->grace, oc->keep, oc->t_origin);
157 }
158
159 /*--------------------------------------------------------------------*/
160
161 VCL_HTTP
VRT_selecthttp(VRT_CTX,enum gethdr_e where)162 VRT_selecthttp(VRT_CTX, enum gethdr_e where)
163 {
164 VCL_HTTP hp;
165
166 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
167 switch (where) {
168 case HDR_REQ:
169 hp = ctx->http_req;
170 break;
171 case HDR_REQ_TOP:
172 hp = ctx->http_req_top;
173 break;
174 case HDR_BEREQ:
175 hp = ctx->http_bereq;
176 break;
177 case HDR_BERESP:
178 hp = ctx->http_beresp;
179 break;
180 case HDR_RESP:
181 hp = ctx->http_resp;
182 break;
183 default:
184 WRONG("VRT_selecthttp 'where' invalid");
185 }
186 return (hp);
187 }
188
189 /*--------------------------------------------------------------------*/
190
191 VCL_STRING
VRT_GetHdr(VRT_CTX,VCL_HEADER hs)192 VRT_GetHdr(VRT_CTX, VCL_HEADER hs)
193 {
194 VCL_HTTP hp;
195 const char *p;
196
197 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
198 if (hs->where == HDR_OBJ) {
199 CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
200 CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
201 return (HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
202 hs->what));
203 }
204 hp = VRT_selecthttp(ctx, hs->where);
205 CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
206 if (!http_GetHdr(hp, hs->what, &p))
207 return (NULL);
208 return (p);
209 }
210
211 /*--------------------------------------------------------------------
212 * Alloc Strands with space for n elements on workspace
213 *
214 * Error handling is deliberately left to the caller
215 */
216
217 struct strands *
VRT_AllocStrandsWS(struct ws * ws,int n)218 VRT_AllocStrandsWS(struct ws *ws, int n)
219 {
220 struct strands *s;
221 const char **p;
222
223 s = WS_Alloc(ws, sizeof *s);
224 p = WS_Alloc(ws, n * sizeof *p);
225
226 if (s == NULL || p == NULL)
227 return (NULL);
228
229 s->n = n;
230 s->p = p;
231
232 return (s);
233 }
234
235 /*--------------------------------------------------------------------
236 * Compare two STRANDS
237 */
238
239 int
VRT_CompareStrands(VCL_STRANDS a,VCL_STRANDS b)240 VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
241 {
242 const char *pa = NULL, *pb = NULL;
243 int na = 0, nb = 0;
244
245 while (1) {
246 if (pa != NULL && *pa == '\0')
247 pa = NULL;
248 if (pb != NULL && *pb == '\0')
249 pb = NULL;
250 if (pa == NULL && na < a->n)
251 pa = a->p[na++];
252 else if (pb == NULL && nb < b->n)
253 pb = b->p[nb++];
254 else if (pa == NULL && pb == NULL)
255 return (0);
256 else if (pa == NULL)
257 return (-1);
258 else if (pb == NULL)
259 return (1);
260 else if (*pa == '\0')
261 pa = NULL;
262 else if (*pb == '\0')
263 pb = NULL;
264 else if (*pa != *pb)
265 return (*pa - *pb);
266 else {
267 pa++;
268 pb++;
269 }
270 }
271 }
272
273 /*--------------------------------------------------------------------
274 * STRANDS to BOOL
275 */
276
277 VCL_BOOL
VRT_Strands2Bool(VCL_STRANDS s)278 VRT_Strands2Bool(VCL_STRANDS s)
279 {
280 int i;
281
282 AN(s);
283 for (i = 0; i < s->n; i++)
284 if (s->p[i] != NULL)
285 return (1);
286 return (0);
287 }
288
289 /*--------------------------------------------------------------------
290 * Hash a STRANDS
291 */
292
293 uint32_t
VRT_HashStrands32(VCL_STRANDS s)294 VRT_HashStrands32(VCL_STRANDS s)
295 {
296 struct VSHA256Context sha_ctx;
297 unsigned char sha256[VSHA256_LEN];
298 const char *p;
299 int i;
300
301 AN(s);
302 VSHA256_Init(&sha_ctx);
303 for (i = 0; i < s->n; i++) {
304 p = s->p[i];
305 if (p != NULL && *p != '\0')
306 VSHA256_Update(&sha_ctx, p, strlen(p));
307 }
308 VSHA256_Final(sha256, &sha_ctx);
309
310 /* NB: for some reason vmod_director's shard director specifically
311 * relied on little-endian decoding of the last 4 octets. In order
312 * to maintain a stable hash function to share across consumers we
313 * need to stick to that.
314 */
315 return (vle32dec(sha256 + VSHA256_LEN - 4));
316 }
317
318 /*--------------------------------------------------------------------
319 * Collapse a STRING_LIST in the space provided, or return NULL
320 */
321
322 char *
VRT_StringList(char * d,unsigned dl,const char * p,va_list ap)323 VRT_StringList(char *d, unsigned dl, const char *p, va_list ap)
324 {
325 char *b, *e;
326 unsigned x;
327
328 b = d;
329 e = b + dl;
330 while (p != vrt_magic_string_end && b < e) {
331 if (p != NULL && *p != '\0') {
332 x = strlen(p);
333 if (b + x < e)
334 memcpy(b, p, x);
335 b += x;
336 }
337 p = va_arg(ap, const char *);
338 }
339 if (b >= e)
340 return (NULL);
341 *b++ = '\0';
342 return (b);
343 }
344
345 /*--------------------------------------------------------------------
346 * Copy and merge a STRING_LIST into a workspace.
347 */
348
349 const char *
VRT_String(struct ws * ws,const char * h,const char * p,va_list ap)350 VRT_String(struct ws *ws, const char *h, const char *p, va_list ap)
351 {
352 char *b, *e;
353 const char *q;
354 unsigned u, x;
355 va_list aq;
356
357 u = WS_ReserveAll(ws);
358 e = b = WS_Reservation(ws);
359 e += u;
360
361 va_copy(aq, ap);
362 do
363 q = va_arg(aq, const char *);
364 while (q == NULL || (q != vrt_magic_string_end && *q == '\0'));
365
366 if (h != NULL && p == NULL && q == vrt_magic_string_end &&
367 WS_Inside(ws, h, NULL)) {
368 va_end(aq);
369 WS_Release(ws, 0);
370 return (h);
371 }
372
373 if (h == NULL && p != NULL && q == vrt_magic_string_end &&
374 WS_Inside(ws, p, NULL)) {
375 va_end(aq);
376 WS_Release(ws, 0);
377 return (p);
378 }
379
380 if (h == NULL && p == NULL) {
381 if (q == vrt_magic_string_end) {
382 va_end(aq);
383 WS_Release(ws, 0);
384 return ("");
385 }
386 do
387 p = va_arg(aq, const char *);
388 while (p == NULL || (p != vrt_magic_string_end && *p == '\0'));
389 if (p == vrt_magic_string_end && WS_Inside(ws, q, NULL)) {
390 va_end(aq);
391 WS_Release(ws, 0);
392 return (q);
393 }
394 p = NULL;
395 va_end(aq);
396 }
397
398 if (h != NULL) {
399 x = strlen(h);
400 if (b + x < e)
401 memcpy(b, h, x);
402 b += x;
403 if (b < e)
404 *b = ' ';
405 b++;
406 }
407 b = VRT_StringList(b, e > b ? e - b : 0, p, ap);
408 if (b == NULL || b == e) {
409 WS_MarkOverflow(ws);
410 WS_Release(ws, 0);
411 return (NULL);
412 }
413 e = b;
414 b = WS_Reservation(ws);
415 WS_Release(ws, e - b);
416 return (b);
417 }
418
419 /*--------------------------------------------------------------------
420 * Copy and merge a STRING_LIST on the current workspace
421 */
422
423 VCL_STRING
VRT_CollectString(VRT_CTX,const char * p,...)424 VRT_CollectString(VRT_CTX, const char *p, ...)
425 {
426 va_list ap;
427 const char *b;
428
429 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
430 CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
431 va_start(ap, p);
432 b = VRT_String(ctx->ws, NULL, p, ap);
433 va_end(ap);
434 if (b == NULL)
435 VRT_fail(ctx, "Workspace overflow");
436 return (b);
437 }
438
439 /*--------------------------------------------------------------------
440 * Collapse STRANDS into the space provided, or return NULL
441 */
442
443 char *
VRT_Strands(char * d,size_t dl,VCL_STRANDS s)444 VRT_Strands(char *d, size_t dl, VCL_STRANDS s)
445 {
446 char *b;
447 const char *e;
448 unsigned x;
449
450 AN(d);
451 AN(s);
452 b = d;
453 e = b + dl;
454 for (int i = 0; i < s->n; i++)
455 if (s->p[i] != NULL && *s->p[i] != '\0') {
456 x = strlen(s->p[i]);
457 if (b + x >= e)
458 return (NULL);
459 memcpy(b, s->p[i], x);
460 b += x;
461 }
462 assert(b < e);
463 *b++ = '\0';
464 return (b);
465 }
466
467 /*--------------------------------------------------------------------
468 * Copy and merge STRANDS into a workspace.
469 */
470
471 VCL_STRING
VRT_StrandsWS(struct ws * ws,const char * h,VCL_STRANDS s)472 VRT_StrandsWS(struct ws *ws, const char *h, VCL_STRANDS s)
473 {
474 const char *q = NULL;
475 struct vsb vsb[1];
476 int i;
477
478 WS_Assert(ws);
479 AN(s);
480
481 for (i = 0; i < s->n; i++) {
482 if (s->p[i] != NULL && *s->p[i] != '\0') {
483 q = s->p[i];
484 break;
485 }
486 }
487
488 if (q == NULL) {
489 if (h == NULL)
490 return ("");
491 if (WS_Inside(ws, h, NULL))
492 return (h);
493 } else if (h == NULL && WS_Inside(ws, q, NULL)) {
494 for (i++; i < s->n; i++)
495 if (s->p[i] != NULL && *s->p[i] != '\0')
496 break;
497 if (i == s->n)
498 return (q);
499 }
500
501 WS_VSB_new(vsb, ws);
502 if (h != NULL)
503 VSB_cat(vsb, h);
504 for (i = 0; i < s->n; i++) {
505 if (s->p[i] != NULL && *s->p[i] != '\0')
506 VSB_cat(vsb, s->p[i]);
507 }
508 return (WS_VSB_finish(vsb, ws, NULL));
509 }
510
511 /*--------------------------------------------------------------------
512 * Copy and merge STRANDS on the current workspace
513 */
514
515 VCL_STRING
VRT_CollectStrands(VRT_CTX,VCL_STRANDS s)516 VRT_CollectStrands(VRT_CTX, VCL_STRANDS s)
517 {
518 const char *b;
519
520 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
521 CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
522 b = VRT_StrandsWS(ctx->ws, NULL, s);
523 if (b == NULL)
524 VRT_fail(ctx, "Workspace overflow");
525 return (b);
526 }
527
528 /*--------------------------------------------------------------------
529 * upper/lower-case STRANDS (onto workspace)
530 */
531
532 #include <stdio.h>
533
534 VCL_STRING
VRT_UpperLowerStrands(VRT_CTX,VCL_STRANDS s,int up)535 VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
536 {
537 unsigned u;
538 char *b, *e, *r;
539 const char *p, *q = NULL;
540 int i, copy = 0;
541
542 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
543 CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
544 AN(s);
545 u = WS_ReserveAll(ctx->ws);
546 r = b = WS_Reservation(ctx->ws);
547 e = b + u;
548 for (i = 0; i < s->n; i++) {
549 if (s->p[i] == NULL || s->p[i][0] == '\0')
550 continue;
551 if (q != NULL)
552 copy = 1;
553 for(p = q = s->p[i]; *p != '\0'; p++) {
554 if ((up && vct_islower(*p)) ||
555 (!up && vct_isupper(*p))) {
556 *b++ = *p ^ 0x20;
557 copy = 1;
558 } else if (b < e) {
559 *b++ = *p;
560 }
561 if (copy && b == e)
562 break;
563 }
564 if (copy && b == e) {
565 WS_Release(ctx->ws, 0);
566 VRT_fail(ctx, "Workspace overflow");
567 return (NULL);
568 }
569 }
570 assert(b <= e);
571 if (!copy) {
572 WS_Release(ctx->ws, 0);
573 return (q);
574 }
575 assert(b < e);
576 *b++ = '\0';
577 assert(b <= e);
578 WS_ReleaseP(ctx->ws, b);
579 return (r);
580 }
581
582 // rfc7230,l,1243,1244
583 // ASCII VCHAR + TAB + obs-text (0x80-ff)
584 static inline VCL_BOOL
validhdr(const char * p)585 validhdr(const char *p)
586 {
587 AN(p);
588 for(;*p != '\0'; p++)
589 if (! vct_ishdrval(*p))
590 return (0);
591 return (1);
592 }
593
594 /*--------------------------------------------------------------------*/
595 VCL_BOOL
VRT_ValidHdr(VRT_CTX,VCL_STRANDS s)596 VRT_ValidHdr(VRT_CTX, VCL_STRANDS s)
597 {
598 int i;
599
600 (void) ctx;
601
602 for (i = 0; i < s->n; i++) {
603 if (s->p[i] == NULL || s->p[i][0] == '\0')
604 continue;
605 if (! validhdr(s->p[i]))
606 return (0);
607 }
608
609 return (1);
610 }
611 /*--------------------------------------------------------------------*/
612
613 VCL_VOID
VRT_SetHdr(VRT_CTX,VCL_HEADER hs,const char * p,...)614 VRT_SetHdr(VRT_CTX , VCL_HEADER hs, const char *p, ...)
615 {
616 VCL_HTTP hp;
617 va_list ap;
618 const char *b;
619
620 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
621 AN(hs);
622 AN(hs->what);
623 hp = VRT_selecthttp(ctx, hs->where);
624 CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
625 if (p == vrt_magic_string_unset) {
626 http_Unset(hp, hs->what);
627 } else {
628 va_start(ap, p);
629 b = VRT_String(hp->ws, hs->what + 1, p, ap);
630 va_end(ap);
631 if (b == NULL) {
632 VSLb(ctx->vsl, SLT_LostHeader, "%s", hs->what + 1);
633 return;
634 }
635 if (FEATURE(FEATURE_VALIDATE_HEADERS) && ! validhdr(b)) {
636 VRT_fail(ctx, "Bad header %s", b);
637 return;
638 }
639 http_Unset(hp, hs->what);
640 http_SetHeader(hp, b);
641 }
642 }
643
644 /*--------------------------------------------------------------------*/
645
646 VCL_VOID
VRT_handling(VRT_CTX,unsigned hand)647 VRT_handling(VRT_CTX, unsigned hand)
648 {
649
650 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
651 assert(hand != VCL_RET_FAIL);
652 AN(ctx->handling);
653 AZ(*ctx->handling);
654 assert(hand > 0);
655 assert(hand < VCL_RET_MAX);
656 *ctx->handling = hand;
657 }
658
659 unsigned
VRT_handled(VRT_CTX)660 VRT_handled(VRT_CTX)
661 {
662 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
663 AN(ctx->handling);
664 return (*ctx->handling);
665 }
666
667 /*--------------------------------------------------------------------*/
668
669 VCL_VOID
VRT_fail(VRT_CTX,const char * fmt,...)670 VRT_fail(VRT_CTX, const char *fmt, ...)
671 {
672 va_list ap;
673
674 assert(ctx->vsl != NULL || ctx->msg != NULL);
675 AN(ctx->handling);
676 if (*ctx->handling == VCL_RET_FAIL)
677 return;
678 AZ(*ctx->handling);
679 AN(fmt);
680 AZ(strchr(fmt, '\n'));
681 va_start(ap, fmt);
682 if (ctx->vsl != NULL) {
683 VSLbv(ctx->vsl, SLT_VCL_Error, fmt, ap);
684 } else {
685 AN(ctx->msg);
686 VSB_vprintf(ctx->msg, fmt, ap);
687 VSB_putc(ctx->msg, '\n');
688 }
689 va_end(ap);
690 *ctx->handling = VCL_RET_FAIL;
691 }
692
693 /*--------------------------------------------------------------------
694 * Feed data into the hash calculation
695 */
696
697 VCL_VOID
VRT_hashdata(VRT_CTX,VCL_STRANDS s)698 VRT_hashdata(VRT_CTX, VCL_STRANDS s)
699 {
700 int i;
701
702 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
703 CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
704 AN(ctx->specific);
705 AN(s);
706 for (i = 0; i < s->n; i++)
707 HSH_AddString(ctx->req, ctx->specific, s->p[i]);
708 /*
709 * Add a 'field-separator' to make it more difficult to
710 * manipulate the hash.
711 */
712 HSH_AddString(ctx->req, ctx->specific, NULL);
713 }
714
715 /*--------------------------------------------------------------------*/
716
717 VCL_TIME
VRT_r_now(VRT_CTX)718 VRT_r_now(VRT_CTX)
719 {
720 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
721 return (ctx->now);
722 }
723
724 /*--------------------------------------------------------------------*/
725
v_matchproto_()726 VCL_STRING v_matchproto_()
727 VRT_IP_string(VRT_CTX, VCL_IP ip)
728 {
729 char *p;
730 unsigned len;
731
732 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
733 if (ip == NULL) {
734 VRT_fail(ctx, "%s: Illegal IP", __func__);
735 return (NULL);
736 }
737 len = WS_ReserveAll(ctx->ws);
738 if (len == 0) {
739 WS_Release(ctx->ws, 0);
740 return (NULL);
741 }
742 p = WS_Reservation(ctx->ws);
743 VTCP_name(ip, p, len, NULL, 0);
744 WS_Release(ctx->ws, strlen(p) + 1);
745 return (p);
746 }
747
v_matchproto_()748 VCL_STRING v_matchproto_()
749 VRT_INT_string(VRT_CTX, VCL_INT num)
750 {
751
752 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
753 return (WS_Printf(ctx->ws, "%jd", (intmax_t)num));
754 }
755
v_matchproto_()756 VCL_STRING v_matchproto_()
757 VRT_REAL_string(VRT_CTX, VCL_REAL num)
758 {
759
760 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
761 return (WS_Printf(ctx->ws, "%.3f", num));
762 }
763
v_matchproto_()764 VCL_STRING v_matchproto_()
765 VRT_TIME_string(VRT_CTX, VCL_TIME t)
766 {
767 char *p;
768
769 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
770 p = WS_Alloc(ctx->ws, VTIM_FORMAT_SIZE);
771 if (p != NULL)
772 VTIM_format(t, p);
773 return (p);
774 }
775
v_matchproto_()776 VCL_STRING v_matchproto_()
777 VRT_BACKEND_string(VCL_BACKEND d)
778 {
779 if (d == NULL)
780 return (NULL);
781 CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
782 return (d->vcl_name);
783 }
784
v_matchproto_()785 VCL_STRING v_matchproto_()
786 VRT_BOOL_string(VCL_BOOL val)
787 {
788
789 return (val ? "true" : "false");
790 }
791
v_matchproto_()792 VCL_STRING v_matchproto_()
793 VRT_BLOB_string(VRT_CTX, VCL_BLOB val)
794 {
795 struct vsb vsb[1];
796 const char *s;
797
798 if (val == NULL)
799 return (NULL);
800 WS_VSB_new(vsb, ctx->ws);
801 VSB_putc(vsb, ':');
802 VENC_Encode_Base64(vsb, val->blob, val->len);
803 VSB_putc(vsb, ':');
804 s = WS_VSB_finish(vsb, ctx->ws, NULL);
805 return (s);
806 }
807
808 /*--------------------------------------------------------------------*/
809
810 VCL_VOID
VRT_Rollback(VRT_CTX,VCL_HTTP hp)811 VRT_Rollback(VRT_CTX, VCL_HTTP hp)
812 {
813
814 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
815 CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
816 if (ctx->method & VCL_MET_PIPE) {
817 VRT_fail(ctx, "Cannot rollback in vcl_pipe {}");
818 return;
819 }
820 if (hp == ctx->http_req) {
821 CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
822 Req_Rollback(ctx);
823 if (ctx->method & VCL_MET_DELIVER)
824 XXXAZ(Resp_Setup_Deliver(ctx->req));
825 if (ctx->method & VCL_MET_SYNTH)
826 Resp_Setup_Synth(ctx->req);
827 } else if (hp == ctx->http_bereq) {
828 Bereq_Rollback(ctx);
829 } else
830 WRONG("VRT_Rollback 'hp' invalid");
831 }
832
833 /*--------------------------------------------------------------------*/
834
835 VCL_VOID
VRT_synth_strands(VRT_CTX,VCL_STRANDS s)836 VRT_synth_strands(VRT_CTX, VCL_STRANDS s)
837 {
838 struct vsb *vsb;
839 int i;
840
841 CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
842 AN(s);
843 for (i = 0; i < s->n; i++) {
844 if (s->p[i] != NULL)
845 VSB_cat(vsb, s->p[i]);
846 else
847 VSB_cat(vsb, "(null)");
848 }
849 }
850
851 VCL_VOID
VRT_synth_blob(VRT_CTX,VCL_BLOB b)852 VRT_synth_blob(VRT_CTX, VCL_BLOB b)
853 {
854 struct vsb *vsb;
855 CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
856
857 if (b->len > 0 && b->blob != NULL)
858 VSB_bcat(vsb, b->blob, b->len);
859 }
860
861 VCL_VOID
VRT_synth_page(VRT_CTX,VCL_STRANDS s)862 VRT_synth_page(VRT_CTX, VCL_STRANDS s)
863 {
864 VRT_synth_strands(ctx, s);
865 }
866
867 /*--------------------------------------------------------------------*/
868
869 static VCL_STRING
vrt_ban_error(VRT_CTX,VCL_STRING err)870 vrt_ban_error(VRT_CTX, VCL_STRING err)
871 {
872 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
873 AN(ctx->vsl);
874 AN(err);
875
876 VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
877 return (err);
878 }
879
880 VCL_STRING
VRT_ban_string(VRT_CTX,VCL_STRING str)881 VRT_ban_string(VRT_CTX, VCL_STRING str)
882 {
883 char *a1, *a2, *a3;
884 char **av;
885 struct ban_proto *bp;
886 const char *err = NULL, *berr = NULL;
887 int i;
888
889 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
890
891 if (str == NULL)
892 return (vrt_ban_error(ctx, "Null argument"));
893
894 bp = BAN_Build();
895 if (bp == NULL)
896 return (vrt_ban_error(ctx, "Out of Memory"));
897
898 av = VAV_Parse(str, NULL, ARGV_NOESC);
899 AN(av);
900 if (av[0] != NULL) {
901 err = av[0];
902 VAV_Free(av);
903 BAN_Abandon(bp);
904 return (vrt_ban_error(ctx, err));
905 }
906 for (i = 0; ;) {
907 a1 = av[++i];
908 if (a1 == NULL) {
909 err = "No ban conditions found.";
910 break;
911 }
912 a2 = av[++i];
913 if (a2 == NULL) {
914 err = "Expected comparison operator.";
915 break;
916 }
917 a3 = av[++i];
918 if (a3 == NULL) {
919 err = "Expected second operand.";
920 break;
921 }
922 berr = BAN_AddTest(bp, a1, a2, a3);
923 if (berr != NULL)
924 break;
925
926 if (av[++i] == NULL) {
927 berr = BAN_Commit(bp);
928 if (berr == NULL)
929 bp = NULL;
930 break;
931 }
932 if (strcmp(av[i], "&&")) {
933 err = WS_Printf(ctx->ws, "Expected && between "
934 "conditions, found \"%s\"", av[i]);
935 if (err == NULL)
936 err = "Expected && between conditions "
937 "(workspace overflow)";
938 break;
939 }
940 }
941 if (berr != NULL) {
942 AZ(err);
943 err = WS_Copy(ctx->ws, berr, -1);
944 if (err == NULL)
945 err = "Unknown error (workspace overflow)";
946 berr = NULL;
947 }
948 AZ(berr);
949 if (bp != NULL)
950 BAN_Abandon(bp);
951 VAV_Free(av);
952 if (err == NULL)
953 return (NULL);
954 return (vrt_ban_error(ctx, err));
955 }
956
957 VCL_BYTES
VRT_CacheReqBody(VRT_CTX,VCL_BYTES maxsize)958 VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize)
959 {
960
961 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
962 CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
963 if (ctx->method != VCL_MET_RECV) {
964 VSLb(ctx->vsl, SLT_VCL_Error,
965 "req.body can only be cached in vcl_recv{}");
966 return (-1);
967 }
968 return (VRB_Cache(ctx->req, maxsize));
969 }
970
971 /*--------------------------------------------------------------------
972 * purges
973 */
974
975 VCL_INT
VRT_purge(VRT_CTX,VCL_DURATION ttl,VCL_DURATION grace,VCL_DURATION keep)976 VRT_purge(VRT_CTX, VCL_DURATION ttl, VCL_DURATION grace, VCL_DURATION keep)
977 {
978
979 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
980
981 if ((ctx->method & (VCL_MET_HIT|VCL_MET_MISS)) == 0) {
982 VRT_fail(ctx,
983 "purge can only happen in vcl_hit{} or vcl_miss{}");
984 return (0);
985 }
986
987 CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
988 CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
989 return (HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
990 ctx->req->t_req, ttl, grace, keep));
991 }
992
993 /*--------------------------------------------------------------------
994 */
995
v_matchproto_()996 struct vsmw_cluster * v_matchproto_()
997 VRT_VSM_Cluster_New(VRT_CTX, size_t sz)
998 {
999 struct vsmw_cluster *vc;
1000
1001 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1002 assert(sz > 0);
1003 AN(vsc_lock);
1004 AN(vsc_unlock);
1005 AN(heritage.proc_vsmw);
1006 vsc_lock();
1007 vc = VSMW_NewCluster(heritage.proc_vsmw, sz, "VSC_cluster");
1008 vsc_unlock();
1009 return (vc);
1010 }
1011
v_matchproto_()1012 void v_matchproto_()
1013 VRT_VSM_Cluster_Destroy(VRT_CTX, struct vsmw_cluster **vsmcp)
1014 {
1015
1016 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1017 AN(vsmcp);
1018 VSMW_DestroyCluster(heritage.proc_vsmw, vsmcp);
1019 }
1020
1021 /*--------------------------------------------------------------------
1022 * Simple stuff
1023 */
1024
1025 int
VRT_strcmp(const char * s1,const char * s2)1026 VRT_strcmp(const char *s1, const char *s2)
1027 {
1028 if (s1 == NULL || s2 == NULL)
1029 return (1);
1030 return (strcmp(s1, s2));
1031 }
1032
1033 void
VRT_memmove(void * dst,const void * src,unsigned len)1034 VRT_memmove(void *dst, const void *src, unsigned len)
1035 {
1036
1037 (void)memmove(dst, src, len);
1038 }
1039
1040 VCL_BOOL
VRT_ipcmp(VRT_CTX,VCL_IP sua1,VCL_IP sua2)1041 VRT_ipcmp(VRT_CTX, VCL_IP sua1, VCL_IP sua2)
1042 {
1043
1044 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1045
1046 if (sua1 == NULL || sua2 == NULL) {
1047 VRT_fail(ctx, "%s: Illegal IP", __func__);
1048 return (1);
1049 }
1050 return (VSA_Compare_IP(sua1, sua2));
1051 }
1052
1053 /*
1054 * the pointer passed as src must have at least VCL_TASK lifetime
1055 */
1056 VCL_BLOB
VRT_blob(VRT_CTX,const char * err,const void * src,size_t len,unsigned type)1057 VRT_blob(VRT_CTX, const char *err, const void *src, size_t len, unsigned type)
1058 {
1059 struct vrt_blob *p;
1060
1061 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1062 CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
1063
1064 p = (void *)WS_Alloc(ctx->ws, sizeof *p);
1065 if (p == NULL) {
1066 VRT_fail(ctx, "Workspace overflow (%s)", err);
1067 return (NULL);
1068 }
1069
1070 p->type = type;
1071 p->len = len;
1072 p->blob = src;
1073
1074 return (p);
1075 }
1076
1077 int
VRT_VSA_GetPtr(VRT_CTX,const struct suckaddr * sua,const unsigned char ** dst)1078 VRT_VSA_GetPtr(VRT_CTX, const struct suckaddr *sua, const unsigned char ** dst)
1079 {
1080
1081 CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1082 AN(dst);
1083
1084 if (sua == NULL) {
1085 VRT_fail(ctx, "%s: Illegal IP", __func__);
1086 *dst = NULL;
1087 return (-1);
1088 }
1089 return (VSA_GetPtr(sua, dst));
1090 }
1091
1092 void
VRT_Format_Proxy(struct vsb * vsb,VCL_INT version,VCL_IP sac,VCL_IP sas,VCL_STRING auth)1093 VRT_Format_Proxy(struct vsb *vsb, VCL_INT version, VCL_IP sac, VCL_IP sas,
1094 VCL_STRING auth)
1095 {
1096 VPX_Format_Proxy(vsb, (int)version, sac, sas, auth);
1097 }
1098
1099 /*
1100 * Clone a struct vrt_endpoint in a single malloc() allocation
1101 */
1102
1103 //lint -e{662} Possible of out-of-bounds pointer (___ beyond end of data)
1104 //lint -e{826} Suspicious pointer-to-pointer conversion (area to o small
1105 struct vrt_endpoint *
VRT_Endpoint_Clone(const struct vrt_endpoint * const vep)1106 VRT_Endpoint_Clone(const struct vrt_endpoint * const vep)
1107 {
1108 size_t sz;
1109 struct vrt_endpoint *nvep;
1110 struct vrt_blob *blob = NULL;
1111 struct suckaddr *sa;
1112 size_t uds_len = 0;
1113 char *p, *e;
1114
1115 CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
1116 sz = sizeof *nvep;
1117 if (vep->ipv4)
1118 sz += vsa_suckaddr_len;
1119 if (vep->ipv6)
1120 sz += vsa_suckaddr_len;
1121 if (vep->uds_path != NULL) {
1122 uds_len = strlen(vep->uds_path) + 1;
1123 sz += uds_len;
1124 }
1125 if (vep->preamble != NULL && vep->preamble->len) {
1126 sz += sizeof(*blob);
1127 sz += vep->preamble->len;
1128 }
1129 p = calloc(1, sz);
1130 AN(p);
1131 e = p + sz;
1132 nvep = (void*)p;
1133 p += sizeof *nvep;
1134 INIT_OBJ(nvep, VRT_ENDPOINT_MAGIC);
1135 if (vep->ipv4) {
1136 sa = (void*)p;
1137 memcpy(sa, vep->ipv4, vsa_suckaddr_len);
1138 nvep->ipv4 = sa;
1139 p += vsa_suckaddr_len;
1140 }
1141 if (vep->ipv6) {
1142 sa = (void*)p;
1143 memcpy(sa, vep->ipv6, vsa_suckaddr_len);
1144 nvep->ipv6 = sa;
1145 p += vsa_suckaddr_len;
1146 }
1147 if (vep->preamble != NULL && vep->preamble->len) {
1148 /* Before uds because we need p to be aligned still */
1149 blob = (void*)p;
1150 p += sizeof(*blob);
1151 nvep->preamble = blob;
1152 memcpy(p, vep->preamble->blob, vep->preamble->len);
1153 blob->len = vep->preamble->len;
1154 blob->blob = p;
1155 p += vep->preamble->len;
1156 }
1157 if (uds_len) {
1158 memcpy(p, vep->uds_path, uds_len);
1159 nvep->uds_path = p;
1160 p += uds_len;
1161 }
1162 assert(p == e);
1163 return (nvep);
1164 }
1165