Browse Source

dns: EBL records support

- support for EBL records
- dns cache support for EBLs
- dns.delete_ebl rpc added
Andrei Pelinescu-Onciul 16 năm trước cách đây
mục cha
commit
2c2dd816c4
4 tập tin đã thay đổi với 232 bổ sung26 xóa
  1. 8 0
      core_cmd.c
  2. 136 25
      dns_cache.c
  3. 71 1
      resolve.c
  4. 17 0
      resolve.h

+ 8 - 0
core_cmd.c

@@ -60,6 +60,7 @@ void dns_cache_delete_srv(rpc_t* rpc, void* ctx);
 void dns_cache_delete_naptr(rpc_t* rpc, void* ctx);
 void dns_cache_delete_cname(rpc_t* rpc, void* ctx);
 void dns_cache_delete_txt(rpc_t* rpc, void* ctx);
+void dns_cache_delete_ebl(rpc_t* rpc, void* ctx);
 
 
 static const char* dns_cache_mem_info_doc[] = {
@@ -135,6 +136,11 @@ static const char* dns_cache_delete_txt_doc[] = {
 	0
 };
 
+static const char* dns_cache_delete_ebl_doc[] = {
+	"deletes an EBL record from the DNS cache",
+	0
+};
+
 
 #ifdef USE_DNS_CACHE_STATS
 void dns_cache_stats_get(rpc_t* rpc, void* ctx);
@@ -739,6 +745,8 @@ rpc_export_t core_rpc_methods[] = {
 		dns_cache_delete_cname_doc,  0	},
 	{"dns.delete_txt",         dns_cache_delete_txt,
 		dns_cache_delete_txt_doc,  0	},
+	{"dns.delete_ebl",         dns_cache_delete_ebl,
+		dns_cache_delete_ebl_doc,  0	},
 #ifdef USE_DNS_CACHE_STATS
 	{"dns.stats_get",    dns_cache_stats_get,   dns_cache_stats_get_doc,
 		0	},

+ 136 - 25
dns_cache.c

@@ -45,6 +45,7 @@
  *  2008-10-17  fixed srv continue with 0 hostname (when falling back to
                   aaaa) (andrei)
  *  2009-03-30  TXT record support, more rpcs (andrei)
+ *  2009-03-30  EBL record support (andrei)
  */
 
 #ifdef USE_DNS_CACHE
@@ -1165,6 +1166,25 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
 				 * just been elimintated */
 			}
 			break;
+		case T_EBL:
+			for(; *p;){
+				if (!rec_matches((*p), type, name)){
+					/* skip this record */
+					p=&(*p)->next; /* advance */
+					continue;
+				}
+				/* padding to char* (because of the char* pointers */
+				size+=ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
+						EBL_RDATA_SIZE(*(struct ebl_rdata*)(*p)->rdata));
+				/* add it to our tmp. lst */
+				*tail=*p;
+				tail=&(*p)->next;
+				/* detach it from the rd list */
+				*p=(*p)->next;
+				/* don't advance p, because the crt. elem. has
+				 * just been elimintated */
+			}
+			break;
 		default:
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
 							"supported\n", type);
@@ -1313,6 +1333,32 @@ inline static struct dns_hash_entry* dns_cache_mk_rd_entry(str* name, int type,
 				rr=rr->next;
 			}
 			break;
+		case T_EBL:
+			for(l=tmp_lst; l; l=l->next){
+				ttl=FIX_TTL(l->ttl);
+				rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
+				max_ttl=MAX(max_ttl, ttl);
+				rr->rdata=(void*)((char*)rr+
+							ROUND_POINTER(sizeof(struct dns_rr)));
+				memcpy(rr->rdata, l->rdata,
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
+				/* adjust the string pointers */
+				((struct ebl_rdata*)rr->rdata)->separator=
+					translate_pointer((char*)rr->rdata, (char*)l->rdata,
+								((struct ebl_rdata*)l->rdata)->separator);
+				((struct ebl_rdata*)rr->rdata)->separator=
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
+								((struct ebl_rdata*)l->rdata)->separator);
+				((struct ebl_rdata*)rr->rdata)->apex=
+						translate_pointer((char*)rr->rdata, (char*)l->rdata,
+								((struct ebl_rdata*)l->rdata)->apex);
+				rr->next=(void*)((char*)rr+
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
+				tail_rr=&(rr->next);
+				rr=rr->next;
+			}
+			break;
 		default:
 			/* do nothing */
 			LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: create: type %d not "
@@ -1427,11 +1473,17 @@ found:
 							CNAME_RDATA_SIZE(*(struct cname_rdata*)l->rdata));
 				break;
 			case T_TXT:
