~ubuntu-branches/ubuntu/lucid/nginx/lucid

« back to all changes in this revision

Viewing changes to src/http/modules/ngx_http_geoip_module.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Rodriguez
  • Date: 2009-11-30 13:34:00 UTC
  • mfrom: (1.1.14 upstream) (4.2.10 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091130133400-n0ux4igma2y3y0pl
Tags: 0.7.63-1ubuntu1
* Merge from debian testing (LP: #490450), remaining changes:
  - Install html files.
    - debian/dirs: Add 'var/www/nginx-default'.
    - debian/nginx.install: Add 'html/* var/www/nginx-default'.
  - Added a UFW profile set: (LP: #308695)
    + debian/nginx.ufw.profile: Added.
    + debian/control: nginx: Suggests ufw.
    + debian/dirs: Added 'etc/ufw/applications.d'
    + debian/rules: Added install rule for the nginx UFW profile. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Copyright (C) Igor Sysoev
 
4
 */
 
5
 
 
6
 
 
7
#include <ngx_config.h>
 
8
#include <ngx_core.h>
 
9
#include <ngx_http.h>
 
10
 
 
11
#include <GeoIP.h>
 
12
#include <GeoIPCity.h>
 
13
 
 
14
 
 
15
typedef struct {
 
16
    GeoIP      *country;
 
17
    GeoIP      *city;
 
18
} ngx_http_geoip_conf_t;
 
19
 
 
20
 
 
21
typedef struct {
 
22
    ngx_str_t  *name;
 
23
    uintptr_t   data;
 
24
} ngx_http_geoip_var_t;
 
25
 
 
26
 
 
27
typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *, u_long addr);
 
28
 
 
29
static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
 
30
    ngx_http_variable_value_t *v, uintptr_t data);
 
31
static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
 
32
    ngx_http_variable_value_t *v, uintptr_t data);
 
33
 
 
34
static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
 
35
static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
 
36
static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
 
37
    void *conf);
 
38
static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
 
39
    void *conf);
 
40
static void ngx_http_geoip_cleanup(void *data);
 
41
 
 
42
 
 
43
static ngx_command_t  ngx_http_geoip_commands[] = {
 
44
 
 
45
    { ngx_string("geoip_country"),
 
46
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
 
47
      ngx_http_geoip_country,
 
48
      NGX_HTTP_MAIN_CONF_OFFSET,
 
49
      0,
 
50
      NULL },
 
51
 
 
52
    { ngx_string("geoip_city"),
 
53
      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
 
54
      ngx_http_geoip_city,
 
55
      NGX_HTTP_MAIN_CONF_OFFSET,
 
56
      0,
 
57
      NULL },
 
58
 
 
59
      ngx_null_command
 
60
};
 
61
 
 
62
 
 
63
static ngx_http_module_t  ngx_http_geoip_module_ctx = {
 
64
    ngx_http_geoip_add_variables,          /* preconfiguration */
 
65
    NULL,                                  /* postconfiguration */
 
66
 
 
67
    ngx_http_geoip_create_conf,            /* create main configuration */
 
68
    NULL,                                  /* init main configuration */
 
69
 
 
70
    NULL,                                  /* create server configuration */
 
71
    NULL,                                  /* merge server configuration */
 
72
 
 
73
    NULL,                                  /* create location configuration */
 
74
    NULL                                   /* merge location configuration */
 
75
};
 
76
 
 
77
 
 
78
ngx_module_t  ngx_http_geoip_module = {
 
79
    NGX_MODULE_V1,
 
80
    &ngx_http_geoip_module_ctx,            /* module context */
 
81
    ngx_http_geoip_commands,               /* module directives */
 
82
    NGX_HTTP_MODULE,                       /* module type */
 
83
    NULL,                                  /* init master */
 
84
    NULL,                                  /* init module */
 
85
    NULL,                                  /* init process */
 
86
    NULL,                                  /* init thread */
 
87
    NULL,                                  /* exit thread */
 
88
    NULL,                                  /* exit process */
 
89
    NULL,                                  /* exit master */
 
90
    NGX_MODULE_V1_PADDING
 
91
};
 
