62 unsigned outside_entries:1;
63 unsigned allow_binary_include:1;
64 unsigned binary_include:1;
65 unsigned proxy_recursive:1;
76 unsigned proxy_recursive:1;
90 static char *ngx_http_geo_add_range(
ngx_conf_t *cf,
100 static char *ngx_http_geo_add_proxy(
ngx_conf_t *cf,
109 static u_char *ngx_http_geo_copy_values(u_char *base, u_char *p,
143 &ngx_http_geo_module_ctx,
144 ngx_http_geo_commands,
167 {
'G',
'E',
'O',
'R',
'N',
'G' }, 0,
sizeof(
void *), 0x12345678, 0
181 struct sockaddr_in *sin;
185 struct in6_addr *inaddr6;
188 if (ngx_http_geo_addr(r, ctx, &addr) !=
NGX_OK) {
198 inaddr6 = &((
struct sockaddr_in6 *) addr.
sockaddr)->sin6_addr;
199 p = inaddr6->s6_addr;
201 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
202 inaddr = p[12] << 24;
203 inaddr += p[13] << 16;
204 inaddr += p[14] << 8;
212 ngx_radix128tree_find(ctx->
u.
trees.tree6, p);
219 sin = (
struct sockaddr_in *) addr.
sockaddr;
220 inaddr = ntohl(sin->sin_addr.s_addr);
248 struct sockaddr_in *sin;
252 struct in6_addr *inaddr6;
257 if (ngx_http_geo_addr(r, ctx, &addr) ==
NGX_OK) {
263 inaddr6 = &((
struct sockaddr_in6 *) addr.
sockaddr)->sin6_addr;
265 if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
266 p = inaddr6->s6_addr;
268 inaddr = p[12] << 24;
269 inaddr += p[13] << 16;
270 inaddr += p[14] << 8;
281 sin = (
struct sockaddr_in *) addr.
sockaddr;
282 inaddr = ntohl(sin->sin_addr.s_addr);
291 range = ctx->
u.
high.
low[inaddr >> 16];
302 }
while ((++range)->value);
319 if (ngx_http_geo_real_addr(r, ctx, addr) !=
NGX_OK) {
340 if (ctx->
index == -1) {
355 "http geo not found");
361 "http geo started: %v", v);
385 static struct in6_addr zero;
397 if (name.
data[0] !=
'$') {
399 "invalid variable name \"%V\"", &name);
415 if (name.
data[0] !=
'$') {
417 "invalid variable name \"%V\"", &name);
469 for (i = 0; i < 0x10000; i++) {
472 if (a == NULL || a->
nelts == 0) {
493 ngx_http_geo_create_binary_base(&ctx);
504 var->
data = (uintptr_t) geo;
510 if (ctx.
tree == NULL) {
512 if (ctx.
tree == NULL) {
520 if (ctx.tree6 == NULL) {
522 if (ctx.tree6 == NULL) {
527 geo->
u.
trees.tree6 = ctx.tree6;
531 var->
data = (uintptr_t) geo;
546 if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
547 (uintptr_t) &ngx_http_variable_null_value)
573 if (
ngx_strcmp(value[0].data,
"ranges") == 0) {
582 "the \"ranges\" directive must be "
583 "the first directive inside \"geo\" block");
594 else if (
ngx_strcmp(value[0].data,
"proxy_recursive") == 0) {
603 "invalid number of the geo parameters");
607 if (
ngx_strcmp(value[0].data,
"include") == 0) {
609 rv = ngx_http_geo_include(cf, ctx, &value[1]);
613 }
else if (
ngx_strcmp(value[0].data,
"proxy") == 0) {
615 if (ngx_http_geo_cidr_value(cf, &value[1], &cidr) !=
NGX_OK) {
619 rv = ngx_http_geo_add_proxy(cf, ctx, &cidr);
625 rv = ngx_http_geo_range(cf, ctx, value);
628 rv = ngx_http_geo_cidr(cf, ctx, value);
650 in_addr_t start, end;
654 if (
ngx_strcmp(value[0].data,
"default") == 0) {
658 "duplicate default geo range value: \"%V\", old value: \"%v\"",
672 "binary geo range base \"%s\" cannot be mixed with usual entries",
688 if (
ngx_strcmp(value[0].data,
"delete") == 0) {
699 p = ngx_strlchr(net->
data, last,
'-');
711 start = ntohl(start);
728 if (ngx_http_geo_delete_range(cf, ctx, start, end)) {
730 "no address range \"%V\" to delete", net);
736 ctx->
value = ngx_http_geo_value(cf, ctx, &value[1]);
738 if (ctx->
value == NULL) {
744 return ngx_http_geo_add_range(cf, ctx, start, end);
758 in_addr_t start, in_addr_t end)
765 for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
775 if ((n | 0xffff) > end) {
819 range[i + 1].
start = (u_short) s;
820 range[i + 1].
end = (u_short) e;
830 "duplicate range \"%V\", value: \"%v\", old value: \"%v\"",
858 range[i + 2].
start = (u_short) (e + 1);
859 range[i + 2].
end = range[
i].
end;
862 range[i + 1].
start = (u_short) s;
863 range[i + 1].
end = (u_short) e;
866 range[
i].
end = (u_short) (s - 1);
886 range[i + 1].
start = (u_short) (e + 1);
888 range[
i].
start = (u_short) s;
889 range[
i].
end = (u_short) e;
910 range[i + 1].
start = (u_short) s;
911 range[i + 1].
end = (u_short) e;
914 range[
i].
end = (u_short) (s - 1);
923 "range \"%V\" overlaps \"%d.%d.%d.%d-%d.%d.%d.%d\"",
925 h >> 8, h & 0xff, s >> 8, s & 0xff,
926 h >> 8, h & 0xff, e >> 8, e & 0xff);
938 range->
start = (u_short) s;
939 range->
end = (u_short) e;
953 in_addr_t start, in_addr_t end)
962 for (n = start; n <= end; n += 0x10000) {
972 if ((n | 0xffff) > end) {
987 for (i = 0; i < a->
nelts; i++) {
1023 if (ctx->
tree == NULL) {
1025 if (ctx->
tree == NULL) {
1030 #if (NGX_HAVE_INET6)
1031 if (ctx->tree6 == NULL) {
1033 if (ctx->tree6 == NULL) {
1039 if (
ngx_strcmp(value[0].data,
"default") == 0) {
1044 rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
1050 #if (NGX_HAVE_INET6)
1054 rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
1064 if (
ngx_strcmp(value[0].data,
"delete") == 0) {
1073 if (ngx_http_geo_cidr_value(cf, net, &cidr) !=
NGX_OK) {
1077 if (cidr.
family == AF_INET) {
1085 #if (NGX_HAVE_INET6)
1087 rc = ngx_radix128tree_delete(ctx->tree6,
1088 cidr.
u.in6.addr.s6_addr,
1089 cidr.
u.in6.mask.s6_addr);
1101 "no network \"%V\" to delete", net);
1107 return ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], net);
1118 val = ngx_http_geo_value(cf, ctx, value);
1126 #if (NGX_HAVE_INET6)
1128 rc = ngx_radix128tree_insert(ctx->tree6, cidr->
u.in6.addr.s6_addr,
1129 cidr->
u.in6.mask.s6_addr,
1143 ngx_radix128tree_find(ctx->tree6,
1144 cidr->
u.in6.addr.s6_addr);
1147 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1150 rc = ngx_radix128tree_delete(ctx->tree6,
1151 cidr->
u.in6.addr.s6_addr,
1152 cidr->
u.in6.mask.s6_addr);
1159 rc = ngx_radix128tree_insert(ctx->tree6, cidr->
u.in6.addr.s6_addr,
1160 cidr->
u.in6.mask.s6_addr,
1168 cidr->
u.
in.
mask, (uintptr_t) val);
1184 "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
1196 cidr->
u.
in.
mask, (uintptr_t) val);
1217 hash = ngx_crc32_long(value->
data, value->
len);
1233 if (val->
data == NULL) {
1308 "low address bits of %V are meaningless", net);
1322 file.
len = name->
len + 4;
1324 if (file.
data == NULL) {
1337 switch (ngx_http_geo_include_binary_base(cf, ctx, &file)) {
1401 "binary geo range base \"%s\" cannot be mixed with usual entries",
1409 "second binary geo range base \"%s\" cannot be mixed with \"%s\"",
1424 ch = name->
data[name->
len - 4];
1425 name->
data[name->
len - 4] =
'\0';
1433 name->
data[name->
len - 4] = ch;
1437 "stale binary geo range base \"%s\"", name->
data);
1454 if ((
size_t) n != size) {
1457 name->
data, n, size);
1463 if (size < 16 ||
ngx_memcmp(&ngx_http_geo_header, header, 12) != 0) {
1465 "incompatible binary geo range base \"%s\"", name->
data);
1476 ngx_crc32_update(&crc32, (u_char *) vv, len);
1477 vv->
data += (size_t) base;
1485 for (i = 0; i < 0x10000; i++) {
1486 ngx_crc32_update(&crc32, (u_char *) &ranges[i],
sizeof(
void *));
1489 ((u_char *) ranges[
i] + (size_t) base);
1495 while ((u_char *) range < base + size) {
1496 while (range->
value) {
1497 ngx_crc32_update(&crc32, (u_char *) range,
1500 ((u_char *) range->
value + (size_t) base);
1503 ngx_crc32_update(&crc32, (u_char *) range,
sizeof(
void *));
1509 if (crc32 != header->
crc32) {
1511 "CRC32 mismatch in binary geo range base \"%s\"", name->
data);
1516 "using binary geo range base \"%s\"", name->
data);
1553 if (fm.
name == NULL) {
1563 "creating binary geo range base \"%s\"", fm.
name);
1581 for (i = 0; i < 0x10000; i++) {
1593 hash = ngx_crc32_long(s.
data, s.
len);
1602 }
while ((++r)->value);
1604 range->
value = NULL;
1606 p = (u_char *) range +
sizeof(
void *);
1610 header->
crc32 = ngx_crc32_long((u_char *) fm.
addr
1625 if (node == sentinel) {
1635 vv->
data = (u_char *) (p - base);
1641 p = ngx_http_geo_copy_values(base, p, node->
left, sentinel);
1643 return ngx_http_geo_copy_values(base, p, node->
right, sentinel);