-					/* padding to char* (because of txt[]->cstr*/
+					/* padding to char* (because of txt[]->cstr)*/
 				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
 												sizeof(struct dns_rr))+
 							TXT_RDATA_SIZE(*(struct txt_rdata*)l->rdata));
 				break;
+			case T_EBL:
+					/* padding to char* (because of char* pointers)*/
+				rec[r].size+=ROUND_POINTER(ROUND_POINTER(
+												sizeof(struct dns_rr))+
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
+				break;
 			default:
 				LOG(L_CRIT, "BUG: dns_cache_mk_rd_entry: type %d not "
 							"supported\n", l->type);
@@ -1571,6 +1623,28 @@ found:
 				rec[r].tail_rr=&(rec[r].rr->next);
 				rec[r].rr=rec[r].rr->next;
 				break;
+			case T_EBL:
+				rec[r].rr->expire=now+S_TO_TICKS(ttl); /* maximum expire */
+				rec[r].max_ttl=MAX(rec[r].max_ttl, ttl);
+				rec[r].rr->rdata=(void*)((char*)rec[r].rr+
+									ROUND_POINTER(sizeof(struct dns_rr)));
+				memcpy(rec[r].rr->rdata, l->rdata,
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata));
+				/* adjust the string pointers */
+				((struct ebl_rdata*)rec[r].rr->rdata)->separator=
+					translate_pointer((char*)rec[r].rr->rdata,
+							(char*)l->rdata,
+							((struct ebl_rdata*)l->rdata)->separator);
+				((struct ebl_rdata*)rec[r].rr->rdata)->apex=
+					translate_pointer((char*)rec[r].rr->rdata,
+							(char*)l->rdata,
+							((struct ebl_rdata*)l->rdata)->apex);
+				rec[r].rr->next=(void*)((char*)rec[r].rr+
+						ROUND_POINTER(ROUND_POINTER(sizeof(struct dns_rr))+
+							EBL_RDATA_SIZE(*(struct ebl_rdata*)l->rdata)));
+				rec[r].tail_rr=&(rec[r].rr->next);
+				rec[r].rr=rec[r].rr->next;
+				break;
 			default:
 				/* do nothing */
 				;
@@ -3521,6 +3595,10 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
 								((struct txt_rdata*)(rr->rdata))->txt[0].cstr:
 								"");
 							break;
+						case T_EBL:
+							rpc->add(ctx, "ss", "ebl",
+								((struct ebl_rdata*)(rr->rdata))->apex);
+							break;
 						default:
 							rpc->add(ctx, "ss", "unknown", "?");
 					}
@@ -3550,6 +3628,8 @@ static char *print_type(unsigned short type)
 			return "CNAME";
 		case T_TXT:
 			return "TXT";
+		case T_EBL:
+			return "EBL";
 		default:
 			return "unkown";
 	}
@@ -3586,6 +3666,8 @@ static int dns_get_type(str* s)
 				return T_SRV;
 			else if (strncasecmp(t, "TXT", len)==0)
 				return T_TXT;
+			else if (strncasecmp(t, "EBL", len)==0)
+				return T_EBL;
 			break;
 		case 5:
 			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)
 						((struct txt_rdata*)(rr->rdata))->txt[i].cstr);
 				}
 				break;
+			case T_EBL:
+				rpc->printf(ctx, "%srr position: %d", SPACE_FORMAT,
+							((struct ebl_rdata*)(rr->rdata))->position);
+				rpc->printf(ctx, "%srr separator: %s", SPACE_FORMAT,
+							((struct ebl_rdata*)(rr->rdata))->separator);
+				rpc->printf(ctx, "%srr apex: %s", SPACE_FORMAT,
+							((struct ebl_rdata*)(rr->rdata))->apex);
+				break;
 			default:
 				rpc->printf(ctx, "%sresource record: unknown",
 									SPACE_FORMAT);
@@ -3779,6 +3869,9 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
 			case T_TXT:
 				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
 				break;
