Browse code

geoip: new module for GeoIP checking

- get details about an ip address from GeoIP database
- results can be accessed via pseudo-variables: $gip(pvc=>key)
- ability to perform many searches and use results in parallel
- geoip db is loaded in cache at startup

Daniel-Constantin Mierla authored on 20/01/2010 10:49:10
Showing 8 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+# $Id$
2
+#
3
+# WARNING: do not run this directly, it should be run by the master Makefile
4
+
5
+include ../../Makefile.defs
6
+auto_gen=
7
+NAME=geoip.so
8
+LIBS= -lGeoIP
9
+
10
+DEFS+=-DOPENSER_MOD_INTERFACE
11
+
12
+SERLIBPATH=../../lib
13
+SER_LIBS+=$(SERLIBPATH)/kmi/kmi
14
+
15
+include ../../Makefile.modules
0 16
new file mode 100644
... ...
@@ -0,0 +1,135 @@
1
+geoip Module
2
+
3
+Daniel-Constantin Mierla
4
+
5
+   asipto.com
6
+
7
+Edited by
8
+
9
+Daniel-Constantin Mierla
10
+
11
+   <miconda@gmail.com>
12
+
13
+   Copyright � 2010 Daniel-Constantin Mierla (asipto.com)
14
+     __________________________________________________________________
15
+
16
+   Table of Contents
17
+
18
+   1. Admin Guide
19
+
20
+        1. Overview
21
+        2. Dependencies
22
+
23
+              2.1. Kamailio Modules
24
+              2.2. External Libraries or Applications
25
+
26
+        3. Exported Parameters
27
+
28
+              3.1. path (string)
29
+
30
+        4. Exported Functions
31
+
32
+              4.1. geoip_match(ipaddr, pvc)
33
+
34
+        5. Exported pseudo-variables
35
+
36
+   List of Examples
37
+
38
+   1.1. Set path parameter
39
+   1.2. geoip_match usage
40
+
41
+Chapter 1. Admin Guide
42
+
43
+   Table of Contents
44
+
45
+   1. Overview
46
+   2. Dependencies
47
+
48
+        2.1. Kamailio Modules
49
+        2.2. External Libraries or Applications
50
+
51
+   3. Exported Parameters
52
+
53
+        3.1. path (string)
54
+
55
+   4. Exported Functions
56
+
57
+        4.1. geoip_match(ipaddr, pvc)
58
+
59
+   5. Exported pseudo-variables
60
+
61
+1. Overview
62
+
63
+   The module loads exports a new class of pseudo-variables -
64
+   $gip(pvc=>key) - to access results upon a query against Max Mind GeoIP
65
+   database.
66
+
67
+   Many queries can be done and store results in different containers to
68
+   be able to use in parallel. Database is loaded at startup in chache.
69
+
70
+2. Dependencies
71
+
72
+   2.1. Kamailio Modules
73
+   2.2. External Libraries or Applications
74
+
75
+2.1. Kamailio Modules
76
+
77
+   The following modules must be loaded before this module:
78
+     * none.
79
+
80
+2.2. External Libraries or Applications
81
+
82
+   The following libraries or applications must be installed before
83
+   running Kamailio with this module loaded:
84
+     * libgeoip - the GeoIP library.
85
+
86
+3. Exported Parameters
87
+
88
+   3.1. path (string)
89
+
90
+3.1. path (string)
91
+
92
+   Path to GeoIP database file.
93
+
94
+   Default value is "null".
95
+
96
+   Example 1.1. Set path parameter
97
+...
98
+modparam("geoip", "path", "/usr/local/share/GeoLiteCity.dat")
99
+...
100
+
101
+4. Exported Functions
102
+
103
+   4.1. geoip_match(ipaddr, pvc)
104
+
105
+4.1.  geoip_match(ipaddr, pvc)
106
+
107
+   Match ipaddr against GeoIP database and set the pvc container. The
108
+   function has to be called before accessing any $gip(pvc=>key).
109
+
110
+   Example 1.2. geoip_match usage
111
+...
112
+if(geoip_match("$si", "src"))
113
+    xlog("SIP message from: $gip(src=>cc)\n");
114
+...
115
+
116
+5. Exported pseudo-variables
117
+
118
+     * $gip(pvc=>key) - pvc is second parameter of geoip_match() and key
119
+       can be:
120
+          + cc - country code
121
+          + tz - time zone
122
+          + zip - postal code
123
+          + lat - latitude
124
+          + lon - longitude
125
+          + dma - dma code
126
+          + ips - ip start
127
+          + ipe - ip end
128
+          + city - city
129
+          + area - area code
130
+          + regc - region
131
+          + regn - region name
132
+          + metro - metro code
133
+
134
+   Exported pseudo-variables are documented at
135
+   http://www.kamailio.org/dokuwiki/.
0 136
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = geoip.xml
2
+
3
+docbook_dir = ../../../docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,36 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
12
+    <bookinfo>
13
+	<title>geoip Module</title>
14
+	<productname class="trade">&kamailioname;</productname>
15
+	<authorgroup>
16
+	    <author>
17
+		<firstname>Daniel-Constantin</firstname>
18
+		<surname>Mierla</surname>
19
+		<affiliation><orgname>asipto.com</orgname></affiliation>
20
+	    </author>
21
+	    <editor>
22
+		<firstname>Daniel-Constantin</firstname>
23
+		<surname>Mierla</surname>
24
+		    <email>miconda@gmail.com</email>
25
+	    </editor>
26
+	</authorgroup>
27
+	<copyright>
28
+	    <year>2010</year>
29
+	    <holder>Daniel-Constantin Mierla (asipto.com)</holder>
30
+	</copyright>
31
+    </bookinfo>
32
+    <toc></toc>
33
+    
34
+	<xi:include href="geoip_admin.xml"/>
35
+    
36
+</book>
0 37
new file mode 100644
... ...
@@ -0,0 +1,162 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<!-- Module User's Guide -->
12
+
13
+<chapter>
14
+    
15
+    <title>&adminguide;</title>
16
+    
17
+    <section>
18
+	<title>Overview</title>
19
+	<para>
20
+		The module loads exports a new class of pseudo-variables -
21
+		$gip(pvc=&gt;key) - to access results upon a query against Max Mind
22
+		GeoIP database.
23
+	</para>
24
+	<para>
25
+		Many queries can be done and store results in different containers to
26
+		be able to use in parallel. Database is loaded at startup in chache.
27
+	</para>
28
+    </section>
29
+    <section>
30
+	<title>Dependencies</title>
31
+	<section>
32
+	    <title>&kamailio; Modules</title>
33
+	    <para>
34
+		The following modules must be loaded before this module:
35
+	    	<itemizedlist>
36
+		    <listitem>
37
+			<para>
38
+			    <emphasis>none</emphasis>.
39
+			</para>
40
+		    </listitem>
41
+	    	</itemizedlist>
42
+	    </para>
43
+	</section>
44
+	<section>
45
+	    <title>External Libraries or Applications</title>
46
+	    <para>
47
+		The following libraries or applications must be installed before running
48
+		&kamailio; with this module loaded:
49
+	    	<itemizedlist>
50
+		    <listitem>
51
+			<para>
52
+			    <emphasis>libgeoip</emphasis> - the GeoIP library.
53
+			</para>
54
+		    </listitem>
55
+	    	</itemizedlist>
56
+	    </para>
57
+	</section>
58
+    </section>
59
+    <section>
60
+	<title>Exported Parameters</title>
61
+	<section>
62
+	    <title><varname>path</varname> (string)</title>
63
+	    <para>
64
+		Path to GeoIP database file.
65
+	    </para>
66
+	    <para>
67
+		<emphasis>
68
+		    Default value is <quote>null</quote>.
69
+		</emphasis>
70
+	    </para>
71
+	    <example>
72
+		<title>Set <varname>path</varname> parameter</title>
73
+		<programlisting format="linespecific">
74
+...
75
+modparam("geoip", "path", "/usr/local/share/GeoLiteCity.dat")
76
+...
77
+</programlisting>
78
+	    </example>
79
+	</section>
80
+
81
+	</section>
82
+	
83
+    <section>
84
+	<title>Exported Functions</title>
85
+ 	<section>
86
+	    <title>
87
+		<function moreinfo="none">geoip_match(ipaddr, pvc)</function>
88
+	    </title>
89
+	    <para>
90
+			Match ipaddr against GeoIP database and set the pvc container. The
91
+			function has to be called before accessing any $gip(pvc=&gt;key).
92
+	    </para>
93
+		<example>
94
+		<title><function>geoip_match</function> usage</title>
95
+		<programlisting format="linespecific">
96
+...
97
+if(geoip_match("$si", "src"))
98
+    xlog("SIP message from: $gip(src=&gt;cc)\n");
99
+...
100
+</programlisting>
101
+	    </example>
102
+	</section>
103
+	
104
+    </section>
105
+	
106
+	<section>
107
+		<title>Exported pseudo-variables</title>
108
+		<itemizedlist>
109
+			<listitem><para>
110
+				<emphasis>$gip(pvc=&gt;key)</emphasis> - pvc is second
111
+				parameter of geoip_match() and key can be:
112
+				</para>
113
+			<itemizedlist>
114
+				<listitem><para>
115
+					<emphasis>cc</emphasis> - country code
116
+				</para></listitem>
117
+				<listitem><para>
118
+					<emphasis>tz</emphasis> - time zone
119
+				</para></listitem>
120
+				<listitem><para>
121
+					<emphasis>zip</emphasis> - postal code
122
+				</para></listitem>
123
+				<listitem><para>
124
+					<emphasis>lat</emphasis> - latitude
125
+				</para></listitem>
126
+				<listitem><para>
127
+					<emphasis>lon</emphasis> - longitude
128
+				</para></listitem>
129
+				<listitem><para>
130
+					<emphasis>dma</emphasis> - dma code
131
+				</para></listitem>
132
+				<listitem><para>
133
+					<emphasis>ips</emphasis> - ip start
134
+				</para></listitem>
135
+				<listitem><para>
136
+					<emphasis>ipe</emphasis> - ip end
137
+				</para></listitem>
138
+				<listitem><para>
139
+					<emphasis>city</emphasis> - city
140
+				</para></listitem>
141
+				<listitem><para>
142
+					<emphasis>area</emphasis> - area code
143
+				</para></listitem>
144
+				<listitem><para>
145
+					<emphasis>regc</emphasis> - region
146
+				</para></listitem>
147
+				<listitem><para>
148
+					<emphasis>regn</emphasis> - region name
149
+				</para></listitem>
150
+				<listitem><para>
151
+					<emphasis>metro</emphasis> - metro code
152
+				</para></listitem>
153
+			</itemizedlist>
154
+			</listitem>
155
+		</itemizedlist>
156
+		<para>
157
+		Exported pseudo-variables are documented at &kamwikilink;.
158
+		</para>
159
+	</section>
160
+
161
+</chapter>
162
+
0 163
new file mode 100644
... ...
@@ -0,0 +1,141 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * This file is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ *
14
+ * This file is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ */
24
+
25
+#include <stdio.h>
26
+#include <unistd.h>
27
+#include <stdlib.h>
28
+#include <string.h>
29
+
30
+#include "../../sr_module.h"
31
+#include "../../dprint.h"
32
+#include "../../ut.h"
33
+#include "../../pvar.h"
34
+#include "../../mod_fix.h"
35
+
36
+#include "geoip_pv.h"
37
+
38
+MODULE_VERSION
39
+
40
+static char *geoip_path = NULL;
41
+
42
+static int  mod_init(void);
43
+static void mod_destroy(void);
44
+
45
+static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2);
46
+static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname);
47
+
48
+static pv_export_t mod_pvs[] = {
49
+	{ {"gip", sizeof("git")-1}, PVT_OTHER, pv_get_geoip, 0,
50
+		pv_parse_geoip_name, 0, 0, 0 },
51
+	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
52
+};
53
+
54
+
55
+static cmd_export_t cmds[]={
56
+	{"geoip_match", (cmd_function)w_geoip_match, 2, fixup_spve_spve,
57
+		0, ANY_ROUTE},
58
+	{0, 0, 0, 0, 0, 0}
59
+};
60
+
61
+static param_export_t params[]={
62
+	{"path",     STR_PARAM, &geoip_path},
63
+	{0, 0, 0}
64
+};
65
+
66
+struct module_exports exports = {
67
+	"geoip",
68
+	DEFAULT_DLFLAGS, /* dlopen flags */
69
+	cmds,
70
+	params,
71
+	0,
72
+	0,              /* exported MI functions */
73
+	mod_pvs,        /* exported pseudo-variables */
74
+	0,              /* extra processes */
75
+	mod_init,       /* module initialization function */
76
+	0,              /* response function */
77
+	mod_destroy,    /* destroy function */
78
+	0               /* per child init function */
79
+};
80
+
81
+
82
+
83
+/**
84
+ * init module function
85
+ */
86
+static int mod_init(void)
87
+{
88
+
89
+	if(geoip_path==NULL || strlen(geoip_path)==0)
90
+	{
91
+		LM_ERR("path to GeoIP database file not set\n");
92
+		return -1;
93
+	}
94
+
95
+	if(geoip_init_pv(geoip_path)!=0)
96
+	{
97
+		LM_ERR("cannot init for database file at: %s\n", geoip_path);
98
+		return -1;
99
+	}
100
+	return 0;
101
+}
102
+
103
+/**
104
+ * destroy module function
105
+ */
106
+static void mod_destroy(void)
107
+{
108
+	geoip_destroy_pv();
109
+}
110
+
111
+static int w_geoip_match(struct sip_msg* msg, char* str1, char* str2)
112
+{
113
+	return geoip_match(msg, (gparam_t*)str1, (gparam_t*)str2);
114
+}
115
+
116
+static int geoip_match(struct sip_msg *msg, gparam_t *target, gparam_t *pvname)
117
+{
118
+	str tomatch;
119
+	str pvclass;
120
+	
121
+	if(msg==NULL)
122
+	{
123
+		LM_ERR("received null msg\n");
124
+		return -1;
125
+	}
126
+
127
+	if(fixup_get_svalue(msg, target, &tomatch)<0)
128
+	{
129
+		LM_ERR("cannot get the address\n");
130
+		return -1;
131
+	}
132
+	if(fixup_get_svalue(msg, pvname, &pvclass)<0)
133
+	{
134
+		LM_ERR("cannot get the pv class\n");
135
+		return -1;
136
+	}
137
+	geoip_pv_reset(&pvclass);
138
+
139
+	return geoip_update_pv(&tomatch, &pvclass);
140
+}
141
+
0 142
new file mode 100644
... ...
@@ -0,0 +1,405 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * This file is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ *
14
+ * This file is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ */
24
+
25
+
26
+#include <assert.h>
27
+#include <ctype.h>
28
+#include <string.h>
29
+#include <stdlib.h>
30
+#include <time.h>
31
+
32
+#include "../../dprint.h"
33
+#include "../../hashes.h"
34
+#include "../../pvar.h"
35
+
36
+#include "geoip_pv.h"
37
+
38
+typedef struct _sr_geoip_record {
39
+	GeoIPRecord *record;
40
+	char *time_zone;
41
+	char *region_name;
42
+	char **range;
43
+	char latitude[16];
44
+	char longitude[16];
45
+	char tomatch[256];
46
+	int flags;
47
+} sr_geoip_record_t;
48
+
49
+typedef struct _sr_geoip_item {
50
+	str pvclass;
51
+	unsigned int hashid;
52
+	sr_geoip_record_t r;
53
+	struct _sr_geoip_item *next;
54
+} sr_geoip_item_t;
55
+
56
+typedef struct _geoip_pv {
57
+	sr_geoip_item_t *item;
58
+	int type;
59
+} geoip_pv_t;
60
+
61
+static GeoIP *_handle_GeoIP = NULL;
62
+
63
+static sr_geoip_item_t *_sr_geoip_list = NULL;
64
+
65
+sr_geoip_record_t *sr_geoip_get_record(str *name)
66
+{
67
+	sr_geoip_item_t *it = NULL;
68
+	unsigned int hashid = 0;
69
+
70
+	hashid =  get_hash1_raw(name->s, name->len);
71
+
72
+	it = _sr_geoip_list;
73
+	while(it!=NULL)
74
+	{
75
+		if(it->hashid==hashid && it->pvclass.len == name->len
76
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
77
+			return &it->r;
78
+		it = it->next;
79
+	}
80
+	return NULL;
81
+}
82
+
83
+sr_geoip_item_t *sr_geoip_add_item(str *name)
84
+{
85
+	sr_geoip_item_t *it = NULL;
86
+	unsigned int hashid = 0;
87
+
88
+	hashid =  get_hash1_raw(name->s, name->len);
89
+
90
+	it = _sr_geoip_list;
91
+	while(it!=NULL)
92
+	{
93
+		if(it->hashid==hashid && it->pvclass.len == name->len
94
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
95
+			return it;
96
+		it = it->next;
97
+	}
98
+	/* add new */
99
+	it = (sr_geoip_item_t*)pkg_malloc(sizeof(sr_geoip_item_t));
100
+	if(it==NULL)
101
+	{
102
+		LM_ERR("no more pkg\n");
103
+		return NULL;
104
+	}
105
+	memset(it, 0, sizeof(sr_geoip_item_t));
106
+	it->pvclass.s = (char*)pkg_malloc(name->len+1);
107
+	if(it->pvclass.s==NULL)
108
+	{
109
+		LM_ERR("no more pkg.\n");
110
+		return NULL;
111
+	}
112
+	memcpy(it->pvclass.s, name->s, name->len);
113
+	it->pvclass.s[name->len] = '\0';
114
+	it->pvclass.len = name->len;
115
+	it->hashid = hashid;
116
+	it->next = _sr_geoip_list;
117
+	_sr_geoip_list = it;
118
+	return it;
119
+}
120
+
121
+
122
+int pv_parse_geoip_name(pv_spec_p sp, str *in)
123
+{
124
+	geoip_pv_t *gpv=NULL;
125
+	char *p;
126
+	str pvc;
127
+	str pvs;
128
+	if(sp==NULL || in==NULL || in->len<=0)
129
+		return -1;
130
+
131
+	gpv = (geoip_pv_t*)pkg_malloc(sizeof(geoip_pv_t));
132
+	if(gpv==NULL)
133
+		return -1;
134
+
135
+	memset(gpv, 0, sizeof(geoip_pv_t));
136
+
137
+	p = in->s;
138
+
139
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
140
+		p++;
141
+	if(p>in->s+in->len || *p=='\0')
142
+		goto error;
143
+	pvc.s = p;
144
+	while(p < in->s + in->len)
145
+	{
146
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
147
+			break;
148
+		p++;
149
+	}
150
+	if(p>in->s+in->len || *p=='\0')
151
+		goto error;
152
+	pvc.len = p - pvc.s;
153
+	if(*p!='=')
154
+	{
155
+		while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
156
+			p++;
157
+		if(p>in->s+in->len || *p=='\0' || *p!='=')
158
+			goto error;
159
+	}
160
+	p++;
161
+	if(*p!='>')
162
+		goto error;
163
+	p++;
164
+
165
+	pvs.len = in->len - (int)(p - in->s);
166
+	pvs.s = p;
167
+	LM_DBG("geoip [%.*s] - key [%.*s]\n", pvc.len, pvc.s,
168
+			pvs.len, pvs.s);
169
+
170
+	gpv->item = sr_geoip_add_item(&pvc);
171
+	if(gpv->item==NULL)
172
+		goto error;
173
+
174
+	switch(pvs.len)
175
+	{
176
+		case 2: 
177
+			if(strncmp(pvs.s, "cc", 2)==0)
178
+				gpv->type = 0;
179
+			else if(strncmp(pvs.s, "tz", 2)==0)
180
+				gpv->type = 1;
181
+			else goto error;
182
+		break;
183
+		case 3: 
184
+			if(strncmp(pvs.s, "zip", 3)==0)
185
+				gpv->type = 2;
186
+			else if(strncmp(pvs.s, "lat", 3)==0)
187
+				gpv->type = 3;
188
+			else if(strncmp(pvs.s, "lon", 3)==0)
189
+				gpv->type = 4;
190
+			else if(strncmp(pvs.s, "dma", 3)==0)
191
+				gpv->type = 5;
192
+			else if(strncmp(pvs.s, "ips", 3)==0)
193
+				gpv->type = 6;
194
+			else if(strncmp(pvs.s, "ipe", 3)==0)
195
+				gpv->type = 7;
196
+			else goto error;
197
+		break;
198
+		case 4: 
199
+			if(strncmp(pvs.s, "city", 4)==0)
200
+				gpv->type = 8;
201
+			else if(strncmp(pvs.s, "area", 4)==0)
202
+				gpv->type = 9;
203
+			else if(strncmp(pvs.s, "regc", 4)==0)
204
+				gpv->type = 10;
205
+			else if(strncmp(pvs.s, "regn", 4)==0)
206
+				gpv->type = 11;
207
+			else goto error;
208
+		break;
209
+		case 5: 
210
+			if(strncmp(pvs.s, "metro", 5)==0)
211
+				gpv->type = 12;
212
+			else goto error;
213
+		break;
214
+		default:
215
+			goto error;
216
+	}
217
+	sp->pvp.pvn.u.dname = (void*)gpv;
218
+	sp->pvp.pvn.type = PV_NAME_OTHER;
219
+
220
+	return 0;
221
+
222
+error:
223
+	LM_ERR("error at PV geoip name: %.*s\n", in->len, in->s);
224
+	return -1;
225
+}
226
+
227
+int pv_geoip_get_strzval(struct sip_msg *msg, pv_param_t *param,
228
+		pv_value_t *res, char *sval)
229
+{
230
+	str s;
231
+	if(sval==NULL)
232
+		return pv_get_null(msg, param, res);
233
+
234
+	s.s = sval;
235
+	s.len = strlen(s.s);
236
+	return pv_get_strval(msg, param, res, &s);
237
+}
238
+
239
+int pv_get_geoip(struct sip_msg *msg, pv_param_t *param,
240
+		pv_value_t *res)
241
+{
242
+	geoip_pv_t *gpv;
243
+
244
+	if(msg==NULL || param==NULL)
245
+		return -1;
246
+
247
+	gpv = (geoip_pv_t*)param->pvn.u.dname;
248
+	if(gpv==NULL)
249
+		return -1;
250
+
251
+	switch(gpv->type)
252
+	{
253
+		case 1: /* tz */
254
+			if(gpv->item->r.time_zone==NULL)
255
+			{
256
+				if(gpv->item->r.flags&1)
257
+					return pv_get_null(msg, param, res);
258
+				gpv->item->r.time_zone
259
+					= (char*)GeoIP_time_zone_by_country_and_region(
260
+						gpv->item->r.record->country_code,
261
+						gpv->item->r.record->region);
262
+				gpv->item->r.flags |= 1;
263
+			}
264
+			return pv_geoip_get_strzval(msg, param, res,
265
+					gpv->item->r.time_zone);
266
+		case 2: /* zip */
267
+			return pv_geoip_get_strzval(msg, param, res,
268
+					gpv->item->r.record->postal_code);
269
+		case 3: /* lat */
270
+			if((gpv->item->r.flags&2)==0)
271
+			{
272
+				snprintf(gpv->item->r.latitude, 15, "%f",
273
+						gpv->item->r.record->latitude);
274
+				gpv->item->r.flags |= 2;
275
+			}
276
+			return pv_geoip_get_strzval(msg, param, res,
277
+					gpv->item->r.latitude);
278
+		case 4: /* lon */
279
+			if((gpv->item->r.flags&4)==0)
280
+			{
281
+				snprintf(gpv->item->r.longitude, 15, "%f",
282
+						gpv->item->r.record->longitude);
283
+				gpv->item->r.flags |= 4;
284
+			}
285
+			return pv_geoip_get_strzval(msg, param, res,
286
+					gpv->item->r.longitude);
287
+		case 5: /* dma */
288
+			return pv_get_sintval(msg, param, res,
289
+					gpv->item->r.record->dma_code);
290
+		case 6: /* ips */
291
+		case 7: /* ipe */
292
+			if((gpv->item->r.flags&8)==0)
293
+			{
294
+				gpv->item->r.range = GeoIP_range_by_ip(_handle_GeoIP,
295
+					gpv->item->r.tomatch);
296
+				gpv->item->r.flags |= 8;
297
+			}
298
+			if(gpv->item->r.range==NULL)
299
+				return pv_get_null(msg, param, res);
300
+			if(gpv->type==6)
301
+				return pv_geoip_get_strzval(msg, param, res,
302
+						gpv->item->r.range[0]);
303
+			return pv_geoip_get_strzval(msg, param, res,
304
+					gpv->item->r.range[1]);
305
+		case 8: /* city */
306
+			return pv_geoip_get_strzval(msg, param, res,
307
+					gpv->item->r.record->city);
308
+		case 9: /* area */
309
+			return pv_get_sintval(msg, param, res,
310
+					gpv->item->r.record->area_code);
311
+		case 10: /* regc */
312
+			return pv_geoip_get_strzval(msg, param, res,
313
+					gpv->item->r.record->region);
314
+		case 11: /* regn */
315
+			if((gpv->item->r.flags&16)==0)
316
+			{
317
+				gpv->item->r.region_name
318
+						= (char*)GeoIP_region_name_by_code(
319
+							gpv->item->r.record->country_code,
320
+							gpv->item->r.record->region);
321
+				gpv->item->r.flags |= 16;
322
+			}
323
+			return pv_geoip_get_strzval(msg, param, res,
324
+					gpv->item->r.region_name);
325
+		case 12: /* metro */
326
+			return pv_get_sintval(msg, param, res,
327
+					gpv->item->r.record->metro_code);
328
+		default: /* cc */
329
+			return pv_geoip_get_strzval(msg, param, res,
330
+					gpv->item->r.record->country_code);
331
+	}
332
+}
333
+
334
+int geoip_init_pv(char *path)
335
+{
336
+	_handle_GeoIP = GeoIP_open(path, GEOIP_MMAP_CACHE);
337
+	
338
+	if(_handle_GeoIP==NULL)
339
+	{
340
+		LM_ERR("cannot open GeoIP database file at: %s\n", path);
341
+		return -1;
342
+	}
343
+	return 0;
344
+}
345
+
346
+void geoip_destroy_list(void)
347
+{
348
+}
349
+
350
+void geoip_destroy_pv(void)
351
+{
352
+	if(_handle_GeoIP!=NULL)
353
+	{
354
+		GeoIP_delete(_handle_GeoIP);
355
+		_handle_GeoIP=NULL;
356
+	}
357
+}
358
+
359
+void geoip_pv_reset(str *name)
360
+{
361
+	sr_geoip_record_t *gr = NULL;
362
+	
363
+	gr = sr_geoip_get_record(name);
364
+
365
+	if(gr==NULL)
366
+		return;
367
+	if(gr->range!=NULL)
368
+		GeoIP_range_by_ip_delete(gr->range);
369
+	if(gr->record!=NULL)
370
+		GeoIPRecord_delete(gr->record);
371
+	memset(gr, 0, sizeof(struct _sr_geoip_record));
372
+}
373
+
374
+int geoip_update_pv(str *tomatch, str *name)
375
+{
376
+	sr_geoip_record_t *gr = NULL;
377
+	
378
+	if(tomatch->len>255)
379
+	{
380
+		LM_DBG("target too long (max 255): %s\n", tomatch->s);
381
+		return -3;
382
+	}
383
+	
384
+	gr = sr_geoip_get_record(name);
385
+	if(gr==NULL)
386
+	{
387
+		LM_DBG("container not found: %s\n", tomatch->s);
388
+		return - 4;
389
+	}
390
+
391
+	strncpy(gr->tomatch, tomatch->s, tomatch->len);
392
+	tomatch->s[tomatch->len] = '\0';
393
+	gr->record = GeoIP_record_by_name(_handle_GeoIP,
394
+			(const char*)gr->tomatch);
395
+	LM_DBG("attempt to match: %s\n", gr->tomatch);
396
+	if (gr->record == NULL)
397
+	{
398
+		LM_DBG("no match for: %s\n", gr->tomatch);
399
+		return -2;
400
+	}
401
+	LM_DBG("geoip PV updated for: %s\n", gr->tomatch);
402
+
403
+	return 1;
404
+}
405
+
0 406
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+/**
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
5
+ *
6
+ * This file is part of Kamailio, a free SIP server.
7
+ *
8
+ * This file is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ *
14
+ * This file is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ *
23
+ */
24
+
25
+#ifndef _GEOIP_PV_H_
26
+#define _GEOIP_PV_H_
27
+
28
+#include <GeoIP.h>
29
+#include <GeoIPCity.h>
30
+
31
+#include "../../pvar.h"
32
+
33
+int pv_parse_geoip_name(pv_spec_p sp, str *in);
34
+int pv_get_geoip(struct sip_msg *msg, pv_param_t *param,
35
+		pv_value_t *res);
36
+
37
+int geoip_init_pv(char *path);
38
+void geoip_destroy_pv(void);
39
+void geoip_pv_reset(str *pvclass);
40
+int geoip_update_pv(str *tomatch, str *pvclass);
41
+
42
+#endif
43
+