Skip to content
Snippets Groups Projects
Commit c62a33c9 authored by Brian May's avatar Brian May
Browse files

Support both IPv6 and IPv4.

parent 551b6dc4
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include <grp.h> #include <grp.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -141,7 +145,13 @@ struct rlimit s_rlimit; ...@@ -141,7 +145,13 @@ struct rlimit s_rlimit;
int main (int argc, char *argv[]) int main (int argc, char *argv[])
{ {
int srvsock, epollfd, nfds, efd, n, res; struct addrinfo *ai;
struct addrinfo hints;
memset (&hints, '\0', sizeof (hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
int e;
int epollfd, nevents, efd, n, res;
int portno = 1986; int portno = 1986;
int optval; int optval;
socklen_t optlen = sizeof(optval); socklen_t optlen = sizeof(optval);
...@@ -165,7 +175,7 @@ int main (int argc, char *argv[]) ...@@ -165,7 +175,7 @@ int main (int argc, char *argv[])
struct client *client_tmp = NULL; struct client *client_tmp = NULL;
socklen_t clilen; socklen_t clilen;
struct sockaddr_in6 serv_addr, cli_addr; struct sockaddr_storage cli_addr;
static struct option long_options[] = { static struct option long_options[] = {
{"port", 1, 0, 0}, {"port", 1, 0, 0},
...@@ -309,32 +319,64 @@ xit\n"); ...@@ -309,32 +319,64 @@ xit\n");
exit (EXIT_FAILURE); exit (EXIT_FAILURE);
} }
srvsock = socket (AF_INET6, SOCK_STREAM, 0); char buf[5];
if (srvsock < 0) snprintf(buf, sizeof buf, "%d", portno);
e = getaddrinfo (NULL, buf, &hints, &ai);
if (e != 0) {
fanout_error ("getaddrinfo");
exit (EXIT_FAILURE);
}
int nfds = 0;
struct addrinfo *runp = ai;
while (runp != NULL) {
++nfds;
runp = runp->ai_next;
}
struct epoll_event fds[nfds];
for (nfds = 0, runp = ai; runp != NULL; runp = runp->ai_next) {
fds[nfds].data.fd = socket (runp->ai_family, runp->ai_socktype, runp->ai_protocol);
if (fds[nfds].data.fd == -1) {
fanout_error ("ERROR opening socket"); fanout_error ("ERROR opening socket");
exit (EXIT_FAILURE);
}
fds[nfds].events = EPOLLIN;
bzero((char *) &serv_addr, sizeof (serv_addr)); optval = 1;
serv_addr.sin6_family = AF_INET6; if (runp->ai_family==AF_INET6 && setsockopt (fds[nfds].data.fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, optlen) == -1) {
serv_addr.sin6_addr = in6addr_any; fanout_error ("failed setting IPV6_V6ONLY");
serv_addr.sin6_port = htons (portno); exit (EXIT_FAILURE);
}
if ((setsockopt (srvsock, SOL_SOCKET, SO_REUSEADDR, &optval, optlen)) == -1) optval = 1;
fanout_error ("failed setting reuseaddr"); if (setsockopt (fds[nfds].data.fd, SOL_SOCKET, SO_REUSEADDR, &optval, optlen) == -1) {
fanout_error ("failed setting REUSEADDR");
exit (EXIT_FAILURE);
}
if (bind (srvsock, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) if (bind (fds[nfds].data.fd, runp->ai_addr, runp->ai_addrlen ) != 0) {
fanout_error ("ERROR on binding"); fanout_error ("ERROR on binding");
exit (EXIT_FAILURE);
if (listen (srvsock, listen_backlog) == -1) } else {
if (listen (fds[nfds].data.fd, listen_backlog) != 0) {
fanout_error ("ERROR listening on server socket"); fanout_error ("ERROR listening on server socket");
exit (EXIT_FAILURE);
}
++nfds;
}
}
freeaddrinfo(ai);
if((epollfd = epoll_create (10)) < 0) if((epollfd = epoll_create (nfds)) < 0)
fanout_error ("ERROR creating epoll instance"); fanout_error ("ERROR creating epoll instance");
ev.events = EPOLLIN; for (n=0; n < nfds; n++) {
ev.data.fd = srvsock; if (epoll_ctl (epollfd, EPOLL_CTL_ADD, fds[n].data.fd, &fds[n]) == -1) {
if (epoll_ctl (epollfd, EPOLL_CTL_ADD, srvsock, &ev) == -1) {
fanout_error ("epoll_ctl: srvsock"); fanout_error ("epoll_ctl: srvsock");
exit (EXIT_FAILURE);
}
} }
...@@ -450,25 +492,32 @@ xit\n"); ...@@ -450,25 +492,32 @@ xit\n");
while (1) { while (1) {
fanout_debug (3, "server waiting for new activity\n"); fanout_debug (3, "server waiting for new activity\n");
if ((nfds = epoll_wait (epollfd, events, max_events, -1)) == -1) if ((nevents = epoll_wait (epollfd, events, max_events, -1)) == -1)
fanout_error ("epoll_wait"); fanout_error ("epoll_wait");
if (nfds == 0) { if (nevents == 0) {
continue; continue;
} }
for (n = 0; n < nfds; n++) { for (n = 0; n < nevents; n++) {
// new connection // new connection
efd = events[n].data.fd; efd = events[n].data.fd;
if (efd == srvsock) {
int newconnection = 0;
for (n=0; n < nfds; n++) {
if (efd == fds[n].data.fd) {
newconnection = 1;
break;
}
}
if (newconnection) {
if ((client_i = calloc (1, sizeof (struct client))) == NULL) { if ((client_i = calloc (1, sizeof (struct client))) == NULL) {
fanout_debug (0, "memory error\n"); fanout_debug (0, "memory error\n");
continue; continue;
} }
clilen = sizeof (cli_addr); clilen = sizeof (cli_addr);
if ((client_i->fd = accept (srvsock, if ((client_i->fd = accept (efd,
(struct sockaddr *)&cli_addr, (struct sockaddr *)&cli_addr,
&clilen)) == -1) { &clilen)) == -1) {
fanout_debug (0, "%s\n", strerror (errno)); fanout_debug (0, "%s\n", strerror (errno));
...@@ -572,7 +621,9 @@ resetting counter\n"); ...@@ -572,7 +621,9 @@ resetting counter\n");
}//end for }//end for
}//end while (1) }//end while (1)
close (srvsock); for (n=0; n < nfds; n++) {
close (fds[n].data.fd);
}
return 0; return 0;
} }
...@@ -695,12 +746,12 @@ void fanout_debug (int level, const char *format, ...) ...@@ -695,12 +746,12 @@ void fanout_debug (int level, const char *format, ...)
char *getsocketpeername (int fd) char *getsocketpeername (int fd)
{ {
struct sockaddr_in6 m_addr; struct sockaddr_storage m_addr;
socklen_t len; socklen_t len;
len = sizeof m_addr; len = sizeof m_addr;
getpeername(fd, (struct sockaddr*)&m_addr, &len); getpeername(fd, (struct sockaddr*)&m_addr, &len);
inet_ntop(AF_INET6, &m_addr.sin6_addr, ipstr, sizeof ipstr); getnameinfo((struct sockaddr*)&m_addr, len, ipstr, sizeof ipstr, NULL, 0, NI_NUMERICHOST);
return ipstr; return ipstr;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment