?revision_form?Rev ?revision_input??revision_submit??revision_endform?
Rev 3 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
--- prayer-1.0.18.orig/prayer/config.c
+++ prayer-1.0.18/prayer/config.c
@@ -1650,7 +1650,7 @@
if (!config_parse_rest(&option))
error = T;
- else if ((s = (strchr(option, ':')))) {
+ else if ((s = (strrchr(option, ':')))) {
*s++ = '\0';
if (!config_parse_number(&port, s))
error = T;
--- prayer-1.0.18.orig/prayer/ipaddr.c
+++ prayer-1.0.18/prayer/ipaddr.c
@@ -32,11 +32,7 @@
BOOL ipaddr_copy(struct ipaddr * dst, struct ipaddr * src)
{
- dst->version = src->version;
- dst->addr[0] = src->addr[0];
- dst->addr[1] = src->addr[1];
- dst->addr[2] = src->addr[2];
- dst->addr[3] = src->addr[3];
+ memcpy(dst, src, sizeof(struct ipaddr));
return (T);
}
@@ -55,19 +51,7 @@
if (addr1->version != addr2->version)
return (NIL);
- if (addr1->addr[0] != addr2->addr[0])
- return (NIL);
-
- if (addr1->addr[1] != addr2->addr[1])
- return (NIL);
-
- if (addr1->addr[2] != addr2->addr[2])
- return (NIL);
-
- if (addr1->addr[3] != addr2->addr[3])
- return (NIL);
-
- return (T);
+ return (memcmp(&addr1->addr, &addr2->addr, addr1->version == 6 ? 16 : 4) == 0);
}
/* ====================================================================== */
@@ -81,8 +65,7 @@
{
static char buf[64];
- sprintf(buf, "%d.%d.%d.%d",
- addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3]);
+ os_inet_ntop(addr->addr, addr->version, buf, 64);
return (buf);
}
@@ -96,7 +79,7 @@
{
char *result;
- if ((result = os_gethostbyaddr(addr->addr)))
+ if ((result = os_gethostbyaddr(addr->addr, addr->version)))
return (result);
return (ipaddr_text(addr));
@@ -116,39 +99,10 @@
BOOL ipaddr_parse(struct ipaddr * addr, char *text)
{
- char *next;
-
if (text == NIL)
return (NIL);
- /* IPv4 only for the moment */
- addr->version = 4;
-
- /* Parse first number */
- if (!(next = strchr(text, '.')))
- return (NIL);
- addr->addr[0] = atoi(text);
- text = next + 1;
-
- /* Parse second number */
- if (!(next = strchr(text, '.')))
- return (NIL);
- addr->addr[1] = atoi(text);
- text = next + 1;
-
- /* Parse third number */
- if (!(next = strchr(text, '.')))
- return (NIL);
- addr->addr[2] = atoi(text);
- text = next + 1;
-
- /* Parse forth number */
- if ((next = strchr(text, '.')))
- return (NIL);
- addr->addr[3] = atoi(text);
-
- /* Looks good */
- return (T);
+ return (os_inet_pton(text, addr));
}
/* ====================================================================== */
@@ -157,56 +111,63 @@
*
* Compare IP address to text list of form:
* ipaddr:
- * text: Text string of form "131.111.0.0/16 : 192.168.0.0/24".
+ * text: Text string of form "131.111.0.0/16 : 192.168.0.0/24 : 2001:12cd:1::/48".
+ * (There has to be a space on either side of the colon for it to
+ * separate two networks)
*
* Returns: T if addr matches list.
************************************************************************/
BOOL ipaddr_compare_list(struct ipaddr * ipaddr, char *text)
{
- char *next, *s, *alloc;
+ char *next = NULL, *s, *alloc;
+ int i;
unsigned long bits, mask;
struct ipaddr parsed;
alloc = text = pool_strdup(NIL, text);
while (text && *text) {
- if ((next = strchr(text, ':')))
- *next++ = '\0';
+ s = text;
+ while ((s = strchr(s, ':'))) {
+ if (*(s - 1) == ' ' || *(s + 1) == ' ') {
+ *(next = s) = '\0';
+ next++;
+ }
+ s++;
+ }
text = string_trim_whitespace(text);
if ((s = strchr(text, '/'))) {
*s++ = '\0';
bits = atoi(s);
- } else
- bits = 32;
-
- if (bits > 32)
- bits = 32;
-
- /* Create mask with appropriate number of bits set */
- mask = 0;
- while (bits > 0) {
- mask >>= 1;
- mask |= 0x80000000;
- bits--;
}
+ else
+ bits = 128; /* Doesn't matter if it's too big */
if (ipaddr_parse(&parsed, text)) {
- unsigned long a1;
- unsigned long a2;
-
- a1 = ((ipaddr->addr[0] << 24) + (ipaddr->addr[1] << 16) +
- (ipaddr->addr[2] << 8) + (ipaddr->addr[3]));
-
- a2 = ((parsed.addr[0] << 24) + (parsed.addr[1] << 16) +
- (parsed.addr[2] << 8) + (parsed.addr[3]));
-
- if ((a1 & mask) == (a2 & mask)) {
- free(alloc);
- return (T);
- }
+ if (parsed.version != ipaddr->version) {
+ text = next; continue;
+ }
+
+ for (i = 0; i < (parsed.version == 6 ? 4 : 1); i++) {
+ if (bits == 0) mask = 0;
+ else if (bits < 32) {
+ mask = (-1) << (32 - bits);
+ bits = 0;
+ }
+ else {
+ mask = -1;
+ bits -= 32;
+ }
+
+ if ((parsed.addr[i] & mask) != (ipaddr->addr[i] & mask)) {
+ text = next; continue;
+ }
+ }
+ free(alloc);
+ return (T);
}
text = next;
}
@@ -225,11 +187,11 @@
void ipaddr_send_iostream(struct ipaddr *addr, struct iostream *stream)
{
+ int i;
ioputc(addr->version, stream);
- ioputc(addr->addr[0], stream);
- ioputc(addr->addr[1], stream);
- ioputc(addr->addr[2], stream);
- ioputc(addr->addr[3], stream);
+ for (i = 0; i < (addr->version == 6 ? 16 : 4); i++) {
+ ioputc(((char *)addr->addr)[i], stream);
+ }
}
/* ====================================================================== */
@@ -246,13 +208,13 @@
if ((c = iogetc(stream)) != EOF) {
addr->version = (unsigned char) c;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < (addr->version == 6 ? 16 : 4); i++) {
if ((c = iogetc(stream)) == EOF) {
rc = NIL;
break;
}
- addr->addr[i] = (unsigned char) c;
+ ((char *)addr->addr)[i] = (unsigned char) c;
}
}
@@ -279,9 +241,14 @@
ipaddr_set(struct ipaddr *ipaddr, unsigned long version,
unsigned char *addr)
{
- if (version != 4)
- log_fatal("ipaddr_set(): IPv4 only supported at the moment!");
+ if (version != 4 && version != 6)
+ log_fatal("ipaddr_set(): IPv4 and IPv6 only supported!");
+
+ ipaddr->version = version;
+ memcpy(ipaddr->addr, addr, version == 6 ? 16 : 4);
+ if (ipaddr->addr[0] == 0 && ipaddr->addr[1] == 0 && ipaddr->addr[2] == 0xffff) {
+ ipaddr->addr[0] = ipaddr->addr[3];
+ ipaddr->version = 4;
+ }
- ipaddr->version = 4;
- memcpy(ipaddr->addr, addr, 4);
}
--- prayer-1.0.18.orig/prayer/ipaddr.h
+++ prayer-1.0.18/prayer/ipaddr.h
@@ -8,7 +8,7 @@
struct ipaddr {
unsigned long version;
- unsigned char addr[4];
+ unsigned long addr[4];
};
struct ipaddr *ipaddr_create(struct pool *pool);
--- prayer-1.0.18.orig/prayer/os.h
+++ prayer-1.0.18/prayer/os.h
@@ -24,7 +24,11 @@
int os_socket_nonblocking(int sockfd);
-char *os_gethostbyaddr(void *addr);
+char *os_gethostbyaddr(void *addr, unsigned int version);
+
+int os_inet_ntop(void *addr, unsigned long version, char *buf, unsigned long buflen);
+
+int os_inet_pton(char *str, struct ipaddr *addr);
void os_child_reaper();
--- prayer-1.0.18.orig/prayer/os_linux.c
+++ prayer-1.0.18/prayer/os_linux.c
@@ -13,14 +13,11 @@
#include <sys/un.h>
#include <sys/resource.h>
#include <netinet/in.h>
-#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <signal.h>
#include <netdb.h>
#include <sys/file.h>
-#include <openssl/rand.h>
-
/* ====================================================================== */
BOOL os_socketpair(int *sockfd)
@@ -63,33 +60,28 @@
int os_connect_inet_socket(char *host, unsigned long port)
{
- struct hostent *hostent;
- struct sockaddr_in serv_addr;
+ struct addrinfo *first_ai, *ai;
+ char port_str[12];
int sockfd;
- /* Open the socket */
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- return (-1);
-
- /* Set up the socket */
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
-
- if ((hostent = gethostbyname(host)) == NIL) {
- close(sockfd);
- return (-1);
- }
- bcopy(hostent->h_addr, (char *) &serv_addr.sin_addr,
- hostent->h_length);
-
- if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
- < 0) {
- close(sockfd);
- return (-1);
- }
-
- return (sockfd);
+ sprintf(port_str, "%lu", port);
+ if (getaddrinfo(host, port_str, NULL, &first_ai)) {
+ return (-1);
+ }
+ for (ai = first_ai; ai->ai_next; ai = ai->ai_next) {
+ /* Open the socket */
+ if ((sockfd = socket(ai->ai_family, SOCK_STREAM, 0)) < 0) {
+ break;
+ }
+ if (connect(sockfd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) {
+ close(sockfd);
+ break;
+ }
+ freeaddrinfo(first_ai);
+ return (sockfd);
+ }
+ freeaddrinfo(first_ai);
+ return (-1);
}
/* ====================================================================== */
@@ -150,9 +141,39 @@
int os_bind_inet_socket(unsigned long port, char *interface)
{
int i, sockfd;
- struct sockaddr_in serv_addr;
+ struct sockaddr_storage serv_addr;
+ struct addrinfo *ai;
+
+ bzero((char *) &serv_addr, sizeof(serv_addr));
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ if (interface) {
+ if (getaddrinfo(interface, NULL, NULL, &ai)) {
+ log_panic
+ ("[os_bind_inet_socket()] Failed to lookup hostname: %s",
+ interface);
+ return -1;
+ }
+#if 0 /* Use the first interface address; don't panic if both IPv6
+ and IPv4 addresses are returned. */
+ if (hostent->h_addr_list[1]) {
+ log_panic
+ ("[os_bind_inet_socket()] Ambiguous interface name: %s",
+ interface);
+ return (-1);
+ }
+#endif
+ memcpy(&serv_addr, ai->ai_addr, ai->ai_addrlen);
+ freeaddrinfo(ai);
+ }
+ else {
+ serv_addr.ss_family = AF_INET6;
+ ((struct sockaddr_in6*)&serv_addr)->sin6_addr = in6addr_any;
+ }
+ /* This isn't formally correct, but *in fact*, sin6_port is at the
+ same place as sin_port, so it works. */
+ ((struct sockaddr_in6*)&serv_addr)->sin6_port = htons(port);
+
+ if ((sockfd = socket(serv_addr.ss_family, SOCK_STREAM, 0)) < 0) {
log_panic("[os_bind_inet_socket()] socket() failed, %s",
strerror(errno));
return (-1);
@@ -168,41 +189,6 @@
return (-1);
}
- bzero((char *) &serv_addr, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- /* Calculate serv_addr for specific interface to bind to */
- if (interface) {
- struct hostent *hostent;
- struct in_addr *s;
-
- if (!(hostent = gethostbyname(interface))) {
- log_panic
- ("[os_bind_inet_socket()] Failed to lookup hostname: %s",
- interface);
-
- return (-1);
- }
-
- if (hostent->h_addr_list[1]) {
- log_panic
- ("[os_bind_inet_socket()] Ambiguous interface name: %s",
- interface);
- return (-1);
- }
-
- if (!(s = ((struct in_addr *)hostent->h_addr_list[0]))) {
- log_panic("[os_bind_inet_socket()] Invalid interface name: %s",
- interface);
- return (-1);
- }
-
- /* s has four bytes in network byte order */
- memcpy(&serv_addr.sin_addr.s_addr, s, sizeof(struct in_addr));
- }
-
/* bind() as Internet domain socket */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <
0) {
@@ -255,8 +242,8 @@
int os_accept_inet(int sockfd, struct ipaddr *ipaddr)
{
- struct sockaddr_in addr;
- socklen_t len = (socklen_t) sizeof(struct sockaddr_in);
+ struct sockaddr_storage addr;
+ socklen_t len = (socklen_t) sizeof(addr);
int newsockfd;
do {
@@ -271,8 +258,12 @@
return (-1);
}
- if (ipaddr)
- ipaddr_set(ipaddr, 4, (unsigned char *) &addr.sin_addr);
+ if (ipaddr) {
+ if (addr.ss_family == AF_INET6)
+ ipaddr_set(ipaddr, 6, (unsigned char *)&((struct sockaddr_in6*)&addr)->sin6_addr);
+ else
+ ipaddr_set(ipaddr, 4, (unsigned char *)&((struct sockaddr_in*)&addr)->sin_addr);
+ }
/* Set close on exec so subprocesses can't interfere */
if (fcntl(newsockfd, F_SETFD, FD_CLOEXEC) < 0) {
@@ -322,9 +313,14 @@
/* Convert IPv4 address into text form */
-char *os_gethostbyaddr(void *opaque)
+char *os_gethostbyaddr(void *opaque, unsigned int version)
{
- struct hostent *hostent = gethostbyaddr(opaque, 4, AF_INET);
+ struct hostent *hostent;
+
+ if (version == 6)
+ hostent = gethostbyaddr(opaque, 16, AF_INET6);
+ else
+ hostent = gethostbyaddr(opaque, 4, AF_INET);
if (hostent && hostent->h_name && hostent->h_name[0])
return (hostent->h_name);
@@ -332,6 +328,32 @@
return (NIL);
}
+int os_inet_ntop(void *addr, unsigned long version, char *buf, unsigned long buflen) {
+ if (version == 6) {
+ if (inet_ntop(AF_INET6, addr, buf, buflen))
+ return (T);
+ }
+ else {
+ if (inet_ntop(AF_INET, addr, buf, buflen))
+ return (T);
+ }
+ return (NIL);
+}
+
+int os_inet_pton(char *str, struct ipaddr *addr) {
+ unsigned char buf[16];
+
+ if (inet_pton(AF_INET6, str, buf)) {
+ ipaddr_set(addr, 6, buf);
+ return (T);
+ }
+ else if (inet_pton(AF_INET, str, buf)) {
+ ipaddr_set(addr, 4, buf);
+ return (T);
+ }
+ return (NIL);
+}
+
/* ====================================================================== */
/* Trivial SIG_CLD handler to prevent zombies from hanging around */