prepare ngx_ptocidr() for IPv6
Igor Sysoev
13 years ago
225 | 225 | /* AF_INET only */ |
226 | 226 | |
227 | 227 | ngx_int_t |
228 | ngx_ptocidr(ngx_str_t *text, void *cidr) | |
229 | { | |
230 | u_char *addr, *mask, *last; | |
231 | ngx_int_t shift; | |
232 | ngx_inet_cidr_t *in_cidr; | |
233 | ||
234 | in_cidr = cidr; | |
228 | ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr) | |
229 | { | |
230 | u_char *addr, *mask, *last; | |
231 | ngx_int_t shift; | |
232 | ||
235 | 233 | addr = text->data; |
236 | 234 | last = addr + text->len; |
237 | 235 | |
238 | 236 | mask = ngx_strlchr(addr, last, '/'); |
239 | 237 | |
240 | in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); | |
241 | ||
242 | if (in_cidr->addr == INADDR_NONE) { | |
238 | cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); | |
239 | ||
240 | if (cidr->u.in.addr == INADDR_NONE) { | |
243 | 241 | return NGX_ERROR; |
244 | 242 | } |
245 | 243 | |
246 | 244 | if (mask == NULL) { |
247 | in_cidr->mask = 0xffffffff; | |
245 | cidr->family = AF_INET; | |
246 | cidr->u.in.mask = 0xffffffff; | |
248 | 247 | return NGX_OK; |
249 | 248 | } |
250 | 249 | |
255 | 254 | return NGX_ERROR; |
256 | 255 | } |
257 | 256 | |
257 | cidr->family = AF_INET; | |
258 | ||
258 | 259 | if (shift == 0) { |
259 | 260 | |
260 | 261 | /* the x86 compilers use the shl instruction that shifts by modulo 32 */ |
261 | 262 | |
262 | in_cidr->mask = 0; | |
263 | ||
264 | if (in_cidr->addr == 0) { | |
263 | cidr->u.in.mask = 0; | |
264 | ||
265 | if (cidr->u.in.addr == 0) { | |
265 | 266 | return NGX_OK; |
266 | 267 | } |
267 | 268 | |
268 | 269 | return NGX_DONE; |
269 | 270 | } |
270 | 271 | |
271 | in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); | |
272 | ||
273 | if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) { | |
272 | cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); | |
273 | ||
274 | if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) { | |
274 | 275 | return NGX_OK; |
275 | 276 | } |
276 | 277 | |
277 | in_cidr->addr &= in_cidr->mask; | |
278 | cidr->u.in.addr &= cidr->u.in.mask; | |
278 | 279 | |
279 | 280 | return NGX_DONE; |
280 | 281 | } |
34 | 34 | |
35 | 35 | |
36 | 36 | typedef struct { |
37 | in_addr_t addr; | |
38 | in_addr_t mask; | |
39 | } ngx_inet_cidr_t; | |
37 | struct in6_addr addr; | |
38 | struct in6_addr mask; | |
39 | } ngx_in6_cidr_t; | |
40 | ||
41 | ||
42 | #if (NGX_HAVE_INET6) | |
43 | ||
44 | typedef struct { | |
45 | in_addr_t addr; | |
46 | in_addr_t mask; | |
47 | } ngx_in_cidr_t; | |
48 | ||
49 | #endif | |
50 | ||
51 | ||
52 | typedef struct { | |
53 | ngx_uint_t family; | |
54 | union { | |
55 | ngx_in_cidr_t in; | |
56 | #if (NGX_HAVE_INET6) | |
57 | ngx_in6_cidr_t in6; | |
58 | #endif | |
59 | } u; | |
60 | } ngx_cidr_t; | |
40 | 61 | |
41 | 62 | |
42 | 63 | typedef union { |
43 | in_addr_t in_addr; | |
64 | in_addr_t in_addr; | |
44 | 65 | } ngx_url_addr_t; |
45 | 66 | |
46 | 67 | |
47 | 68 | typedef struct { |
48 | struct sockaddr *sockaddr; | |
49 | socklen_t socklen; | |
50 | ngx_str_t name; | |
69 | struct sockaddr *sockaddr; | |
70 | socklen_t socklen; | |
71 | ngx_str_t name; | |
51 | 72 | } ngx_peer_addr_t; |
52 | 73 | |
53 | 74 | |
54 | 75 | typedef struct { |
55 | ngx_str_t url; | |
56 | ngx_str_t host; | |
57 | ngx_str_t port_text; | |
58 | ngx_str_t uri; | |
76 | ngx_str_t url; | |
77 | ngx_str_t host; | |
78 | ngx_str_t port_text; | |
79 | ngx_str_t uri; | |
59 | 80 | |
60 | in_port_t port; | |
61 | in_port_t default_port; | |
62 | int family; | |
81 | in_port_t port; | |
82 | in_port_t default_port; | |
83 | int family; | |
63 | 84 | |
64 | unsigned listen:1; | |
65 | unsigned uri_part:1; | |
66 | unsigned no_resolve:1; | |
67 | unsigned one_addr:1; | |
85 | unsigned listen:1; | |
86 | unsigned uri_part:1; | |
87 | unsigned no_resolve:1; | |
88 | unsigned one_addr:1; | |
68 | 89 | |
69 | unsigned no_port:1; | |
70 | unsigned wildcard:1; | |
90 | unsigned no_port:1; | |
91 | unsigned wildcard:1; | |
71 | 92 | |
72 | ngx_url_addr_t addr; | |
93 | ngx_url_addr_t addr; | |
73 | 94 | |
74 | socklen_t socklen; | |
75 | u_char sockaddr[NGX_SOCKADDRLEN]; | |
95 | socklen_t socklen; | |
96 | u_char sockaddr[NGX_SOCKADDRLEN]; | |
76 | 97 | |
77 | ngx_peer_addr_t *addrs; | |
78 | ngx_uint_t naddrs; | |
98 | ngx_peer_addr_t *addrs; | |
99 | ngx_uint_t naddrs; | |
79 | 100 | |
80 | char *err; | |
101 | char *err; | |
81 | 102 | } ngx_url_t; |
82 | 103 | |
83 | 104 | |
85 | 106 | size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, |
86 | 107 | ngx_uint_t port); |
87 | 108 | size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len); |
88 | ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr); | |
109 | ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr); | |
89 | 110 | ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u); |
90 | 111 | ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u); |
91 | 112 |
1039 | 1039 | ngx_str_t *value; |
1040 | 1040 | ngx_event_debug_t *dc; |
1041 | 1041 | struct hostent *h; |
1042 | ngx_inet_cidr_t in_cidr; | |
1042 | ngx_cidr_t cidr; | |
1043 | 1043 | |
1044 | 1044 | value = cf->args->elts; |
1045 | ||
1046 | /* AF_INET only */ | |
1047 | 1045 | |
1048 | 1046 | dc = ngx_array_push(&ecf->debug_connection); |
1049 | 1047 | if (dc == NULL) { |
1050 | 1048 | return NGX_CONF_ERROR; |
1051 | 1049 | } |
1052 | 1050 | |
1053 | rc = ngx_ptocidr(&value[1], &in_cidr); | |
1051 | rc = ngx_ptocidr(&value[1], &cidr); | |
1054 | 1052 | |
1055 | 1053 | if (rc == NGX_DONE) { |
1056 | 1054 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
1059 | 1057 | } |
1060 | 1058 | |
1061 | 1059 | if (rc == NGX_OK) { |
1062 | dc->mask = in_cidr.mask; | |
1063 | dc->addr = in_cidr.addr; | |
1060 | ||
1061 | /* AF_INET only */ | |
1062 | ||
1063 | if (cidr.family != AF_INET) { | |
1064 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1065 | "\"debug_connection\" supports IPv4 only"); | |
1066 | return NGX_CONF_ERROR; | |
1067 | } | |
1068 | ||
1069 | dc->mask = cidr.u.in.mask; | |
1070 | dc->addr = cidr.u.in.addr; | |
1071 | ||
1064 | 1072 | return NGX_CONF_OK; |
1065 | 1073 | } |
1066 | 1074 |
140 | 140 | |
141 | 141 | ngx_int_t rc; |
142 | 142 | ngx_str_t *value; |
143 | ngx_inet_cidr_t in_cidr; | |
143 | ngx_cidr_t cidr; | |
144 | 144 | ngx_http_access_rule_t *rule; |
145 | 145 | |
146 | 146 | if (alcf->rules == NULL) { |
167 | 167 | return NGX_CONF_OK; |
168 | 168 | } |
169 | 169 | |
170 | rc = ngx_ptocidr(&value[1], &in_cidr); | |
170 | rc = ngx_ptocidr(&value[1], &cidr); | |
171 | 171 | |
172 | 172 | if (rc == NGX_ERROR) { |
173 | 173 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", |
175 | 175 | return NGX_CONF_ERROR; |
176 | 176 | } |
177 | 177 | |
178 | if (cidr.family != AF_INET) { | |
179 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
180 | "\"allow\" supports IPv4 only"); | |
181 | return NGX_CONF_ERROR; | |
182 | } | |
183 | ||
178 | 184 | if (rc == NGX_DONE) { |
179 | 185 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
180 | 186 | "low address bits of %V are meaningless", &value[1]); |
181 | 187 | } |
182 | 188 | |
183 | rule->mask = in_cidr.mask; | |
184 | rule->addr = in_cidr.addr; | |
189 | rule->mask = cidr.u.in.mask; | |
190 | rule->addr = cidr.u.in.addr; | |
185 | 191 | |
186 | 192 | return NGX_CONF_OK; |
187 | 193 | } |
777 | 777 | ngx_int_t rc, del; |
778 | 778 | ngx_str_t *net; |
779 | 779 | ngx_uint_t i; |
780 | ngx_inet_cidr_t cidrin; | |
780 | ngx_cidr_t cidr; | |
781 | 781 | ngx_http_variable_value_t *val, *old; |
782 | 782 | |
783 | 783 | if (ctx->tree == NULL) { |
788 | 788 | } |
789 | 789 | |
790 | 790 | if (ngx_strcmp(value[0].data, "default") == 0) { |
791 | cidrin.addr = 0; | |
792 | cidrin.mask = 0; | |
791 | cidr.u.in.addr = 0; | |
792 | cidr.u.in.mask = 0; | |
793 | 793 | net = &value[0]; |
794 | 794 | |
795 | 795 | } else { |
803 | 803 | } |
804 | 804 | |
805 | 805 | if (ngx_strcmp(net->data, "255.255.255.255") == 0) { |
806 | cidrin.addr = 0xffffffff; | |
807 | cidrin.mask = 0xffffffff; | |
806 | cidr.u.in.addr = 0xffffffff; | |
807 | cidr.u.in.mask = 0xffffffff; | |
808 | 808 | |
809 | 809 | } else { |
810 | rc = ngx_ptocidr(net, &cidrin); | |
810 | rc = ngx_ptocidr(net, &cidr); | |
811 | 811 | |
812 | 812 | if (rc == NGX_ERROR) { |
813 | 813 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
815 | 815 | return NGX_CONF_ERROR; |
816 | 816 | } |
817 | 817 | |
818 | if (cidr.family != AF_INET) { | |
819 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
820 | "\"geo\" supports IPv4 only"); | |
821 | return NGX_CONF_ERROR; | |
822 | } | |
823 | ||
818 | 824 | if (rc == NGX_DONE) { |
819 | 825 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
820 | 826 | "low address bits of %V are meaningless", |
821 | 827 | net); |
822 | 828 | } |
823 | 829 | |
824 | cidrin.addr = ntohl(cidrin.addr); | |
825 | cidrin.mask = ntohl(cidrin.mask); | |
830 | cidr.u.in.addr = ntohl(cidr.u.in.addr); | |
831 | cidr.u.in.mask = ntohl(cidr.u.in.mask); | |
826 | 832 | } |
827 | 833 | |
828 | 834 | if (del) { |
829 | if (ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask) | |
835 | if (ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, | |
836 | cidr.u.in.mask) | |
830 | 837 | != NGX_OK) |
831 | 838 | { |
832 | 839 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
844 | 851 | } |
845 | 852 | |
846 | 853 | for (i = 2; i; i--) { |
847 | rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask, | |
854 | rc = ngx_radix32tree_insert(ctx->tree, cidr.u.in.addr, cidr.u.in.mask, | |
848 | 855 | (uintptr_t) val); |
849 | 856 | if (rc == NGX_OK) { |
850 | 857 | return NGX_CONF_OK; |
857 | 864 | /* rc == NGX_BUSY */ |
858 | 865 | |
859 | 866 | old = (ngx_http_variable_value_t *) |
860 | ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask); | |
867 | ngx_radix32tree_find(ctx->tree, cidr.u.in.addr & cidr.u.in.mask); | |
861 | 868 | |
862 | 869 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
863 | 870 | "duplicate network \"%V\", value: \"%v\", old value: \"%v\"", |
864 | 871 | net, val, old); |
865 | 872 | |
866 | rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask); | |
873 | rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr, cidr.u.in.mask); | |
867 | 874 | |
868 | 875 | if (rc == NGX_ERROR) { |
869 | 876 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree"); |
281 | 281 | |
282 | 282 | ngx_int_t rc; |
283 | 283 | ngx_str_t *value; |
284 | ngx_inet_cidr_t in_cidr; | |
284 | ngx_cidr_t cidr; | |
285 | 285 | ngx_http_realip_from_t *from; |
286 | 286 | |
287 | 287 | if (rlcf->from == NULL) { |
299 | 299 | |
300 | 300 | value = cf->args->elts; |
301 | 301 | |
302 | rc = ngx_ptocidr(&value[1], &in_cidr); | |
302 | rc = ngx_ptocidr(&value[1], &cidr); | |
303 | 303 | |
304 | 304 | if (rc == NGX_ERROR) { |
305 | 305 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", |
307 | 307 | return NGX_CONF_ERROR; |
308 | 308 | } |
309 | 309 | |
310 | if (cidr.family != AF_INET) { | |
311 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
312 | "\"realip_from\" supports IPv4 only"); | |
313 | return NGX_CONF_ERROR; | |
314 | } | |
315 | ||
310 | 316 | if (rc == NGX_DONE) { |
311 | 317 | ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
312 | 318 | "low address bits of %V are meaningless", &value[1]); |
313 | 319 | } |
314 | 320 | |
315 | from->mask = in_cidr.mask; | |
316 | from->addr = in_cidr.addr; | |
321 | from->mask = cidr.u.in.mask; | |
322 | from->addr = cidr.u.in.addr; | |
317 | 323 | |
318 | 324 | return NGX_CONF_OK; |
319 | 325 | } |