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