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