commit 0989e87037363bc4977b23da4304c51284026a14
parent 2878cc2d95ecac6eef2c33c8cd79a126dc9aa7f0
Author: Christoph Lohmann <20h@r-36.net>
Date: Sat, 13 Apr 2013 21:04:46 +0200
Adding IPv6 support.
Diffstat:
main.c | | | 94 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
1 file changed, 65 insertions(+), 29 deletions(-)
diff --git a/main.c b/main.c
@@ -242,6 +242,40 @@ initsignals(void)
signal(SIGPIPE, SIG_IGN);
}
+int
+getlistenfd(struct addrinfo *hints, char *bindip, char *port)
+{
+ struct addrinfo *ai, *rp;
+ int on, listfd;
+
+ listfd = -1;
+
+ if(getaddrinfo(bindip, port, hints, &ai))
+ return -1;
+ if(ai == nil)
+ return -1;
+
+ on = 1;
+ for(rp = ai; rp != nil; rp = rp->ai_next) {
+ listfd = socket(rp->ai_family, rp->ai_socktype,
+ rp->ai_protocol);
+ if(listfd < 0)
+ continue;
+ if(setsockopt(listfd, SOL_SOCKET, SO_REUSEADDR, &on,
+ sizeof(on)) < 0) {
+ break;
+ }
+ if(bind(listfd, rp->ai_addr, rp->ai_addrlen) == 0)
+ break;
+ close(listfd);
+ }
+ if(rp == nil)
+ return -1;
+ freeaddrinfo(ai);
+
+ return listfd;
+}
+
void
usage(void)
{
@@ -256,10 +290,10 @@ usage(void)
int
main(int argc, char *argv[])
{
- struct addrinfo hints, *ai, *rp;
+ struct addrinfo hints;
struct sockaddr_storage clt;
socklen_t cltlen;
- int sock, dofork, on;
+ int sock, dofork, v4, v6;
char *port, *base, clienth[NI_MAXHOST], clientp[NI_MAXSERV];
char *user, *group, *bindip, *ohost, *sport;
struct passwd *us;
@@ -275,8 +309,16 @@ main(int argc, char *argv[])
bindip = nil;
ohost = nil;
sport = port;
+ v4 = 1;
+ v6 = 1;
ARGBEGIN {
+ case '4':
+ v6 = 0;
+ break;
+ case '6':
+ v4 = 0;
+ break;
case 'b':
base = EARGF(usage());
break;
@@ -318,8 +360,9 @@ main(int argc, char *argv[])
free(ohost);
return 1;
}
- } else
+ } else {
ohost = gstrdup(ohost);
+ }
if(group != nil) {
if((gr = getgrnam(group)) == nil) {
@@ -349,36 +392,29 @@ main(int argc, char *argv[])
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_family = AF_INET;
- if(getaddrinfo(bindip, port, &hints, &ai)) {
- perror("getaddrinfo");
- return 1;
- }
- if(ai == nil) {
- perror("getaddrinfo");
- return 1;
+ if(bindip)
+ hints.ai_flags |= AI_CANONNAME;
+
+ if(v6) {
+ hints.ai_family = PF_INET6;
+ listfd = getlistenfd(&hints, bindip, port);
+ if(!v4 && listfd < 0) {
+ perror("getlistenfd");
+ return 1;
+ }
}
-
- on = 1;
- for(rp = ai; rp != nil; rp = rp->ai_next) {
- listfd = socket(rp->ai_family, rp->ai_socktype,
- rp->ai_protocol);
- if(listfd < 0)
- continue;
- if(setsockopt(listfd, SOL_SOCKET, SO_REUSEADDR, &on,
- sizeof(on)) < 0) {
- break;
+ if(v4) {
+ hints.ai_family = PF_INET;
+ listfd = getlistenfd(&hints, bindip, port);
+ if(listfd < 0) {
+ perror("getlistenfd");
+ return 1;
}
- if(bind(listfd, rp->ai_addr, rp->ai_addrlen) == 0)
- break;
- close(listfd);
}
- if(rp == nil) {
- perror("getaddrinfo");
+ if(listfd < 0) {
+ perror("You did not specify and TCP protocol.");
return 1;
}
- freeaddrinfo(ai);
if(listen(listfd, 255)) {
perror("listen");
@@ -416,7 +452,7 @@ main(int argc, char *argv[])
getnameinfo((struct sockaddr *)&clt, cltlen, clienth,
sizeof(clienth), clientp, sizeof(clientp),
- NI_NUMERICHOST);
+ NI_NUMERICHOST|NI_NUMERICSERV);
switch(fork()) {
case -1: