Module: sip-router Branch: master Commit: 997f13c89d16361799651cd77214ffdcf26d532c URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=997f13c8...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Sun Apr 13 16:22:38 2014 +0200
ipops: new pv to get hostname details:
- $HN(n) - hostname - $HN(d) - domain - $HN(f) - fullname - $HN(i) - ip address - based on gethsontname and resolving it
---
modules/ipops/ipops_mod.c | 2 + modules/ipops/ipops_pv.c | 166 +++++++++++++++++++++++++++++++++++++++++++++ modules/ipops/ipops_pv.h | 4 + 3 files changed, 172 insertions(+), 0 deletions(-)
diff --git a/modules/ipops/ipops_mod.c b/modules/ipops/ipops_mod.c index d90aaa3..4e174f5 100644 --- a/modules/ipops/ipops_mod.c +++ b/modules/ipops/ipops_mod.c @@ -96,6 +96,8 @@ static int w_dns_query(struct sip_msg* msg, char* str1, char* str2); static pv_export_t mod_pvs[] = { { {"dns", sizeof("dns")-1}, PVT_OTHER, pv_get_dns, 0, pv_parse_dns_name, 0, 0, 0 }, + { {"HN", sizeof("HN")-1}, PVT_OTHER, pv_get_hn, 0, + pv_parse_hn_name, 0, 0, 0 }, { {0, 0}, 0, 0, 0, 0, 0, 0, 0 } };
diff --git a/modules/ipops/ipops_pv.c b/modules/ipops/ipops_pv.c index 08be1fe..d6edadd 100644 --- a/modules/ipops/ipops_pv.c +++ b/modules/ipops/ipops_pv.c @@ -33,6 +33,7 @@
#include "../../dprint.h" #include "../../hashes.h" +#include "../../resolve.h" #include "../../pvar.h"
@@ -428,3 +429,168 @@ int dns_update_pv(str *hostname, str *name)
return 1; } + + +struct _hn_pv_data { + str data; + str fullname; + str hostname; + str domain; + str ipaddr; +}; + +static struct _hn_pv_data *_hn_data = NULL; + +/** + * + */ +int hn_pv_data_init(void) +{ + char hbuf[512]; + int hlen; + char *d; + struct hostent *he; + int i; + + if(_hn_data != NULL) + return 0; + + if (gethostname(hbuf, 512)<0) { + LM_WARN("gethostname failed - host pvs will be null\n"); + return -1; + } + + hlen = strlen(hbuf); + if(hlen<=0) { + LM_WARN("empty hostname result - host pvs will be null\n"); + return -1; + } + + _hn_data = (struct _hn_pv_data*)pkg_malloc(sizeof(struct _hn_pv_data)+46+2*(hlen+1)); + if(_hn_data==NULL) { + LM_ERR("no more pkg to init hostname data\n"); + return -1; + } + memset(_hn_data, 0, sizeof(struct _hn_pv_data)+46+2*(hlen+1)); + + _hn_data->data.len = hlen; + _hn_data->data.s = (char*)_hn_data + sizeof(struct _hn_pv_data); + _hn_data->fullname.len = hlen; + _hn_data->fullname.s = _hn_data->data.s + hlen + 1; + + strcpy(_hn_data->data.s, hbuf); + strcpy(_hn_data->fullname.s, hbuf); + + d=strchr(_hn_data->data.s, '.'); + if (d) { + _hn_data->hostname.len = d - _hn_data->data.s; + _hn_data->hostname.s = _hn_data->data.s; + _hn_data->domain.len = _hn_data->fullname.len + - _hn_data->hostname.len-1; + _hn_data->domain.s = d+1; + } else { + _hn_data->hostname = _hn_data->fullname; + } + + he=resolvehost(_hn_data->fullname.s); + if (he) { + if ((strlen(he->h_name)!=_hn_data->fullname.len) + || strncmp(he->h_name, _hn_data->fullname.s, + _hn_data->fullname.len)) { + LM_WARN("hostname '%.*s' different than gethostbyname '%s'\n", + _hn_data->fullname.len, _hn_data->fullname.s, he->h_name); + } + + if (he->h_addr_list) { + for (i=0; he->h_addr_list[i]; i++) { + if (inet_ntop(he->h_addrtype, he->h_addr_list[i], hbuf, 46)) { + if (_hn_data->ipaddr.len==0) { + _hn_data->ipaddr.len = strlen(hbuf); + _hn_data->ipaddr.s = _hn_data->fullname.s + hlen + 1; + strcpy(_hn_data->ipaddr.s, hbuf); + } else if (strncmp(_hn_data->ipaddr.s, hbuf, + _hn_data->ipaddr.len)!=0) { + LM_WARN("many IPs to hostname: %s not used\n", hbuf); + } + } + } + } else { + LM_WARN(" can't resolve hostname's address: %s\n", + _hn_data->fullname.s); + } + } + + DBG("Hostname: %.*s\n", _hn_data->hostname.len, ZSW(_hn_data->hostname.s)); + DBG("Domain: %.*s\n", _hn_data->domain.len, ZSW(_hn_data->domain.s)); + DBG("Fullname: %.*s\n", _hn_data->fullname.len, ZSW(_hn_data->fullname.s)); + DBG("IPaddr: %.*s\n", _hn_data->ipaddr.len, ZSW(_hn_data->ipaddr.s)); + + return 0; +} + +/** + * + */ +int pv_parse_hn_name(pv_spec_p sp, str *in) +{ + if(sp==NULL || in==NULL || in->len<=0) + return -1; + + switch(in->len) + { + case 1: + if(strncmp(in->s, "n", 1)==0) + sp->pvp.pvn.u.isname.name.n = 0; + else if(strncmp(in->s, "f", 1)==0) + sp->pvp.pvn.u.isname.name.n = 1; + else if(strncmp(in->s, "d", 1)==0) + sp->pvp.pvn.u.isname.name.n = 2; + else if(strncmp(in->s, "i", 1)==0) + sp->pvp.pvn.u.isname.name.n = 3; + else goto error; + break; + default: + goto error; + } + sp->pvp.pvn.type = PV_NAME_INTSTR; + sp->pvp.pvn.u.isname.type = 0; + + hn_pv_data_init(); + + return 0; + +error: + LM_ERR("unknown host PV name %.*s\n", in->len, in->s); + return -1; +} + +/** + * + */ +int pv_get_hn(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res) +{ + if(param==NULL) + return -1; + if(_hn_data==NULL) + return pv_get_null(msg, param, res);; + switch(param->pvn.u.isname.name.n) + { + case 1: + if(_hn_data->fullname.len==0) + return pv_get_null(msg, param, res);; + return pv_get_strval(msg, param, res, &_hn_data->fullname); + case 2: + if(_hn_data->domain.len==0) + return pv_get_null(msg, param, res);; + return pv_get_strval(msg, param, res, &_hn_data->domain); + case 3: + if(_hn_data->ipaddr.len==0) + return pv_get_null(msg, param, res);; + return pv_get_strval(msg, param, res, &_hn_data->ipaddr); + default: + if(_hn_data->hostname.len==0) + return pv_get_null(msg, param, res);; + return pv_get_strval(msg, param, res, &_hn_data->hostname); + } +} diff --git a/modules/ipops/ipops_pv.h b/modules/ipops/ipops_pv.h index 043d891..16c8ac8 100644 --- a/modules/ipops/ipops_pv.h +++ b/modules/ipops/ipops_pv.h @@ -35,5 +35,9 @@ int dns_init_pv(char *path); void dns_destroy_pv(void); int dns_update_pv(str *tomatch, str *name);
+int pv_parse_hn_name(pv_spec_p sp, str *in); +int pv_get_hn(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res); + #endif