+			case T_EBL:
+				rr_size = ROUND_POINTER(sizeof(struct dns_rr));
+				break;
 			default:
 				LOG(L_ERR, "ERROR: dns_cache_clone_entry: type %d not "
 							"supported\n", e->type);
@@ -3819,30 +3912,42 @@ static struct dns_hash_entry *dns_cache_clone_entry(struct dns_hash_entry *e,
 		else
 			last_rr = rr;
 
-		if (e->type == T_NAPTR) {
-			/* there are pointers inside the NAPTR rdata stucture */
-			((struct naptr_rdata*)rr->rdata)->flags =
-				translate_pointer((char*)new, (char*)e,
-					((struct naptr_rdata*)rr->rdata)->flags);
-
-			((struct naptr_rdata*)rr->rdata)->services =
-				translate_pointer((char*)new, (char*)e,
-					((struct naptr_rdata*)rr->rdata)->services);
-
-			((struct naptr_rdata*)rr->rdata)->regexp =
-				translate_pointer((char*)new, (char*)e,
-					((struct naptr_rdata*)rr->rdata)->regexp);
-
-			((struct naptr_rdata*)rr->rdata)->repl =
-				translate_pointer((char*)new, (char*)e,
-					((struct naptr_rdata*)rr->rdata)->repl);
-		}else if (e->type == T_TXT){
-			/* there are pointers inside the TXT structure */
-			for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
-				((struct txt_rdata*)rr->rdata)->txt[i].cstr=
-					translate_pointer((char*) new, (char*) e,
-						((struct txt_rdata*)rr->rdata)->txt[i].cstr);
-			}
+		switch(e->type){
+			case T_NAPTR:
+				/* there are pointers inside the NAPTR rdata stucture */
+				((struct naptr_rdata*)rr->rdata)->flags =
+					translate_pointer((char*)new, (char*)e,
+						((struct naptr_rdata*)rr->rdata)->flags);
+
+				((struct naptr_rdata*)rr->rdata)->services =
+					translate_pointer((char*)new, (char*)e,
+						((struct naptr_rdata*)rr->rdata)->services);
+
+				((struct naptr_rdata*)rr->rdata)->regexp =
+					translate_pointer((char*)new, (char*)e,
+						((struct naptr_rdata*)rr->rdata)->regexp);
+
+				((struct naptr_rdata*)rr->rdata)->repl =
+					translate_pointer((char*)new, (char*)e,
+						((struct naptr_rdata*)rr->rdata)->repl);
+				break;
+			case T_TXT:
+				/* there are pointers inside the TXT structure */
+				for (i=0; i<((struct txt_rdata*)rr->rdata)->cstr_no; i++){
+					((struct txt_rdata*)rr->rdata)->txt[i].cstr=
+						translate_pointer((char*) new, (char*) e,
+							((struct txt_rdata*)rr->rdata)->txt[i].cstr);
+				}
+				break;
+			case T_EBL:
+				/* there are pointers inside the EBL structure */
+				((struct ebl_rdata*)rr->rdata)->separator =
+					translate_pointer((char*)new, (char*)e,
+							((struct ebl_rdata*)rr->rdata)->separator);
+				((struct ebl_rdata*)rr->rdata)->apex =
+					translate_pointer((char*)new, (char*)e,
+							((struct ebl_rdata*)rr->rdata)->apex);
+				break;
 		}
 	}
 
@@ -3915,6 +4020,7 @@ static void dns_cache_add_record(rpc_t* rpc, void* ctx, unsigned short type)
 	case T_CNAME:
 	case T_NAPTR:
 	case T_TXT:
+	case T_EBL:
 		rpc->fault(ctx, 400, "not implemented");
 		return;
 	default:
@@ -4217,6 +4323,11 @@ void dns_cache_delete_txt(rpc_t* rpc, void* ctx)
 	dns_cache_delete_record(rpc, ctx, T_TXT);
 }
 
+void dns_cache_delete_ebl(rpc_t* rpc, void* ctx)
+{
+	dns_cache_delete_record(rpc, ctx, T_EBL);
+}
+
 
 
 #ifdef DNS_WATCHDOG_SUPPORT

+ 71 - 1
resolve.c

@@ -527,6 +527,70 @@ error:
 
 
 
