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 135
 	0
136 136
 };
137 137
 
138
+static const char* dns_cache_delete_ebl_doc[] = {
139
+	"deletes an EBL record from the DNS cache",
140
+	0
141
+};
142
+
138 143
 
139 144
 #ifdef USE_DNS_CACHE_STATS
140 145
 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
... ...
@@ -739,6 +745,8 @@ rpc_export_t core_rpc_methods[] = {
739 739
 		dns_cache_delete_cname_doc,  0	},
740 740
 	{"dns.delete_txt",         dns_cache_delete_txt,
741 741
 		dns_cache_delete_txt_doc,  0	},
742
+	{"dns.delete_ebl",         dns_cache_delete_ebl,
743
+		dns_cache_delete_ebl_doc,  0	},
742 744
 #ifdef USE_DNS_CACHE_STATS
743 745
 	{"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
744 746
 		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 1165
 				 * just been elimintated */
1166 1166
 			}
1167 1167
 			break;
1168
+		case T_EBL:
1169
+			for(; *p;){
1170
+				if (!rec_matches((*p), type, name)){
1171
+					/* skip this record */
1172
+					p=&(*p)->next; /* advance */
1173
+					continue;
1174
+				}
1175
+				/* padding to char* (because of the char* pointers */
1176
+				size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1177
+						EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
1178
+				/* add it to our tmp. lst */
1179
+				*tail=*p;
1180
+				tail=&(*p)->next;
1181
+				/* detach it from the rd list */
1182
+				*p=(*p)->next;
1183
+				/* don't advance p, because the crt. elem. has
1184
+				 * just been elimintated */
1185
+			}
1186
+			break;
1168 1187
 		default:
1169 1188
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1170 1189
 							"supported\n", type);
... ...
@@ -1313,6 +1333,32 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
1313 1313
 				rr=rr->next;
1314 1314
 			}
1315 1315
 			break;
1316
+		case T_EBL:
1317
+			for(l=tmp_lst; l; l=l->next){
1318
+				ttl=FIX_TTL(l->ttl);
1319
+				rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1320
+				max_ttl=MAX(max_ttl, ttl);
1321
+				rr->rdata=(void*)((char*)rr+
1322
+							ROUND_POINTER(sizeof(struct dns_rr)));
1323
+				memcpy(rr->rdata, l->rdata,
1324
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1325
+				/* adjust the string pointers */
1326
+				((struct ebl_rdata*)rr->rdata)->separator=
1327
+					translate_pointer((char*)rr->rdata, (char*)l->rdata,
1328
+								((struct ebl_rdata*)l->rdata)->separator);
1329
+				((struct ebl_rdata*)rr->rdata)->separator=
1330
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
1331
+								((struct ebl_rdata*)l->rdata)->separator);
1332
+				((struct ebl_rdata*)rr->rdata)->apex=
1333
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
1334
+								((struct ebl_rdata*)l->rdata)->apex);
1335
+				rr->next=(void*)((char*)rr+
1336
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1337
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1338
+				tail_rr=&(rr->next);
1339
+				rr=rr->next;
1340
+			}
1341
+			break;
1316 1342
 		default:
1317 1343
 			/* do nothing */
1318 1344
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: create: type %d not "
... ...
@@ -1427,11 +1473,17 @@ found:
1427 1427
 							CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
1428 1428
 				break;
1429 1429
 			case T_TXT:
1430
-					/* padding to char* (because of txt[]->cstr*/
1430
+					/* padding to char* (because of txt[]->cstr)*/
1431 1431
 				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1432 1432
 												sizeof(struct dns_rr))+
1433 1433
 							TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
1434 1434
 				break;
1435
+			case T_EBL:
1436
+					/* padding to char* (because of char* pointers)*/
1437
+				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
1438
+												sizeof(struct dns_rr))+
1439
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1440
+				break;
1435 1441
 			default:
1436 1442
 				LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
1437 1443
 							"supported\n", l->type);
... ...
@@ -1571,6 +1623,28 @@ found:
1571 1571
 				rec[r].tail_rr=&(rec[r].rr->next);
1572 1572
 				rec[r].rr=rec[r].rr->next;
