Browse code

dns: EBL records support

- support for EBL records
- dns cache support for EBLs
- dns.delete_ebl rpc added

Andrei Pelinescu-Onciul authored on 31/03/2009 17:07:44
Showing 4 changed files
... ...
@@ -60,6 +60,7 @@ void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
60 60
 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx);
61 61
 void dns_cache_delete_cname(rpc_t* rpc, void* ctx);
62 62
 void dns_cache_delete_txt(rpc_t* rpc, void* ctx);
63
+void dns_cache_delete_ebl(rpc_t* rpc, void* ctx);
63 64
 
64 65
 
65 66
 static const char* dns_cache_mem_info_doc[] = {
... ...
@@ -135,6 +136,11 @@ static const char* dns_cache_delete_txt_doc[] = {
135 136
 	0
136 137
 };
137 138
 
139
+static const char* dns_cache_delete_ebl_doc[] = {
140
+	"deletes an EBL record from the DNS cache",
141
+	0
142
+};
143
+
138 144
 
139 145
 #ifdef USE_DNS_CACHE_STATS
140 146
 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
... ...
@@ -739,6 +745,8 @@ rpc_export_t core_rpc_methods[] = {
739 745
 		dns_cache_delete_cname_doc,  0	},
740 746
 	{"dns.delete_txt",         dns_cache_delete_txt,
741 747
 		dns_cache_delete_txt_doc,  0	},
748
+	{"dns.delete_ebl",         dns_cache_delete_ebl,
749
+		dns_cache_delete_ebl_doc,  0	},
742 750
 #ifdef USE_DNS_CACHE_STATS
743 751
 	{"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
744 752
 		0	},
... ...
@@ -45,6 +45,7 @@
45 45
  *  2008-10-17  fixed srv continue with 0 hostname (when falling back to
46 46
                   aaaa) (andrei)
47 47
  *  2009-03-30  TXT record support, more rpcs (andrei)
48
+ *  2009-03-30  EBL record support (andrei)
48 49
  */
49 50
 
50 51
 #ifdef USE_DNS_CACHE
... ...
@@ -1165,6 +1166,25 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
1165 1166
 				 * just been elimintated */
1166 1167
 			}
1167 1168
 			break;
1169
+		case T_EBL:
1170
+			for(; *p;){
1171
+				if (!rec_matches((*p), type, name)){
1172
+					/* skip this record */
1173
+					p=&(*p)->next; /* advance */
1174
+					continue;
1175
+				}
1176
+				/* padding to char* (because of the char* pointers */
1177
+				size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1178
+						EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1179
+				/* add it to our tmp. lst */
1180
+				*tail=*p;
1181
+				tail=&(*p)->next;
1182
+				/* detach it from the rd list */
1183
+				*p=(*p)->next;
1184
+				/* don't advance p, because the crt. elem. has
1185
+				 * just been elimintated */
1186
+			}
1187
+			break;
1168 1188
 		default:
1169 1189
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1170 1190
 							"supported\n", type);
... ...
@@ -1313,6 +1333,32 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
1313 1333
 				rr=rr->next;
1314 1334
 			}
1315 1335
 			break;
1336
+		case T_EBL:
1337
+			for(l=tmp_lst; l; l=l->next){
1338
+				ttl=FIX_TTL(l->ttl);
1339
+				rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1340
+				max_ttl=MAX(max_ttl, ttl);
1341
+				rr->rdata=(void*)((char*)rr+
1342
+							ROUND_POINTER(sizeof(struct dns_rr)));
1343
+				memcpy(rr->rdata, l->rdata,
1344
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1345
+				/* adjust the string pointers */
1346
+				((struct ebl_rdata*)rr->rdata)->separator=
1347
+					translate_pointer((char*)rr->rdata, (char*)l->rdata,
1348
+								((struct ebl_rdata*)l->rdata)->separator);
1349
+				((struct ebl_rdata*)rr->rdata)->separator=
1350
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
1351
+								((struct ebl_rdata*)l->rdata)->separator);
1352
+				((struct ebl_rdata*)rr->rdata)->apex=
1353
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
1354
+								((struct ebl_rdata*)l->rdata)->apex);
1355
+				rr->next=(void*)((char*)rr+
1356
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1357
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1358
+				tail_rr=&(rr->next);
1359
+				rr=rr->next;
1360
+			}
1361
+			break;
1316 1362
 		default:
1317 1363
 			/* do nothing */
1318 1364
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: create: type %d not "
... ...
@@ -1427,11 +1473,17 @@ found:
1427 1473
 							CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1428 1474
 				break;
1429 1475
 			case T_TXT:
