Browse code

dns: TXT records support

- support for TXT lookups, both single and multiple strings are
supported.

Andrei Pelinescu-Onciul authored on 30/03/2009 18:40:23
Showing 2 changed files
... ...
@@ -456,6 +456,73 @@ error:
456 456
 
457 457
 
458 458
 
459
+/** parses a TXT record into a txt_rdata structure.
460
+ *   @param msg   - pointer to the dns message
461
+ *   @param end   - pointer to the end of the record (rdata end)
462
+ *   @param rdata - pointer  to the rdata part of the txt answer
463
+ * returns 0 on error, or a dyn. alloc'ed txt_rdata structure */
464
+/*  TXT rdata format:
465
+ *
466
+ * one or several character strings:
467
+ *  01234567
468
+ * +--------------------+
469
+ * | len    | string   / ...
470
+ * |------------------+
471
+ */
472
+static struct txt_rdata* dns_txt_parser(unsigned char* msg, unsigned char* end,
473
+										unsigned char* rdata)
474
+{
475
+	struct txt_rdata* txt;
476
+	int len, n, i;
477
+	int str_size;
478
+	unsigned char* p;
479
+	unsigned char* st;
480
+	
481
+	txt=0;
482
+	if (unlikely((rdata+1)>end)) goto error;
483
+	n=0;
484
+	str_size=0;
485
+	/* count the number of strings */
486
+	p=rdata;
487
+	do{
488
+		len=*p;
489
+		p+=len+1;
490
+		str_size+=len+1; /* 1 for the term. 0 */
491
+		if (unlikely(p>end)) goto error;
492
+		n++;
493
+	}while(p<end);
494
+	/* alloc sizeof struct + space for the dns_cstr array + space for
495
+	   the strings */
496
+	txt=local_malloc(sizeof(struct txt_rdata) +(n-1)*sizeof(struct dns_cstr)+
497
+						str_size);
498
+	if(unlikely(txt==0)){
499
+		LOG(L_ERR, "ERROR: dns_txt_parser: out of memory\n");
500
+		goto error;
501
+	}
502
+	/* string table */
503
+	st=(unsigned char*)txt+sizeof(struct txt_rdata) +
504
+		(n-1)*sizeof(struct dns_cstr);
505
+	txt->cstr_no=n;
506
+	txt->tslen=str_size;
507
+	/* fill the structure */
508
+	p=rdata;
509
+	for (i=0; i<n; i++){
510
+		len=*p;
511
+		memcpy(st, p+1, len);
512
+		st[len]=0;
513
+		txt->txt[i].cstr_len=len;
514
+		txt->txt[i].cstr=(char*)st;
515
+		st+=len+1;
516
+		p+=len+1;
517
+	}
518
+	return txt;
519
+error:
520
+	if (txt) local_free(txt);
521
+	return 0;
522
+}
523
+
524
+
525
+
459 526
 /* frees completely a struct rdata list */
460 527
 void free_rdata_list(struct rdata* head)
461 528
 {
... ...
@@ -689,6 +756,12 @@ again:
689 689
 				*last=rd;
690 690
 				last=&(rd->next);
691 691
 				break;
692
+			case T_TXT:
693
+				rd->rdata= dns_txt_parser(buff.buff, p+rdlength, p);
694
+				if (rd->rdata==0) goto error_parse;
695
+				*last=rd;
696
+				last=&(rd->next);
697
+				break;
692 698
 			default:
693 699
 				LOG(L_ERR, "WARNING: get_record: unknown type %d\n", rtype);
694 700
 				rd->rdata=0;
... ...
@@ -152,6 +152,24 @@ struct cname_rdata {
152 152
 /* real size of the structure */
153 153
 #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata)+(s).name_len)
154 154
 
155
+/* dns character-string */
156
+struct dns_cstr{
157
+	char* cstr; /* pointer to null term. string */
158
+	unsigned char cstr_len;
159
+};
160
+
161
+/* txt rec. struct */
162
+struct txt_rdata {
163
+	unsigned short cstr_no; /* number of strings */
164
+	unsigned short tslen; /* total strings table len */
165
+	struct dns_cstr txt[1]; /* at least 1 */
166
+	/* all txt[*].cstr point inside a string table at the end of the struct.*/
167
+};
168
+
169
+#define TXT_RDATA_SIZE(s) \
170
+	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
171
+	 	(s).tslen)
172
+
155 173
 
156 174
 #ifdef HAVE_RESOLV_RES
157 175
 int match_search_list(const struct __res_state* res, char* name);