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