aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-10-20 11:25:01 +0900
committerMartin Schanzenbach <schanzen@gnunet.org>2022-10-20 11:25:01 +0900
commit03c7d8ec09d7e294bacd1aa1e5e61692d686629c (patch)
tree5f175efa6d5e6da486456fca420220eab34175b8 /src/namestore
parente1bf9b2b29bbc8112656e0cfbd36b69ab5e3ab49 (diff)
downloadgnunet-03c7d8ec09d7e294bacd1aa1e5e61692d686629c.tar.gz
gnunet-03c7d8ec09d7e294bacd1aa1e5e61692d686629c.zip
-cleanup and make zonefile parsing more robust
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/example_zonefile2
-rw-r--r--src/namestore/gnunet-namestore-zonefile.c191
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
3example.com. IN SOA ns.example.com. username.example.com. ( 2020091025 ; A comment 3example.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
19mail IN A 192.0.2.3 ; IPv4 address for mail.example.com 20mail IN A 192.0.2.3 ; IPv4 address for mail.example.com
20mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com 21mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com
21mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com 22mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com
23
22mail3 IN TXT "This is ; quoted" ; A quoted comment separator 24mail3 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 */
46static struct GNUNET_GNSRECORD_Data rd[MAX_RECORDS_PER_NAME];
47
48/**
49 * Number of records for currently parsed set
50 */
51static 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 */
43static char *res; 66static char *res;
44 67
68/**
69 * Statistics, how many published record sets
70 */
71static unsigned int published_sets = 0;
72
73/**
74 * Statistics, how many records published in aggregate
75 */
76static 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
203static int
204parse_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
225static int
226parse_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)
181static void 255static void
182parse (void *cls) 256parse (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 }