From b739d1d747d49e1bc89b363254cf23210bd1bf46 Mon Sep 17 00:00:00 2001 From: Sergey Okhapkin Date: Tue, 27 Jan 2015 08:24:12 -0500 Subject: [PATCH 1/4] Geoip2 module --- modules/geoip2/Makefile | 15 + modules/geoip2/README | 146 +++++++++ modules/geoip2/doc/Makefile | 4 + modules/geoip2/doc/geoip2.xml | 36 +++ modules/geoip2/doc/geoip2_admin.xml | 175 ++++++++++ modules/geoip2/geoip2_mod.c | 139 ++++++++ modules/geoip2/geoip2_pv.c | 476 ++++++++++++++++++++++++++++ modules/geoip2/geoip2_pv.h | 40 +++ 8 files changed, 1031 insertions(+) create mode 100644 modules/geoip2/Makefile create mode 100644 modules/geoip2/README create mode 100644 modules/geoip2/doc/Makefile create mode 100644 modules/geoip2/doc/geoip2.xml create mode 100644 modules/geoip2/doc/geoip2_admin.xml create mode 100644 modules/geoip2/geoip2_mod.c create mode 100644 modules/geoip2/geoip2_pv.c create mode 100644 modules/geoip2/geoip2_pv.h diff --git a/modules/geoip2/Makefile b/modules/geoip2/Makefile new file mode 100644 index 00000000000..f4b26a43177 --- /dev/null +++ b/modules/geoip2/Makefile @@ -0,0 +1,15 @@ +# $Id$ +# +# WARNING: do not run this directly, it should be run by the master Makefile + +include ../../Makefile.defs +auto_gen= +NAME=geoip2.so +LIBS= -lmaxminddb + +DEFS+=-DKAMAILIO_MOD_INTERFACE + +SERLIBPATH=../../lib +SER_LIBS+=$(SERLIBPATH)/kmi/kmi + +include ../../Makefile.modules diff --git a/modules/geoip2/README b/modules/geoip2/README new file mode 100644 index 00000000000..61231529d95 --- /dev/null +++ b/modules/geoip2/README @@ -0,0 +1,146 @@ +geoip2 Module + +Sergey Okhapkin + + callwithus.com + +Edited by + +Daniel-Constantin Mierla + + + + Copyright © 2010 Daniel-Constantin Mierla (asipto.com) + __________________________________________________________________ + + Table of Contents + + 1. Admin Guide + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Parameters + + 3.1. path (string) + + 4. Functions + + 4.1. geoip_match(ipaddr, pvc) + + 5. Exported pseudo-variables + + List of Examples + + 1.1. Set path parameter + 1.2. geoip_match usage + +Chapter 1. Admin Guide + + Table of Contents + + 1. Overview + 2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + + 3. Parameters + + 3.1. path (string) + + 4. Functions + + 4.1. geoip_match(ipaddr, pvc) + + 5. Exported pseudo-variables + +1. Overview + + This module allows real-time queries against the Max Mind GeoIP2 + database to be performed from the config script. + + The Max Mind GeoIP2 database is a map of IP network address assignments + to geographical locales that can be useful -- though approximate -- in + identifying the physical location with which an IP host address is + associated on a relatively granular level. + + This database itself can be obtained on a free or commercial basis from + http://dev.maxmind.com/geoip/. The library libmaxminddb that interfaces + with the Max Mind API, as well as scripts to automate downloading of + the on-disk version are available at + http://dev.maxmind.com/geoip/geoip2/downloadable/. + + This module exports a new class of pseudo-variables - $gip(pvc=>key) - + to enable access to the results of a query to the database. + + Many queries can be done and store results in different containers to + be able to use in parallel. Database is loaded at startup in cache. + +2. Dependencies + + 2.1. Kamailio Modules + 2.2. External Libraries or Applications + +2.1. Kamailio Modules + + The following modules must be loaded before this module: + * none. + +2.2. External Libraries or Applications + + The following libraries or applications must be installed before + running Kamailio with this module loaded: + * libmaxminddb - the GeoIP2 library. + +3. Parameters + + 3.1. path (string) + +3.1. path (string) + + Path to the GeoIP2 database file. + + Default value is “null”. + + Example 1.1. Set path parameter +... +modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb") +... + +4. Functions + + 4.1. geoip_match(ipaddr, pvc) + +4.1. geoip_match(ipaddr, pvc) + + Match ipaddr against the GeoIP database and set the pvc container. The + function has to be called before accessing a key via: $gip(pvc=>key). + + Example 1.2. geoip_match usage +... +if(geoip_match("$si", "src")) + xlog("SIP message from: $gip(src=>cc)\n"); +... + +5. Exported pseudo-variables + + * $gip(pvc=>key) - pvc is an identifier for this query result; it is + designated by the second parameter of geoip_match(). The key can be + one of the following: + + cc - country code + + tz - time zone + + zip - postal code + + lat - latitude + + lon - longitude + + nmask - network mask (CIDR format) + + city - city + + regc - region + + regn - region name + + metro - metro code + + Exported pseudo-variables are documented at + http://www.kamailio.org/wiki/. diff --git a/modules/geoip2/doc/Makefile b/modules/geoip2/doc/Makefile new file mode 100644 index 00000000000..997a9b25a11 --- /dev/null +++ b/modules/geoip2/doc/Makefile @@ -0,0 +1,4 @@ +docs = geoip2.xml + +docbook_dir = ../../../docbook +include $(docbook_dir)/Makefile.module diff --git a/modules/geoip2/doc/geoip2.xml b/modules/geoip2/doc/geoip2.xml new file mode 100644 index 00000000000..d69b0edd503 --- /dev/null +++ b/modules/geoip2/doc/geoip2.xml @@ -0,0 +1,36 @@ + + + +%docentities; + +]> + + + + geoip2 Module + &kamailioname; + + + Sergey + Okhapkin + callwithus.com + + + Daniel-Constantin + Mierla + miconda@gmail.com + + + + 2010 + Daniel-Constantin Mierla (asipto.com) + + + + + + + diff --git a/modules/geoip2/doc/geoip2_admin.xml b/modules/geoip2/doc/geoip2_admin.xml new file mode 100644 index 00000000000..f897e497122 --- /dev/null +++ b/modules/geoip2/doc/geoip2_admin.xml @@ -0,0 +1,175 @@ + + + +%docentities; + +]> + + + + + + &adminguide; + +
+ Overview + + This module allows real-time queries against the Max Mind GeoIP2 + database to be performed from the config script. + + + The Max Mind GeoIP2 database is a map of IP network address assignments + to geographical locales that can be useful -- though approximate -- + in identifying the physical location with which an IP host address + is associated on a relatively granular level. + + + This database itself can be obtained on a free or commercial basis + from + http://dev.maxmind.com/geoip/. The + library libmaxminddb + that interfaces with the Max Mind API, as well as scripts to + automate downloading of the on-disk version are available at + + http://dev.maxmind.com/geoip/geoip2/downloadable/. + + + This module exports a new class of pseudo-variables - + $gip(pvc=>key) - to enable access to the results of a query to the + database. + + + Many queries can be done and store results in different containers to + be able to use in parallel. Database is loaded at startup in cache. + +
+
+ Dependencies +
+ &kamailio; Modules + + The following modules must be loaded before this module: + + + + none. + + + + +
+
+ External Libraries or Applications + + The following libraries or applications must be installed before running + &kamailio; with this module loaded: + + + + libmaxminddb - the GeoIP2 library. + + + + +
+
+
+ Parameters +
+ <varname>path</varname> (string) + + Path to the GeoIP2 database file. + + + + Default value is null. + + + + Set <varname>path</varname> parameter + +... +modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb") +... + + +
+ +
+ +
+ Functions +
+ + <function moreinfo="none">geoip_match(ipaddr, pvc)</function> + + + Match ipaddr against the GeoIP database and set the pvc container. The + function has to be called before accessing a key via: $gip(pvc=>key). + + + <function>geoip_match</function> usage + +... +if(geoip_match("$si", "src")) + xlog("SIP message from: $gip(src=>cc)\n"); +... + + +
+ +
+ +
+ Exported pseudo-variables + + + $gip(pvc=>key) - pvc is an + identifier for this query result; it is designated by the second + parameter of geoip_match(). The key can be one of + the following: + + + + cc - country code + + + tz - time zone + + + zip - postal code + + + lat - latitude + + + lon - longitude + + + nmask - network mask (CIDR format) + + + city - city + + + regc - region + + + regn - region name + + + metro - metro code + + + + + + Exported pseudo-variables are documented at &kamwikilink;. + +
+ +
+ diff --git a/modules/geoip2/geoip2_mod.c b/modules/geoip2/geoip2_mod.c new file mode 100644 index 00000000000..fecd34258f9 --- /dev/null +++ b/modules/geoip2/geoip2_mod.c @@ -0,0 +1,139 @@ +/** + * $Id$ + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include + +#include "../../sr_module.h" +#include "../../dprint.h" +#include "../../ut.h" +#include "../../pvar.h" +#include "../../mod_fix.h" + +#include "geoip2_pv.h" + +MODULE_VERSION + +static char *geoip_path = NULL; + +static int mod_init(void); +static void mod_destroy(void); + +static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2); +static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname); + +static pv_export_t mod_pvs[] = { + { {"gip", sizeof("git")-1}, PVT_OTHER, pv_get_geoip, 0, + pv_parse_geoip_name, 0, 0, 0 }, + { {0, 0}, 0, 0, 0, 0, 0, 0, 0 } +}; + + +static cmd_export_t cmds[]={ + {"geoip_match", (cmd_function)w_geoip_match, 2, fixup_spve_spve, + 0, ANY_ROUTE}, + {0, 0, 0, 0, 0, 0} +}; + +static param_export_t params[]={ + {"path", PARAM_STRING, &geoip_path}, + {0, 0, 0} +}; + +struct module_exports exports = { + "geoip2", + DEFAULT_DLFLAGS, /* dlopen flags */ + cmds, + params, + 0, + 0, /* exported MI functions */ + mod_pvs, /* exported pseudo-variables */ + 0, /* extra processes */ + mod_init, /* module initialization function */ + 0, /* response function */ + mod_destroy, /* destroy function */ + 0 /* per child init function */ +}; + + + +/** + * init module function + */ +static int mod_init(void) +{ + + if(geoip_path==NULL || strlen(geoip_path)==0) + { + LM_ERR("path to GeoIP database file not set\n"); + return -1; + } + + if(geoip_init_pv(geoip_path)!=0) + { + LM_ERR("cannot init for database file at: %s\n", geoip_path); + return -1; + } + return 0; +} + +/** + * destroy module function + */ +static void mod_destroy(void) +{ + geoip_destroy_pv(); +} + +static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2) +{ + return geoip_match(msg, (gparam_t*)str1, (gparam_t*)str2); +} + +static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname) +{ + str tomatch; + str pvclass; + + if(msg==NULL) + { + LM_ERR("received null msg\n"); + return -1; + } + + if(fixup_get_svalue(msg, target, &tomatch)<0) + { + LM_ERR("cannot get the address\n"); + return -1; + } + if(fixup_get_svalue(msg, pvname, &pvclass)<0) + { + LM_ERR("cannot get the pv class\n"); + return -1; + } + geoip_pv_reset(&pvclass); + + return geoip_update_pv(&tomatch, &pvclass); +} + diff --git a/modules/geoip2/geoip2_pv.c b/modules/geoip2/geoip2_pv.c new file mode 100644 index 00000000000..4e6b8faf370 --- /dev/null +++ b/modules/geoip2/geoip2_pv.c @@ -0,0 +1,476 @@ +/** + * $Id$ + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#include +#include +#include +#include +#include + +#include "../../dprint.h" +#include "../../hashes.h" +#include "../../pvar.h" + +#include "geoip2_pv.h" + +typedef struct _sr_geoip_record { + MMDB_lookup_result_s record; + str time_zone; + str zip; + str city; + str region_code; + str region_name; + str country; + char latitude[16]; + char longitude[16]; + char metro[16]; + char nmask[8]; + char tomatch[256]; + int flags; +} sr_geoip_record_t; + +typedef struct _sr_geoip_item { + str pvclass; + unsigned int hashid; + sr_geoip_record_t r; + struct _sr_geoip_item *next; +} sr_geoip_item_t; + +typedef struct _geoip_pv { + sr_geoip_item_t *item; + int type; +} geoip_pv_t; + +static MMDB_s _handle_GeoIP; + +static sr_geoip_item_t *_sr_geoip_list = NULL; + +sr_geoip_record_t *sr_geoip_get_record(str *name) +{ + sr_geoip_item_t *it = NULL; + unsigned int hashid = 0; + + hashid = get_hash1_raw(name->s, name->len); + + it = _sr_geoip_list; + while(it!=NULL) + { + if(it->hashid==hashid && it->pvclass.len == name->len + && strncmp(it->pvclass.s, name->s, name->len)==0) + return &it->r; + it = it->next; + } + return NULL; +} + +sr_geoip_item_t *sr_geoip_add_item(str *name) +{ + sr_geoip_item_t *it = NULL; + unsigned int hashid = 0; + + hashid = get_hash1_raw(name->s, name->len); + + it = _sr_geoip_list; + while(it!=NULL) + { + if(it->hashid==hashid && it->pvclass.len == name->len + && strncmp(it->pvclass.s, name->s, name->len)==0) + return it; + it = it->next; + } + /* add new */ + it = (sr_geoip_item_t*)pkg_malloc(sizeof(sr_geoip_item_t)); + if(it==NULL) + { + LM_ERR("no more pkg\n"); + return NULL; + } + memset(it, 0, sizeof(sr_geoip_item_t)); + it->pvclass.s = (char*)pkg_malloc(name->len+1); + if(it->pvclass.s==NULL) + { + LM_ERR("no more pkg.\n"); + pkg_free(it); + return NULL; + } + memcpy(it->pvclass.s, name->s, name->len); + it->pvclass.s[name->len] = '\0'; + it->pvclass.len = name->len; + it->hashid = hashid; + it->next = _sr_geoip_list; + _sr_geoip_list = it; + return it; +} + + +int pv_parse_geoip_name(pv_spec_p sp, str *in) +{ + geoip_pv_t *gpv=NULL; + char *p; + str pvc; + str pvs; + if(sp==NULL || in==NULL || in->len<=0) + return -1; + + gpv = (geoip_pv_t*)pkg_malloc(sizeof(geoip_pv_t)); + if(gpv==NULL) + return -1; + + memset(gpv, 0, sizeof(geoip_pv_t)); + + p = in->s; + + while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) + p++; + if(p>in->s+in->len || *p=='\0') + goto error; + pvc.s = p; + while(p < in->s + in->len) + { + if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r') + break; + p++; + } + if(p>in->s+in->len || *p=='\0') + goto error; + pvc.len = p - pvc.s; + if(*p!='=') + { + while(ps+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) + p++; + if(p>in->s+in->len || *p=='\0' || *p!='=') + goto error; + } + p++; + if(*p!='>') + goto error; + p++; + + pvs.len = in->len - (int)(p - in->s); + pvs.s = p; + LM_DBG("geoip [%.*s] - key [%.*s]\n", pvc.len, pvc.s, + pvs.len, pvs.s); + + gpv->item = sr_geoip_add_item(&pvc); + if(gpv->item==NULL) + goto error; + + switch(pvs.len) + { + case 2: + if(strncmp(pvs.s, "cc", 2)==0) + gpv->type = 0; + else if(strncmp(pvs.s, "tz", 2)==0) + gpv->type = 1; + else goto error; + break; + case 3: + if(strncmp(pvs.s, "zip", 3)==0) + gpv->type = 2; + else if(strncmp(pvs.s, "lat", 3)==0) + gpv->type = 3; + else if(strncmp(pvs.s, "lon", 3)==0) + gpv->type = 4; + else goto error; + break; + case 4: + if(strncmp(pvs.s, "city", 4)==0) + gpv->type = 8; + else if(strncmp(pvs.s, "regc", 4)==0) + gpv->type = 10; + else if(strncmp(pvs.s, "regn", 4)==0) + gpv->type = 11; + else goto error; + break; + case 5: + if(strncmp(pvs.s, "metro", 5)==0) + gpv->type = 12; + else if(strncmp(pvs.s, "nmask", 5)==0) + gpv->type = 13; + else goto error; + break; + default: + goto error; + } + sp->pvp.pvn.u.dname = (void*)gpv; + sp->pvp.pvn.type = PV_NAME_OTHER; + + return 0; + +error: + if(gpv!=NULL) + pkg_free(gpv); + + LM_ERR("error at PV geoip name: %.*s\n", in->len, in->s); + return -1; +} + +int pv_geoip_get_strzval(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res, char *sval) +{ + str s; + if(sval==NULL) + return pv_get_null(msg, param, res); + + s.s = sval; + s.len = strlen(s.s); + return pv_get_strval(msg, param, res, &s); +} + +int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res) +{ + geoip_pv_t *gpv; + MMDB_entry_data_s entry_data; + + if(msg==NULL || param==NULL) + return -1; + + gpv = (geoip_pv_t*)param->pvn.u.dname; + if(gpv==NULL) + return -1; + if(gpv->item==NULL) + return pv_get_null(msg, param, res); + + switch(gpv->type) + { + case 1: /* tz */ + if(gpv->item->r.time_zone.s==NULL) + { + if(gpv->item->r.flags&1) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "location","time_zone", NULL + ) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.time_zone.s = (char *)entry_data.utf8_string; + gpv->item->r.time_zone.len = entry_data.data_size; + } + gpv->item->r.flags |= 1; + } + return pv_get_strval(msg, param, res, &gpv->item->r.time_zone); + case 2: /* zip */ + if(gpv->item->r.zip.s==NULL) + { + if(gpv->item->r.flags&32) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "postal","code", NULL) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.zip.s = (char *)entry_data.utf8_string; + gpv->item->r.zip.len = entry_data.data_size; + } + gpv->item->r.flags |= 32; + } + return pv_get_strval(msg, param, res, &gpv->item->r.zip); + case 3: /* lat */ + if((gpv->item->r.flags&2)==0) + { + gpv->item->r.latitude[0] = '\0'; + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "location","latitude", NULL) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_DOUBLE) + snprintf(gpv->item->r.latitude, 15, "%f", entry_data.double_value); + gpv->item->r.flags |= 2; + } + return pv_geoip_get_strzval(msg, param, res, + gpv->item->r.latitude); + case 4: /* lon */ + if((gpv->item->r.flags&4)==0) + { + gpv->item->r.latitude[0] = '\0'; + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "location","longitude", NULL) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_DOUBLE) + snprintf(gpv->item->r.longitude, 15, "%f", entry_data.double_value); + gpv->item->r.flags |= 4; + } + return pv_geoip_get_strzval(msg, param, res, + gpv->item->r.longitude); + case 8: /* city */ + if(gpv->item->r.city.s==NULL) + { + if(gpv->item->r.flags&64) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "city","names","en", NULL + ) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.city.s = (char *)entry_data.utf8_string; + gpv->item->r.city.len = entry_data.data_size; + } + gpv->item->r.flags |= 64; + } + return pv_get_strval(msg, param, res, &gpv->item->r.city); + case 10: /* regc */ + if(gpv->item->r.region_code.s==NULL) + { + if(gpv->item->r.flags&128) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "subdivisions","0","iso_code", NULL + ) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.region_code.s = (char *)entry_data.utf8_string; + gpv->item->r.region_code.len = entry_data.data_size; + } + gpv->item->r.flags |= 128; + } + return pv_get_strval(msg, param, res, &gpv->item->r.region_code); + case 11: /* regn */ + if(gpv->item->r.region_name.s==NULL) + { + if(gpv->item->r.flags&16) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "subdivisions","0","names","en", NULL + ) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.region_name.s = (char *)entry_data.utf8_string; + gpv->item->r.region_name.len = entry_data.data_size; + } + gpv->item->r.flags |= 16; + } + return pv_get_strval(msg, param, res, &gpv->item->r.region_name); + case 12: /* metro */ + if((gpv->item->r.flags&256)==0) + { + gpv->item->r.metro[0] = '\0'; + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "location","metro_code", NULL) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UINT16) + snprintf(gpv->item->r.metro, 15, "%hd", entry_data.uint16); + gpv->item->r.flags |= 256; + } + return pv_geoip_get_strzval(msg, param, res, + gpv->item->r.metro); + case 13: /* nmask */ + if((gpv->item->r.flags&1024)==0) + { + gpv->item->r.nmask[0] = '\0'; + snprintf(gpv->item->r.nmask, 8, "%hd", gpv->item->r.record.netmask); + gpv->item->r.flags |= 1024; + } + return pv_geoip_get_strzval(msg, param, res, + gpv->item->r.nmask); + default: /* cc */ + if(gpv->item->r.country.s==NULL) + { + if(gpv->item->r.flags&512) + return pv_get_null(msg, param, res); + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "country","iso_code", NULL + ) != MMDB_SUCCESS) + return pv_get_null(msg, param, res); + if(entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + gpv->item->r.country.s = (char *)entry_data.utf8_string; + gpv->item->r.country.len = entry_data.data_size; + } + if(MMDB_get_value(&gpv->item->r.record.entry, &entry_data, + "traits","is_anonymous_proxy", NULL) == MMDB_SUCCESS + && entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_BOOLEAN + && entry_data.boolean) { + gpv->item->r.country.s = "A1"; + gpv->item->r.country.len = 2; + } + gpv->item->r.flags |= 512; + } + return pv_get_strval(msg, param, res, &gpv->item->r.country); + } +} + +int geoip_init_pv(char *path) +{ + int status = MMDB_open(path, MMDB_MODE_MMAP, &_handle_GeoIP); + + if(MMDB_SUCCESS != status) + { + LM_ERR("cannot open GeoIP database file at: %s\n", path); + return -1; + } + return 0; +} + +void geoip_destroy_list(void) +{ +} + +void geoip_destroy_pv(void) +{ + MMDB_close(&_handle_GeoIP); +} + +void geoip_pv_reset(str *name) +{ + sr_geoip_record_t *gr = NULL; + + gr = sr_geoip_get_record(name); + + if(gr==NULL) + return; + memset(gr, 0, sizeof(struct _sr_geoip_record)); +} + +int geoip_update_pv(str *tomatch, str *name) +{ + sr_geoip_record_t *gr = NULL; + int gai_error, mmdb_error; + + if(tomatch->len>255) + { + LM_DBG("target too long (max 255): %s\n", tomatch->s); + return -3; + } + + gr = sr_geoip_get_record(name); + if(gr==NULL) + { + LM_DBG("container not found: %s\n", tomatch->s); + return - 4; + } + + strncpy(gr->tomatch, tomatch->s, tomatch->len); + tomatch->s[tomatch->len] = '\0'; + gr->record = MMDB_lookup_string(&_handle_GeoIP, + (const char*)gr->tomatch, + &gai_error, &mmdb_error + ); + LM_DBG("attempt to match: %s\n", gr->tomatch); + if (gai_error || MMDB_SUCCESS != mmdb_error || !gr->record.found_entry) + { + LM_DBG("no match for: %s\n", gr->tomatch); + return -2; + } + LM_DBG("geoip PV updated for: %s\n", gr->tomatch); + + return 1; +} + diff --git a/modules/geoip2/geoip2_pv.h b/modules/geoip2/geoip2_pv.h new file mode 100644 index 00000000000..baa52be5c95 --- /dev/null +++ b/modules/geoip2/geoip2_pv.h @@ -0,0 +1,40 @@ +/** + * $Id$ + * + * This file is part of Kamailio, a free SIP server. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _GEOIP_PV_H_ +#define _GEOIP_PV_H_ + +#include + +#include "../../pvar.h" + +int pv_parse_geoip_name(pv_spec_p sp, str *in); +int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, + pv_value_t *res); + +int geoip_init_pv(char *path); +void geoip_destroy_pv(void); +void geoip_pv_reset(str *pvclass); +int geoip_update_pv(str *tomatch, str *pvclass); + +#endif + From 0ea380cb86a7840b50f5c637203e9f63433b6afa Mon Sep 17 00:00:00 2001 From: Sergey Okhapkin Date: Mon, 2 Feb 2015 10:09:40 -0500 Subject: [PATCH 2/4] exported function name change --- modules/geoip2/geoip2_mod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/geoip2/geoip2_mod.c b/modules/geoip2/geoip2_mod.c index fecd34258f9..44bc59797f8 100644 --- a/modules/geoip2/geoip2_mod.c +++ b/modules/geoip2/geoip2_mod.c @@ -51,7 +51,7 @@ static pv_export_t mod_pvs[] = { static cmd_export_t cmds[]={ - {"geoip_match", (cmd_function)w_geoip_match, 2, fixup_spve_spve, + {"geoip2_match", (cmd_function)w_geoip_match, 2, fixup_spve_spve, 0, ANY_ROUTE}, {0, 0, 0, 0, 0, 0} }; From 554591218030ef85be5e11ed6b5da521d06de049 Mon Sep 17 00:00:00 2001 From: Sergey Okhapkin Date: Mon, 2 Feb 2015 10:53:45 -0500 Subject: [PATCH 3/4] s/geoip/geoip2/ --- modules/geoip2/README | 26 ++++---- modules/geoip2/doc/geoip2_admin.xml | 16 ++--- modules/geoip2/geoip2_mod.c | 32 +++++----- modules/geoip2/geoip2_pv.c | 92 ++++++++++++++--------------- modules/geoip2/geoip2_pv.h | 12 ++-- 5 files changed, 89 insertions(+), 89 deletions(-) diff --git a/modules/geoip2/README b/modules/geoip2/README index 61231529d95..c9cb1edab3b 100644 --- a/modules/geoip2/README +++ b/modules/geoip2/README @@ -29,14 +29,14 @@ Daniel-Constantin Mierla 4. Functions - 4.1. geoip_match(ipaddr, pvc) + 4.1. geoip2_match(ipaddr, pvc) 5. Exported pseudo-variables List of Examples 1.1. Set path parameter - 1.2. geoip_match usage + 1.2. geoip2_match usage Chapter 1. Admin Guide @@ -54,7 +54,7 @@ Chapter 1. Admin Guide 4. Functions - 4.1. geoip_match(ipaddr, pvc) + 4.1. geoip2_match(ipaddr, pvc) 5. Exported pseudo-variables @@ -74,7 +74,7 @@ Chapter 1. Admin Guide the on-disk version are available at http://dev.maxmind.com/geoip/geoip2/downloadable/. - This module exports a new class of pseudo-variables - $gip(pvc=>key) - + This module exports a new class of pseudo-variables - $gip2(pvc=>key) - to enable access to the results of a query to the database. Many queries can be done and store results in different containers to @@ -113,24 +113,24 @@ modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb") 4. Functions - 4.1. geoip_match(ipaddr, pvc) + 4.1. geoip2_match(ipaddr, pvc) -4.1. geoip_match(ipaddr, pvc) +4.1. geoip2_match(ipaddr, pvc) Match ipaddr against the GeoIP database and set the pvc container. The - function has to be called before accessing a key via: $gip(pvc=>key). + function has to be called before accessing a key via: $gip2(pvc=>key). - Example 1.2. geoip_match usage + Example 1.2. geoip2_match usage ... -if(geoip_match("$si", "src")) - xlog("SIP message from: $gip(src=>cc)\n"); +if(geoip2_match("$si", "src")) + xlog("SIP message from: $gip2(src=>cc)\n"); ... 5. Exported pseudo-variables - * $gip(pvc=>key) - pvc is an identifier for this query result; it is - designated by the second parameter of geoip_match(). The key can be - one of the following: + * $gip2(pvc=>key) - pvc is an identifier for this query result; it is + designated by the second parameter of geoip2_match(). The key can + be one of the following: + cc - country code + tz - time zone + zip - postal code diff --git a/modules/geoip2/doc/geoip2_admin.xml b/modules/geoip2/doc/geoip2_admin.xml index f897e497122..244930dd733 100644 --- a/modules/geoip2/doc/geoip2_admin.xml +++ b/modules/geoip2/doc/geoip2_admin.xml @@ -38,7 +38,7 @@ This module exports a new class of pseudo-variables - - $gip(pvc=>key) - to enable access to the results of a query to the + $gip2(pvc=>key) - to enable access to the results of a query to the database. @@ -104,18 +104,18 @@ modparam("geoip2", "path", "/usr/local/share/GeoIP/GeoLite2-City.mmdb") Functions
- <function moreinfo="none">geoip_match(ipaddr, pvc)</function> + <function moreinfo="none">geoip2_match(ipaddr, pvc)</function> Match ipaddr against the GeoIP database and set the pvc container. The - function has to be called before accessing a key via: $gip(pvc=>key). + function has to be called before accessing a key via: $gip2(pvc=>key). - <function>geoip_match</function> usage + <function>geoip2_match</function> usage ... -if(geoip_match("$si", "src")) - xlog("SIP message from: $gip(src=>cc)\n"); +if(geoip2_match("$si", "src")) + xlog("SIP message from: $gip2(src=>cc)\n"); ... @@ -127,9 +127,9 @@ if(geoip_match("$si", "src")) Exported pseudo-variables - $gip(pvc=>key) - pvc is an + $gip2(pvc=>key) - pvc is an identifier for this query result; it is designated by the second - parameter of geoip_match(). The key can be one of + parameter of geoip2_match(). The key can be one of the following: diff --git a/modules/geoip2/geoip2_mod.c b/modules/geoip2/geoip2_mod.c index 44bc59797f8..d9b2314dea8 100644 --- a/modules/geoip2/geoip2_mod.c +++ b/modules/geoip2/geoip2_mod.c @@ -35,29 +35,29 @@ MODULE_VERSION -static char *geoip_path = NULL; +static char *geoip2_path = NULL; static int mod_init(void); static void mod_destroy(void); -static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2); -static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname); +static int w_geoip2_match(struct sip_msg* msg, char* str1, char* str2); +static int geoip2_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname); static pv_export_t mod_pvs[] = { - { {"gip", sizeof("git")-1}, PVT_OTHER, pv_get_geoip, 0, - pv_parse_geoip_name, 0, 0, 0 }, + { {"gip2", sizeof("gip2")-1}, PVT_OTHER, pv_get_geoip2, 0, + pv_parse_geoip2_name, 0, 0, 0 }, { {0, 0}, 0, 0, 0, 0, 0, 0, 0 } }; static cmd_export_t cmds[]={ - {"geoip2_match", (cmd_function)w_geoip_match, 2, fixup_spve_spve, + {"geoip2_match", (cmd_function)w_geoip2_match, 2, fixup_spve_spve, 0, ANY_ROUTE}, {0, 0, 0, 0, 0, 0} }; static param_export_t params[]={ - {"path", PARAM_STRING, &geoip_path}, + {"path", PARAM_STRING, &geoip2_path}, {0, 0, 0} }; @@ -84,15 +84,15 @@ struct module_exports exports = { static int mod_init(void) { - if(geoip_path==NULL || strlen(geoip_path)==0) + if(geoip2_path==NULL || strlen(geoip2_path)==0) { LM_ERR("path to GeoIP database file not set\n"); return -1; } - if(geoip_init_pv(geoip_path)!=0) + if(geoip2_init_pv(geoip2_path)!=0) { - LM_ERR("cannot init for database file at: %s\n", geoip_path); + LM_ERR("cannot init for database file at: %s\n", geoip2_path); return -1; } return 0; @@ -103,15 +103,15 @@ static int mod_init(void) */ static void mod_destroy(void) { - geoip_destroy_pv(); + geoip2_destroy_pv(); } -static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2) +static int w_geoip2_match(struct sip_msg* msg, char* str1, char* str2) { - return geoip_match(msg, (gparam_t*)str1, (gparam_t*)str2); + return geoip2_match(msg, (gparam_t*)str1, (gparam_t*)str2); } -static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname) +static int geoip2_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname) { str tomatch; str pvclass; @@ -132,8 +132,8 @@ static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname) LM_ERR("cannot get the pv class\n"); return -1; } - geoip_pv_reset(&pvclass); + geoip2_pv_reset(&pvclass); - return geoip_update_pv(&tomatch, &pvclass); + return geoip2_update_pv(&tomatch, &pvclass); } diff --git a/modules/geoip2/geoip2_pv.c b/modules/geoip2/geoip2_pv.c index 4e6b8faf370..f9f7dbba6a2 100644 --- a/modules/geoip2/geoip2_pv.c +++ b/modules/geoip2/geoip2_pv.c @@ -33,7 +33,7 @@ #include "geoip2_pv.h" -typedef struct _sr_geoip_record { +typedef struct _sr_geoip2_record { MMDB_lookup_result_s record; str time_zone; str zip; @@ -47,32 +47,32 @@ typedef struct _sr_geoip_record { char nmask[8]; char tomatch[256]; int flags; -} sr_geoip_record_t; +} sr_geoip2_record_t; -typedef struct _sr_geoip_item { +typedef struct _sr_geoip2_item { str pvclass; unsigned int hashid; - sr_geoip_record_t r; - struct _sr_geoip_item *next; -} sr_geoip_item_t; + sr_geoip2_record_t r; + struct _sr_geoip2_item *next; +} sr_geoip2_item_t; -typedef struct _geoip_pv { - sr_geoip_item_t *item; +typedef struct _geoip2_pv { + sr_geoip2_item_t *item; int type; -} geoip_pv_t; +} geoip2_pv_t; static MMDB_s _handle_GeoIP; -static sr_geoip_item_t *_sr_geoip_list = NULL; +static sr_geoip2_item_t *_sr_geoip2_list = NULL; -sr_geoip_record_t *sr_geoip_get_record(str *name) +sr_geoip2_record_t *sr_geoip2_get_record(str *name) { - sr_geoip_item_t *it = NULL; + sr_geoip2_item_t *it = NULL; unsigned int hashid = 0; hashid = get_hash1_raw(name->s, name->len); - it = _sr_geoip_list; + it = _sr_geoip2_list; while(it!=NULL) { if(it->hashid==hashid && it->pvclass.len == name->len @@ -83,14 +83,14 @@ sr_geoip_record_t *sr_geoip_get_record(str *name) return NULL; } -sr_geoip_item_t *sr_geoip_add_item(str *name) +sr_geoip2_item_t *sr_geoip2_add_item(str *name) { - sr_geoip_item_t *it = NULL; + sr_geoip2_item_t *it = NULL; unsigned int hashid = 0; hashid = get_hash1_raw(name->s, name->len); - it = _sr_geoip_list; + it = _sr_geoip2_list; while(it!=NULL) { if(it->hashid==hashid && it->pvclass.len == name->len @@ -99,13 +99,13 @@ sr_geoip_item_t *sr_geoip_add_item(str *name) it = it->next; } /* add new */ - it = (sr_geoip_item_t*)pkg_malloc(sizeof(sr_geoip_item_t)); + it = (sr_geoip2_item_t*)pkg_malloc(sizeof(sr_geoip2_item_t)); if(it==NULL) { LM_ERR("no more pkg\n"); return NULL; } - memset(it, 0, sizeof(sr_geoip_item_t)); + memset(it, 0, sizeof(sr_geoip2_item_t)); it->pvclass.s = (char*)pkg_malloc(name->len+1); if(it->pvclass.s==NULL) { @@ -117,26 +117,26 @@ sr_geoip_item_t *sr_geoip_add_item(str *name) it->pvclass.s[name->len] = '\0'; it->pvclass.len = name->len; it->hashid = hashid; - it->next = _sr_geoip_list; - _sr_geoip_list = it; + it->next = _sr_geoip2_list; + _sr_geoip2_list = it; return it; } -int pv_parse_geoip_name(pv_spec_p sp, str *in) +int pv_parse_geoip2_name(pv_spec_p sp, str *in) { - geoip_pv_t *gpv=NULL; + geoip2_pv_t *gpv=NULL; char *p; str pvc; str pvs; if(sp==NULL || in==NULL || in->len<=0) return -1; - gpv = (geoip_pv_t*)pkg_malloc(sizeof(geoip_pv_t)); + gpv = (geoip2_pv_t*)pkg_malloc(sizeof(geoip2_pv_t)); if(gpv==NULL) return -1; - memset(gpv, 0, sizeof(geoip_pv_t)); + memset(gpv, 0, sizeof(geoip2_pv_t)); p = in->s; @@ -168,10 +168,10 @@ int pv_parse_geoip_name(pv_spec_p sp, str *in) pvs.len = in->len - (int)(p - in->s); pvs.s = p; - LM_DBG("geoip [%.*s] - key [%.*s]\n", pvc.len, pvc.s, + LM_DBG("geoip2 [%.*s] - key [%.*s]\n", pvc.len, pvc.s, pvs.len, pvs.s); - gpv->item = sr_geoip_add_item(&pvc); + gpv->item = sr_geoip2_add_item(&pvc); if(gpv->item==NULL) goto error; @@ -221,11 +221,11 @@ int pv_parse_geoip_name(pv_spec_p sp, str *in) if(gpv!=NULL) pkg_free(gpv); - LM_ERR("error at PV geoip name: %.*s\n", in->len, in->s); + LM_ERR("error at PV geoip2 name: %.*s\n", in->len, in->s); return -1; } -int pv_geoip_get_strzval(struct sip_msg *msg, pv_param_t *param, +int pv_geoip2_get_strzval(struct sip_msg *msg, pv_param_t *param, pv_value_t *res, char *sval) { str s; @@ -237,16 +237,16 @@ int pv_geoip_get_strzval(struct sip_msg *msg, pv_param_t *param, return pv_get_strval(msg, param, res, &s); } -int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, +int pv_get_geoip2(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) { - geoip_pv_t *gpv; + geoip2_pv_t *gpv; MMDB_entry_data_s entry_data; if(msg==NULL || param==NULL) return -1; - gpv = (geoip_pv_t*)param->pvn.u.dname; + gpv = (geoip2_pv_t*)param->pvn.u.dname; if(gpv==NULL) return -1; if(gpv->item==NULL) @@ -296,7 +296,7 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, snprintf(gpv->item->r.latitude, 15, "%f", entry_data.double_value); gpv->item->r.flags |= 2; } - return pv_geoip_get_strzval(msg, param, res, + return pv_geoip2_get_strzval(msg, param, res, gpv->item->r.latitude); case 4: /* lon */ if((gpv->item->r.flags&4)==0) @@ -309,7 +309,7 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, snprintf(gpv->item->r.longitude, 15, "%f", entry_data.double_value); gpv->item->r.flags |= 4; } - return pv_geoip_get_strzval(msg, param, res, + return pv_geoip2_get_strzval(msg, param, res, gpv->item->r.longitude); case 8: /* city */ if(gpv->item->r.city.s==NULL) @@ -370,7 +370,7 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, snprintf(gpv->item->r.metro, 15, "%hd", entry_data.uint16); gpv->item->r.flags |= 256; } - return pv_geoip_get_strzval(msg, param, res, + return pv_geoip2_get_strzval(msg, param, res, gpv->item->r.metro); case 13: /* nmask */ if((gpv->item->r.flags&1024)==0) @@ -379,7 +379,7 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, snprintf(gpv->item->r.nmask, 8, "%hd", gpv->item->r.record.netmask); gpv->item->r.flags |= 1024; } - return pv_geoip_get_strzval(msg, param, res, + return pv_geoip2_get_strzval(msg, param, res, gpv->item->r.nmask); default: /* cc */ if(gpv->item->r.country.s==NULL) @@ -407,7 +407,7 @@ int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, } } -int geoip_init_pv(char *path) +int geoip2_init_pv(char *path) { int status = MMDB_open(path, MMDB_MODE_MMAP, &_handle_GeoIP); @@ -419,29 +419,29 @@ int geoip_init_pv(char *path) return 0; } -void geoip_destroy_list(void) +void geoip2_destroy_list(void) { } -void geoip_destroy_pv(void) +void geoip2_destroy_pv(void) { MMDB_close(&_handle_GeoIP); } -void geoip_pv_reset(str *name) +void geoip2_pv_reset(str *name) { - sr_geoip_record_t *gr = NULL; + sr_geoip2_record_t *gr = NULL; - gr = sr_geoip_get_record(name); + gr = sr_geoip2_get_record(name); if(gr==NULL) return; - memset(gr, 0, sizeof(struct _sr_geoip_record)); + memset(gr, 0, sizeof(struct _sr_geoip2_record)); } -int geoip_update_pv(str *tomatch, str *name) +int geoip2_update_pv(str *tomatch, str *name) { - sr_geoip_record_t *gr = NULL; + sr_geoip2_record_t *gr = NULL; int gai_error, mmdb_error; if(tomatch->len>255) @@ -450,7 +450,7 @@ int geoip_update_pv(str *tomatch, str *name) return -3; } - gr = sr_geoip_get_record(name); + gr = sr_geoip2_get_record(name); if(gr==NULL) { LM_DBG("container not found: %s\n", tomatch->s); @@ -469,7 +469,7 @@ int geoip_update_pv(str *tomatch, str *name) LM_DBG("no match for: %s\n", gr->tomatch); return -2; } - LM_DBG("geoip PV updated for: %s\n", gr->tomatch); + LM_DBG("geoip2 PV updated for: %s\n", gr->tomatch); return 1; } diff --git a/modules/geoip2/geoip2_pv.h b/modules/geoip2/geoip2_pv.h index baa52be5c95..05ebf80d77b 100644 --- a/modules/geoip2/geoip2_pv.h +++ b/modules/geoip2/geoip2_pv.h @@ -27,14 +27,14 @@ #include "../../pvar.h" -int pv_parse_geoip_name(pv_spec_p sp, str *in); -int pv_get_geoip(struct sip_msg *msg, pv_param_t *param, +int pv_parse_geoip2_name(pv_spec_p sp, str *in); +int pv_get_geoip2(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); -int geoip_init_pv(char *path); -void geoip_destroy_pv(void); -void geoip_pv_reset(str *pvclass); -int geoip_update_pv(str *tomatch, str *pvclass); +int geoip2_init_pv(char *path); +void geoip2_destroy_pv(void); +void geoip2_pv_reset(str *pvclass); +int geoip2_update_pv(str *tomatch, str *pvclass); #endif From d611b31edd549783748bbac890cd4ddb01da9fbc Mon Sep 17 00:00:00 2001 From: Sergey Okhapkin Date: Tue, 3 Feb 2015 21:26:57 -0500 Subject: [PATCH 4/4] Ignore location records with non-local socket address - the patch allows to share location table between multiple instances of kamailio. On startup kamailio will only read location table records belonging to the current instance and will not remove those records from the table on registration expiry. --- modules/usrloc/udomain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/usrloc/udomain.c b/modules/usrloc/udomain.c index 8006e1718bc..f4dc48bc8d2 100644 --- a/modules/usrloc/udomain.c +++ b/modules/usrloc/udomain.c @@ -310,6 +310,7 @@ static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact) ci.sock = grep_sock_info( &host, (unsigned short)port, proto); if (ci.sock==0) { LM_INFO("non-local socket <%s>...ignoring\n", p); + return 0; } }