92
 
 
93
 
 
94
static ngx_http_variable_t  ngx_http_geoip_vars[] = {
 
95
 
 
96
    { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable,
 
97
      (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
 
98
 
 
99
    { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable,
 
100
      (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
 
101
 
 
102
    { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable,
 
103
      (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
 
104
 
 
105
    { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable,
 
106
      offsetof(GeoIPRecord, country_code), 0, 0 },
 
107
 
 
108
    { ngx_string("geoip_city_country_code3"), NULL,
 
109
      ngx_http_geoip_city_variable,
 
110
      offsetof(GeoIPRecord, country_code3), 0, 0 },
 
111
 
 
112
    { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable,
 
113
      offsetof(GeoIPRecord, country_name), 0, 0 },
 
114
 
 
115
    { ngx_string("geoip_region"), NULL,
 
116
      ngx_http_geoip_city_variable,
 
117
      offsetof(GeoIPRecord, region), 0, 0 },
 
118
 
 
119
    { ngx_string("geoip_city"), NULL,
 
120
      ngx_http_geoip_city_variable,
 
121
      offsetof(GeoIPRecord, city), 0, 0 },
 
122
 
 
123
    { ngx_string("geoip_postal_code"), NULL,
 
124
      ngx_http_geoip_city_variable,
 
125
      offsetof(GeoIPRecord, postal_code), 0, 0 },
 
126
 
 
127
    { ngx_null_string, NULL, NULL, 0, 0, 0 }
 
128
};
 
129
 
 
130
 
 
131
static ngx_int_t
 
132
ngx_http_geoip_country_variable(ngx_http_request_t *r,
 
133
    ngx_http_variable_value_t *v, uintptr_t data)
 
134
{
 
135
    ngx_http_geoip_variable_handler_pt  handler =
 
136
        (ngx_http_geoip_variable_handler_pt) data;
 
137
 
 
138
    u_long                  addr;
 
139
    const char             *val;
 
140
    struct sockaddr_in     *sin;
 
141
    ngx_http_geoip_conf_t  *gcf;
 
142
 
 
143
    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
 
144
 
 
145
    if (gcf->country == NULL) {
 
146
        goto not_found;
 
147
    }
 
148
 
 
149
    if (r->connection->sockaddr->sa_family != AF_INET) {
 
150
        goto not_found;
 
151
    }
 
152
 
 
153
    sin = (struct sockaddr_in *) r->connection->sockaddr;
 
154
    addr = ntohl(sin->sin_addr.s_addr);
 
155
 
 
156
    val = handler(gcf->country, addr);
 
157
 
 
158
    if (val == NULL) {
 
159
        goto not_found;
 
160
    }
 
161
 
 
162
    v->len = ngx_strlen(val);
 
163
    v->valid = 1;
 
164
    v->no_cacheable = 0;
 
165
    v->not_found = 0;
 
166
    v->data = (u_char *) val;
 
167
 
 
168
    return NGX_OK;
 
169
 
 
170
not_found:
 
171
 
 
172
    v->not_found = 1;
 
173
 
 
174
    return NGX_OK;
 
175
}
 
176
 
 
177
 
 
178
static ngx_int_t
 
179
ngx_http_geoip_city_variable(ngx_http_request_t *r,
 
180
    ngx_http_variable_value_t *v, uintptr_t data)
 
181
{
 
182
    u_long                  addr;
 
183
    char                   *val;
 
184
    size_t                  len;
 
185
    GeoIPRecord            *gr;
 
186
    struct sockaddr_in     *sin;
 
187
    ngx_http_geoip_conf_t  *gcf;
 
188
 
 
189
    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
 
190
 
 
191
    if (gcf->city == NULL) {
 
192
        goto not_found;
 
193
    }
 
194
 
 
195
    if (r->connection->sockaddr->sa_family != AF_INET) {
 
196
        goto not_found;
 
197
    }
 
198
 
 
199
    sin = (struct sockaddr_in *) r->connection->sockaddr;
 
200
    addr = ntohl(sin->sin_addr.s_addr);
 
201
 
 
202
    gr = GeoIP_record_by_ipnum(gcf->city, addr);
 
203
 
 
204
    if (gr == NULL) {
 
205
        goto not_found;
 
206
    }
 
207
 
 
208
    val = *(char **) ((char *) gr + data);
 
209
 
 
210
    if (val == NULL) {
 
211
        goto no_value;
 
212
    }
 
213
 
 
214
    len = ngx_strlen(val);
 
215
    v->data = ngx_pnalloc(r->pool, len);
 
216
 
 
217
    if (v->data == NULL) {
 
218
        GeoIPRecord_delete(gr);
 
219
        return NGX_ERROR;
 
220
    }
 
221
 
 
222
    ngx_memcpy(v->data, val, len);
 
223
 
 
224
    v->len = len;
 
225
    v->valid = 1;
 
226
    v->no_cacheable = 0;
 
227
    v->not_found = 0;
 
228
 
 
229
    GeoIPRecord_delete(gr);
 
230
 
 
231
    return NGX_OK;
 
232
 
 
233
no_value:
 
234
 
 
235
    GeoIPRecord_delete(gr);
 
236
 
 
237
not_found:
 
238
 
 
239
    v->not_found = 1;
 
240
 
 
241
    return NGX_OK;
 
242
}
 
243
 
 
244
 
 
245
static ngx_int_t
 
246
ngx_http_geoip_add_variables(ngx_conf_t *cf)
 
247
{
 
248
    ngx_http_variable_t  *var, *v;
 
249
 
 
250
    for (v = ngx_http_geoip_vars; v->name.len; v++) {
 
251
        var = ngx_http_add_variable(cf, &v->name, v->flags);
 
252
        if (var == NULL) {
 
253
            return NGX_ERROR;
 
254
        }
 
255
 
 
256
        var->get_handler = v->get_handler;
 
257
        var->data = v->data;
 
258
    }
 
259
 
 
260
    return NGX_OK;
 
261
}
 
262
 
 
263
 
 
264
static void *
 
265
ngx_http_geoip_create_conf(ngx_conf_t *cf)
 
266
{
 
267
    ngx_pool_cleanup_t     *cln;
 
268
    ngx_http_geoip_conf_t  *conf;
 
269
 
 
270
    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t));
 
271
    if (conf == NULL) {
 
272
        return NULL;
 
273
    }
 
274
 
 
275
    cln = ngx_pool_cleanup_add(cf->pool, 0);
 
276
    if (cln == NULL) {
 
277
        return NULL;
 
278
    }
 
279
 
 
280
    cln->handler = ngx_http_geoip_cleanup;
 
281
    cln->data = conf;
 
282
 
 
283
    return conf;
 
284
}
 
285
 
 
286
 
 
287
static char *
 
288
ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
289
{
 
290
    ngx_http_geoip_conf_t  *gcf = conf;
 
291
 
 
292
    ngx_str_t  *value;
 
293
 
 
294
    if (gcf->country) {
 
295
        return "is duplicate";
 
296
    }
 
297
 
 
298
    value = cf->args->elts;
 
299
 
 
300
    gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
 
301
 
 
302
    if (gcf->country == NULL) {
 
303
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
304
                           "GeoIO_open(\"%V\") failed", &value[1]);
 
305
 
 
306
        return NGX_CONF_ERROR;
 
307
    }
 
308
 
 
309
    switch (gcf->country->databaseType) {
 
310
 
 
311
    case GEOIP_COUNTRY_EDITION:
 
312
    case GEOIP_PROXY_EDITION:
 
313
    case GEOIP_NETSPEED_EDITION:
 
314
 
 
315
        return NGX_CONF_OK;
 
316
 
 
317
    default:
 
318
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
319
                           "invalid GeoIP database \"%V\" type:%d",
 
320
                           &value[1], gcf->country->databaseType);
 
321
        return NGX_CONF_ERROR;
 
322
    }
 
323
}
 
324
 
 
325
 
 
326
static char *
 
327
ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 
328
{
 
329
    ngx_http_geoip_conf_t  *gcf = conf;
 
330
 
 
331
    ngx_str_t  *value;
 
332
 
 
333
    if (gcf->city) {
 
334
        return "is duplicate";
 
335
    }
 
336
 
 
337
    value = cf->args->elts;
 
338
 
 
339
    gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
 
340
 
 
341
    if (gcf->city == NULL) {
 
342
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
343
                           "GeoIO_open(\"%V\") failed", &value[1]);
 
344
 
 
345
        return NGX_CONF_ERROR;
 
346
    }
 
347
 
 
348
    switch (gcf->city->databaseType) {
 
349
 
 
350
    case GEOIP_CITY_EDITION_REV0:
 
351
    case GEOIP_CITY_EDITION_REV1:
 
352
 
 
353
        return NGX_CONF_OK;
 
354
 
 
355
    default:
 
356
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
357
                           "invalid GeoIP City database \"%V\" type:%d",
 
358
                           &value[1], gcf->city->databaseType);
 
359
        return NGX_CONF_ERROR;
 
360
    }
 
361
}
 
362
 
 
363
 
 
364
static void
 
365
ngx_http_geoip_cleanup(void *data)
 
366
{
 
367
    ngx_http_geoip_conf_t  *gcf = data;
 
368
 
 
369
    if (gcf->country) {
 
370
        GeoIP_delete(gcf->country);
 
371
    }
 
372
 
 
373
    if (gcf->city) {
 
374
        GeoIP_delete(gcf->city);
 
375
    }
 
376
}