[SR-Dev] git:master: dns: TXT records support

Andrei Pelinescu-Onciul andrei at iptel.org
Mon Mar 30 21:04:04 CEST 2009


Module: sip-router
Branch: master
Commit: 8f4ba87e4170e025a50ca12581acd8b12a085298
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8f4ba87e4170e025a50ca12581acd8b12a085298

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Mon Mar 30 20:40:23 2009 +0200

dns: TXT records support

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

---

 resolve.c |   73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 resolve.h |   18 +++++++++++++++
 2 files changed, 91 insertions(+), 0 deletions(-)

diff --git a/resolve.c b/resolve.c
index 9f55f3d..8dfde34 100644
--- a/resolve.c
+++ b/resolve.c
@@ -456,6 +456,73 @@ error:
 
 
 
+/** parses a TXT record into a txt_rdata structure.
+ *   @param msg   - pointer to the dns message
+ *   @param end   - 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 */
+/*  TXT rdata format:
+ *
+ * one or several character strings:
+ *  01234567
+ * +--------------------+
+ * | len    | string   / ...
+ * |------------------+
+ */
+static struct txt_rdata* dns_txt_parser(unsigned char* msg, unsigned char* end,
+										unsigned char* rdata)
+{
+	struct txt_rdata* txt;
+	int len, n, i;
+	int str_size;
+	unsigned char* p;
+	unsigned char* st;
+	
+	txt=0;
+	if (unlikely((rdata+1)>end)) goto error;
+	n=0;
+	str_size=0;
+	/* count the number of strings */
+	p=rdata;
+	do{
+		len=*p;
+		p+=len+1;
+		str_size+=len+1; /* 1 for the term. 0 */
+		if (unlikely(p>end)) goto error;
+		n++;
+	}while(p<end);
+	/* alloc sizeof struct + space for the dns_cstr array + space for
+	   the strings */
+	txt=local_malloc(sizeof(struct txt_rdata) +(n-1)*sizeof(struct dns_cstr)+
+						str_size);
+	if(unlikely(txt==0)){
+		LOG(L_ERR, "ERROR: dns_txt_parser: out of memory\n");
+		goto error;
+	}
+	/* string table */
+	st=(unsigned char*)txt+sizeof(struct txt_rdata) +
+		(n-1)*sizeof(struct dns_cstr);
+	txt->cstr_no=n;
+	txt->tslen=str_size;
+	/* fill the structure */
+	p=rdata;
+	for (i=0; i<n; i++){
+		len=*p;
+		memcpy(st, p+1, len);
+		st[len]=0;
+		txt->txt[i].cstr_len=len;
+		txt->txt[i].cstr=(char*)st;
+		st+=len+1;
+		p+=len+1;
+	}
+	return txt;
+error:
+	if (txt) local_free(txt);
+	return 0;
+}
+
+
+
 /* frees completely a struct rdata list */
 void free_rdata_list(struct rdata* head)
 {
@@ -689,6 +756,12 @@ again:
 				*last=rd;
 				last=&(rd->next);
 				break;
+			case T_TXT:
+				rd->rdata= dns_txt_parser(buff.buff, p+rdlength, p);
+				if (rd->rdata==0) goto error_parse;
+				*last=rd;
+				last=&(rd->next);
+				break;
 			default:
 				LOG(L_ERR, "WARNING: get_record: unknown type %d\n", rtype);
 				rd->rdata=0;
diff --git a/resolve.h b/resolve.h
index eba6ad4..b4d66ae 100644
--- a/resolve.h
+++ b/resolve.h
@@ -152,6 +152,24 @@ struct cname_rdata {
 /* real size of the structure */
 #define CNAME_RDATA_SIZE(s) (sizeof(struct cname_rdata)+(s).name_len)
 
+/* dns character-string */
+struct dns_cstr{
+	char* cstr; /* pointer to null term. string */
+	unsigned char cstr_len;
+};
+
+/* txt rec. struct */
+struct txt_rdata {
+	unsigned short cstr_no; /* number of strings */
+	unsigned short tslen; /* total strings table len */
+	struct dns_cstr txt[1]; /* at least 1 */
+	/* all txt[*].cstr point inside a string table at the end of the struct.*/
+};
+
+#define TXT_RDATA_SIZE(s) \
+	(sizeof(struct txt_rdata)+((s).cstr_no-1)*sizeof(struct dns_cstr)+\
+	 	(s).tslen)
+
 
 #ifdef HAVE_RESOLV_RES
 int match_search_list(const struct __res_state* res, char* name);




More information about the sr-dev mailing list