Module: sip-router
Branch: master
Commit: 8f4ba87e4170e025a50ca12581acd8b12a085298
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8f4ba87…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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);