Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | magnus | 1 | --- prayer-1.0.18.orig/prayer/config.c |
2 | +++ prayer-1.0.18/prayer/config.c |
||
3 | @@ -1650,7 +1650,7 @@ |
||
4 | |||
5 | if (!config_parse_rest(&option)) |
||
6 | error = T; |
||
7 | - else if ((s = (strchr(option, ':')))) { |
||
8 | + else if ((s = (strrchr(option, ':')))) { |
||
9 | *s++ = '\0'; |
||
10 | if (!config_parse_number(&port, s)) |
||
11 | error = T; |
||
12 | --- prayer-1.0.18.orig/prayer/ipaddr.c |
||
13 | +++ prayer-1.0.18/prayer/ipaddr.c |
||
14 | @@ -32,11 +32,7 @@ |
||
15 | |||
16 | BOOL ipaddr_copy(struct ipaddr * dst, struct ipaddr * src) |
||
17 | { |
||
18 | - dst->version = src->version; |
||
19 | - dst->addr[0] = src->addr[0]; |
||
20 | - dst->addr[1] = src->addr[1]; |
||
21 | - dst->addr[2] = src->addr[2]; |
||
22 | - dst->addr[3] = src->addr[3]; |
||
23 | + memcpy(dst, src, sizeof(struct ipaddr)); |
||
24 | |||
25 | return (T); |
||
26 | } |
||
27 | @@ -55,19 +51,7 @@ |
||
28 | if (addr1->version != addr2->version) |
||
29 | return (NIL); |
||
30 | |||
31 | - if (addr1->addr[0] != addr2->addr[0]) |
||
32 | - return (NIL); |
||
33 | - |
||
34 | - if (addr1->addr[1] != addr2->addr[1]) |
||
35 | - return (NIL); |
||
36 | - |
||
37 | - if (addr1->addr[2] != addr2->addr[2]) |
||
38 | - return (NIL); |
||
39 | - |
||
40 | - if (addr1->addr[3] != addr2->addr[3]) |
||
41 | - return (NIL); |
||
42 | - |
||
43 | - return (T); |
||
44 | + return (memcmp(&addr1->addr, &addr2->addr, addr1->version == 6 ? 16 : 4) == 0); |
||
45 | } |
||
46 | |||
47 | /* ====================================================================== */ |
||
48 | @@ -81,8 +65,7 @@ |
||
49 | { |
||
50 | static char buf[64]; |
||
51 | |||
52 | - sprintf(buf, "%d.%d.%d.%d", |
||
53 | - addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3]); |
||
54 | + os_inet_ntop(addr->addr, addr->version, buf, 64); |
||
55 | |||
56 | return (buf); |
||
57 | } |
||
58 | @@ -96,7 +79,7 @@ |
||
59 | { |
||
60 | char *result; |
||
61 | |||
62 | - if ((result = os_gethostbyaddr(addr->addr))) |
||
63 | + if ((result = os_gethostbyaddr(addr->addr, addr->version))) |
||
64 | return (result); |
||
65 | |||
66 | return (ipaddr_text(addr)); |
||
67 | @@ -116,39 +99,10 @@ |
||
68 | |||
69 | BOOL ipaddr_parse(struct ipaddr * addr, char *text) |
||
70 | { |
||
71 | - char *next; |
||
72 | - |
||
73 | if (text == NIL) |
||
74 | return (NIL); |
||
75 | |||
76 | - /* IPv4 only for the moment */ |
||
77 | - addr->version = 4; |
||
78 | - |
||
79 | - /* Parse first number */ |
||
80 | - if (!(next = strchr(text, '.'))) |
||
81 | - return (NIL); |
||
82 | - addr->addr[0] = atoi(text); |
||
83 | - text = next + 1; |
||
84 | - |
||
85 | - /* Parse second number */ |
||
86 | - if (!(next = strchr(text, '.'))) |
||
87 | - return (NIL); |
||
88 | - addr->addr[1] = atoi(text); |
||
89 | - text = next + 1; |
||
90 | - |
||
91 | - /* Parse third number */ |
||
92 | - if (!(next = strchr(text, '.'))) |
||
93 | - return (NIL); |
||
94 | - addr->addr[2] = atoi(text); |
||
95 | - text = next + 1; |
||
96 | - |
||
97 | - /* Parse forth number */ |
||
98 | - if ((next = strchr(text, '.'))) |
||
99 | - return (NIL); |
||
100 | - addr->addr[3] = atoi(text); |
||
101 | - |
||
102 | - /* Looks good */ |
||
103 | - return (T); |
||
104 | + return (os_inet_pton(text, addr)); |
||
105 | } |
||
106 | |||
107 | /* ====================================================================== */ |
||
108 | @@ -157,56 +111,63 @@ |
||
109 | * |
||
110 | * Compare IP address to text list of form: |
||
111 | * ipaddr: |
||
112 | - * text: Text string of form "131.111.0.0/16 : 192.168.0.0/24". |
||
113 | + * text: Text string of form "131.111.0.0/16 : 192.168.0.0/24 : 2001:12cd:1::/48". |
||
114 | + * (There has to be a space on either side of the colon for it to |
||
115 | + * separate two networks) |
||
116 | * |
||
117 | * Returns: T if addr matches list. |
||
118 | ************************************************************************/ |
||
119 | |||
120 | BOOL ipaddr_compare_list(struct ipaddr * ipaddr, char *text) |
||
121 | { |
||
122 | - char *next, *s, *alloc; |
||
123 | + char *next = NULL, *s, *alloc; |
||
124 | + int i; |
||
125 | unsigned long bits, mask; |
||
126 | struct ipaddr parsed; |
||
127 | |||
128 | alloc = text = pool_strdup(NIL, text); |
||
129 | |||
130 | while (text && *text) { |
||
131 | - if ((next = strchr(text, ':'))) |
||
132 | - *next++ = '\0'; |
||
133 | + s = text; |
||
134 | + while ((s = strchr(s, ':'))) { |
||
135 | + if (*(s - 1) == ' ' || *(s + 1) == ' ') { |
||
136 | + *(next = s) = '\0'; |
||
137 | + next++; |
||
138 | + } |
||
139 | + s++; |
||
140 | + } |
||
141 | |||
142 | text = string_trim_whitespace(text); |
||
143 | |||
144 | if ((s = strchr(text, '/'))) { |
||
145 | *s++ = '\0'; |
||
146 | bits = atoi(s); |
||
147 | - } else |
||
148 | - bits = 32; |
||
149 | - |
||
150 | - if (bits > 32) |
||
151 | - bits = 32; |
||
152 | - |
||
153 | - /* Create mask with appropriate number of bits set */ |
||
154 | - mask = 0; |
||
155 | - while (bits > 0) { |
||
156 | - mask >>= 1; |
||
157 | - mask |= 0x80000000; |
||
158 | - bits--; |
||
159 | } |
||
160 | + else |
||
161 | + bits = 128; /* Doesn't matter if it's too big */ |
||
162 | |||
163 | if (ipaddr_parse(&parsed, text)) { |
||
164 | - unsigned long a1; |
||
165 | - unsigned long a2; |
||
166 | - |
||
167 | - a1 = ((ipaddr->addr[0] << 24) + (ipaddr->addr[1] << 16) + |
||
168 | - (ipaddr->addr[2] << 8) + (ipaddr->addr[3])); |
||
169 | - |
||
170 | - a2 = ((parsed.addr[0] << 24) + (parsed.addr[1] << 16) + |
||
171 | - (parsed.addr[2] << 8) + (parsed.addr[3])); |
||
172 | - |
||
173 | - if ((a1 & mask) == (a2 & mask)) { |
||
174 | - free(alloc); |
||
175 | - return (T); |
||
176 | - } |
||
177 | + if (parsed.version != ipaddr->version) { |
||
178 | + text = next; continue; |
||
179 | + } |
||
180 | + |
||
181 | + for (i = 0; i < (parsed.version == 6 ? 4 : 1); i++) { |
||
182 | + if (bits == 0) mask = 0; |
||
183 | + else if (bits < 32) { |
||
184 | + mask = (-1) << (32 - bits); |
||
185 | + bits = 0; |
||
186 | + } |
||
187 | + else { |
||
188 | + mask = -1; |
||
189 | + bits -= 32; |
||
190 | + } |
||
191 | + |
||
192 | + if ((parsed.addr[i] & mask) != (ipaddr->addr[i] & mask)) { |
||
193 | + text = next; continue; |
||
194 | + } |
||
195 | + } |
||
196 | + free(alloc); |
||
197 | + return (T); |
||
198 | } |
||
199 | text = next; |
||
200 | } |
||
201 | @@ -225,11 +187,11 @@ |
||
202 | |||
203 | void ipaddr_send_iostream(struct ipaddr *addr, struct iostream *stream) |
||
204 | { |
||
205 | + int i; |
||
206 | ioputc(addr->version, stream); |
||
207 | - ioputc(addr->addr[0], stream); |
||
208 | - ioputc(addr->addr[1], stream); |
||
209 | - ioputc(addr->addr[2], stream); |
||
210 | - ioputc(addr->addr[3], stream); |
||
211 | + for (i = 0; i < (addr->version == 6 ? 16 : 4); i++) { |
||
212 | + ioputc(((char *)addr->addr)[i], stream); |
||
213 | + } |
||
214 | } |
||
215 | |||
216 | /* ====================================================================== */ |
||
217 | @@ -246,13 +208,13 @@ |
||
218 | |||
219 | if ((c = iogetc(stream)) != EOF) { |
||
220 | addr->version = (unsigned char) c; |
||
221 | - for (i = 0; i < 4; i++) { |
||
222 | + for (i = 0; i < (addr->version == 6 ? 16 : 4); i++) { |
||
223 | if ((c = iogetc(stream)) == EOF) { |
||
224 | rc = NIL; |
||
225 | break; |
||
226 | } |
||
227 | |||
228 | - addr->addr[i] = (unsigned char) c; |
||
229 | + ((char *)addr->addr)[i] = (unsigned char) c; |
||
230 | } |
||
231 | } |
||
232 | |||
233 | @@ -279,9 +241,14 @@ |
||
234 | ipaddr_set(struct ipaddr *ipaddr, unsigned long version, |
||
235 | unsigned char *addr) |
||
236 | { |
||
237 | - if (version != 4) |
||
238 | - log_fatal("ipaddr_set(): IPv4 only supported at the moment!"); |
||
239 | + if (version != 4 && version != 6) |
||
240 | + log_fatal("ipaddr_set(): IPv4 and IPv6 only supported!"); |
||
241 | + |
||
242 | + ipaddr->version = version; |
||
243 | + memcpy(ipaddr->addr, addr, version == 6 ? 16 : 4); |
||
244 | + if (ipaddr->addr[0] == 0 && ipaddr->addr[1] == 0 && ipaddr->addr[2] == 0xffff) { |
||
245 | + ipaddr->addr[0] = ipaddr->addr[3]; |
||
246 | + ipaddr->version = 4; |
||
247 | + } |
||
248 | |||
249 | - ipaddr->version = 4; |
||
250 | - memcpy(ipaddr->addr, addr, 4); |
||
251 | } |
||
252 | --- prayer-1.0.18.orig/prayer/ipaddr.h |
||
253 | +++ prayer-1.0.18/prayer/ipaddr.h |
||
254 | @@ -8,7 +8,7 @@ |
||
255 | |||
256 | struct ipaddr { |
||
257 | unsigned long version; |
||
258 | - unsigned char addr[4]; |
||
259 | + unsigned long addr[4]; |
||
260 | }; |
||
261 | |||
262 | struct ipaddr *ipaddr_create(struct pool *pool); |
||
263 | --- prayer-1.0.18.orig/prayer/os.h |
||
264 | +++ prayer-1.0.18/prayer/os.h |
||
265 | @@ -24,7 +24,11 @@ |
||
266 | |||
267 | int os_socket_nonblocking(int sockfd); |
||
268 | |||
269 | -char *os_gethostbyaddr(void *addr); |
||
270 | +char *os_gethostbyaddr(void *addr, unsigned int version); |
||
271 | + |
||
272 | +int os_inet_ntop(void *addr, unsigned long version, char *buf, unsigned long buflen); |
||
273 | + |
||
274 | +int os_inet_pton(char *str, struct ipaddr *addr); |
||
275 | |||
276 | void os_child_reaper(); |
||
277 | |||
278 | --- prayer-1.0.18.orig/prayer/os_linux.c |
||
279 | +++ prayer-1.0.18/prayer/os_linux.c |
||
280 | @@ -13,14 +13,11 @@ |
||
281 | #include <sys/un.h> |
||
282 | #include <sys/resource.h> |
||
283 | #include <netinet/in.h> |
||
284 | -#include <netinet/tcp.h> |
||
285 | #include <arpa/inet.h> |
||
286 | #include <signal.h> |
||
287 | #include <netdb.h> |
||
288 | #include <sys/file.h> |
||
289 | |||
290 | -#include <openssl/rand.h> |
||
291 | - |
||
292 | /* ====================================================================== */ |
||
293 | |||
294 | BOOL os_socketpair(int *sockfd) |
||
295 | @@ -63,33 +60,28 @@ |
||
296 | |||
297 | int os_connect_inet_socket(char *host, unsigned long port) |
||
298 | { |
||
299 | - struct hostent *hostent; |
||
300 | - struct sockaddr_in serv_addr; |
||
301 | + struct addrinfo *first_ai, *ai; |
||
302 | + char port_str[12]; |
||
303 | int sockfd; |
||
304 | |||
305 | - /* Open the socket */ |
||
306 | - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) |
||
307 | - return (-1); |
||
308 | - |
||
309 | - /* Set up the socket */ |
||
310 | - bzero((char *) &serv_addr, sizeof(serv_addr)); |
||
311 | - serv_addr.sin_family = AF_INET; |
||
312 | - serv_addr.sin_port = htons(port); |
||
313 | - |
||
314 | - if ((hostent = gethostbyname(host)) == NIL) { |
||
315 | - close(sockfd); |
||
316 | - return (-1); |
||
317 | - } |
||
318 | - bcopy(hostent->h_addr, (char *) &serv_addr.sin_addr, |
||
319 | - hostent->h_length); |
||
320 | - |
||
321 | - if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) |
||
322 | - < 0) { |
||
323 | - close(sockfd); |
||
324 | - return (-1); |
||
325 | - } |
||
326 | - |
||
327 | - return (sockfd); |
||
328 | + sprintf(port_str, "%lu", port); |
||
329 | + if (getaddrinfo(host, port_str, NULL, &first_ai)) { |
||
330 | + return (-1); |
||
331 | + } |
||
332 | + for (ai = first_ai; ai->ai_next; ai = ai->ai_next) { |
||
333 | + /* Open the socket */ |
||
334 | + if ((sockfd = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) { |
||
335 | + break; |
||
336 | + } |
||
337 | + if (connect(sockfd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) { |
||
338 | + close(sockfd); |
||
339 | + break; |
||
340 | + } |
||
341 | + freeaddrinfo(first_ai); |
||
342 | + return (sockfd); |
||
343 | + } |
||
344 | + freeaddrinfo(first_ai); |
||
345 | + return (-1); |
||
346 | } |
||
347 | |||
348 | /* ====================================================================== */ |
||
349 | @@ -150,9 +141,39 @@ |
||
350 | int os_bind_inet_socket(unsigned long port, char *interface) |
||
351 | { |
||
352 | int i, sockfd; |
||
353 | - struct sockaddr_in serv_addr; |
||
354 | + struct sockaddr_storage serv_addr; |
||
355 | + struct addrinfo *ai; |
||
356 | + |
||
357 | + bzero((char *) &serv_addr, sizeof(serv_addr)); |
||
358 | |||
359 | - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
||
360 | + if (interface) { |
||
361 | + if (getaddrinfo(interface, NULL, NULL, &ai)) { |
||
362 | + log_panic |
||
363 | + ("[os_bind_inet_socket()] Failed to lookup hostname: %s", |
||
364 | + interface); |
||
365 | + return -1; |
||
366 | + } |
||
367 | +#if 0 /* Use the first interface address; don't panic if both IPv6 |
||
368 | + and IPv4 addresses are returned. */ |
||
369 | + if (hostent->h_addr_list[1]) { |
||
370 | + log_panic |
||
371 | + ("[os_bind_inet_socket()] Ambiguous interface name: %s", |
||
372 | + interface); |
||
373 | + return (-1); |
||
374 | + } |
||
375 | +#endif |
||
376 | + memcpy(&serv_addr, ai->ai_addr, ai->ai_addrlen); |
||
377 | + freeaddrinfo(ai); |
||
378 | + } |
||
379 | + else { |
||
380 | + serv_addr.ss_family = AF_INET6; |
||
381 | + ((struct sockaddr_in6*)&serv_addr)->sin6_addr = in6addr_any; |
||
382 | + } |
||
383 | + /* This isn't formally correct, but *in fact*, sin6_port is at the |
||
384 | + same place as sin_port, so it works. */ |
||
385 | + ((struct sockaddr_in6*)&serv_addr)->sin6_port = htons(port); |
||
386 | + |
||
387 | + if ((sockfd = socket(serv_addr.ss_family, SOCK_STREAM, 0)) < 0) { |
||
388 | log_panic("[os_bind_inet_socket()] socket() failed, %s", |
||
389 | strerror(errno)); |
||
390 | return (-1); |
||
391 | @@ -168,41 +189,6 @@ |
||
392 | return (-1); |
||
393 | } |
||
394 | |||
395 | - bzero((char *) &serv_addr, sizeof(serv_addr)); |
||
396 | - serv_addr.sin_family = AF_INET; |
||
397 | - serv_addr.sin_port = htons(port); |
||
398 | - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
||
399 | - |
||
400 | - /* Calculate serv_addr for specific interface to bind to */ |
||
401 | - if (interface) { |
||
402 | - struct hostent *hostent; |
||
403 | - struct in_addr *s; |
||
404 | - |
||
405 | - if (!(hostent = gethostbyname(interface))) { |
||
406 | - log_panic |
||
407 | - ("[os_bind_inet_socket()] Failed to lookup hostname: %s", |
||
408 | - interface); |
||
409 | - |
||
410 | - return (-1); |
||
411 | - } |
||
412 | - |
||
413 | - if (hostent->h_addr_list[1]) { |
||
414 | - log_panic |
||
415 | - ("[os_bind_inet_socket()] Ambiguous interface name: %s", |
||
416 | - interface); |
||
417 | - return (-1); |
||
418 | - } |
||
419 | - |
||
420 | - if (!(s = ((struct in_addr *)hostent->h_addr_list[0]))) { |
||
421 | - log_panic("[os_bind_inet_socket()] Invalid interface name: %s", |
||
422 | - interface); |
||
423 | - return (-1); |
||
424 | - } |
||
425 | - |
||
426 | - /* s has four bytes in network byte order */ |
||
427 | - memcpy(&serv_addr.sin_addr.s_addr, s, sizeof(struct in_addr)); |
||
428 | - } |
||
429 | - |
||
430 | /* bind() as Internet domain socket */ |
||
431 | if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < |
||
432 | 0) { |
||
433 | @@ -255,8 +242,8 @@ |
||
434 | |||
435 | int os_accept_inet(int sockfd, struct ipaddr *ipaddr) |
||
436 | { |
||
437 | - struct sockaddr_in addr; |
||
438 | - socklen_t len = (socklen_t) sizeof(struct sockaddr_in); |
||
439 | + struct sockaddr_storage addr; |
||
440 | + socklen_t len = (socklen_t) sizeof(addr); |
||
441 | int newsockfd; |
||
442 | |||
443 | do { |
||
444 | @@ -271,8 +258,12 @@ |
||
445 | return (-1); |
||
446 | } |
||
447 | |||
448 | - if (ipaddr) |
||
449 | - ipaddr_set(ipaddr, 4, (unsigned char *) &addr.sin_addr); |
||
450 | + if (ipaddr) { |
||
451 | + if (addr.ss_family == AF_INET6) |
||
452 | + ipaddr_set(ipaddr, 6, (unsigned char *)&((struct sockaddr_in6*)&addr)->sin6_addr); |
||
453 | + else |
||
454 | + ipaddr_set(ipaddr, 4, (unsigned char *)&((struct sockaddr_in*)&addr)->sin_addr); |
||
455 | + } |
||
456 | |||
457 | /* Set close on exec so subprocesses can't interfere */ |
||
458 | if (fcntl(newsockfd, F_SETFD, FD_CLOEXEC) < 0) { |
||
459 | @@ -322,9 +313,14 @@ |
||
460 | |||
461 | /* Convert IPv4 address into text form */ |
||
462 | |||
463 | -char *os_gethostbyaddr(void *opaque) |
||
464 | +char *os_gethostbyaddr(void *opaque, unsigned int version) |
||
465 | { |
||
466 | - struct hostent *hostent = gethostbyaddr(opaque, 4, AF_INET); |
||
467 | + struct hostent *hostent; |
||
468 | + |
||
469 | + if (version == 6) |
||
470 | + hostent = gethostbyaddr(opaque, 16, AF_INET6); |
||
471 | + else |
||
472 | + hostent = gethostbyaddr(opaque, 4, AF_INET); |
||
473 | |||
474 | if (hostent && hostent->h_name && hostent->h_name[0]) |
||
475 | return (hostent->h_name); |
||
476 | @@ -332,6 +328,32 @@ |
||
477 | return (NIL); |
||
478 | } |
||
479 | |||
480 | +int os_inet_ntop(void *addr, unsigned long version, char *buf, unsigned long buflen) { |
||
481 | + if (version == 6) { |
||
482 | + if (inet_ntop(AF_INET6, addr, buf, buflen)) |
||
483 | + return (T); |
||
484 | + } |
||
485 | + else { |
||
486 | + if (inet_ntop(AF_INET, addr, buf, buflen)) |
||
487 | + return (T); |
||
488 | + } |
||
489 | + return (NIL); |
||
490 | +} |
||
491 | + |
||
492 | +int os_inet_pton(char *str, struct ipaddr *addr) { |
||
493 | + unsigned char buf[16]; |
||
494 | + |
||
495 | + if (inet_pton(AF_INET6, str, buf)) { |
||
496 | + ipaddr_set(addr, 6, buf); |
||
497 | + return (T); |
||
498 | + } |
||
499 | + else if (inet_pton(AF_INET, str, buf)) { |
||
500 | + ipaddr_set(addr, 4, buf); |
||
501 | + return (T); |
||
502 | + } |
||
503 | + return (NIL); |
||
504 | +} |
||
505 | + |
||
506 | /* ====================================================================== */ |
||
507 | |||
508 | /* Trivial SIG_CLD handler to prevent zombies from hanging around */ |