1430
-					/* padding to char* (because of txt[]->cstr*/
1476
+					/* padding to char* (because of txt[]->cstr)*/
1431 1477
 				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1432 1478
 												sizeof(struct dns_rr))+
1433 1479
 							TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1434 1480
 				break;
1481
+			case T_EBL:
1482
+					/* padding to char* (because of char* pointers)*/
1483
+				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1484
+												sizeof(struct dns_rr))+
1485
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1486
+				break;
1435 1487
 			default:
1436 1488
 				LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1437 1489
 							"supported\n", l->type);
... ...
@@ -1571,6 +1623,28 @@ found:
1571 1623
 				rec[r].tail_rr=&(rec[r].rr->next);
1572 1624
 				rec[r].rr=rec[r].rr->next;
1573 1625
 				break;
1626
+			case T_EBL:
1627
+				rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1628
+				rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1629
+				rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1630
+									ROUND_POINTER(sizeof(struct dns_rr)));
1631
+				memcpy(rec[r].rr->rdata, l->rdata,
1632
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1633
+				/* adjust the string pointers */
1634
+				((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1635
+					translate_pointer((char*)rec[r].rr->rdata,
1636
+							(char*)l->rdata,
1637
+							((struct ebl_rdata*)l->rdata)->separator);
1638
+				((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1639
+					translate_pointer((char*)rec[r].rr->rdata,
1640
+							(char*)l->rdata,
1641
+							((struct ebl_rdata*)l->rdata)->apex);
1642
+				rec[r].rr->next=(void*)((char*)rec[r].rr+
1643
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1644
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1645
+				rec[r].tail_rr=&(rec[r].rr->next);
1646
+				rec[r].rr=rec[r].rr->next;
1647
+				break;
1574 1648
 			default:
1575 1649
 				/* do nothing */
1576 1650
 				;
... ...
@@ -3521,6 +3595,10 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
3521 3595
 								((struct txt_rdata*)(rr->rdata))->txt[0].cstr:
3522 3596
 								"");
3523 3597
 							break;
3598
+						case T_EBL:
3599
+							rpc->add(ctx, "ss", "ebl",
3600
+								((struct ebl_rdata*)(rr->rdata))->apex);
3601
+							break;
3524 3602
 						default:
3525 3603
 							rpc->add(ctx, "ss", "unknown", "?");
3526 3604
 					}
... ...
@@ -3550,6 +3628,8 @@ static char *print_type(unsigned short type)
3550 3628
 			return "CNAME";
3551 3629
 		case T_TXT:
3552 3630
 			return "TXT";
3631
+		case T_EBL:
3632
+			return "EBL";
3553 3633
 		default:
3554 3634
 			return "unkown";
3555 3635
 	}
... ...
@@ -3586,6 +3666,8 @@ static int dns_get_type(str* s)
3586 3666
 				return T_SRV;
3587 3667
 			else if (strncasecmp(t, "TXT", len)==0)
3588 3668
 				return T_TXT;
3669
+			else if (strncasecmp(t, "EBL", len)==0)
3670
+				return T_EBL;
3589 3671
 			break;
3590 3672
 		case 5:
3591 3673
 			if (strncasecmp(t, "NAPTR", len)==0)
... ...
@@ -3680,6 +3762,14 @@ void dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
3680 3762
 						((struct txt_rdata*)(rr->rdata))->txt[i].cstr);
3681 3763
 				}
3682 3764
 				break;
3765
+			case T_EBL:
3766
+				rpc->printf(ctx, "%srr position: %d", SPACE_FORMAT,
3767
+							((struct ebl_rdata*)(rr->rdata))->position);
3768
+				rpc->printf(ctx, "%srr separator: %s", SPACE_FORMAT,
3769
+							((struct ebl_rdata*)(rr->rdata))->separator);
3770
+				rpc->printf(ctx, "%srr apex: %s", SPACE_FORMAT,
3771
+							((struct ebl_rdata*)(rr->rdata))->apex);
3772
+				break;
3683 3773
 			default:
3684 3774
 				rpc->printf(ctx, "%sresource record: unknown",
3685 3775
 									SPACE_FORMAT);
... ...
@@ -3779,6 +3869,9 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
3779 3869
 			case T_TXT:
3780 3870
 				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
3781 3871
 				break;
3872
+			case T_EBL:
3873
+				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
3874
+				break;
3782 3875
 			default:
3783 3876
 				LOG(L_ERR, "ERROR: dns_cache_clone_entry: type %d not "
3784 3877
 							"supported\n", e->type);
... ...
@@ -3819,30 +3912,42 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
3819 3912
 		else
3820 3913
 			last_rr = rr;
3821 3914
 
3822
-		if (e->type == T_NAPTR) {
3823
-			/* there are pointers inside the NAPTR rdata stucture */
3824
-			((struct naptr_rdata*)rr->rdata)->flags =
3825
-				translate_pointer((char*)new, (char*)e,
3826
-					((struct naptr_rdata*)rr->rdata)->flags);
3827
-
3828
-			((struct naptr_rdata*)rr->rdata)->services =
3829
-				translate_pointer((char*)new, (char*)e,
3830
-					((struct naptr_rdata*)rr->rdata)->services);
3831
-
3832
-			((struct naptr_rdata*)rr->rdata)->regexp =
3833
-				translate_pointer((char*)new, (char*)e,
3834
-					((struct naptr_rdata*)rr->rdata)->regexp);
3835
-
3836
-			((struct naptr_rdata*)rr->rdata)->repl =
3837
-				translate_pointer((char*)new, (char*)e,
3838
-					((struct naptr_rdata*)rr->rdata)->repl);
3839
-		}else if (e->type == T_TXT){
3840
-			/* there are pointers inside the TXT structure */
3841
-			for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
3842
-				((struct txt_rdata*)rr->rdata)->txt[i].cstr=
3843
-					translate_pointer((char*) new, (char*) e,
3844
-						((struct txt_rdata*)rr->rdata)->txt[i].cstr);
3845
-			}
3915
+		switch(e->type){
3916
+			case T_NAPTR:
3917
+				/* there are pointers inside the NAPTR rdata stucture */
3918
+				((struct naptr_rdata*)rr->rdata)->flags =
3919
+					translate_pointer((char*)new, (char*)e,
3920
+						((struct naptr_rdata*)rr->rdata)->flags);
3921
+
3922
+				((struct naptr_rdata*)rr->rdata)->services =
3923
+					translate_pointer((char*)new, (char*)e,
3924
+						((struct naptr_rdata*)rr->rdata)->services);
3925
+
3926
+				((struct naptr_rdata*)rr->rdata)->regexp =
3927
+					translate_pointer((char*)new, (char*)e,
3928
+						((struct naptr_rdata*)rr->rdata)->regexp);
3929
+
3930
+				((struct naptr_rdata*)rr->rdata)->repl =
3931
+					translate_pointer((char*)new, (char*)e,
3932
+						((struct naptr_rdata*)rr->rdata)->repl);
3933
+				break;
3934
+			case T_TXT:
3935
+				/* there are pointers inside the TXT structure */
3936
+				for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
3937
+					((struct txt_rdata*)rr->rdata)->txt[i].cstr=
3938
+						translate_pointer((char*) new, (char*) e,
3939
+							((struct txt_rdata*)rr->rdata)->txt[i].cstr);
3940
+				}
3941
+				break;
3942
+			case T_EBL:
3943
+				/* there are pointers inside the EBL structure */
3944
+				((struct ebl_rdata*)rr->rdata)->separator =
3945
+					translate_pointer((char*)new, (char*)e,
3946
+							((struct ebl_rdata*)rr->rdata)->separator);
3947
+				((struct ebl_rdata*)rr->rdata)->apex =
3948
+					translate_pointer((char*)new, (char*)e,
3949
+							((struct ebl_rdata*)rr->rdata)->apex);
3950
+				break;
3846 3951
 		}
