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