diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-10-20 11:25:01 +0900 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-10-20 11:25:01 +0900 |
commit | 03c7d8ec09d7e294bacd1aa1e5e61692d686629c (patch) | |
tree | 5f175efa6d5e6da486456fca420220eab34175b8 /src/namestore | |
parent | e1bf9b2b29bbc8112656e0cfbd36b69ab5e3ab49 (diff) | |
download | gnunet-03c7d8ec09d7e294bacd1aa1e5e61692d686629c.tar.gz gnunet-03c7d8ec09d7e294bacd1aa1e5e61692d686629c.zip |
-cleanup and make zonefile parsing more robust
Diffstat (limited to 'src/namestore')
-rw-r--r-- | src/namestore/example_zonefile | 2 | ||||
-rw-r--r-- | src/namestore/gnunet-namestore-zonefile.c | 191 |
2 files changed, 146 insertions, 47 deletions
diff --git a/src/namestore/example_zonefile b/src/namestore/example_zonefile index d75adcbde..0564368e8 100644 --- a/src/namestore/example_zonefile +++ b/src/namestore/example_zonefile | |||
@@ -2,6 +2,7 @@ $ORIGIN example.com. ; designates the start of this zone file in the namespa | |||
2 | $TTL 3600 ; default expiration time (in seconds) of all RRs without their own TTL value | 2 | $TTL 3600 ; default expiration time (in seconds) of all RRs without their own TTL value |
3 | example.com. IN SOA ns.example.com. username.example.com. ( 2020091025 ; A comment | 3 | example.com. IN SOA ns.example.com. username.example.com. ( 2020091025 ; A comment |
4 | 7200 ; Comment | 4 | 7200 ; Comment |
5 | ; empty line on purpose | ||
5 | 3600 | 6 | 3600 |
6 | 1209600 | 7 | 1209600 |
7 | 3600 ) | 8 | 3600 ) |
@@ -19,4 +20,5 @@ wwwtest IN CNAME www ; wwwtest.example.com is another | |||
19 | mail IN A 192.0.2.3 ; IPv4 address for mail.example.com | 20 | mail IN A 192.0.2.3 ; IPv4 address for mail.example.com |
20 | mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com | 21 | mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com |
21 | mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com | 22 | mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com |
23 | |||
22 | mail3 IN TXT "This is ; quoted" ; A quoted comment separator | 24 | mail3 IN TXT "This is ; quoted" ; A quoted comment separator |
diff --git a/src/namestore/gnunet-namestore-zonefile.c b/src/namestore/gnunet-namestore-zonefile.c index 22ae4a9f5..733cdb380 100644 --- a/src/namestore/gnunet-namestore-zonefile.c +++ b/src/namestore/gnunet-namestore-zonefile.c | |||
@@ -27,6 +27,29 @@ | |||
27 | #include <gnunet_util_lib.h> | 27 | #include <gnunet_util_lib.h> |
28 | #include <gnunet_namestore_plugin.h> | 28 | #include <gnunet_namestore_plugin.h> |
29 | 29 | ||
30 | #define MAX_RECORDS_PER_NAME 50 | ||
31 | |||
32 | /** | ||
33 | * Maximum length of a zonefile line | ||
34 | */ | ||
35 | #define MAX_ZONEFILE_LINE_LEN 4096 | ||
36 | |||
37 | /** | ||
38 | * FIXME: Soft limit this? | ||
39 | */ | ||
40 | #define MAX_ZONEFILE_RECORD_DATA_LEN 2048 | ||
41 | |||
42 | /** | ||
43 | * The record data under a single label. Reused. | ||
44 | * Hard limit. | ||
45 | */ | ||
46 | static struct GNUNET_GNSRECORD_Data rd[MAX_RECORDS_PER_NAME]; | ||
47 | |||
48 | /** | ||
49 | * Number of records for currently parsed set | ||
50 | */ | ||
51 | static unsigned int rd_count = 0; | ||
52 | |||
30 | /** | 53 | /** |
31 | * Return code | 54 | * Return code |
32 | */ | 55 | */ |
@@ -42,6 +65,16 @@ static char *ego_name = NULL; | |||
42 | */ | 65 | */ |
43 | static char *res; | 66 | static char *res; |
44 | 67 | ||
68 | /** | ||
69 | * Statistics, how many published record sets | ||
70 | */ | ||
71 | static unsigned int published_sets = 0; | ||
72 | |||
73 | /** | ||
74 | * Statistics, how many records published in aggregate | ||
75 | */ | ||
76 | static unsigned int published_records = 0; | ||
77 | |||
45 | 78 | ||
46 | /** | 79 | /** |
47 | * Handle to identity lookup. | 80 | * Handle to identity lookup. |
@@ -84,6 +117,11 @@ do_shutdown (void *cls) | |||
84 | GNUNET_NAMESTORE_cancel (ns_qe); | 117 | GNUNET_NAMESTORE_cancel (ns_qe); |
85 | if (NULL != ns) | 118 | if (NULL != ns) |
86 | GNUNET_NAMESTORE_disconnect (ns); | 119 | GNUNET_NAMESTORE_disconnect (ns); |
120 | for (int i = 0; i < rd_count; i++) | ||
121 | { | ||
122 | void *rd_ptr = (void*) rd[i].data; | ||
123 | GNUNET_free (rd_ptr); | ||
124 | } | ||
87 | 125 | ||
88 | } | 126 | } |
89 | 127 | ||
@@ -162,6 +200,42 @@ next_token (char *token) | |||
162 | return next; | 200 | return next; |
163 | } | 201 | } |
164 | 202 | ||
203 | static int | ||
204 | parse_ttl (char *token, struct GNUNET_TIME_Relative *ttl) | ||
205 | { | ||
206 | char *next; | ||
207 | unsigned int ttl_tmp; | ||
208 | |||
209 | next = strchr (token, ';'); | ||
210 | if (NULL != next) | ||
211 | next[0] = '\0'; | ||
212 | next = strchr (token, ' '); | ||
213 | if (NULL != next) | ||
214 | next[0] = '\0'; | ||
215 | if (1 != sscanf (token, "%u", &ttl_tmp)) | ||
216 | { | ||
217 | fprintf (stderr, "Unable to parse TTL `%s'\n", token); | ||
218 | return GNUNET_SYSERR; | ||
219 | } | ||
220 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TTL is: %u\n", ttl_tmp); | ||
221 | ttl->rel_value_us = ttl_tmp * 1000 * 1000; | ||
222 | return GNUNET_OK; | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | parse_origin (char *token, char *origin) | ||
227 | { | ||
228 | char *next; | ||
229 | next = strchr (token, ';'); | ||
230 | if (NULL != next) | ||
231 | next[0] = '\0'; | ||
232 | next = strchr (token, ' '); | ||
233 | if (NULL != next) | ||
234 | next[0] = '\0'; | ||
235 | strcpy (origin, token); | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Origin is: %s\n", origin); | ||
237 | } | ||
238 | |||
165 | /** | 239 | /** |
166 | * Main function that will be run. | 240 | * Main function that will be run. |
167 | * | 241 | * |
@@ -181,40 +255,38 @@ next_token (char *token) | |||
181 | static void | 255 | static void |
182 | parse (void *cls) | 256 | parse (void *cls) |
183 | { | 257 | { |
184 | static struct GNUNET_GNSRECORD_Data rd[50]; // Let's hope we do not need more | 258 | char buf[MAX_ZONEFILE_LINE_LEN]; |
185 | char buf[5000]; /* buffer to hold entire line (adjust MAXC as needed) */ | 259 | char payload[MAX_ZONEFILE_RECORD_DATA_LEN]; |
186 | char payload[5000]; | ||
187 | char *next; | 260 | char *next; |
188 | char *token; | 261 | char *token; |
189 | char *payload_pos; | 262 | char *payload_pos; |
190 | char origin[255]; | 263 | char origin[GNUNET_DNSPARSER_MAX_NAME_LENGTH]; |
191 | static char lastname[255]; | 264 | static char lastname[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; |
192 | char newname[255]; | 265 | char newname[GNUNET_DNSPARSER_MAX_LABEL_LENGTH]; |
193 | void *data; | 266 | void *data; |
194 | size_t data_size; | 267 | size_t data_size; |
195 | struct GNUNET_TIME_Relative ttl; | 268 | struct GNUNET_TIME_Relative ttl; |
196 | int origin_line = 0; | 269 | int origin_line = 0; |
197 | int ttl_line = 0; | 270 | int ttl_line = 0; |
198 | int type; | 271 | int type; |
199 | static unsigned int rd_count = 0; | ||
200 | uint32_t ttl_tmp; | ||
201 | int name_changed = 0; | 272 | int name_changed = 0; |
202 | int bracket_unclosed = 0; | 273 | int bracket_unclosed = 0; |
203 | int quoted = 0; | 274 | int quoted = 0; |
204 | static unsigned int published_sets = 0; | ||
205 | static unsigned int published_records = 0; | ||
206 | 275 | ||
207 | /* use filename provided as 1st argument (stdin by default) */ | 276 | /* use filename provided as 1st argument (stdin by default) */ |
208 | int i = 0; | 277 | int i = 0; |
209 | while (res = fgets (buf, 5000, stdin)) /* read each line of input */ | 278 | while (res = fgets (buf, sizeof(buf), stdin)) /* read each line of input */ |
210 | { | 279 | { |
211 | i++; | 280 | i++; |
212 | origin_line = 0; | 281 | origin_line = 0; |
213 | ttl_line = 0; | 282 | ttl_line = 0; |
214 | token = trim (buf); | 283 | token = trim (buf); |
215 | printf ("Trimmed line (bracket %s): `%s'\n", | 284 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
216 | (bracket_unclosed > 0) ? "unclosed" : "closed", | 285 | "Trimmed line (bracket %s): `%s'\n", |
217 | token); | 286 | (bracket_unclosed > 0) ? "unclosed" : "closed", |
287 | token); | ||
288 | if ((1 == strlen (token)) && (' ' == *token)) | ||
289 | continue; // I guess we can safely ignore blank lines | ||
218 | if (bracket_unclosed == 0) | 290 | if (bracket_unclosed == 0) |
219 | { | 291 | { |
220 | /* Payload is already parsed */ | 292 | /* Payload is already parsed */ |
@@ -240,22 +312,31 @@ parse (void *cls) | |||
240 | } | 312 | } |
241 | else | 313 | else |
242 | { | 314 | { |
243 | printf ("TOKEN: %s\n", token); | ||
244 | if (0 == strcmp (token, "IN")) // Inherit name from before | 315 | if (0 == strcmp (token, "IN")) // Inherit name from before |
245 | { | 316 | { |
246 | printf ("Old name: %s\n", lastname); | 317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
318 | "Old name: %s\n", lastname); | ||
247 | strcpy (newname, lastname); | 319 | strcpy (newname, lastname); |
248 | token[strlen (token)] = ' '; | 320 | token[strlen (token)] = ' '; |
249 | } | 321 | } |
250 | else if (token[strlen (token) - 1] != '.') // no fqdn | 322 | else if (token[strlen (token) - 1] != '.') // no fqdn |
251 | { | 323 | { |
252 | printf ("New name: %s\n", token); | 324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: %s\n", token); |
325 | if (GNUNET_DNSPARSER_MAX_LABEL_LENGTH < strlen (token)) | ||
326 | { | ||
327 | fprintf (stderr, | ||
328 | _ ("Name `%s' is too long\n"), | ||
329 | token); | ||
330 | ret = 1; | ||
331 | GNUNET_SCHEDULER_shutdown (); | ||
332 | return; | ||
333 | } | ||
253 | strcpy (newname, token); | 334 | strcpy (newname, token); |
254 | token = next_token (next); | 335 | token = next_token (next); |
255 | } | 336 | } |
256 | else if (0 == strcmp (token, origin)) | 337 | else if (0 == strcmp (token, origin)) |
257 | { | 338 | { |
258 | printf ("New name: @\n"); | 339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: @\n"); |
259 | strcpy (newname, "@"); | 340 | strcpy (newname, "@"); |
260 | token = next_token (next); | 341 | token = next_token (next); |
261 | } | 342 | } |
@@ -272,7 +353,16 @@ parse (void *cls) | |||
272 | break; | 353 | break; |
273 | } | 354 | } |
274 | token[strlen (token) - strlen (origin) - 1] = '\0'; | 355 | token[strlen (token) - strlen (origin) - 1] = '\0'; |
275 | printf ("New name: %s\n", token); | 356 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New name: %s\n", token); |
357 | if (GNUNET_DNSPARSER_MAX_LABEL_LENGTH < strlen (token)) | ||
358 | { | ||
359 | fprintf (stderr, | ||
360 | _ ("Name `%s' is too long\n"), | ||
361 | token); | ||
362 | ret = 1; | ||
363 | GNUNET_SCHEDULER_shutdown (); | ||
364 | return; | ||
365 | } | ||
276 | strcpy (newname, token); | 366 | strcpy (newname, token); |
277 | token = next_token (next); | 367 | token = next_token (next); |
278 | } | 368 | } |
@@ -293,45 +383,48 @@ parse (void *cls) | |||
293 | 383 | ||
294 | if (ttl_line) | 384 | if (ttl_line) |
295 | { | 385 | { |
296 | next = strchr (token, ';'); | 386 | if (GNUNET_SYSERR == parse_ttl (token, &ttl)) |
297 | if (NULL != next) | ||
298 | next[0] = '\0'; | ||
299 | next = strchr (token, ' '); | ||
300 | if (NULL != next) | ||
301 | next[0] = '\0'; | ||
302 | if (1 != sscanf (token, "%u", &ttl_tmp)) | ||
303 | { | 387 | { |
304 | fprintf (stderr, "Unable to parse TTL `%s'\n", token); | 388 | ret = 1; |
305 | break; | 389 | GNUNET_SCHEDULER_shutdown (); |
390 | return; | ||
306 | } | 391 | } |
307 | printf ("TTL is: %u\n", ttl_tmp); | ||
308 | ttl.rel_value_us = ttl_tmp * 1000 * 1000; | ||
309 | continue; | 392 | continue; |
310 | } | 393 | } |
311 | if (origin_line) | 394 | if (origin_line) |
312 | { | 395 | { |
313 | next = strchr (token, ';'); | 396 | if (GNUNET_SYSERR == parse_origin (token, origin)) |
314 | if (NULL != next) | 397 | { |
315 | next[0] = '\0'; | 398 | ret = 1; |
316 | next = strchr (token, ' '); | 399 | GNUNET_SCHEDULER_shutdown (); |
317 | if (NULL != next) | 400 | return; |
318 | next[0] = '\0'; | 401 | } |
319 | strcpy (origin, token); | ||
320 | printf ("Origin is: %s\n", origin); | ||
321 | continue; | 402 | continue; |
322 | } | 403 | } |
323 | // This is a record, let's go | 404 | // This is a record, let's go |
405 | if (MAX_RECORDS_PER_NAME == rd_count) | ||
406 | { | ||
407 | fprintf (stderr, | ||
408 | _ ("Only %u records per unique name supported.\n"), | ||
409 | MAX_RECORDS_PER_NAME); | ||
410 | ret = 1; | ||
411 | GNUNET_SCHEDULER_shutdown (); | ||
412 | return; | ||
413 | |||
414 | } | ||
324 | rd[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | 415 | rd[rd_count].flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; |
325 | rd[rd_count].expiration_time = ttl.rel_value_us; | 416 | rd[rd_count].expiration_time = ttl.rel_value_us; |
326 | next = strchr (token, ' '); | 417 | next = strchr (token, ' '); |
327 | if (NULL == next) | 418 | if (NULL == next) |
328 | { | 419 | { |
329 | fprintf (stderr, "Error, last token: %s\n", token); | 420 | fprintf (stderr, "Error, last token: %s\n", token); |
421 | ret = 1; | ||
422 | GNUNET_SCHEDULER_shutdown (); | ||
330 | break; | 423 | break; |
331 | } | 424 | } |
332 | next[0] = '\0'; | 425 | next[0] = '\0'; |
333 | next++; | 426 | next++; |
334 | printf ("class is: %s\n", token); | 427 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "class is: %s\n", token); |
335 | while (*next == ' ') | 428 | while (*next == ' ') |
336 | next++; | 429 | next++; |
337 | token = next; | 430 | token = next; |
@@ -343,7 +436,7 @@ parse (void *cls) | |||
343 | } | 436 | } |
344 | next[0] = '\0'; | 437 | next[0] = '\0'; |
345 | next++; | 438 | next++; |
346 | printf ("type is: %s\n", token); | 439 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "type is: %s\n", token); |
347 | type = GNUNET_GNSRECORD_typename_to_number (token); | 440 | type = GNUNET_GNSRECORD_typename_to_number (token); |
348 | rd[rd_count].record_type = type; | 441 | rd[rd_count].record_type = type; |
349 | while (*next == ' ') | 442 | while (*next == ' ') |
@@ -368,13 +461,12 @@ parse (void *cls) | |||
368 | continue; | 461 | continue; |
369 | } | 462 | } |
370 | *payload_pos = '\0'; | 463 | *payload_pos = '\0'; |
371 | printf ("data is: %s\n\n", payload); | 464 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "data is: %s\n\n", payload); |
372 | if (GNUNET_OK != | 465 | if (GNUNET_OK != |
373 | GNUNET_GNSRECORD_string_to_value (type, payload, | 466 | GNUNET_GNSRECORD_string_to_value (type, payload, |
374 | &data, | 467 | &data, |
375 | &data_size)) | 468 | &data_size)) |
376 | { | 469 | { |
377 | // FIXME free rd | ||
378 | fprintf (stderr, | 470 | fprintf (stderr, |
379 | _ ("Data `%s' invalid\n"), | 471 | _ ("Data `%s' invalid\n"), |
380 | payload); | 472 | payload); |
@@ -399,13 +491,18 @@ parse (void *cls) | |||
399 | NULL); | 491 | NULL); |
400 | published_sets++; | 492 | published_sets++; |
401 | published_records += rd_count; | 493 | published_records += rd_count; |
402 | // FIXME cleanup rd | 494 | for (int i = 0; i < rd_count; i++) |
495 | { | ||
496 | data = (void*) rd[i].data; | ||
497 | GNUNET_free (data); | ||
498 | } | ||
403 | if (name_changed) | 499 | if (name_changed) |
404 | { | 500 | { |
405 | rd[0] = rd[rd_count]; // recover last rd parsed. | 501 | rd[0] = rd[rd_count]; // recover last rd parsed. |
406 | rd_count = 1; | 502 | rd_count = 1; |
407 | strcpy (lastname, newname); | 503 | strcpy (lastname, newname); |
408 | } else | 504 | } |
505 | else | ||
409 | rd_count = 0; | 506 | rd_count = 0; |
410 | return; | 507 | return; |
411 | } | 508 | } |