3847 3952
 	}
3848 3953
 
... ...
@@ -3915,6 +4020,7 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type)
3915 4020
 	case T_CNAME:
3916 4021
 	case T_NAPTR:
3917 4022
 	case T_TXT:
4023
+	case T_EBL:
3918 4024
 		rpc->fault(ctx, 400, "not implemented");
3919 4025
 		return;
3920 4026
 	default:
... ...
@@ -4217,6 +4323,11 @@ void dns_cache_delete_txt(rpc_t* rpc, void* ctx)
4217 4323
 	dns_cache_delete_record(rpc, ctx, T_TXT);
4218 4324
 }
4219 4325
 
4326
+void dns_cache_delete_ebl(rpc_t* rpc, void* ctx)
4327
+{
4328
+	dns_cache_delete_record(rpc, ctx, T_EBL);
4329
+}
4330
+
4220 4331
 
4221 4332
 
4222 4333
 #ifdef DNS_WATCHDOG_SUPPORT
... ...
@@ -527,6 +527,70 @@ error:
527 527
 
528 528
 
529 529
 
530
+/** parses an EBL record into a txt_rdata structure.
531
+ *   @param msg   - pointer to the dns message
532
+ *   @param end   - pointer to the end of the dns message
533
+ *   @param eor   - pointer to the end of the record (rdata end)
534
+ *   @param rdata - pointer  to the rdata part of the txt answer
535
+ * returns 0 on error, or a dyn. alloc'ed txt_rdata structure */
536
+/*  EBL rdata format:
537
+ *  (see http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03)
538
+ * one or several character strings:
539
+ *  01234567
540
+ * +--------+
541
+ * | postion|
542
+ * +-----------+
543
+ * / separator /
544
+ * +-----------+
545
+ * /   apex    /
546
+ * +----------+
547
+ *
548
+ * where separator is a character string ( 8 bit len, followed by len chars)
549
+ * and apex is a domain-name.
550
+ */
551
+static struct ebl_rdata* dns_ebl_parser(unsigned char* msg, unsigned char* end,
552
+										unsigned char* eor,
553
+										unsigned char* rdata)
554
+{
555
+	struct ebl_rdata* ebl;
556
+	int sep_len;
557
+	int apex_len;
558
+	char apex[MAX_DNS_NAME];
559
+	
560
+	ebl=0;
561
+	/* check if len is at least 4 chars (minimum possible):
562
+	     pos (1 byte) +  sep. (min 1 byte) + apex (min. 2 bytes) 
563
+	   and also check if rdata+1 (pos) + 1 (sep. len) + sep_len + 1 is ok*/
564
+	if (unlikely(((rdata+4)>eor)||((rdata+1+1+rdata[1]+2)>eor))) goto error;
565
+	sep_len=rdata[1];
566
+	if (unlikely(dn_expand(msg, end, rdata+1+1+sep_len,
567
+							apex, MAX_DNS_NAME-1)==-1))
568
+		goto error;
569
+	apex_len=strlen(apex);
570
+	/* alloc sizeof struct + space for the 2 null-terminated strings */
571
+	ebl=local_malloc(sizeof(struct ebl_rdata)-1+sep_len+1+apex_len+1);
572
+	if (ebl==0){
573
+		LOG(L_ERR, "ERROR: dns_ebl_parser: out of memory\n");
574
+		goto error;
575
+	}
576
+	ebl->position=rdata[0];
577
+	ebl->separator=&ebl->str_table[0];
578
+	ebl->apex=ebl->separator+sep_len+1;
579
+	ebl->separator_len=sep_len;
580
+	ebl->apex_len=apex_len;
581
+	memcpy(ebl->separator, rdata+2, sep_len);
582
+	ebl->separator[sep_len]=0;
583
+	memcpy(ebl->apex, apex, apex_len);
584
+	ebl->apex[apex_len]=0;
585
+	
586
+	return ebl;
587
+error:
588
+	if (ebl) local_free(ebl);
589
+	return 0;
590
+}
591
+
592
+
593
+
530 594
 /* frees completely a struct rdata list */