1573 1573
 				break;
1574
+			case T_EBL:
1575
+				rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
1576
+				rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
1577
+				rec[r].rr->rdata=(void*)((char*)rec[r].rr+
1578
+									ROUND_POINTER(sizeof(struct dns_rr)));
1579
+				memcpy(rec[r].rr->rdata, l->rdata,
1580
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
1581
+				/* adjust the string pointers */
1582
+				((struct ebl_rdata*)rec[r].rr->rdata)->separator=
1583
+					translate_pointer((char*)rec[r].rr->rdata,
1584
+							(char*)l->rdata,
1585
+							((struct ebl_rdata*)l->rdata)->separator);
1586
+				((struct ebl_rdata*)rec[r].rr->rdata)->apex=
1587
+					translate_pointer((char*)rec[r].rr->rdata,
1588
+							(char*)l->rdata,
1589
+							((struct ebl_rdata*)l->rdata)->apex);
1590
+				rec[r].rr->next=(void*)((char*)rec[r].rr+
1591
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
1592
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
1593
+				rec[r].tail_rr=&(rec[r].rr->next);
1594
+				rec[r].rr=rec[r].rr->next;
1595
+				break;
1574 1596
 			default:
1575 1597
 				/* do nothing */
1576 1598
 				;
... ...
@@ -3521,6 +3595,10 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
3521 3521
 								((struct txt_rdata*)(rr->rdata))->txt[0].cstr:
3522 3522
 								"");
3523 3523
 							break;
3524
+						case T_EBL:
3525
+							rpc->add(ctx, "ss", "ebl",
3526
+								((struct ebl_rdata*)(rr->rdata))->apex);
3527
+							break;
3524 3528
 						default:
3525 3529
 							rpc->add(ctx, "ss", "unknown", "?");
3526 3530
 					}
... ...
@@ -3550,6 +3628,8 @@ static char *print_type(unsigned short type)
3550 3550
 			return "CNAME";
3551 3551
 		case T_TXT:
3552 3552
 			return "TXT";
3553
+		case T_EBL:
3554
+			return "EBL";
3553 3555
 		default:
3554 3556
 			return "unkown";
3555 3557
 	}
... ...
@@ -3586,6 +3666,8 @@ static int dns_get_type(str* s)
3586 3586
 				return T_SRV;
3587 3587
 			else if (strncasecmp(t, "TXT", len)==0)
3588 3588
 				return T_TXT;
3589
+			else if (strncasecmp(t, "EBL", len)==0)
3590
+				return T_EBL;
3589 3591
 			break;
3590 3592
 		case 5:
3591 3593
 			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 3680
 						((struct txt_rdata*)(rr->rdata))->txt[i].cstr);
3681 3681
 				}
3682 3682
 				break;
3683
+			case T_EBL:
3684
+				rpc->printf(ctx, "%srr position: %d", SPACE_FORMAT,
3685
+							((struct ebl_rdata*)(rr->rdata))->position);
3686
+				rpc->printf(ctx, "%srr separator: %s", SPACE_FORMAT,
3687
+							((struct ebl_rdata*)(rr->rdata))->separator);
3688
+				rpc->printf(ctx, "%srr apex: %s", SPACE_FORMAT,
3689
+							((struct ebl_rdata*)(rr->rdata))->apex);
3690
+				break;
3683 3691
 			default:
3684 3692
 				rpc->printf(ctx, "%sresource record: unknown",
3685 3693
 									SPACE_FORMAT);
... ...
@@ -3779,6 +3869,9 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
3779 3779
 			case T_TXT:
3780 3780
 				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
3781 3781
 				break;
3782
+			case T_EBL:
3783
+				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
3784
+				break;
3782 3785
 			default:
3783 3786
 				LOG(L_ERR, "ERROR: dns_cache_clone_entry: type %d not "
3784 3787
 							"supported\n", e->type);
... ...
@@ -3819,30 +3912,42 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
3819 3819
 		else
3820 3820
 			last_rr = rr;