+/** parses an EBL record into a txt_rdata structure.
+ *   @param msg   - pointer to the dns message
+ *   @param end   - pointer to the end of the dns message
+ *   @param eor   - pointer to the end of the record (rdata end)
+ *   @param rdata - pointer  to the rdata part of the txt answer
+ * returns 0 on error, or a dyn. alloc'ed txt_rdata structure */
+/*  EBL rdata format:
+ *  (see http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03)
+ * one or several character strings:
+ *  01234567
+ * +--------+
+ * | postion|
+ * +-----------+
+ * / separator /
+ * +-----------+
+ * /   apex    /
+ * +----------+
+ *
+ * where separator is a character string ( 8 bit len, followed by len chars)
+ * and apex is a domain-name.
+ */
+static struct ebl_rdata* dns_ebl_parser(unsigned char* msg, unsigned char* end,
+										unsigned char* eor,
+										unsigned char* rdata)
+{
+	struct ebl_rdata* ebl;
+	int sep_len;
+	int apex_len;
+	char apex[MAX_DNS_NAME];
+	
+	ebl=0;
+	/* check if len is at least 4 chars (minimum possible):
+	     pos (1 byte) +  sep. (min 1 byte) + apex (min. 2 bytes) 
+	   and also check if rdata+1 (pos) + 1 (sep. len) + sep_len + 1 is ok*/
+	if (unlikely(((rdata+4)>eor)||((rdata+1+1+rdata[1]+2)>eor))) goto error;
+	sep_len=rdata[1];
+	if (unlikely(dn_expand(msg, end, rdata+1+1+sep_len,
+							apex, MAX_DNS_NAME-1)==-1))
+		goto error;
+	apex_len=strlen(apex);
+	/* alloc sizeof struct + space for the 2 null-terminated strings */
+	ebl=local_malloc(sizeof(struct ebl_rdata)-1+sep_len+1+apex_len+1);
+	if (ebl==0){
+		LOG(L_ERR, "ERROR: dns_ebl_parser: out of memory\n");
+		goto error;
+	}
+	ebl->position=rdata[0];
+	ebl->separator=&ebl->str_table[0];
+	ebl->apex=ebl->separator+sep_len+1;
+	ebl->separator_len=sep_len;
+	ebl->apex_len=apex_len;
+	memcpy(ebl->separator, rdata+2, sep_len);
+	ebl->separator[sep_len]=0;
+	memcpy(ebl->apex, apex, apex_len);
+	ebl->apex[apex_len]=0;
+	
+	return ebl;
+error:
+	if (ebl) local_free(ebl);
+	return 0;
+}
+
+
+
 /* frees completely a struct rdata list */
 void free_rdata_list(struct rdata* head)
 {
@@ -761,7 +825,13 @@ again:
 				last=&(rd->next);
 				break;
 			case T_TXT:
-				rd->rdata= dns_txt_parser(buff.buff, p+rdlength, p);
+				rd->rdata= dns_txt_parser(buff.buff, rd_end, p);
+				if (rd->rdata==0) goto error_parse;
+				*last=rd;
+				last=&(rd->next);
+				break;
+			case T_EBL:
+				rd->rdata= dns_ebl_parser(buff.buff, end, rd_end, p);
 				if (rd->rdata==0) goto error_parse;
 				*last=rd;
 				last=&(rd->next);

+ 17 - 0
resolve.h

@@ -69,6 +69,10 @@
 #define MAX_DNS_NAME 256
 #define MAX_DNS_STRING 255
 
+#ifndef T_EBL
+/** not official yet - iEnum. */
+#define T_EBL 65300
+#endif
 
 /* get_record flags */
 #define RES_ONLY_TYPE 1   /* return only the specified type records */
@@ -170,6 +174,19 @@ struct txt_rdata {
 	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
 	 	(s).tslen)
 
+/* ebl rec. struct, see
+   http://tools.ietf.org/html/draft-ietf-enum-branch-location-record-03 */
+struct ebl_rdata {
+	char* separator; /* points inside str_table */
+	char* apex;      /* point inside str_table */
+	unsigned char separator_len; /* separator len w/o the terminating 0 */
+	unsigned char apex_len;      /* apex len w/p the terminating 0 */
+	unsigned char position;
+	char str_table[1]; /* contains the 2 strings: separator and apex */
+};
+#define EBL_RDATA_SIZE(s) \
+	(sizeof(struct ebl_rdata)-1+(s).separator_len+1+(s).apex_len+1)
+
 
 #ifdef HAVE_RESOLV_RES
 int match_search_list(const struct __res_state* res, char* name);