531 595
 void free_rdata_list(struct rdata* head)
532 596
 {
... ...
@@ -761,7 +825,13 @@ again:
761 825
 				last=&(rd->next);
762 826
 				break;
763 827
 			case T_TXT:
764
-				rd->rdata= dns_txt_parser(buff.buff, p+rdlength, p);
828
+				rd->rdata= dns_txt_parser(buff.buff, rd_end, p);
829
+				if (rd->rdata==0) goto error_parse;
830
+				*last=rd;
831
+				last=&(rd->next);
832
+				break;
833
+			case T_EBL:
834
+				rd->rdata= dns_ebl_parser(buff.buff, end, rd_end, p);
765 835
 				if (rd->rdata==0) goto error_parse;
766 836
 				*last=rd;
767 837
 				last=&(rd->next);
... ...
@@ -69,6 +69,10 @@
69 69
 #define MAX_DNS_NAME 256
70 70
 #define MAX_DNS_STRING 255
71 71
 
72
+#ifndef T_EBL
73
+/** not official yet - iEnum. */
74
+#define T_EBL 65300
75
+#endif
72 76
 
73 77
 /* get_record flags */
74 78
 #define RES_ONLY_TYPE 1   /* return only the specified type records */
... ...
@@ -170,6 +174,19 @@ struct txt_rdata {
170 174
 	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
171 175
 	 	(s).tslen)
172 176
 
177
+/* ebl rec. struct, see
178
+   http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
179
+struct ebl_rdata {
180
+	char* separator; /* points inside str_table */
181
+	char* apex;      /* point inside str_table */
182
+	unsigned char separator_len; /* separator len w/o the terminating 0 */
183
+	unsigned char apex_len;      /* apex len w/p the terminating 0 */
184
+	unsigned char position;
185
+	char str_table[1]; /* contains the 2 strings: separator and apex */
186
+};
187
+#define EBL_RDATA_SIZE(s) \
188
+	(sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
189
+
173 190
 
174 191
 #ifdef HAVE_RESOLV_RES
175 192
 int match_search_list(const struct __res_state* res, char* name);