Date: Thu, 10 Nov 2005 19:08:11 -0600 (CST) From: Craig Boston <craig@tobuj.gank.org> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/88821: [PATCH] IPv6 support for ggate Message-ID: <20051111010811.1E7032D2D3@ion.gank.org> Resent-Message-ID: <200511110110.jAB1AGKu030956@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 88821 >Category: bin >Synopsis: [PATCH] IPv6 support for ggate >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Nov 11 01:10:16 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Craig Boston >Release: FreeBSD 6.0-STABLE i386 >Organization: I wish I had some >Environment: System: FreeBSD hostname.gank.org 6.0-STABLE FreeBSD 6.0-STABLE #0: Sat Nov 5 20:59:05 CST 2005 root@hostname.gank.org:/compile/obj/compile/src/sys/HOSTNAME i386 >Description: Adds full IPv6 support to ggated and complete address family independence to ggatec. >How-To-Repeat: n/a >Fix: --- ggate_ipv6_2.patch begins here --- diff -ruN ggate.orig/ggatec/ggatec.c ggate/ggatec/ggatec.c --- ggate.orig/ggatec/ggatec.c Thu Nov 10 18:53:21 2005 +++ ggate/ggatec/ggatec.c Thu Nov 10 18:53:25 2005 @@ -50,6 +50,7 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> +#include <netdb.h> #include <geom/gate/g_gate.h> #include "ggate.h" @@ -63,7 +64,7 @@ static unsigned flags = 0; static int force = 0; static unsigned queue_size = G_GATE_QUEUE_SIZE; -static unsigned port = G_GATE_PORT; +static const char *port = G_GATE_PORT_STR; static off_t mediasize; static unsigned sectorsize = 0; static unsigned timeout = G_GATE_TIMEOUT; @@ -244,37 +245,55 @@ struct g_gate_version ver; struct g_gate_cinit cinit; struct g_gate_sinit sinit; - struct sockaddr_in serv; + struct addrinfo hints; + struct addrinfo *res, *p; int sfd; /* * Do the network stuff. */ - bzero(&serv, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = g_gate_str2ip(host); - if (serv.sin_addr.s_addr == INADDR_NONE) { - g_gate_log(LOG_DEBUG, "Invalid IP/host name: %s.", host); + bzero(&hints, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + sfd = -1; + if (getaddrinfo(host, port, &hints, &res) != 0) { + g_gate_log(LOG_DEBUG, "Invalid IP/host name or port: %s (%s).", + host, port); return (-1); - } - serv.sin_port = htons(port); - sfd = socket(AF_INET, SOCK_STREAM, 0); - if (sfd == -1) { - g_gate_log(LOG_DEBUG, "Cannot open socket: %s.", - strerror(errno)); - return (-1); - } + } else { + p = res; + while (p) { + sfd = socket(p->ai_family, p->ai_socktype, 0); + if (sfd == -1) { + g_gate_log(LOG_DEBUG, "Cannot open socket: %s.", + strerror(errno)); + freeaddrinfo(res); + return (-1); + } - g_gate_socket_settings(sfd); + g_gate_socket_settings(sfd); - if (connect(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) { - g_gate_log(LOG_DEBUG, "Cannot connect to server: %s.", - strerror(errno)); - close(sfd); + if (connect(sfd, p->ai_addr, p->ai_addrlen) == 0) + break; + + /* Non-critical error, try next address */ + g_gate_log(LOG_DEBUG, "Cannot connect to server: %s.", + strerror(errno)); + close(sfd); + sfd = -1; + + p = p->ai_next; + } + } + freeaddrinfo(res); + + if (sfd == -1) { + g_gate_log(LOG_DEBUG, "Invalid IP/host name or port: %s (%s).", + host, port); return (-1); } - g_gate_log(LOG_INFO, "Connected to the server: %s:%d.", host, port); + g_gate_log(LOG_INFO, "Connected to the server: %s (%s).", host, port); /* * Create and send version packet. @@ -454,7 +473,7 @@ ggioc.gctl_maxcount = queue_size; ggioc.gctl_timeout = timeout; ggioc.gctl_unit = unit; - snprintf(ggioc.gctl_info, sizeof(ggioc.gctl_info), "%s:%u %s", host, + snprintf(ggioc.gctl_info, sizeof(ggioc.gctl_info), "%s (%s) %s", host, port, path); g_gate_ioctl(G_GATE_CMD_CREATE, &ggioc); if (unit == -1) @@ -535,9 +554,7 @@ if (action != CREATE && action != RESCUE) usage(); errno = 0; - port = strtoul(optarg, NULL, 10); - if (port == 0 && errno != 0) - errx(EXIT_FAILURE, "Invalid port."); + port = optarg; break; case 'q': if (action != CREATE) diff -ruN ggate.orig/ggated/ggated.8 ggate/ggated/ggated.8 --- ggate.orig/ggated/ggated.8 Thu Nov 10 18:53:21 2005 +++ ggate/ggated/ggated.8 Thu Nov 10 18:53:25 2005 @@ -55,7 +55,10 @@ Available options: .Bl -tag -width ".Ar exports\ file" .It Fl a Ar address -Specifies an IP address to bind to. +Specifies an IP address to bind to. To bind to multiple addresses, +specify each address with a separate +.Fl a +option. .It Fl h Print available options. .It Fl n @@ -74,7 +77,7 @@ Size of send buffer to use. Default is 131072 (128kB). .It Fl v -Do not fork, run in foreground and print debug informations on standard +Do not fork, run in foreground and print debug information on standard output. .It Ar "exports file" An alternate location for the exports file. @@ -82,9 +85,10 @@ .Pp The format of an exports file is as follows: .Bd -literal -offset indent -1.2.3.4 RO /dev/acd0 -1.2.3.0/24 RW /tmp/test.img -hostname WO /tmp/image +1.2.3.4 RO /dev/acd0 +1.2.3.0/24 RW /tmp/test.img +2001:DB8:17C0::/64 RW /tmp/foo +hostname WO /tmp/image .Ed .Sh EXIT STATUS Exit status is 0 on success, or 1 if the command fails. diff -ruN ggate.orig/ggated/ggated.c ggate/ggated/ggated.c --- ggate.orig/ggated/ggated.c Thu Nov 10 18:53:21 2005 +++ ggate/ggated/ggated.c Thu Nov 10 18:53:25 2005 @@ -44,6 +44,7 @@ #include <netinet/in.h> #include <netinet/tcp.h> #include <arpa/inet.h> +#include <netdb.h> #include <signal.h> #include <assert.h> #include <err.h> @@ -68,7 +69,7 @@ time_t c_birthtime; char *c_path; uint64_t c_token; - in_addr_t c_srcip; + struct sockaddr_storage c_srcaddr; LIST_ENTRY(ggd_connection) c_next; }; @@ -83,16 +84,22 @@ #define r_error r_hdr.gh_error struct ggd_export { - char *e_path; /* path to device/file */ - in_addr_t e_ip; /* remote IP address */ - in_addr_t e_mask; /* IP mask */ - unsigned e_flags; /* flags (RO/RW) */ - SLIST_ENTRY(ggd_export) e_next; + char *e_path; /* path to device/file */ + struct sockaddr_storage e_addr; /* remote IP address */ + struct sockaddr_storage e_mask; /* IP mask */ + unsigned e_flags; /* flags (RO/RW) */ + SLIST_ENTRY(ggd_export) e_next; +}; + +struct ggd_listen { + const char *l_name; /* host name / address */ + struct sockaddr_storage l_addr; /* bind address & port */ + int l_fd; /* socket */ + SLIST_ENTRY(ggd_listen) l_next; }; static const char *exports_file = GGATED_EXPORT_FILE; static int got_sighup = 0; -in_addr_t bindaddr; static TAILQ_HEAD(, ggd_request) inqueue = TAILQ_HEAD_INITIALIZER(inqueue); static TAILQ_HEAD(, ggd_request) outqueue = TAILQ_HEAD_INITIALIZER(outqueue); @@ -115,71 +122,88 @@ exit(EXIT_FAILURE); } -static char * -ip2str(in_addr_t ip) +static const char * +ip2str(struct sockaddr *addr) { - static char sip[16]; + static char sip[64]; + + if (getnameinfo(addr, addr->sa_len, sip, sizeof(sip), + NULL, 0, NI_NUMERICHOST) == 0) + return (sip); - snprintf(sip, sizeof(sip), "%u.%u.%u.%u", - ((ip >> 24) & 0xff), - ((ip >> 16) & 0xff), - ((ip >> 8) & 0xff), - (ip & 0xff)); - return (sip); + return ("Unknown"); } -static in_addr_t -countmask(unsigned m) +static struct sockaddr_storage +countmask(struct sockaddr* addr, int mask) /* also normalizes addr */ { - in_addr_t mask; + struct sockaddr_storage ss; + int i, alen; + unsigned char *mp, *ap; - if (m == 0) { - mask = 0x0; - } else { - mask = 1 << (32 - m); - mask--; - mask = ~mask; + bzero(&ss, sizeof(ss)); + ss.ss_family = addr->sa_family; + ss.ss_len = addr->sa_len; + + switch (addr->sa_family) { + case AF_INET: + alen = 4; /* 32 bits */ + ap = (unsigned char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; + mp = (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr; + break; + case AF_INET6: + alen = 16; /* 128 bits */ + ap = (unsigned char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; + mp = (unsigned char*)&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr; + break; + default: + g_gate_xlog("Unknown address family in countmask"); + } + + i = 0; + while (mask > 0 && i < alen) { + if (mask < 8) { + mp[i] = ~(0xff >> mask); + ap[i] &= mp[i]; + } else + mp[i] = 0xff; + i++; + mask -= 8; } - return (mask); + while (i < alen) { /* zero out remaining bits of addr */ + ap[i] = 0; + i++; + } + + return (ss); } static void line_parse(char *line, unsigned lineno) { struct ggd_export *ex; - char *word, *path, *sflags; - unsigned flags, i, vmask; - in_addr_t ip, mask; + char *pmask, *word, *path, *sflags; + unsigned flags, i; + int vmask; + struct addrinfo hints, *res, *p; - ip = mask = flags = vmask = 0; + flags = vmask = 0; path = NULL; sflags = NULL; + pmask = NULL; for (i = 0, word = strtok(line, " \t"); word != NULL; i++, word = strtok(NULL, " \t")) { switch (i) { case 0: /* IP address or host name */ - ip = g_gate_str2ip(strsep(&word, "/")); - if (ip == INADDR_NONE) { + bzero(&hints, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo(strsep(&word, "/"), NULL, &hints, + &res) != 0) g_gate_xlog("Invalid IP/host name at line %u.", lineno); - } - ip = ntohl(ip); - if (word == NULL) - vmask = 32; - else { - errno = 0; - vmask = strtoul(word, NULL, 10); - if (vmask == 0 && errno != 0) { - g_gate_xlog("Invalid IP mask value at " - "line %u.", lineno); - } - if ((unsigned)vmask > 32) { - g_gate_xlog("Invalid IP mask value at line %u.", - lineno); - } - } - mask = countmask(vmask); + pmask = word; break; case 1: /* flags */ if (strcasecmp("rd", word) == 0 || @@ -209,22 +233,46 @@ if (i != 3) g_gate_xlog("Too few arguments at line %u.", lineno); - ex = malloc(sizeof(*ex)); - if (ex == NULL) - g_gate_xlog("No enough memory."); - ex->e_path = strdup(path); - if (ex->e_path == NULL) - g_gate_xlog("No enough memory."); - - /* Made 'and' here. */ - ex->e_ip = (ip & mask); - ex->e_mask = mask; - ex->e_flags = flags; + p = res; + while (p) { + ex = malloc(sizeof(*ex)); + if (ex == NULL) + g_gate_xlog("Not enough memory."); + ex->e_path = strdup(path); + if (ex->e_path == NULL) + g_gate_xlog("Not enough memory."); + + if (pmask == NULL && p->ai_family == AF_INET6) + vmask = 128; + else if (pmask == NULL) + vmask = 32; + else { + errno = 0; + vmask = strtoul(pmask, NULL, 10); + if (vmask == 0 && errno != 0) { + g_gate_xlog("Invalid IP mask value at " + "line %u.", lineno); + } + } + + if ((vmask > 32 && p->ai_family == AF_INET) || + (vmask > 128 && p->ai_family == AF_INET6)) + g_gate_xlog("Invalid IP mask value at line %u", + lineno); + + memcpy(&ex->e_addr, p->ai_addr, p->ai_addrlen); + ex->e_mask = countmask((struct sockaddr*)&ex->e_addr, vmask); + ex->e_flags = flags; + + SLIST_INSERT_HEAD(&exports, ex, e_next); - SLIST_INSERT_HEAD(&exports, ex, e_next); + g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", + ip2str((struct sockaddr*)&ex->e_addr), vmask, path, sflags); - g_gate_log(LOG_DEBUG, "Added %s/%u %s %s to exports list.", - ip2str(ex->e_ip), vmask, path, sflags); + p = p->ai_next; + } + + freeaddrinfo(res); } static void @@ -302,12 +350,12 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit, struct ggd_connection *conn) { - char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */ + char ipmask[80]; /* 80 == strlen("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")+1 */ int error = 0, flags; - strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask)); + strlcpy(ipmask, ip2str((struct sockaddr*)&ex->e_addr), sizeof(ipmask)); strlcat(ipmask, "/", sizeof(ipmask)); - strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask)); + strlcat(ipmask, ip2str((struct sockaddr*)&ex->e_mask), sizeof(ipmask)); if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) { if (ex->e_flags == O_WRONLY) { g_gate_log(LOG_WARNING, "Read-only access requested, " @@ -355,17 +403,53 @@ return (0); } +static int +mask_compare(struct sockaddr *a, struct sockaddr *b, struct sockaddr *m) { + unsigned char *ap, *bp, *mp; + int alen; + if (a->sa_family != m->sa_family || b->sa_family != m->sa_family) + return (0); + + switch (m->sa_family) { + case AF_INET: + alen = 4; + ap = (unsigned char*)&((struct sockaddr_in*)a)->sin_addr.s_addr; + bp = (unsigned char*)&((struct sockaddr_in*)b)->sin_addr.s_addr; + mp = (unsigned char*)&((struct sockaddr_in*)m)->sin_addr.s_addr; + break; + case AF_INET6: + alen = 16; + ap = (unsigned char*)&((struct sockaddr_in6*)a)->sin6_addr.s6_addr; + bp = (unsigned char*)&((struct sockaddr_in6*)b)->sin6_addr.s6_addr; + mp = (unsigned char*)&((struct sockaddr_in6*)m)->sin6_addr.s6_addr; + break; + default: + return (0); + } + + while (alen > 0) { + if ((*ap & *mp) != (*bp & *mp)) + return (0); + + ap++; + bp++; + mp++; + alen--; + } + + return (1); +} + static struct ggd_export * exports_find(struct sockaddr *s, struct g_gate_cinit *cinit, struct ggd_connection *conn) { struct ggd_export *ex; - in_addr_t ip; int error; - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); SLIST_FOREACH(ex, &exports, e_next) { - if ((ip & ex->e_mask) != ex->e_ip) { + if (!mask_compare(s, (struct sockaddr*)&ex->e_addr, + (struct sockaddr*)&ex->e_mask)) { g_gate_log(LOG_DEBUG, "exports[%s]: IP mismatch.", ex->e_path); continue; @@ -384,7 +468,7 @@ } } g_gate_log(LOG_WARNING, "Unauthorized connection from: %s.", - ip2str(ip)); + ip2str(s)); errno = EPERM; return (NULL); } @@ -404,7 +488,8 @@ LIST_REMOVE(conn, c_next); g_gate_log(LOG_NOTICE, "Connection from %s [%s] removed.", - ip2str(conn->c_srcip), conn->c_path); + ip2str((struct sockaddr*)&conn->c_srcaddr), + conn->c_path); close(conn->c_diskfd); close(conn->c_sendfd); close(conn->c_recvfd); @@ -430,7 +515,6 @@ connection_new(struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) { struct ggd_connection *conn; - in_addr_t ip; /* * First, look for old connections. @@ -449,8 +533,7 @@ return (NULL); } conn->c_token = cinit->gc_token; - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); - conn->c_srcip = ip; + memcpy(&conn->c_srcaddr, s, s->sa_len); conn->c_sendfd = conn->c_recvfd = -1; if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) conn->c_sendfd = sfd; @@ -461,7 +544,7 @@ time(&conn->c_birthtime); conn->c_flags = cinit->gc_flags; LIST_INSERT_HEAD(&connections, conn, c_next); - g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(ip), + g_gate_log(LOG_DEBUG, "Connection created [%s, %s].", ip2str(s), conn->c_path); return (conn); } @@ -470,13 +553,10 @@ connection_add(struct ggd_connection *conn, struct g_gate_cinit *cinit, struct sockaddr *s, int sfd) { - in_addr_t ip; - - ip = htonl(((struct sockaddr_in *)(void *)s)->sin_addr.s_addr); if ((cinit->gc_flags & GGATE_FLAG_SEND) != 0) { if (conn->c_sendfd != -1) { g_gate_log(LOG_WARNING, - "Send socket already exists [%s, %s].", ip2str(ip), + "Send socket already exists [%s, %s].", ip2str(s), conn->c_path); return (EEXIST); } @@ -485,12 +565,12 @@ if (conn->c_recvfd != -1) { g_gate_log(LOG_WARNING, "Receive socket already exists [%s, %s].", - ip2str(ip), conn->c_path); + ip2str(s), conn->c_path); return (EEXIST); } conn->c_recvfd = sfd; } - g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(ip), + g_gate_log(LOG_DEBUG, "Connection added [%s, %s].", ip2str(s), conn->c_path); return (0); } @@ -505,7 +585,7 @@ LIST_REMOVE(conn, c_next); g_gate_log(LOG_DEBUG, "Connection removed [%s %s].", - ip2str(conn->c_srcip), conn->c_path); + ip2str((struct sockaddr*)&conn->c_srcaddr), conn->c_path); if (conn->c_sendfd != -1) close(conn->c_sendfd); if (conn->c_recvfd != -1) @@ -815,10 +895,7 @@ static void log_connection(struct sockaddr *from) { - in_addr_t ip; - - ip = htonl(((struct sockaddr_in *)(void *)from)->sin_addr.s_addr); - g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(ip)); + g_gate_log(LOG_INFO, "Connection from: %s.", ip2str(from)); } static int @@ -940,14 +1017,16 @@ int main(int argc, char *argv[]) { - struct sockaddr_in serv; - struct sockaddr from; + SLIST_HEAD(, ggd_listen) listens = SLIST_HEAD_INITIALIZER(&listens); + struct ggd_listen *cl, *nl; + struct addrinfo hints, *res, *p; + struct sockaddr_storage from; socklen_t fromlen; - int sfd, tmpsfd; - unsigned port; + int maxfd, tmpsfd; + fd_set listenfds; + const char *port; - bindaddr = htonl(INADDR_ANY); - port = G_GATE_PORT; + port = G_GATE_PORT_STR; for (;;) { int ch; @@ -956,20 +1035,17 @@ break; switch (ch) { case 'a': - bindaddr = g_gate_str2ip(optarg); - if (bindaddr == INADDR_NONE) { - errx(EXIT_FAILURE, - "Invalid IP/host name to bind to."); - } + nl = malloc(sizeof(*nl)); + bzero(nl, sizeof(*nl)); + nl->l_name = optarg; + /* delay resolution until we know port number */ + SLIST_INSERT_HEAD(&listens, nl, l_next); break; case 'n': nagle = 0; break; case 'p': - errno = 0; - port = strtoul(optarg, NULL, 10); - if (port == 0 && errno != 0) - errx(EXIT_FAILURE, "Invalid port."); + port = optarg; break; case 'R': errno = 0; @@ -998,6 +1074,79 @@ exports_file = argv[0]; exports_get(); + if (SLIST_EMPTY(&listens)) { + /* Bind to all address families */ + bzero(&hints, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo(NULL, port, &hints, &res)) + g_gate_xlog("Cannot get passive address: %s", + strerror(errno)); + + p = res; + while (p) { + nl = malloc(sizeof(*nl)); + bzero(nl, sizeof(*nl)); + memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); + SLIST_INSERT_HEAD(&listens, nl, l_next); + + p = p->ai_next; + } + freeaddrinfo(res); + } else { + /* Bind to some specific addresses */ + SLIST_FOREACH(cl, &listens, l_next) { + bzero(&hints, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if (getaddrinfo(cl->l_name, port, &hints, &res)) + g_gate_xlog("Invalid IP/host name to bind to: " + "%s", cl->l_name); + + /* Re-use current list entry for first match, add + * new ones after that */ + p = res; + nl = cl; + while (p) { + if (p != res) { + nl = malloc(sizeof(*nl)); + bzero(nl, sizeof(*nl)); + } + + memcpy(&nl->l_addr, p->ai_addr, p->ai_addrlen); + + if (p != res) { + SLIST_INSERT_HEAD(&listens, nl, l_next); + } + p = p->ai_next; + } + freeaddrinfo(res); + } + } + + /* Actually create sockets and bind to them */ + maxfd = 0; + SLIST_FOREACH(cl, &listens, l_next) { + cl->l_fd = socket(cl->l_addr.ss_family, SOCK_STREAM, 0); + if (cl->l_fd == -1) + g_gate_xlog("Cannot open stream socket: %s.", + strerror(errno)); + g_gate_socket_settings(cl->l_fd); + + if (bind(cl->l_fd, (struct sockaddr *)&cl->l_addr, + cl->l_addr.ss_len) == -1) + g_gate_xlog("bind(): %s.", strerror(errno)); + if (listen(cl->l_fd, 5) == -1) + g_gate_xlog("listen(): %s.", strerror(errno)); + + if (maxfd <= cl->l_fd) + maxfd = cl->l_fd + 1; + + g_gate_log(LOG_INFO, "Listen on address: %s (%s).", + ip2str((struct sockaddr *)&cl->l_addr), port); + } + if (!g_gate_verbose) { /* Run in daemon mode. */ if (daemon(0, 0) == -1) @@ -1005,40 +1154,44 @@ } signal(SIGCHLD, SIG_IGN); - - sfd = socket(AF_INET, SOCK_STREAM, 0); - if (sfd == -1) - g_gate_xlog("Cannot open stream socket: %s.", strerror(errno)); - bzero(&serv, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = bindaddr; - serv.sin_port = htons(port); - - g_gate_socket_settings(sfd); - - if (bind(sfd, (struct sockaddr *)&serv, sizeof(serv)) == -1) - g_gate_xlog("bind(): %s.", strerror(errno)); - if (listen(sfd, 5) == -1) - g_gate_xlog("listen(): %s.", strerror(errno)); - - g_gate_log(LOG_INFO, "Listen on port: %d.", port); - signal(SIGHUP, huphandler); for (;;) { - fromlen = sizeof(from); - tmpsfd = accept(sfd, &from, &fromlen); - if (tmpsfd == -1) - g_gate_xlog("accept(): %s.", strerror(errno)); + FD_ZERO(&listenfds); + SLIST_FOREACH(cl, &listens, l_next) { + FD_SET(cl->l_fd, &listenfds); + } + + select(maxfd, &listenfds, NULL, NULL, NULL); if (got_sighup) { got_sighup = 0; exports_get(); } - if (!handshake(&from, tmpsfd)) - close(tmpsfd); + SLIST_FOREACH(cl, &listens, l_next) { + if (!FD_ISSET(cl->l_fd, &listenfds)) + continue; + + fromlen = sizeof(from); + tmpsfd = accept(cl->l_fd, (struct sockaddr*)&from, + &fromlen); + + if (tmpsfd == -1) { + g_gate_log(LOG_WARNING, "accept(): %s.", + strerror(errno)); + continue; + } + + if (!handshake((struct sockaddr*)&from, tmpsfd)) + close(tmpsfd); + } + } + while (!SLIST_EMPTY(&listens)) { + cl = SLIST_FIRST(&listens); + close(cl->l_fd); + SLIST_REMOVE_HEAD(&listens, l_next); + free(cl); } - close(sfd); exit(EXIT_SUCCESS); } diff -ruN ggate.orig/shared/ggate.c ggate/shared/ggate.c --- ggate.orig/shared/ggate.c Thu Nov 10 18:53:21 2005 +++ ggate/shared/ggate.c Thu Nov 10 18:53:25 2005 @@ -375,21 +375,3 @@ exit(EXIT_SUCCESS); } #endif /* LIBGEOM */ - -in_addr_t -g_gate_str2ip(const char *str) -{ - struct hostent *hp; - in_addr_t ip; - - ip = inet_addr(str); - if (ip != INADDR_NONE) { - /* It is a valid IP address. */ - return (ip); - } - /* Check if it is a valid host name. */ - hp = gethostbyname(str); - if (hp == NULL) - return (INADDR_NONE); - return (((struct in_addr *)(void *)hp->h_addr)->s_addr); -} diff -ruN ggate.orig/shared/ggate.h ggate/shared/ggate.h --- ggate.orig/shared/ggate.h Thu Nov 10 18:53:21 2005 +++ ggate/shared/ggate.h Thu Nov 10 18:53:25 2005 @@ -33,6 +33,7 @@ #include <stdarg.h> #define G_GATE_PORT 3080 +#define G_GATE_PORT_STR "3080" #define G_GATE_RCVBUF 131072 #define G_GATE_SNDBUF 131072 @@ -110,7 +111,6 @@ #ifdef LIBGEOM void g_gate_list(int unit, int verbose); #endif -in_addr_t g_gate_str2ip(const char *str); /* * g_gate_swap2h_* - functions swap bytes to host byte order (from big endian). --- ggate_ipv6_2.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051111010811.1E7032D2D3>