3821 3821
 
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
-			}
3822
+		switch(e->type){
3823
+			case T_NAPTR:
3824
+				/* there are pointers inside the NAPTR rdata stucture */
3825
+				((struct naptr_rdata*)rr->rdata)->flags =
3826
+					translate_pointer((char*)new, (char*)e,
3827
+						((struct naptr_rdata*)rr->rdata)->flags);
3828
+
3829
+				((struct naptr_rdata*)rr->rdata)->services =
3830
+					translate_pointer((char*)new, (char*)e,
3831
+						((struct naptr_rdata*)rr->rdata)->services);
3832
+
3833
+				((struct naptr_rdata*)rr->rdata)->regexp =
3834
+					translate_pointer((char*)new, (char*)e,
3835
+						((struct naptr_rdata*)rr->rdata)->regexp);
3836
+
3837
+				((struct naptr_rdata*)rr->rdata)->repl =
3838
+					translate_pointer((char*)new, (char*)e,
3839
+						((struct naptr_rdata*)rr->rdata)->repl);
3840
+				break;
3841
+			case T_TXT:
3842
+				/* there are pointers inside the TXT structure */
3843
+				for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
3844
+					((struct txt_rdata*)rr->rdata)->txt[i].cstr=
3845
+						translate_pointer((char*) new, (char*) e,
3846
+							((struct txt_rdata*)rr->rdata)->txt[i].cstr);
3847
+				}
3848
+				break;
3849
+			case T_EBL:
3850
+				/* there are pointers inside the EBL structure */
3851
+				((struct ebl_rdata*)rr->rdata)->separator =
3852
+					translate_pointer((char*)new, (char*)e,
3853
+							((struct ebl_rdata*)rr->rdata)->separator);
3854
+				((struct ebl_rdata*)rr->rdata)->apex =
3855
+					translate_pointer((char*)new, (char*)e,
3856
+							((struct ebl_rdata*)rr->rdata)->apex);
3857
+				break;
3846 3858
 		}
3847 3859
 	}
3848 3860
 
... ...
@@ -3915,6 +4020,7 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type)
3915 3915
 	case T_CNAME:
3916 3916
 	case T_NAPTR:
3917 3917
 	case T_TXT:
3918
+	case T_EBL:
3918 3919
 		rpc->fault(ctx, 400, "not implemented");
3919 3920
 		return;
3920 3921
 	default:
... ...
@@ -4217,6 +4323,11 @@ void dns_cache_delete_txt(rpc_t* rpc, void* ctx)
4217 4217
 	dns_cache_delete_record(rpc, ctx, T_TXT);
4218 4218
 }
4219 4219
 
4220
+void dns_cache_delete_ebl(rpc_t* rpc, void* ctx)
4221
+{
4222
+	dns_cache_delete_record(rpc, ctx, T_EBL);
4223
+}
4224
+
4220 4225
 
4221 4226
 
4222 4227
 #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 761
 				last=&(rd->next);
762 762
 				break;
763 763
 			case T_TXT:
764
-				rd->rdata= dns_txt_parser(buff.buff, p+rdlength, p);
764
+				rd->rdata= dns_txt_parser(buff.buff, rd_end, p);
765
+				if (rd->rdata==0) goto error_parse;
766
+				*last=rd;
767
+				last=&(rd->next);
768
+				break;
769
+			case T_EBL:
770
+				rd->rdata= dns_ebl_parser(buff.buff, end, rd_end, p);
765 771
 				if (rd->rdata==0) goto error_parse;
766 772
 				*last=rd;
767 773
 				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 170
 	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
171 171
 	 	(s).tslen)
172 172
 
173
+/* ebl rec. struct, see
174
+   http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
175
+struct ebl_rdata {
176
+	char* separator; /* points inside str_table */
177
+	char* apex;      /* point inside str_table */
178
+	unsigned char separator_len; /* separator len w/o the terminating 0 */
179
+	unsigned char apex_len;      /* apex len w/p the terminating 0 */
180
+	unsigned char position;
181
+	char str_table[1]; /* contains the 2 strings: separator and apex */
182
+};
183
+#define EBL_RDATA_SIZE(s) \
184
+	(sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
185
+
173 186
 
174 187
 #ifdef HAVE_RESOLV_RES
175 188
 int match_search_list(const struct __res_state* res, char* name);