]>
Commit | Line | Data |
---|---|---|
997358a6 MW |
1 | /* automatic handling of confread struct arguments |
2 | * Copyright (C) 2006 Andreas Steffen | |
3 | * Hochschule fuer Technik Rapperswil, Switzerland | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | * for more details. | |
997358a6 MW |
14 | */ |
15 | ||
16 | #include <stddef.h> | |
17 | #include <stdlib.h> | |
18 | #include <string.h> | |
19 | ||
163b2273 | 20 | #include <library.h> |
f05b4272 | 21 | #include <utils/debug.h> |
997358a6 | 22 | |
997358a6 | 23 | #include "keywords.h" |
997358a6 MW |
24 | #include "confread.h" |
25 | #include "args.h" | |
26 | ||
27 | /* argument types */ | |
28 | ||
29 | typedef enum { | |
3d7a244b AS |
30 | ARG_NONE, |
31 | ARG_ENUM, | |
32 | ARG_UINT, | |
33 | ARG_TIME, | |
34 | ARG_ULNG, | |
9c7faa86 | 35 | ARG_ULLI, |
3d7a244b AS |
36 | ARG_PCNT, |
37 | ARG_STR, | |
38 | ARG_LST, | |
39 | ARG_MISC | |
997358a6 MW |
40 | } arg_t; |
41 | ||
42 | /* various keyword lists */ | |
43 | ||
44 | static const char *LST_bool[] = { | |
3d7a244b AS |
45 | "no", |
46 | "yes", | |
47 | NULL | |
997358a6 MW |
48 | }; |
49 | ||
50 | static const char *LST_sendcert[] = { | |
3d7a244b AS |
51 | "always", |
52 | "ifasked", | |
53 | "never", | |
54 | "yes", | |
55 | "no", | |
56 | NULL | |
997358a6 MW |
57 | }; |
58 | ||
0644ebd3 | 59 | static const char *LST_unique[] = { |
3d7a244b AS |
60 | "no", |
61 | "yes", | |
62 | "replace", | |
63 | "keep", | |
f4cc7ea1 | 64 | "never", |
3d7a244b | 65 | NULL |
0644ebd3 MW |
66 | }; |
67 | ||
4841189b | 68 | static const char *LST_strict[] = { |
3d7a244b AS |
69 | "no", |
70 | "yes", | |
71 | "ifuri", | |
72 | NULL | |
4841189b | 73 | }; |
997358a6 | 74 | static const char *LST_dpd_action[] = { |
3d7a244b AS |
75 | "none", |
76 | "clear", | |
77 | "hold", | |
78 | "restart", | |
79 | NULL | |
997358a6 MW |
80 | }; |
81 | ||
82 | static const char *LST_startup[] = { | |
3d7a244b AS |
83 | "ignore", |
84 | "add", | |
85 | "route", | |
86 | "start", | |
87 | NULL | |
997358a6 MW |
88 | }; |
89 | ||
997358a6 | 90 | static const char *LST_keyexchange[] = { |
3d7a244b AS |
91 | "ike", |
92 | "ikev1", | |
93 | "ikev2", | |
94 | NULL | |
997358a6 MW |
95 | }; |
96 | ||
e838c39b TB |
97 | static const char *LST_authby[] = { |
98 | "psk", | |
99 | "secret", | |
100 | "pubkey", | |
101 | "rsa", | |
102 | "rsasig", | |
103 | "ecdsa", | |
104 | "ecdsasig", | |
105 | "xauthpsk", | |
106 | "xauthrsasig", | |
107 | "never", | |
108 | NULL | |
109 | }; | |
110 | ||
997358a6 | 111 | typedef struct { |
3d7a244b AS |
112 | arg_t type; |
113 | size_t offset; | |
114 | const char **list; | |
997358a6 MW |
115 | } token_info_t; |
116 | ||
117 | static const token_info_t token_info[] = | |
118 | { | |
3d7a244b | 119 | /* config setup keywords */ |
3d7a244b | 120 | { ARG_STR, offsetof(starter_config_t, setup.charondebug), NULL }, |
3d7a244b | 121 | { ARG_ENUM, offsetof(starter_config_t, setup.uniqueids), LST_unique }, |
3d7a244b AS |
122 | { ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool }, |
123 | { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict }, | |
25fb9d3f | 124 | { ARG_MISC, 0, NULL /* KW_PKCS11_DEPRECATED */ }, |
9707d9db | 125 | { ARG_MISC, 0, NULL /* KW_SETUP_DEPRECATED */ }, |
3d7a244b AS |
126 | |
127 | /* conn section keywords */ | |
128 | { ARG_STR, offsetof(starter_conn_t, name), NULL }, | |
129 | { ARG_ENUM, offsetof(starter_conn_t, startup), LST_startup }, | |
130 | { ARG_ENUM, offsetof(starter_conn_t, keyexchange), LST_keyexchange }, | |
131 | { ARG_MISC, 0, NULL /* KW_TYPE */ }, | |
3d7a244b AS |
132 | { ARG_MISC, 0, NULL /* KW_COMPRESS */ }, |
133 | { ARG_ENUM, offsetof(starter_conn_t, install_policy), LST_bool }, | |
e129168b | 134 | { ARG_ENUM, offsetof(starter_conn_t, aggressive), LST_bool }, |
3d7a244b | 135 | { ARG_MISC, 0, NULL /* KW_AUTH */ }, |
e838c39b | 136 | { ARG_STR, offsetof(starter_conn_t, authby), LST_authby }, |
3d7a244b | 137 | { ARG_STR, offsetof(starter_conn_t, eap_identity), NULL }, |
64d7b073 | 138 | { ARG_STR, offsetof(starter_conn_t, aaa_identity), NULL }, |
3d7a244b AS |
139 | { ARG_MISC, 0, NULL /* KW_MOBIKE */ }, |
140 | { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ }, | |
141 | { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL }, | |
142 | { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL }, | |
143 | { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL }, | |
ca41aa06 TB |
144 | { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_bytes), NULL }, |
145 | { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_bytes), NULL }, | |
146 | { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_life_packets), NULL }, | |
147 | { ARG_ULLI, offsetof(starter_conn_t, sa_ipsec_margin_packets), NULL }, | |
3d7a244b AS |
148 | { ARG_MISC, 0, NULL /* KW_KEYINGTRIES */ }, |
149 | { ARG_PCNT, offsetof(starter_conn_t, sa_rekey_fuzz), NULL }, | |
150 | { ARG_MISC, 0, NULL /* KW_REKEY */ }, | |
151 | { ARG_MISC, 0, NULL /* KW_REAUTH */ }, | |
152 | { ARG_STR, offsetof(starter_conn_t, ike), NULL }, | |
153 | { ARG_STR, offsetof(starter_conn_t, esp), NULL }, | |
3d7a244b AS |
154 | { ARG_TIME, offsetof(starter_conn_t, dpd_delay), NULL }, |
155 | { ARG_TIME, offsetof(starter_conn_t, dpd_timeout), NULL }, | |
156 | { ARG_ENUM, offsetof(starter_conn_t, dpd_action), LST_dpd_action }, | |
f34ebc84 | 157 | { ARG_ENUM, offsetof(starter_conn_t, close_action), LST_dpd_action }, |
8015c91c | 158 | { ARG_TIME, offsetof(starter_conn_t, inactivity), NULL }, |
3d7a244b AS |
159 | { ARG_MISC, 0, NULL /* KW_MODECONFIG */ }, |
160 | { ARG_MISC, 0, NULL /* KW_XAUTH */ }, | |
8143f109 | 161 | { ARG_STR, offsetof(starter_conn_t, xauth_identity), NULL }, |
3d7a244b AS |
162 | { ARG_ENUM, offsetof(starter_conn_t, me_mediation), LST_bool }, |
163 | { ARG_STR, offsetof(starter_conn_t, me_mediated_by), NULL }, | |
164 | { ARG_STR, offsetof(starter_conn_t, me_peerid), NULL }, | |
2b26a9c3 | 165 | { ARG_UINT, offsetof(starter_conn_t, reqid), NULL }, |
ee26c537 | 166 | { ARG_MISC, 0, NULL /* KW_MARK */ }, |
26c4d010 AS |
167 | { ARG_MISC, 0, NULL /* KW_MARK_IN */ }, |
168 | { ARG_MISC, 0, NULL /* KW_MARK_OUT */ }, | |
6c302616 | 169 | { ARG_MISC, 0, NULL /* KW_TFC */ }, |
25fb9d3f | 170 | { ARG_MISC, 0, NULL /* KW_PFS_DEPRECATED */ }, |
9707d9db | 171 | { ARG_MISC, 0, NULL /* KW_CONN_DEPRECATED */ }, |
3d7a244b AS |
172 | |
173 | /* ca section keywords */ | |
174 | { ARG_STR, offsetof(starter_ca_t, name), NULL }, | |
175 | { ARG_ENUM, offsetof(starter_ca_t, startup), LST_startup }, | |
176 | { ARG_STR, offsetof(starter_ca_t, cacert), NULL }, | |
3d7a244b AS |
177 | { ARG_STR, offsetof(starter_ca_t, crluri), NULL }, |
178 | { ARG_STR, offsetof(starter_ca_t, crluri2), NULL }, | |
179 | { ARG_STR, offsetof(starter_ca_t, ocspuri), NULL }, | |
180 | { ARG_STR, offsetof(starter_ca_t, ocspuri2), NULL }, | |
181 | { ARG_STR, offsetof(starter_ca_t, certuribase), NULL }, | |
9707d9db | 182 | { ARG_MISC, 0, NULL /* KW_CA_DEPRECATED */ }, |
3d7a244b AS |
183 | |
184 | /* end keywords */ | |
e59a5000 | 185 | { ARG_STR, offsetof(starter_end_t, host), NULL }, |
667b7372 | 186 | { ARG_UINT, offsetof(starter_end_t, ikeport), NULL }, |
8dd094e1 | 187 | { ARG_STR, offsetof(starter_end_t, subnet), NULL }, |
3d7a244b | 188 | { ARG_MISC, 0, NULL /* KW_PROTOPORT */ }, |
61e48488 | 189 | { ARG_STR, offsetof(starter_end_t, sourceip), NULL }, |
17319aa2 | 190 | { ARG_STR, offsetof(starter_end_t, dns), NULL }, |
3d7a244b AS |
191 | { ARG_ENUM, offsetof(starter_end_t, firewall), LST_bool }, |
192 | { ARG_ENUM, offsetof(starter_end_t, hostaccess), LST_bool }, | |
193 | { ARG_ENUM, offsetof(starter_end_t, allow_any), LST_bool }, | |
194 | { ARG_STR, offsetof(starter_end_t, updown), NULL }, | |
195 | { ARG_STR, offsetof(starter_end_t, auth), NULL }, | |
196 | { ARG_STR, offsetof(starter_end_t, auth2), NULL }, | |
197 | { ARG_STR, offsetof(starter_end_t, id), NULL }, | |
198 | { ARG_STR, offsetof(starter_end_t, id2), NULL }, | |
199 | { ARG_STR, offsetof(starter_end_t, rsakey), NULL }, | |
200 | { ARG_STR, offsetof(starter_end_t, cert), NULL }, | |
201 | { ARG_STR, offsetof(starter_end_t, cert2), NULL }, | |
6367de28 | 202 | { ARG_STR, offsetof(starter_end_t, cert_policy), NULL }, |
3d7a244b AS |
203 | { ARG_ENUM, offsetof(starter_end_t, sendcert), LST_sendcert }, |
204 | { ARG_STR, offsetof(starter_end_t, ca), NULL }, | |
205 | { ARG_STR, offsetof(starter_end_t, ca2), NULL }, | |
206 | { ARG_STR, offsetof(starter_end_t, groups), NULL }, | |
46df61df | 207 | { ARG_STR, offsetof(starter_end_t, groups2), NULL }, |
9707d9db | 208 | { ARG_MISC, 0, NULL /* KW_END_DEPRECATED */ }, |
997358a6 MW |
209 | }; |
210 | ||
10c13ed2 | 211 | static void free_list(char **list) |
997358a6 | 212 | { |
3d7a244b | 213 | char **s; |
997358a6 | 214 | |
3d7a244b AS |
215 | for (s = list; *s; s++) |
216 | { | |
217 | free(*s); | |
218 | } | |
219 | free(list); | |
997358a6 MW |
220 | } |
221 | ||
10c13ed2 | 222 | char** new_list(char *value) |
997358a6 | 223 | { |
3d7a244b AS |
224 | char *val, *b, *e, *end, **ret; |
225 | int count; | |
226 | ||
7cce0e96 | 227 | val = strdupnull(value); |
3d7a244b | 228 | if (!val) |
10c13ed2 | 229 | { |
3d7a244b | 230 | return NULL; |
10c13ed2 | 231 | } |
3d7a244b AS |
232 | end = val + strlen(val); |
233 | for (b = val, count = 0; b < end;) | |
234 | { | |
235 | for (e = b; ((*e != ' ') && (*e != '\0')); e++); | |
236 | *e = '\0'; | |
237 | if (e != b) | |
10c13ed2 | 238 | { |
3d7a244b | 239 | count++; |
10c13ed2 | 240 | } |
3d7a244b AS |
241 | b = e + 1; |
242 | } | |
243 | if (count == 0) | |
244 | { | |
245 | free(val); | |
246 | return NULL; | |
247 | } | |
248 | ret = (char **)malloc((count+1) * sizeof(char *)); | |
249 | ||
250 | for (b = val, count = 0; b < end; ) | |
251 | { | |
252 | for (e = b; (*e != '\0'); e++); | |
253 | if (e != b) | |
10c13ed2 | 254 | { |
7cce0e96 | 255 | ret[count++] = strdupnull(b); |
10c13ed2 | 256 | } |
3d7a244b AS |
257 | b = e + 1; |
258 | } | |
259 | ret[count] = NULL; | |
67411e66 | 260 | free(val); |
3d7a244b | 261 | return ret; |
997358a6 MW |
262 | } |
263 | ||
264 | ||
265 | /* | |
266 | * assigns an argument value to a struct field | |
267 | */ | |
10c13ed2 AS |
268 | bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base, |
269 | bool *assigned) | |
997358a6 | 270 | { |
3d7a244b AS |
271 | char *p = base + token_info[token].offset; |
272 | const char **list = token_info[token].list; | |
997358a6 | 273 | |
3d7a244b | 274 | int index = -1; /* used for enumeration arguments */ |
997358a6 | 275 | |
f82365ad | 276 | seen_t *seen = (seen_t*)base; /* seen flags are at the top of the struct */ |
997358a6 | 277 | |
3d7a244b | 278 | *assigned = FALSE; |
997358a6 | 279 | |
163b2273 | 280 | DBG3(DBG_APP, " %s=%s", kw->entry->name, kw->value); |
997358a6 | 281 | |
f82365ad | 282 | if (*seen & SEEN_KW(token, first)) |
997358a6 | 283 | { |
163b2273 | 284 | DBG1(DBG_APP, "# duplicate '%s' option", kw->entry->name); |
997358a6 | 285 | return FALSE; |
997358a6 | 286 | } |
997358a6 | 287 | |
3d7a244b | 288 | /* set flag that this argument has been seen */ |
f82365ad | 289 | *seen |= SEEN_KW(token, first); |
997358a6 | 290 | |
3d7a244b AS |
291 | /* is there a keyword list? */ |
292 | if (list != NULL && token_info[token].type != ARG_LST) | |
997358a6 | 293 | { |
3d7a244b | 294 | bool match = FALSE; |
997358a6 | 295 | |
3d7a244b | 296 | while (*list != NULL && !match) |
997358a6 | 297 | { |
3d7a244b AS |
298 | index++; |
299 | match = streq(kw->value, *list++); | |
997358a6 | 300 | } |
3d7a244b | 301 | if (!match) |
997358a6 | 302 | { |
163b2273 | 303 | DBG1(DBG_APP, "# bad value: %s=%s", kw->entry->name, kw->value); |
3d7a244b | 304 | return FALSE; |
997358a6 | 305 | } |
997358a6 | 306 | } |
997358a6 | 307 | |
3d7a244b AS |
308 | switch (token_info[token].type) |
309 | { | |
310 | case ARG_NONE: | |
163b2273 | 311 | DBG1(DBG_APP, "# option '%s' not supported yet", kw->entry->name); |
3d7a244b AS |
312 | return FALSE; |
313 | case ARG_ENUM: | |
314 | { | |
3d7a244b AS |
315 | if (index < 0) |
316 | { | |
163b2273 TB |
317 | DBG1(DBG_APP, "# bad enumeration value: %s=%s (%d)", |
318 | kw->entry->name, kw->value, index); | |
3d7a244b AS |
319 | return FALSE; |
320 | } | |
5533a889 TB |
321 | |
322 | if (token_info[token].list == LST_bool) | |
323 | { | |
324 | bool *b = (bool *)p; | |
325 | *b = (index > 0); | |
326 | } | |
327 | else | |
328 | { | |
329 | int *i = (int *)p; | |
330 | *i = index; | |
331 | } | |
3d7a244b | 332 | } |
997358a6 MW |
333 | break; |
334 | ||
3d7a244b | 335 | case ARG_UINT: |
997358a6 | 336 | { |
3d7a244b | 337 | char *endptr; |
7daf5226 | 338 | u_int *u = (u_int *)p; |
3d7a244b AS |
339 | |
340 | *u = strtoul(kw->value, &endptr, 10); | |
341 | ||
342 | if (*endptr != '\0') | |
343 | { | |
163b2273 TB |
344 | DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name, |
345 | kw->value); | |
3d7a244b AS |
346 | return FALSE; |
347 | } | |
997358a6 | 348 | } |
3d7a244b AS |
349 | break; |
350 | case ARG_ULNG: | |
351 | case ARG_PCNT: | |
997358a6 | 352 | { |
3d7a244b AS |
353 | char *endptr; |
354 | unsigned long *l = (unsigned long *)p; | |
355 | ||
356 | *l = strtoul(kw->value, &endptr, 10); | |
357 | ||
358 | if (token_info[token].type == ARG_ULNG) | |
359 | { | |
360 | if (*endptr != '\0') | |
361 | { | |
163b2273 TB |
362 | DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name, |
363 | kw->value); | |
3d7a244b AS |
364 | return FALSE; |
365 | } | |
366 | } | |
367 | else | |
368 | { | |
369 | if ((*endptr != '%') || (endptr[1] != '\0') || endptr == kw->value) | |
370 | { | |
163b2273 TB |
371 | DBG1(DBG_APP, "# bad percent value: %s=%s", kw->entry->name, |
372 | kw->value); | |
3d7a244b AS |
373 | return FALSE; |
374 | } | |
375 | } | |
376 | ||
997358a6 | 377 | } |
3d7a244b | 378 | break; |
9c7faa86 TB |
379 | case ARG_ULLI: |
380 | { | |
381 | char *endptr; | |
382 | unsigned long long *ll = (unsigned long long *)p; | |
383 | ||
384 | *ll = strtoull(kw->value, &endptr, 10); | |
385 | ||
386 | if (*endptr != '\0') | |
387 | { | |
163b2273 TB |
388 | DBG1(DBG_APP, "# bad integer value: %s=%s", kw->entry->name, |
389 | kw->value); | |
9c7faa86 TB |
390 | return FALSE; |
391 | } | |
392 | } | |
393 | break; | |
3d7a244b | 394 | case ARG_TIME: |
997358a6 | 395 | { |
3d7a244b AS |
396 | char *endptr; |
397 | time_t *t = (time_t *)p; | |
398 | ||
399 | *t = strtoul(kw->value, &endptr, 10); | |
400 | ||
401 | /* time in seconds? */ | |
402 | if (*endptr == '\0' || (*endptr == 's' && endptr[1] == '\0')) | |
10c13ed2 | 403 | { |
3d7a244b | 404 | break; |
10c13ed2 | 405 | } |
3d7a244b AS |
406 | if (endptr[1] == '\0') |
407 | { | |
408 | if (*endptr == 'm') /* time in minutes? */ | |
409 | { | |
410 | *t *= 60; | |
411 | break; | |
412 | } | |
413 | if (*endptr == 'h') /* time in hours? */ | |
414 | { | |
415 | *t *= 3600; | |
416 | break; | |
417 | } | |
418 | if (*endptr == 'd') /* time in days? */ | |
419 | { | |
420 | *t *= 3600*24; | |
421 | break; | |
422 | } | |
423 | } | |
163b2273 TB |
424 | DBG1(DBG_APP, "# bad duration value: %s=%s", kw->entry->name, |
425 | kw->value); | |
3d7a244b | 426 | return FALSE; |
997358a6 | 427 | } |
3d7a244b AS |
428 | case ARG_STR: |
429 | { | |
430 | char **cp = (char **)p; | |
997358a6 | 431 | |
3d7a244b AS |
432 | /* free any existing string */ |
433 | free(*cp); | |
997358a6 | 434 | |
3d7a244b | 435 | /* assign the new string */ |
7cce0e96 | 436 | *cp = strdupnull(kw->value); |
3d7a244b AS |
437 | } |
438 | break; | |
439 | case ARG_LST: | |
997358a6 | 440 | { |
3d7a244b AS |
441 | char ***listp = (char ***)p; |
442 | ||
443 | /* free any existing list */ | |
444 | if (*listp != NULL) | |
10c13ed2 | 445 | { |
3d7a244b | 446 | free_list(*listp); |
10c13ed2 | 447 | } |
3d7a244b AS |
448 | /* create a new list and assign values */ |
449 | *listp = new_list(kw->value); | |
450 | ||
451 | /* is there a keyword list? */ | |
452 | if (list != NULL) | |
453 | { | |
454 | char ** lst; | |
455 | ||
7daf5226 | 456 | for (lst = *listp; lst && *lst; lst++) |
3d7a244b AS |
457 | { |
458 | bool match = FALSE; | |
459 | ||
460 | list = token_info[token].list; | |
7daf5226 | 461 | |
3d7a244b AS |
462 | while (*list != NULL && !match) |
463 | { | |
464 | match = streq(*lst, *list++); | |
465 | } | |
466 | if (!match) | |
467 | { | |
163b2273 TB |
468 | DBG1(DBG_APP, "# bad value: %s=%s", |
469 | kw->entry->name, *lst); | |
3d7a244b AS |
470 | return FALSE; |
471 | } | |
472 | } | |
473 | } | |
997358a6 | 474 | } |
1c004beb | 475 | /* fall through */ |
3d7a244b AS |
476 | default: |
477 | return TRUE; | |
997358a6 | 478 | } |
997358a6 | 479 | |
3d7a244b AS |
480 | *assigned = TRUE; |
481 | return TRUE; | |
997358a6 MW |
482 | } |
483 | ||
484 | /* | |
485 | * frees all dynamically allocated arguments in a struct | |
486 | */ | |
10c13ed2 | 487 | void free_args(kw_token_t first, kw_token_t last, char *base) |
997358a6 | 488 | { |
3d7a244b | 489 | kw_token_t token; |
997358a6 | 490 | |
3d7a244b | 491 | for (token = first; token <= last; token++) |
997358a6 | 492 | { |
3d7a244b | 493 | char *p = base + token_info[token].offset; |
997358a6 | 494 | |
3d7a244b | 495 | switch (token_info[token].type) |
997358a6 | 496 | { |
3d7a244b AS |
497 | case ARG_STR: |
498 | { | |
499 | char **cp = (char **)p; | |
500 | ||
501 | free(*cp); | |
502 | *cp = NULL; | |
503 | } | |
504 | break; | |
505 | case ARG_LST: | |
506 | { | |
507 | char ***listp = (char ***)p; | |
508 | ||
509 | if (*listp != NULL) | |
510 | { | |
511 | free_list(*listp); | |
512 | *listp = NULL; | |
513 | } | |
514 | } | |
515 | break; | |
516 | default: | |
517 | break; | |
518 | } | |
997358a6 | 519 | } |
997358a6 MW |
520 | } |
521 | ||
522 | /* | |
523 | * clone all dynamically allocated arguments in a struct | |
524 | */ | |
10c13ed2 | 525 | void clone_args(kw_token_t first, kw_token_t last, char *base1, char *base2) |
997358a6 | 526 | { |
3d7a244b | 527 | kw_token_t token; |
997358a6 | 528 | |
3d7a244b | 529 | for (token = first; token <= last; token++) |
997358a6 | 530 | { |
3d7a244b AS |
531 | if (token_info[token].type == ARG_STR) |
532 | { | |
533 | char **cp1 = (char **)(base1 + token_info[token].offset); | |
534 | char **cp2 = (char **)(base2 + token_info[token].offset); | |
997358a6 | 535 | |
7cce0e96 | 536 | *cp1 = strdupnull(*cp2); |
3d7a244b | 537 | } |
997358a6 | 538 | } |
997358a6 MW |
539 | } |
540 | ||
10c13ed2 | 541 | static bool cmp_list(char **list1, char **list2) |
997358a6 | 542 | { |
3d7a244b | 543 | if ((list1 == NULL) && (list2 == NULL)) |
10c13ed2 | 544 | { |
3d7a244b | 545 | return TRUE; |
10c13ed2 | 546 | } |
3d7a244b | 547 | if ((list1 == NULL) || (list2 == NULL)) |
10c13ed2 | 548 | { |
3d7a244b | 549 | return FALSE; |
10c13ed2 | 550 | } |
997358a6 | 551 | |
3d7a244b AS |
552 | for ( ; *list1 && *list2; list1++, list2++) |
553 | { | |
554 | if (strcmp(*list1,*list2) != 0) | |
10c13ed2 | 555 | { |
3d7a244b | 556 | return FALSE; |
10c13ed2 | 557 | } |
3d7a244b | 558 | } |
997358a6 | 559 | |
3d7a244b | 560 | if ((*list1 != NULL) || (*list2 != NULL)) |
10c13ed2 | 561 | { |
3d7a244b | 562 | return FALSE; |
10c13ed2 | 563 | } |
997358a6 | 564 | |
3d7a244b | 565 | return TRUE; |
997358a6 MW |
566 | } |
567 | ||
568 | /* | |
569 | * compare all arguments in a struct | |
570 | */ | |
10c13ed2 | 571 | bool cmp_args(kw_token_t first, kw_token_t last, char *base1, char *base2) |
997358a6 | 572 | { |
3d7a244b | 573 | kw_token_t token; |
997358a6 | 574 | |
3d7a244b | 575 | for (token = first; token <= last; token++) |
997358a6 | 576 | { |
3d7a244b AS |
577 | char *p1 = base1 + token_info[token].offset; |
578 | char *p2 = base2 + token_info[token].offset; | |
579 | ||
580 | switch (token_info[token].type) | |
581 | { | |
582 | case ARG_ENUM: | |
10c13ed2 AS |
583 | if (token_info[token].list == LST_bool) |
584 | { | |
585 | bool *b1 = (bool *)p1; | |
586 | bool *b2 = (bool *)p2; | |
587 | ||
588 | if (*b1 != *b2) | |
589 | { | |
590 | return FALSE; | |
591 | } | |
592 | } | |
593 | else | |
3d7a244b AS |
594 | { |
595 | int *i1 = (int *)p1; | |
596 | int *i2 = (int *)p2; | |
597 | ||
598 | if (*i1 != *i2) | |
10c13ed2 | 599 | { |
3d7a244b | 600 | return FALSE; |
10c13ed2 | 601 | } |
3d7a244b AS |
602 | } |
603 | break; | |
604 | case ARG_UINT: | |
605 | { | |
606 | u_int *u1 = (u_int *)p1; | |
607 | u_int *u2 = (u_int *)p2; | |
608 | ||
609 | if (*u1 != *u2) | |
10c13ed2 | 610 | { |
3d7a244b | 611 | return FALSE; |
10c13ed2 | 612 | } |
3d7a244b AS |
613 | } |
614 | break; | |
615 | case ARG_ULNG: | |
616 | case ARG_PCNT: | |
617 | { | |
618 | unsigned long *l1 = (unsigned long *)p1; | |
619 | unsigned long *l2 = (unsigned long *)p2; | |
620 | ||
621 | if (*l1 != *l2) | |
10c13ed2 | 622 | { |
3d7a244b | 623 | return FALSE; |
10c13ed2 | 624 | } |
3d7a244b AS |
625 | } |
626 | break; | |
9c7faa86 TB |
627 | case ARG_ULLI: |
628 | { | |
629 | unsigned long long *ll1 = (unsigned long long *)p1; | |
630 | unsigned long long *ll2 = (unsigned long long *)p2; | |
631 | ||
632 | if (*ll1 != *ll2) | |
633 | { | |
634 | return FALSE; | |
635 | } | |
636 | } | |
637 | break; | |
3d7a244b AS |
638 | case ARG_TIME: |
639 | { | |
640 | time_t *t1 = (time_t *)p1; | |
641 | time_t *t2 = (time_t *)p2; | |
642 | ||
643 | if (*t1 != *t2) | |
10c13ed2 | 644 | { |
3d7a244b | 645 | return FALSE; |
10c13ed2 | 646 | } |
3d7a244b AS |
647 | } |
648 | break; | |
649 | case ARG_STR: | |
650 | { | |
651 | char **cp1 = (char **)p1; | |
652 | char **cp2 = (char **)p2; | |
653 | ||
654 | if (*cp1 == NULL && *cp2 == NULL) | |
10c13ed2 | 655 | { |
3d7a244b | 656 | break; |
10c13ed2 | 657 | } |
3d7a244b | 658 | if (*cp1 == NULL || *cp2 == NULL || strcmp(*cp1, *cp2) != 0) |
10c13ed2 | 659 | { |
3d7a244b | 660 | return FALSE; |
10c13ed2 | 661 | } |
3d7a244b AS |
662 | } |
663 | break; | |
664 | case ARG_LST: | |
665 | { | |
666 | char ***listp1 = (char ***)p1; | |
667 | char ***listp2 = (char ***)p2; | |
668 | ||
669 | if (!cmp_list(*listp1, *listp2)) | |
10c13ed2 | 670 | { |
3d7a244b | 671 | return FALSE; |
10c13ed2 | 672 | } |
3d7a244b AS |
673 | } |
674 | break; | |
675 | default: | |
676 | break; | |
677 | } | |
997358a6 | 678 | } |
3d7a244b | 679 | return TRUE; |
997358a6 | 680 | } |