blob: 17f5ed061d6230d02f07d160fad098a45046b211 [file] [log] [blame]
Willy Tarreau2ac57182012-04-19 15:24:50 +02001/*
2 * Functions used to parse typed argument lists
3 *
4 * Copyright 2012 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <sys/types.h>
14#include <sys/socket.h>
15#include <arpa/inet.h>
16
Willy Tarreaub2551052020-06-09 09:07:15 +020017#include <haproxy/arg.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020018#include <haproxy/chunk.h>
Willy Tarreauf268ee82020-06-04 17:05:57 +020019#include <haproxy/global.h>
Willy Tarreauab213a52021-07-16 10:13:00 +020020#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020021#include <haproxy/tools.h>
Willy Tarreau2ac57182012-04-19 15:24:50 +020022
Thierry FOURNIER49f45af2014-12-08 19:50:43 +010023const char *arg_type_names[ARGT_NBTYPES] = {
Willy Tarreau2ac57182012-04-19 15:24:50 +020024 [ARGT_STOP] = "end of arguments",
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +020025 [ARGT_SINT] = "integer",
Willy Tarreau2ac57182012-04-19 15:24:50 +020026 [ARGT_STR] = "string",
27 [ARGT_IPV4] = "IPv4 address",
28 [ARGT_MSK4] = "IPv4 mask",
29 [ARGT_IPV6] = "IPv6 address",
30 [ARGT_MSK6] = "IPv6 mask",
31 [ARGT_TIME] = "delay",
32 [ARGT_SIZE] = "size",
33 [ARGT_FE] = "frontend",
34 [ARGT_BE] = "backend",
35 [ARGT_TAB] = "table",
36 [ARGT_SRV] = "server",
37 [ARGT_USR] = "user list",
Willy Tarreau53c250e2015-01-19 18:58:20 +010038 [ARGT_MAP] = "map",
Willy Tarreau46947782015-01-19 19:00:58 +010039 [ARGT_REG] = "regex",
Willy Tarreauf7ead612015-09-21 20:57:12 +020040 [ARGT_VAR] = "variable",
Frédéric Lécaille3a463c92019-02-25 15:20:35 +010041 [ARGT_PBUF_FNUM] = "Protocol buffers field number",
Willy Tarreau2ac57182012-04-19 15:24:50 +020042 /* Unassigned types must never happen. Better crash during parsing if they do. */
43};
44
Willy Tarreau2e845be2012-10-19 19:49:09 +020045/* This dummy arg list may be used by default when no arg is found, it helps
46 * parsers by removing pointer checks.
47 */
Willy Tarreau3d241e72015-01-19 18:44:07 +010048struct arg empty_arg_list[ARGM_NBARGS] = { };
Willy Tarreau2e845be2012-10-19 19:49:09 +020049
Willy Tarreaua4312fa2013-04-02 16:34:32 +020050/* This function clones a struct arg_list template into a new one which is
51 * returned.
52 */
53struct arg_list *arg_list_clone(const struct arg_list *orig)
54{
55 struct arg_list *new;
56
57 if ((new = calloc(1, sizeof(*new))) != NULL) {
58 /* ->list will be set by the caller when inserting the element.
59 * ->arg and ->arg_pos will be set by the caller.
60 */
61 new->ctx = orig->ctx;
62 new->kw = orig->kw;
63 new->conv = orig->conv;
64 new->file = orig->file;
65 new->line = orig->line;
66 }
67 return new;
68}
69
70/* This function clones a struct <arg_list> template into a new one which is
71 * set to point to arg <arg> at pos <pos>, and which is returned if the caller
72 * wants to apply further changes.
73 */
74struct arg_list *arg_list_add(struct arg_list *orig, struct arg *arg, int pos)
75{
76 struct arg_list *new;
77
78 new = arg_list_clone(orig);
Willy Tarreaua9e2e4b2017-04-12 22:28:52 +020079 if (new) {
80 new->arg = arg;
81 new->arg_pos = pos;
Willy Tarreau2b718102021-04-21 07:32:39 +020082 LIST_APPEND(&orig->list, &new->list);
Willy Tarreaua9e2e4b2017-04-12 22:28:52 +020083 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +020084 return new;
85}
86
Willy Tarreau80b53ff2020-02-14 08:40:37 +010087/* This function builds an argument list from a config line, and stops at the
88 * first non-matching character, which is pointed to in <end_ptr>. A valid arg
89 * list starts with an opening parenthesis '(', contains a number of comma-
90 * delimited words, and ends with the closing parenthesis ')'. An empty list
91 * (with or without the parenthesis) will lead to a valid empty argument if the
92 * keyword has a mandatory one. The function returns the number of arguments
93 * emitted, or <0 in case of any error. Everything needed it automatically
94 * allocated. A pointer to an error message might be returned in err_msg if not
95 * NULL, in which case it would be allocated and the caller will have to check
96 * it and free it. The output arg list is returned in argp which must be valid.
97 * The returned array is always terminated by an arg of type ARGT_STOP (0),
98 * unless the mask indicates that no argument is supported. Unresolved arguments
99 * are appended to arg list <al>, which also serves as a template to create new
Christopher Faulet35926a12021-09-30 08:48:56 +0200100 * entries. <al> may be NULL if unresolved arguments are not allowed. The mask
101 * is composed of a number of mandatory arguments in its lower ARGM_BITS bits,
102 * and a concatenation of each argument type in each subsequent ARGT_BITS-bit
103 * sblock. If <err_msg> is not NULL, it must point to a freeable or NULL
104 * pointer. The caller is expected to restart the parsing from the new pointer
105 * set in <end_ptr>, which is the first character considered as not being part
106 * of the arg list. The input string ends on the first between <len> characters
107 * (when len is positive) or the first NUL character. Placing -1 in <len> will
108 * make it virtually unbounded (~2GB long strings).
Willy Tarreau2ac57182012-04-19 15:24:50 +0200109 */
David Carlier15073a32016-03-15 19:00:35 +0000110int make_arg_list(const char *in, int len, uint64_t mask, struct arg **argp,
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100111 char **err_msg, const char **end_ptr, int *err_arg,
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200112 struct arg_list *al)
Willy Tarreau2ac57182012-04-19 15:24:50 +0200113{
114 int nbarg;
115 int pos;
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200116 struct arg *arg;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200117 const char *beg;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200118 const char *ptr_err = NULL;
119 int min_arg;
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100120 int empty;
Willy Tarreau0622f022017-04-12 22:32:04 +0200121 struct arg_list *new_al = al;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200122
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200123 *argp = NULL;
124
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100125 empty = 0;
126 if (!len || *in != '(') {
127 /* it's already not for us, stop here */
128 empty = 1;
129 len = 0;
130 } else {
131 /* skip opening parenthesis */
132 len--;
133 in++;
134 }
135
Willy Tarreau3d241e72015-01-19 18:44:07 +0100136 min_arg = mask & ARGM_MASK;
137 mask >>= ARGM_BITS;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200138
139 pos = 0;
Willy Tarreau3d241e72015-01-19 18:44:07 +0100140 /* find between 0 and NBARGS the max number of args supported by the mask */
141 for (nbarg = 0; nbarg < ARGM_NBARGS && ((mask >> (nbarg * ARGT_BITS)) & ARGT_MASK); nbarg++);
Willy Tarreau2ac57182012-04-19 15:24:50 +0200142
143 if (!nbarg)
144 goto end_parse;
145
146 /* Note: an empty input string contains an empty argument if this argument
147 * is marked mandatory. Otherwise we can ignore it.
148 */
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100149 if (empty && !min_arg)
Willy Tarreau2ac57182012-04-19 15:24:50 +0200150 goto end_parse;
151
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200152 arg = *argp = calloc(nbarg + 1, sizeof(**argp));
Willy Tarreau2ac57182012-04-19 15:24:50 +0200153
Remi Tricot-Le Breton17acbab2021-05-19 12:00:54 +0200154 if (!arg)
155 goto alloc_err;
156
Willy Tarreau2ac57182012-04-19 15:24:50 +0200157 /* Note: empty arguments after a comma always exist. */
158 while (pos < nbarg) {
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200159 unsigned int uint;
Willy Tarreauef21fac2020-02-14 13:37:20 +0100160 int squote = 0, dquote = 0;
161 char *out;
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200162
Willy Tarreauef21fac2020-02-14 13:37:20 +0100163 chunk_reset(&trash);
164 out = trash.area;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200165
Willy Tarreauef21fac2020-02-14 13:37:20 +0100166 while (len && *in && trash.data < trash.size - 1) {
167 if (*in == '"' && !squote) { /* double quote outside single quotes */
168 if (dquote)
169 dquote = 0;
170 else
171 dquote = 1;
172 in++; len--;
173 continue;
174 }
175 else if (*in == '\'' && !dquote) { /* single quote outside double quotes */
176 if (squote)
177 squote = 0;
178 else
179 squote = 1;
180 in++; len--;
181 continue;
182 }
183 else if (*in == '\\' && !squote && len != 1) {
184 /* '\', ', ' ', '"' support being escaped by '\' */
185 if (len == 1 || in[1] == 0)
186 goto unquote_err;
187
188 if (in[1] == '\\' || in[1] == ' ' || in[1] == '"' || in[1] == '\'') {
189 in++; len--;
190 *out++ = *in;
191 }
192 else if (in[1] == 'r') {
193 in++; len--;
194 *out++ = '\r';
195 }
196 else if (in[1] == 'n') {
197 in++; len--;
198 *out++ = '\n';
199 }
200 else if (in[1] == 't') {
201 in++; len--;
202 *out++ = '\t';
203 }
204 else {
205 /* just a lone '\' */
206 *out++ = *in;
207 }
208 in++; len--;
209 }
210 else {
211 if (!squote && !dquote && (*in == ',' || *in == ')')) {
212 /* end of argument */
213 break;
214 }
215 /* verbatim copy */
216 *out++ = *in++;
217 len--;
218 }
219 trash.data = out - trash.area;
220 }
Willy Tarreau807aef82020-02-15 14:54:28 +0100221
Willy Tarreau9af749b2020-02-16 10:46:37 +0100222 if (len && *in && *in != ',' && *in != ')')
Willy Tarreau807aef82020-02-15 14:54:28 +0100223 goto buffer_err;
224
Willy Tarreauef21fac2020-02-14 13:37:20 +0100225 trash.area[trash.data] = 0;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200226
Willy Tarreau3d241e72015-01-19 18:44:07 +0100227 arg->type = (mask >> (pos * ARGT_BITS)) & ARGT_MASK;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200228
229 switch (arg->type) {
230 case ARGT_SINT:
Willy Tarreau338c6702020-02-14 11:34:35 +0100231 if (!trash.data) // empty number
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200232 goto empty_err;
Willy Tarreau338c6702020-02-14 11:34:35 +0100233 beg = trash.area;
234 arg->data.sint = read_int64(&beg, trash.area + trash.data);
235 if (beg < trash.area + trash.data)
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200236 goto parse_err;
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200237 arg->type = ARGT_SINT;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200238 break;
239
240 case ARGT_FE:
241 case ARGT_BE:
242 case ARGT_TAB:
243 case ARGT_SRV:
244 case ARGT_USR:
Willy Tarreau46947782015-01-19 19:00:58 +0100245 case ARGT_REG:
Willy Tarreau496aa012012-06-01 10:38:29 +0200246 /* These argument types need to be stored as strings during
247 * parsing then resolved later.
248 */
Christopher Faulet35926a12021-09-30 08:48:56 +0200249 if (!al)
250 goto resolve_err;
Willy Tarreau496aa012012-06-01 10:38:29 +0200251 arg->unresolved = 1;
Willy Tarreau0622f022017-04-12 22:32:04 +0200252 new_al = arg_list_add(al, arg, pos);
Willy Tarreau266ce552022-11-14 07:20:54 +0100253 __fallthrough;
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200254
Willy Tarreau2ac57182012-04-19 15:24:50 +0200255 case ARGT_STR:
256 /* all types that must be resolved are stored as strings
257 * during the parsing. The caller must at one point resolve
258 * them and free the string.
259 */
Willy Tarreau338c6702020-02-14 11:34:35 +0100260 arg->data.str.area = my_strndup(trash.area, trash.data);
261 arg->data.str.data = trash.data;
262 arg->data.str.size = trash.data + 1;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200263 break;
264
265 case ARGT_IPV4:
Willy Tarreau338c6702020-02-14 11:34:35 +0100266 if (!trash.data) // empty address
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200267 goto empty_err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200268
Willy Tarreau338c6702020-02-14 11:34:35 +0100269 if (inet_pton(AF_INET, trash.area, &arg->data.ipv4) <= 0)
Willy Tarreau2ac57182012-04-19 15:24:50 +0200270 goto parse_err;
271 break;
272
273 case ARGT_MSK4:
Willy Tarreau338c6702020-02-14 11:34:35 +0100274 if (!trash.data) // empty mask
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200275 goto empty_err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200276
Willy Tarreau338c6702020-02-14 11:34:35 +0100277 if (!str2mask(trash.area, &arg->data.ipv4))
Willy Tarreau2ac57182012-04-19 15:24:50 +0200278 goto parse_err;
279
280 arg->type = ARGT_IPV4;
281 break;
282
283 case ARGT_IPV6:
Willy Tarreau338c6702020-02-14 11:34:35 +0100284 if (!trash.data) // empty address
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200285 goto empty_err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200286
Willy Tarreau338c6702020-02-14 11:34:35 +0100287 if (inet_pton(AF_INET6, trash.area, &arg->data.ipv6) <= 0)
Willy Tarreau2ac57182012-04-19 15:24:50 +0200288 goto parse_err;
289 break;
290
Tim Duesterhusb814da62018-01-25 16:24:50 +0100291 case ARGT_MSK6:
Willy Tarreau338c6702020-02-14 11:34:35 +0100292 if (!trash.data) // empty mask
Tim Duesterhusb814da62018-01-25 16:24:50 +0100293 goto empty_err;
294
Willy Tarreau338c6702020-02-14 11:34:35 +0100295 if (!str2mask6(trash.area, &arg->data.ipv6))
Tim Duesterhusb814da62018-01-25 16:24:50 +0100296 goto parse_err;
297
298 arg->type = ARGT_IPV6;
299 break;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200300
301 case ARGT_TIME:
Willy Tarreau338c6702020-02-14 11:34:35 +0100302 if (!trash.data) // empty time
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200303 goto empty_err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200304
Willy Tarreau338c6702020-02-14 11:34:35 +0100305 ptr_err = parse_time_err(trash.area, &uint, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200306 if (ptr_err) {
307 if (ptr_err == PARSE_TIME_OVER || ptr_err == PARSE_TIME_UNDER)
Willy Tarreau338c6702020-02-14 11:34:35 +0100308 ptr_err = trash.area;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200309 goto parse_err;
Willy Tarreau9faebe32019-06-07 19:00:37 +0200310 }
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200311 arg->data.sint = uint;
312 arg->type = ARGT_SINT;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200313 break;
314
315 case ARGT_SIZE:
Willy Tarreau338c6702020-02-14 11:34:35 +0100316 if (!trash.data) // empty size
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200317 goto empty_err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200318
Willy Tarreau338c6702020-02-14 11:34:35 +0100319 ptr_err = parse_size_err(trash.area, &uint);
Willy Tarreau2ac57182012-04-19 15:24:50 +0200320 if (ptr_err)
321 goto parse_err;
322
Thierry FOURNIERbf65cd42015-07-20 17:45:02 +0200323 arg->data.sint = uint;
324 arg->type = ARGT_SINT;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200325 break;
326
Frédéric Lécaille3a463c92019-02-25 15:20:35 +0100327 case ARGT_PBUF_FNUM:
Willy Tarreau338c6702020-02-14 11:34:35 +0100328 if (!trash.data)
Frédéric Lécaille756d97f2019-03-04 19:03:48 +0100329 goto empty_err;
330
Willy Tarreau338c6702020-02-14 11:34:35 +0100331 if (!parse_dotted_uints(trash.area, &arg->data.fid.ids, &arg->data.fid.sz))
Frédéric Lécaille3a463c92019-02-25 15:20:35 +0100332 goto parse_err;
333
334 break;
335
Willy Tarreau2ac57182012-04-19 15:24:50 +0200336 /* FIXME: other types need to be implemented here */
337 default:
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200338 goto not_impl;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200339 }
340
341 pos++;
342 arg++;
343
344 /* don't go back to parsing if we reached end */
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100345 if (!len || !*in || *in == ')' || pos >= nbarg)
Willy Tarreau2ac57182012-04-19 15:24:50 +0200346 break;
347
348 /* skip comma */
349 in++; len--;
350 }
351
352 end_parse:
Willy Tarreau2ac57182012-04-19 15:24:50 +0200353 if (pos < min_arg) {
354 /* not enough arguments */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200355 memprintf(err_msg,
Willy Tarreaub111d422013-12-13 00:38:47 +0100356 "missing arguments (got %d/%d), type '%s' expected",
Willy Tarreau3d241e72015-01-19 18:44:07 +0100357 pos, min_arg, arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK]);
Willy Tarreau2ac57182012-04-19 15:24:50 +0200358 goto err;
359 }
360
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100361 if (empty) {
362 /* nothing to do */
363 } else if (*in == ')') {
364 /* skip the expected closing parenthesis */
365 in++;
366 } else {
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200367 /* the caller is responsible for freeing this message */
Willy Tarreau338c6702020-02-14 11:34:35 +0100368 char *word = (len > 0) ? my_strndup(in, len) : (char *)in;
Willy Tarreau3e293a92021-05-06 14:50:30 +0200369
370 if (*word)
371 memprintf(err_msg, "expected ')' before '%s'", word);
372 else
373 memprintf(err_msg, "expected ')'");
374
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100375 if (len > 0)
376 free(word);
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500377 /* when we're missing a right paren, the empty part preceding
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100378 * already created an empty arg, adding one to the position, so
379 * let's fix the reporting to avoid being confusing.
380 */
381 if (pos > 1)
382 pos--;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200383 goto err;
384 }
385
386 /* note that pos might be < nbarg and this is not an error, it's up to the
387 * caller to decide what to do with optional args.
388 */
Willy Tarreau2ac57182012-04-19 15:24:50 +0200389 if (err_arg)
390 *err_arg = pos;
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100391 if (end_ptr)
392 *end_ptr = in;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200393 return pos;
394
Willy Tarreau2ac57182012-04-19 15:24:50 +0200395 err:
Willy Tarreau0622f022017-04-12 22:32:04 +0200396 if (new_al == al) {
397 /* only free the arg area if we have not queued unresolved args
398 * still pointing to it.
399 */
Willy Tarreau69a23ae2021-07-17 18:36:43 +0200400 free_args(*argp);
Willy Tarreau0622f022017-04-12 22:32:04 +0200401 free(*argp);
402 }
Willy Tarreau681e49d2013-12-06 15:30:05 +0100403 *argp = NULL;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200404 if (err_arg)
405 *err_arg = pos;
Willy Tarreau80b53ff2020-02-14 08:40:37 +0100406 if (end_ptr)
407 *end_ptr = in;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200408 return -1;
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200409
410 empty_err:
Willy Tarreau75fd2ff2020-07-21 15:44:38 +0200411 /* If we've only got an empty set of parenthesis with nothing
412 * in between, there is no arg at all.
413 */
414 if (!pos) {
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100415 ha_free(argp);
Willy Tarreau75fd2ff2020-07-21 15:44:38 +0200416 }
417
Willy Tarreau77e463f2020-02-28 16:41:29 +0100418 if (pos >= min_arg)
419 goto end_parse;
420
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200421 memprintf(err_msg, "expected type '%s' at position %d, but got nothing",
Willy Tarreau3d241e72015-01-19 18:44:07 +0100422 arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK], pos + 1);
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200423 goto err;
424
425 parse_err:
Willy Tarreau338c6702020-02-14 11:34:35 +0100426 /* come here with the word attempted to parse in trash */
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200427 memprintf(err_msg, "failed to parse '%s' as type '%s' at position %d",
Willy Tarreau338c6702020-02-14 11:34:35 +0100428 trash.area, arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK], pos + 1);
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200429 goto err;
430
431 not_impl:
Willy Tarreaueb6cead2012-09-20 19:43:14 +0200432 memprintf(err_msg, "parsing for type '%s' was not implemented, please report this bug",
Willy Tarreau3d241e72015-01-19 18:44:07 +0100433 arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK]);
Willy Tarreau4e6336f2012-04-27 16:32:26 +0200434 goto err;
Willy Tarreau338c6702020-02-14 11:34:35 +0100435
436 buffer_err:
437 memprintf(err_msg, "too small buffer size to store decoded argument %d, increase bufsize ?",
438 pos + 1);
439 goto err;
Willy Tarreauef21fac2020-02-14 13:37:20 +0100440
441 unquote_err:
442 /* come here with the parsed part in <trash.area>:<trash.data> and the
443 * unparsable part in <in>.
444 */
445 trash.area[trash.data] = 0;
446 memprintf(err_msg, "failed to parse '%s' after '%s' as type '%s' at position %d",
447 in, trash.area, arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK], pos + 1);
448 goto err;
449
Remi Tricot-Le Breton17acbab2021-05-19 12:00:54 +0200450alloc_err:
451 memprintf(err_msg, "out of memory");
452 goto err;
Christopher Faulet35926a12021-09-30 08:48:56 +0200453
454 resolve_err:
455 memprintf(err_msg, "unresolved argument of type '%s' at position %d not allowed",
456 arg_type_names[(mask >> (pos * ARGT_BITS)) & ARGT_MASK], pos + 1);
457 goto err;
Willy Tarreau2ac57182012-04-19 15:24:50 +0200458}
Willy Tarreauab213a52021-07-16 10:13:00 +0200459
460/* Free all args of an args array, taking care of unresolved arguments as well.
461 * It stops at the ARGT_STOP, which must be present. The array itself is not
462 * freed, it's up to the caller to do it. However it is returned, allowing to
463 * call free(free_args(argptr)). It is valid to call it with a NULL args, and
464 * nothing will be done).
465 */
466struct arg *free_args(struct arg *args)
467{
468 struct arg *arg;
469
470 for (arg = args; arg && arg->type != ARGT_STOP; arg++) {
471 if (arg->type == ARGT_STR || arg->unresolved)
472 chunk_destroy(&arg->data.str);
473 else if (arg->type == ARGT_REG)
474 regex_free(arg->data.reg);
475 else if (arg->type == ARGT_PBUF_FNUM)
476 ha_free(&arg->data.fid.ids);
477 }
478 return args;
479}