root/cherokee/trunk/cherokee/rule_geoip.c

Revision 4141, 4.2 KB (checked in by alo, 8 months ago)

New year, new copyright notice: 's/2009/2010/g'.

Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3/* Cherokee
4 *
5 * Authors:
6 *      Alvaro Lopez Ortega <alvaro@alobbs.com>
7 *
8 * Copyright (C) 2001-2010 Alvaro Lopez Ortega
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
13 *
14 * This program 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., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25#include "common-internal.h"
26#include "rule_geoip.h"
27#include "plugin_loader.h"
28#include "virtual_server.h"
29#include "socket.h"
30#include "connection-protected.h"
31#include "util.h"
32
33#define ENTRIES "rule,geoip"
34#define MAGIC   0XDEADBEEF
35
36PLUGIN_INFO_RULE_EASIEST_INIT(geoip);
37
38
39
40/* Specific plug-in functions
41 */
42
43static GeoIP   *_geoip      = NULL;
44static cuint_t  _geoip_refs = 0;
45
46static GeoIP *
47geoip_get (void)
48{
49        int    i;
50        GeoIP *gi;
51
52        /* Return the global if it's ready
53         */
54        if (likely (_geoip != NULL)) {
55                _geoip_refs += 1;
56                return _geoip;
57        }
58
59        /* Try to open a GeoIP database
60         */
61        for (i = 0; i < NUM_DB_TYPES; ++i) {
62                if (GeoIP_db_avail(i)) {
63                        gi = GeoIP_open_type (i, GEOIP_STANDARD);
64                        if (gi != NULL) {
65                                _geoip = gi;
66                                _geoip_refs += 1;
67
68                                return _geoip;
69                        }
70                }
71        }
72
73        return NULL;
74}
75
76static void
77geoip_release (void)
78{
79        _geoip_refs -= 1;
80
81        if (_geoip_refs <= 0) {
82                GeoIP_delete (_geoip);
83                _geoip = NULL;
84        }
85}
86
87
88/* The rule itself
89 */
90
91static ret_t
92match (cherokee_rule_t         *rule_,
93       cherokee_connection_t   *conn,
94       cherokee_config_entry_t *ret_conf)
95{
96        ret_t                  ret;
97        void                  *foo;
98        const char            *country;
99        cherokee_rule_geoip_t *rule = RULE_GEOIP(rule_);
100
101        UNUSED(ret_conf);
102
103        country = GeoIP_country_code_by_ipnum (rule->geoip, SOCKET_ADDRESS_IPv4(&conn->socket));
104        if (country == NULL) {
105                TRACE(ENTRIES, "Rule geoip did found the country for ip='%lu'\n",
106                        SOCKET_ADDRESS_IPv4(&conn->socket));
107                return ret_not_found;
108        }
109
110        ret = cherokee_avl_get_ptr (&rule->countries, country, &foo);
111        if (ret != ret_ok) {
112                TRACE(ENTRIES, "Rule geoip did not match '%s'\n", country);
113                return ret;
114        }
115
116        TRACE(ENTRIES, "Match geoip did match: '%s'\n", country);
117        return ret_ok;
118}
119
120
121static ret_t
122parse_contry_list (cherokee_buffer_t *value, cherokee_avl_t *countries)
123{
124        char              *val;
125        char              *tmpp;
126        cherokee_buffer_t  tmp = CHEROKEE_BUF_INIT;
127
128        TRACE(ENTRIES, "Adding geoip countries: '%s'\n", value->buf);
129        cherokee_buffer_add_buffer (&tmp, value);
130
131        tmpp = tmp.buf;
132        while ((val = strsep(&tmpp, ",")) != NULL) {
133                TRACE(ENTRIES, "Adding country: '%s'\n", val);
134                cherokee_avl_add_ptr (countries, val, (void *)MAGIC);
135        }
136
137        cherokee_buffer_mrproper (&tmp);
138        return ret_ok;
139}
140
141
142static ret_t
143configure (cherokee_rule_geoip_t       *rule,
144           cherokee_config_node_t    *conf,
145           cherokee_virtual_server_t *vsrv)
146{
147        ret_t              ret;
148        cherokee_buffer_t *tmp = NULL;
149
150        UNUSED(vsrv);
151
152        ret = cherokee_config_node_read (conf, "countries", &tmp);
153        if (ret != ret_ok) {
154                LOG_CRITICAL (CHEROKEE_ERROR_RULE_NO_PROPERTY,
155                              RULE(rule)->priority, "geoip");
156                return ret_error;
157        }
158
159        return parse_contry_list (tmp, &rule->countries);
160}
161
162static ret_t
163_free (void *p)
164{
165        cherokee_rule_geoip_t *rule = RULE_GEOIP(p);
166
167        if (rule->geoip) {
168                geoip_release();
169        }
170
171        return ret_ok;
172}
173
174ret_t
175cherokee_rule_geoip_new (cherokee_rule_t **rule)
176{
177        CHEROKEE_NEW_STRUCT (n, rule_geoip);
178
179        /* Parent class constructor
180         */
181        cherokee_rule_init_base (RULE(n), PLUGIN_INFO_PTR(geoip));
182
183        /* Virtual methods
184         */
185        RULE(n)->match     = (rule_func_match_t) match;
186        RULE(n)->configure = (rule_func_configure_t) configure;
187        MODULE(n)->free    = (module_func_free_t) _free;
188
189        /* Properties
190         */
191        n->geoip = geoip_get();
192        if (n->geoip == NULL)
193                return ret_error;
194
195        cherokee_avl_init (&n->countries);
196
197        *rule = RULE(n);
198        return ret_ok;
199}
200
Note: See TracBrowser for help on using the browser.