]> jfr.im git - irc/quakenet/newserv.git/blob - geoip/geoip.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / geoip / geoip.c
1 /*
2 Geoip module
3 Copyright (C) 2004-2006 Chris Porter.
4 */
5
6 #include "../nick/nick.h"
7 #include "../core/error.h"
8 #include "../core/config.h"
9 #include "../core/hooks.h"
10 #include "../control/control.h"
11 #include "../lib/version.h"
12
13 #include <strings.h>
14
15 #include "libGeoIP/GeoIP.h"
16 #include "geoip.h"
17
18 MODULE_VERSION("");
19
20 int geoip_totals[COUNTRY_MAX + 1];
21 static int geoip_nickext = -1;
22 static GeoIP *gi = NULL;
23
24 static void geoip_setupuser(nick *np);
25
26 static void geoip_new_nick(int hook, void *args);
27 static void geoip_quit(int hook, void *args);
28 static void geoip_whois_handler(int hooknum, void *arg);
29
30 void _init(void) {
31 int i;
32 nick *np;
33 sstring *filename;
34
35 filename = getcopyconfigitem("geoip", "db", "GeoIP.dat", 256);
36 gi = GeoIP_open(filename->content, GEOIP_MEMORY_CACHE);
37 freesstring(filename);
38
39 if(!gi)
40 return;
41
42 geoip_nickext = registernickext("geoip");
43 if(geoip_nickext == -1)
44 return; /* PPA: registerchanext produces an error, however the module should stop loading */
45
46 memset(geoip_totals, 0, sizeof(geoip_totals));
47
48 for(i=0;i<NICKHASHSIZE;i++)
49 for(np=nicktable[i];np;np=np->next)
50 geoip_setupuser(np);
51
52 registerhook(HOOK_NICK_LOSTNICK, &geoip_quit);
53 registerhook(HOOK_NICK_NEWNICK, &geoip_new_nick);
54 registerhook(HOOK_CONTROL_WHOISREQUEST, &geoip_whois_handler);
55 }
56
57 void _fini(void) {
58 if(gi)
59 GeoIP_delete(gi);
60
61 if(geoip_nickext == -1)
62 return;
63
64 releasenickext(geoip_nickext);
65
66 deregisterhook(HOOK_NICK_NEWNICK, &geoip_new_nick);
67 deregisterhook(HOOK_NICK_LOSTNICK, &geoip_quit);
68 deregisterhook(HOOK_CONTROL_WHOISREQUEST, &geoip_whois_handler);
69 }
70
71 static void geoip_setupuser(nick *np) {
72 if (!irc_in_addr_is_ipv4(&np->ipaddress))
73 return; /* geoip only supports ipv4 */
74
75 unsigned int ip = irc_in_addr_v4_to_int(&np->ipaddress);
76 int country = GeoIP_id_by_ipnum(gi, ip);
77 if((country < COUNTRY_MIN) || (country > COUNTRY_MAX))
78 return;
79
80 geoip_totals[country]++;
81 np->exts[geoip_nickext] = (void *)(long)country;
82 }
83
84 static void geoip_new_nick(int hook, void *args) {
85 geoip_setupuser((nick *)args);
86 }
87
88 static void geoip_quit(int hook, void *args) {
89 int item;
90 nick *np = (nick *)args;
91
92 item = (int)((long)np->exts[geoip_nickext]);
93
94 if((item < COUNTRY_MIN) || (item > COUNTRY_MAX))
95 return;
96
97 geoip_totals[item]--;
98 }
99
100 static void geoip_whois_handler(int hooknum, void *arg) {
101 int item;
102 char message[512];
103 const char *longcountry, *shortcountry;
104 nick *np = (nick *)arg;
105
106 if(!np)
107 return;
108
109 item = (int)((long)np->exts[geoip_nickext]);
110 if((item < COUNTRY_MIN) || (item > COUNTRY_MAX))
111 return;
112
113 shortcountry = GeoIP_code_by_id(item);
114 longcountry = GeoIP_name_by_id(item);
115
116 if(shortcountry && longcountry) {
117 snprintf(message, sizeof(message), "Country : %s (%s)", shortcountry, longcountry);
118 triggerhook(HOOK_CONTROL_WHOISREPLY, message);
119 }
120 }
121
122 int geoip_lookupcode(char *code) {
123 int i;
124 for(i=COUNTRY_MIN;i<COUNTRY_MAX;i++)
125 if(!strcasecmp(code, GeoIP_country_code[i]))
126 return i;
127
128 return -1;
129 }