Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

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 */