From 294b8d92c2d3a9bdd115788b8293b785cfd3f5af Mon Sep 17 00:00:00 2001 From: BtbN Date: Tue, 15 Jan 2013 02:18:13 +0100 Subject: [PATCH] Make tcp_server_create IPv6 aware --- src/tcp.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/tcp.c b/src/tcp.c index a97b079b..ab3d432f 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -478,21 +478,55 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque) int fd, x; struct epoll_event e; tcp_server_t *ts; - struct sockaddr_in s; + struct addrinfo hints, *res, *ressave, *use = NULL; + char *portBuf = (char*)malloc(6); int one = 1; + int zero = 0; + memset(&e, 0, sizeof(e)); - fd = tvh_socket(AF_INET, SOCK_STREAM, 0); + + snprintf(portBuf, 6, "%d", port); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + x = getaddrinfo(NULL, portBuf, &hints, &res); + free(portBuf); + + if(x != 0) + return NULL; + + ressave = res; + while(res) + { + if(res->ai_family == AF_INET6) + { + use = res; + break; + } + else if(use == NULL) + { + use = res; + } + res = res->ai_next; + } + + fd = tvh_socket(use->ai_family, use->ai_socktype, use->ai_protocol); if(fd == -1) return NULL; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); + if(use->ai_family == AF_INET6) + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(int)); - memset(&s, 0, sizeof(s)); - s.sin_family = AF_INET; - s.sin_port = htons(port); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); - x = bind(fd, (struct sockaddr *)&s, sizeof(s)); - if(x < 0) { + x = bind(fd, use->ai_addr, use->ai_addrlen); + freeaddrinfo(ressave); + + if(x != 0) + { close(fd); return NULL; } @@ -504,11 +538,10 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque) ts->start = start; ts->opaque = opaque; - e.events = EPOLLIN; e.data.ptr = ts; - epoll_ctl(tcp_server_epoll_fd, EPOLL_CTL_ADD, fd, &e); + return ts; }