[PATCH 1/4] Make clones.c support non-IPv4 addresses.

The code that detects clones based on the full IP address will work for non-IPv4 addresses now. Based on mamikk's old patch. --- src/clones.c | 41 ++++++++++++++++++++++++----------------- 1 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/clones.c b/src/clones.c index e929f70..63e9fb1 100644 --- a/src/clones.c +++ b/src/clones.c @@ -94,14 +94,20 @@ get_clones(aClient *cptr, CloneEnt **ceip, CloneEnt **ce24, int create) char ip24[HOSTIPLEN+1]; char *s; - strcpy(ip24, cptr->hostip); - /* deliberate core if strrchr fails -- we need a valid IP string */ - s = strrchr(ip24, '.'); - *++s = '*'; - *++s = 0; + if (cptr->ip_family == AF_INET) + { + strcpy(ip24, cptr->hostip); + /* deliberate core if strrchr fails -- we need a valid IP string */ + s = strrchr(ip24, '.'); + *++s = '*'; + *++s = 0; + } *ceip = get_clone(cptr->hostip, create); - *ce24 = get_clone(ip24, create); + if (cptr->ip_family == AF_INET) + *ce24 = get_clone(ip24, create); + else + *ce24 = NULL; } static int @@ -274,9 +280,7 @@ clones_add(aClient *cptr) CloneEnt *ceip; CloneEnt *ce24; - if (cptr->ip_family != AF_INET) - return; - if (cptr->ip.ip4.s_addr == 0) + if (cptr->ip_family == AF_INET && cptr->ip.ip4.s_addr == 0) return; get_clones(cptr, &ceip, &ce24, 1); @@ -288,12 +292,14 @@ clones_add(aClient *cptr) ceip->clients = cptr; ceip->gcount++; - ce24->gcount++; + if (ce24) + ce24->gcount++; if (MyConnect(cptr)) { ceip->lcount++; - ce24->lcount++; + if (ce24) + ce24->lcount++; } } @@ -306,9 +312,7 @@ clones_remove(aClient *cptr) CloneEnt *ceip; CloneEnt *ce24; - if (cptr->ip_family != AF_INET) - return; - if (cptr->ip.ip4.s_addr == 0) + if (cptr->ip_family == AF_INET && cptr->ip.ip4.s_addr == 0) return; get_clones(cptr, &ceip, &ce24, 0); @@ -321,17 +325,20 @@ clones_remove(aClient *cptr) ceip->clients = cptr->clone.next; ceip->gcount--; - ce24->gcount--; + if (ce24) + ce24->gcount--; /* !$%#&*%@ user state handling! */ if (cptr->uplink == &me) { ceip->lcount--; - ce24->lcount--; + if (ce24) + ce24->lcount--; } expire_clone(ceip); - expire_clone(ce24); + if (ce24) + expire_clone(ce24); } #endif /* THROTTLE_ENABLE */ -- 1.7.2.3

--- src/s_auth.c | 80 +++++++++++++++++++++++++++++++++++++--------------------- 1 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/s_auth.c b/src/s_auth.c index 3f0782b..6163af6 100644 --- a/src/s_auth.c +++ b/src/s_auth.c @@ -41,7 +41,7 @@ static void authsenderr(aClient *); /* * start_auth - * + * * Flag the client to show that an attempt to contact the ident server on * the client's host. The connect and subsequently the socket are all * put into 'non-blocking' mode. Should the connect or any later phase @@ -50,13 +50,21 @@ static void authsenderr(aClient *); */ void start_auth(aClient *cptr) { - struct sockaddr_in sock; - struct sockaddr_in localaddr; + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } sock; + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } localaddr; unsigned int locallen; Debug((DEBUG_NOTICE, "start_auth(%x) fd %d status %d", cptr, cptr->fd, cptr->status)); - if ((cptr->authfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + if ((cptr->authfd = socket(cptr->ip_family, SOCK_STREAM, 0)) == -1) { #ifdef USE_SYSLOG syslog(LOG_ERR, "Unable to create auth socket for %s:%m", @@ -77,6 +85,7 @@ void start_auth(aClient *cptr) sendto_one(cptr, "%s", REPORT_DO_ID); #endif set_non_blocking(cptr->authfd, cptr); + /* * get the local address of the client and bind to that to make the * auth request. This used to be done only for ifdef VIRTTUAL_HOST, @@ -84,28 +93,31 @@ void start_auth(aClient *cptr) * originate from that same address-- and machines with multiple IP * addresses are common now */ - locallen = sizeof(struct sockaddr_in); - - memset(&localaddr, '\0', locallen); - getsockname(cptr->fd, (struct sockaddr *) &localaddr, &locallen); - localaddr.sin_port = htons(0); - - if (bind(cptr->authfd, (struct sockaddr *) &localaddr, - sizeof(localaddr)) == -1) + locallen = sizeof(localaddr); + memset(&localaddr, '\0', sizeof(localaddr)); + getsockname(cptr->fd, &localaddr.sa, &locallen); + if (localaddr.sa.sa_family == AF_INET) + localaddr.addr4.sin_port = htons(0); + + if (bind(cptr->authfd, &localaddr.sa, + sizeof(localaddr)) == -1) { report_error("binding auth stream socket %s:%s", cptr); close(cptr->authfd); cptr->authfd = -1; return; } - - memcpy((char *) &sock.sin_addr, (char *) &cptr->ip, - sizeof(struct in_addr)); - sock.sin_port = htons(113); - sock.sin_family = AF_INET; + memset(&sock, '\0', sizeof(sock)); + if (cptr->ip_family == AF_INET) + { + memcpy((char *) &sock.addr4.sin_addr, (char *) &cptr->ip.ip4, + sizeof(struct in_addr)); + sock.addr4.sin_port = htons(113); + sock.addr4.sin_family = AF_INET; + } - if (connect(cptr->authfd, (struct sockaddr *) &sock, + if (connect(cptr->authfd, &sock.sa, sizeof(sock)) == -1 && errno != EINPROGRESS) { ircstp->is_abad++; @@ -128,7 +140,7 @@ void start_auth(aClient *cptr) /* * send_authports - * + * * Send the ident server a query giving "theirport , ourport". The write * is only attempted *once* so it is deemed to be a fail if the entire * write doesn't write all the data given. This shouldnt be a problem @@ -137,16 +149,24 @@ void start_auth(aClient *cptr) */ void send_authports(aClient *cptr) { - struct sockaddr_in us, them; + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } us; + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } them; char authbuf[32]; - unsigned int ulen, tlen; + unsigned int ulen = sizeof(us), tlen = sizeof(them); Debug((DEBUG_NOTICE, "write_authports(%x) fd %d authfd %d stat %d", cptr, cptr->fd, cptr->authfd, cptr->status)); - tlen = ulen = sizeof(us); - if (getsockname(cptr->fd, (struct sockaddr *) &us, &ulen) || - getpeername(cptr->fd, (struct sockaddr *) &them, &tlen)) + if (getsockname(cptr->fd, &us.sa, &ulen) || + getpeername(cptr->fd, &them.sa, &tlen)) { #ifdef USE_SYSLOG syslog(LOG_DEBUG, "auth get{sock,peer}name error for %s:%m", @@ -156,12 +176,14 @@ void send_authports(aClient *cptr) return; } - (void) ircsprintf(authbuf, "%u , %u\r\n", - (unsigned int) ntohs(them.sin_port), - (unsigned int) ntohs(us.sin_port)); - - Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", - authbuf, inetntoa((char *) &them.sin_addr))); + if (us.sa.sa_family == AF_INET) + { + (void) ircsprintf(authbuf, "%u , %u\r\n", + (unsigned int) ntohs(them.addr4.sin_port), + (unsigned int) ntohs(us.addr4.sin_port)); + Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", + authbuf, inetntoa((char *) &them.sin_addr))); + } if (send(cptr->authfd, authbuf, strlen(authbuf), 0) != strlen(authbuf)) { authsenderr(cptr); -- 1.7.2.3

--- include/struct.h | 5 +- src/s_bsd.c | 215 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 133 insertions(+), 87 deletions(-) diff --git a/include/struct.h b/include/struct.h index 9dce1cd..c68b05d 100644 --- a/include/struct.h +++ b/include/struct.h @@ -788,10 +788,9 @@ struct Listener { struct Listener *next; /* next listener */ int fd; /* fd of this listener */ u_short port; - char allow_string[32]; /* allow from */ - char vhost_string[32]; /* bind to */ + char allow_string[HOSTLEN + 1]; /* allow from */ + char vhost_string[HOSTLEN + 1]; /* bind to */ struct in_addr allow_ip; /* allow from */ - struct in_addr vhost_ip; /* bind to */ time_t lasttime; /* last time I accepted */ long sendK; /* counters, see below */ u_short sendB; diff --git a/src/s_bsd.c b/src/s_bsd.c index f920906..0c596ec 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -77,7 +77,7 @@ int rcvbufmax = 0, sndbufmax = 0; void reset_sock_opts(int, int); #endif -static void set_listener_sock_opts(int, aListener *); +static void set_listener_sock_opts(int, aListener *, int); static void set_listener_non_blocking(int, aListener *); /* listener list, count */ aListener *listen_list = NULL; @@ -272,64 +272,69 @@ int add_listener(aPort *aport) { aListener *lptr; aListener lstn; - struct sockaddr_in server; - int ad[4]; + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } server; unsigned int len = sizeof(server); - char ipname[20]; #ifdef USE_SSL extern int ssl_capable; #endif memset(&lstn, 0, sizeof(aListener)); - ad[0] = ad[1] = ad[2] = ad[3] = 0; + lstn.port = aport->port; + + memset(&server, 0, sizeof(server)); + if (!BadPtr(aport->address) && (*aport->address != '*')) + { + strncpyzt(lstn.vhost_string, aport->address, sizeof(lstn.vhost_string)); + + server.addr4.sin_family = AF_INET; + server.addr4.sin_addr.s_addr = inet_addr(aport->address); + server.addr4.sin_port = htons(lstn.port); + } + else + { + server.addr4.sin_family = AF_INET; + server.addr4.sin_addr.s_addr = INADDR_ANY; + server.addr4.sin_port = htons(lstn.port); + } - if(!BadPtr(aport->allow)) + if(!BadPtr(aport->allow) && server.sa.sa_family == AF_INET) { + int ad[4]; + char ipname[20]; + + ad[0] = ad[1] = ad[2] = ad[3] = 0; + strncpyzt(lstn.allow_string, aport->allow, sizeof(lstn.allow_string)); - sscanf(lstn.allow_string, "%d.%d.%d.%d", &ad[0], &ad[1], + sscanf(lstn.allow_string, "%d.%d.%d.%d", &ad[0], &ad[1], &ad[2], &ad[3]); ircsprintf(ipname, "%d.%d.%d.%d", ad[0], ad[1], ad[2], ad[3]); lstn.allow_ip.s_addr = inet_addr(ipname); } - if (!BadPtr(aport->address) && (*aport->address != '*')) - { - lstn.vhost_ip.s_addr = inet_addr(aport->address); - strncpyzt(lstn.vhost_string, aport->address, sizeof(lstn.vhost_string)); - } - - lstn.port = aport->port; - if(lstn.port <= 0) /* stop stupidity cold */ return -1; - lstn.fd = socket(AF_INET, SOCK_STREAM, 0); + lstn.fd = socket(server.sa.sa_family, SOCK_STREAM, 0); if (lstn.fd < 0) { report_listener_error("opening stream socket %s:%s", &lstn); return -1; } - set_listener_sock_opts(lstn.fd, &lstn); - - memset(&server, '\0', sizeof(server)); - server.sin_family = AF_INET; + set_listener_sock_opts(lstn.fd, &lstn, server.sa.sa_family); - if (lstn.vhost_ip.s_addr) - server.sin_addr.s_addr = lstn.vhost_ip.s_addr; - else - server.sin_addr.s_addr = INADDR_ANY; - - server.sin_port = htons(lstn.port); - - if (bind(lstn.fd, (struct sockaddr *) &server, sizeof(struct sockaddr_in))) + if (bind(lstn.fd, &server.sa, sizeof(server))) { report_listener_error("binding stream socket %s:%s", &lstn); close(lstn.fd); return -1; } - if (getsockname(lstn.fd, (struct sockaddr *) &server, &len)) + if (getsockname(lstn.fd, &server.sa, &len)) { report_listener_error("getsockname failed for %s:%s", &lstn); close(lstn.fd); @@ -575,23 +580,31 @@ void write_pidfile() */ static int check_init(aClient * cptr, char *sockn) { - struct sockaddr_in sk; - unsigned int len = sizeof(struct sockaddr_in); + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } sk; + unsigned int len = sizeof(sk); /* If descriptor is a tty, special checking... * IT can't EVER be a tty */ - if (getpeername(cptr->fd, (struct sockaddr *) &sk, &len) == -1) + if (getpeername(cptr->fd, &sk.sa, &len) == -1) return -1; - strcpy(sockn, (char *) inetntoa((char *) &sk.sin_addr)); - if (inet_netof(sk.sin_addr) == IN_LOOPBACKNET) + if (sk.sa.sa_family == AF_INET) { - cptr->hostp = NULL; - strncpyzt(sockn, me.sockhost, HOSTLEN); + strcpy(sockn, (char *) inetntoa((char *) &sk.addr4.sin_addr)); + if (inet_netof(sk.addr4.sin_addr) == IN_LOOPBACKNET) + { + cptr->hostp = NULL; + strncpyzt(sockn, me.sockhost, HOSTLEN); + } + memcpy((char *) &cptr->ip.ip4, (char *) &sk.addr4.sin_addr, + sizeof(struct in_addr)); + + cptr->port = (int) (ntohs(sk.addr4.sin_port)); } - memcpy((char *) &cptr->ip, (char *) &sk.sin_addr, sizeof(struct in_addr)); - - cptr->port = (int) (ntohs(sk.sin_port)); return 0; } @@ -1070,10 +1083,19 @@ static void set_sock_opts(int fd, aClient * cptr) #endif } -static void set_listener_sock_opts(int fd, aListener *lptr) +static void set_listener_sock_opts(int fd, aListener *lptr, int family) { int opt; +#ifdef IPV6_V6ONLY + if (family == AF_INET6) + { + opt = 1; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, + sizeof(opt)) < 0) + report_listener_error("setsockopt(IPV6_V6ONLY) %s:%s", lptr); + } +#endif #ifdef SO_REUSEADDR opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, @@ -1217,49 +1239,57 @@ aClient *add_connection(aListener *lptr, int fd) { Link lin; aClient *acptr = NULL; - char *s, *t; - struct sockaddr_in addr; - unsigned int len = sizeof(struct sockaddr_in); + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } addr; + unsigned int len = sizeof(addr); struct userBan *ban; - - if (getpeername(fd, (struct sockaddr *) &addr, &len) == -1) - { + + if (getpeername(fd, &addr.sa, &len) == -1) + { ircstp->is_ref++; close(fd); return NULL; } acptr = make_client(NULL, &me); + acptr->ip_family = addr.sa.sa_family; - /* + /* * Copy ascii address to 'sockhost' just in case. Then we have * something valid to put into error messages... */ - get_sockhost(acptr, (char *) inetntoa((char *) &addr.sin_addr)); - acptr->ip_family = AF_INET; - memcpy((char *) &acptr->ip, (char *) &addr.sin_addr, - sizeof(struct in_addr)); - - acptr->port = ntohs(addr.sin_port); - /* - * Check that this socket (client) is allowed to accept - * connections from this IP#. - */ - for (s = (char *) &lptr->allow_ip, t = (char *) &acptr->ip, len = 4; - len > 0; len--, s++, t++) - { - if (!*s) - continue; - if (*s != *t) - break; - } - if (len) - { - ircstp->is_ref++; - acptr->fd = -2; - free_client(acptr); - close(fd); - return NULL; + if (acptr->ip_family == AF_INET) + { + char *s, *t; + + get_sockhost(acptr, (char *) inetntoa((char *) &addr.addr4.sin_addr)); + memcpy((char *) &acptr->ip.ip4, (char *) &addr.addr4.sin_addr, + sizeof(struct in_addr)); + acptr->port = ntohs(addr.addr4.sin_port); + + /* + * Check that this socket (client) is allowed to accept + * connections from this IP#. + */ + for (s = (char *) &lptr->allow_ip, t = (char *) &acptr->ip.ip4, len = 4; + len > 0; len--, s++, t++) + { + if (!*s) + continue; + if (*s != *t) + break; + } + if (len) + { + ircstp->is_ref++; + acptr->fd = -2; + free_client(acptr); + close(fd); + return NULL; + } } lptr->ccount++; @@ -1302,9 +1332,13 @@ aClient *add_connection(aListener *lptr, int fd) #endif lin.flags = ASYNC_CLIENT; lin.value.cptr = acptr; - Debug((DEBUG_DNS, "lookup %s", inetntoa((char *) &addr.sin_addr))); - acptr->hostp = gethost_byaddr((char *) &acptr->ip, &lin); - if (!acptr->hostp) + if (acptr->ip_family == AF_INET) + { + Debug((DEBUG_DNS, "lookup %s", + inetntoa((char *) &addr.addr4.sin_addr))); + acptr->hostp = gethost_byaddr((char *) &acptr->ip.ip4, &lin); + } + if (acptr->ip_family == AF_INET && !acptr->hostp) SetDNS(acptr); #ifdef SHOW_HEADERS else @@ -1554,18 +1588,22 @@ void read_error_exit(aClient *cptr, int length, int err) void accept_connection(aListener *lptr) { - static struct sockaddr_in addr; - unsigned int addrlen = sizeof(struct sockaddr_in); + union + { + struct sockaddr sa; + struct sockaddr_in addr4; + } addr; + unsigned int addrlen = sizeof(addr); char host[HOSTLEN + 2]; int newfd; int i; - + lptr->lasttime = timeofday; - - for (i = 0; i < 100; i++) /* accept up to 100 times per call + + for (i = 0; i < 100; i++) /* accept up to 100 times per call * to deal with high connect rates */ { - if((newfd = accept(lptr->fd, (struct sockaddr *) &addr, &addrlen)) < 0) + if((newfd = accept(lptr->fd, &addr.sa, &addrlen)) < 0) { switch(errno) { @@ -1585,11 +1623,20 @@ void accept_connection(aListener *lptr) return; } - strncpyzt(host, (char *) inetntoa((char *) &addr.sin_addr), - sizeof(host)); + if (addr.sa.sa_family == AF_INET) + { + strncpyzt(host, (char *) inetntoa((char *) &addr.addr4.sin_addr), + sizeof(host)); + } + else + { + /* unknown address family. */ + close(newfd); + return; + } /* if they are throttled, drop them silently. */ - if (throttle_check(host, newfd, NOW) == 0) + if (throttle_check(host, newfd, NOW) == 0) { ircstp->is_ref++; ircstp->is_throt++; @@ -1597,7 +1644,7 @@ void accept_connection(aListener *lptr) return; } - if (newfd >= MAX_ACTIVECONN) + if (newfd >= MAX_ACTIVECONN) { ircstp->is_ref++; sendto_realops_lev(CCONN_LEV,"All connections in use. fd: %d (%s)", -- 1.7.2.3

A port can be enabled for IPv6 by using bind ::0; (or some other IPv6 address) in the configuration block for that port. Resolving IPv6 hostnames is not supported yet. The ipmask token in the port block is also ignored. --- include/h.h | 1 + include/struct.h | 1 + src/clones.c | 6 ++++++ src/s_auth.c | 21 +++++++++++++++++++++ src/s_bsd.c | 38 +++++++++++++++++++++++++++++++++++--- src/s_user.c | 11 ++++++++++- src/support.c | 25 ++++++++++++++++++++++++- 7 files changed, 98 insertions(+), 5 deletions(-) diff --git a/include/h.h b/include/h.h index 137fcba..8fc4181 100644 --- a/include/h.h +++ b/include/h.h @@ -180,6 +180,7 @@ extern char *getreply(int); extern char *strerror(int); extern int dgets(int, char *, int); extern char *inetntoa(char *); +extern char *inet6ntoa(char *); extern char *cipntoa(aClient *); extern int dbufalloc, dbufblocks, debuglevel, errno; extern int highest_fd, debuglevel, portnum, diff --git a/include/struct.h b/include/struct.h index c68b05d..10074df 100644 --- a/include/struct.h +++ b/include/struct.h @@ -890,6 +890,7 @@ struct Client union { struct in_addr ip4; + struct in6_addr ip6; } ip; /* keep real ip# too */ char hostip[HOSTIPLEN + 1]; /* Keep real ip as string * too - Dianora */ diff --git a/src/clones.c b/src/clones.c index 63e9fb1..c4751a0 100644 --- a/src/clones.c +++ b/src/clones.c @@ -282,6 +282,9 @@ clones_add(aClient *cptr) if (cptr->ip_family == AF_INET && cptr->ip.ip4.s_addr == 0) return; + if (cptr->ip_family == AF_INET6 && + memcmp(&cptr->ip.ip6, &in6addr_any, sizeof(struct in6_addr)) == 0) + return; get_clones(cptr, &ceip, &ce24, 1); @@ -314,6 +317,9 @@ clones_remove(aClient *cptr) if (cptr->ip_family == AF_INET && cptr->ip.ip4.s_addr == 0) return; + if (cptr->ip_family == AF_INET6 && + memcmp(&cptr->ip.ip6, &in6addr_any, sizeof(struct in6_addr)) == 0) + return; get_clones(cptr, &ceip, &ce24, 0); diff --git a/src/s_auth.c b/src/s_auth.c index 6163af6..de8469a 100644 --- a/src/s_auth.c +++ b/src/s_auth.c @@ -54,11 +54,13 @@ void start_auth(aClient *cptr) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } sock; union { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } localaddr; unsigned int locallen; @@ -98,6 +100,8 @@ void start_auth(aClient *cptr) getsockname(cptr->fd, &localaddr.sa, &locallen); if (localaddr.sa.sa_family == AF_INET) localaddr.addr4.sin_port = htons(0); + else if (localaddr.sa.sa_family == AF_INET6) + localaddr.addr6.sin6_port = htons(0); if (bind(cptr->authfd, &localaddr.sa, sizeof(localaddr)) == -1) @@ -116,6 +120,13 @@ void start_auth(aClient *cptr) sock.addr4.sin_port = htons(113); sock.addr4.sin_family = AF_INET; } + else if (cptr->ip_family == AF_INET6) + { + memcpy((char *) &sock.addr6.sin6_addr, (char *) &cptr->ip.ip6, + sizeof(struct in6_addr)); + sock.addr6.sin6_port = htons(113); + sock.addr6.sin6_family = AF_INET6; + } if (connect(cptr->authfd, &sock.sa, sizeof(sock)) == -1 && errno != EINPROGRESS) @@ -153,11 +164,13 @@ void send_authports(aClient *cptr) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } us; union { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } them; char authbuf[32]; unsigned int ulen = sizeof(us), tlen = sizeof(them); @@ -184,6 +197,14 @@ void send_authports(aClient *cptr) Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", authbuf, inetntoa((char *) &them.sin_addr))); } + else if (us.sa.sa_family == AF_INET6) + { + (void) ircsprintf(authbuf, "%u , %u\r\n", + (unsigned int) ntohs(them.addr6.sin6_port), + (unsigned int) ntohs(us.addr6.sin6_port)); + Debug((DEBUG_SEND, "sending [%s] to auth port %s.113", + authbuf, inet6ntoa((char *) &them.sin_addr))); + } if (send(cptr->authfd, authbuf, strlen(authbuf), 0) != strlen(authbuf)) { authsenderr(cptr); diff --git a/src/s_bsd.c b/src/s_bsd.c index 0c596ec..dc3a231 100644 --- a/src/s_bsd.c +++ b/src/s_bsd.c @@ -276,6 +276,7 @@ int add_listener(aPort *aport) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } server; unsigned int len = sizeof(server); #ifdef USE_SSL @@ -290,9 +291,17 @@ int add_listener(aPort *aport) { strncpyzt(lstn.vhost_string, aport->address, sizeof(lstn.vhost_string)); - server.addr4.sin_family = AF_INET; - server.addr4.sin_addr.s_addr = inet_addr(aport->address); - server.addr4.sin_port = htons(lstn.port); + if (inet_pton(AF_INET6, aport->address, &server.addr6.sin6_addr) == 1) + { + server.addr6.sin6_family = AF_INET6; + server.addr6.sin6_port = htons(lstn.port); + } + else + { + server.addr4.sin_family = AF_INET; + server.addr4.sin_addr.s_addr = inet_addr(aport->address); + server.addr4.sin_port = htons(lstn.port); + } } else { @@ -584,6 +593,7 @@ static int check_init(aClient * cptr, char *sockn) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } sk; unsigned int len = sizeof(sk); @@ -605,6 +615,13 @@ static int check_init(aClient * cptr, char *sockn) cptr->port = (int) (ntohs(sk.addr4.sin_port)); } + else if (sk.sa.sa_family == AF_INET6) + { + strcpy(sockn, (char *) inet6ntoa((char *) &sk.addr6.sin6_addr)); + memcpy((char *) &cptr->ip.ip6, (char *) &sk.addr6.sin6_addr, + sizeof(struct in6_addr)); + cptr->port = (int) (ntohs(sk.addr6.sin6_port)); + } return 0; } @@ -1243,6 +1260,7 @@ aClient *add_connection(aListener *lptr, int fd) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } addr; unsigned int len = sizeof(addr); struct userBan *ban; @@ -1291,6 +1309,14 @@ aClient *add_connection(aListener *lptr, int fd) return NULL; } } + else if (acptr->ip_family == AF_INET6) + { + get_sockhost(acptr, (char *) inet6ntoa((char *) &addr.addr6.sin6_addr)); + memcpy((char *) &acptr->ip.ip6, (char *) &addr.addr6.sin6_addr, + sizeof(struct in6_addr)); + acptr->port = ntohs(addr.addr6.sin6_port); + } + lptr->ccount++; lptr->clients++; @@ -1592,6 +1618,7 @@ void accept_connection(aListener *lptr) { struct sockaddr sa; struct sockaddr_in addr4; + struct sockaddr_in6 addr6; } addr; unsigned int addrlen = sizeof(addr); char host[HOSTLEN + 2]; @@ -1628,6 +1655,11 @@ void accept_connection(aListener *lptr) strncpyzt(host, (char *) inetntoa((char *) &addr.addr4.sin_addr), sizeof(host)); } + else if (addr.sa.sa_family == AF_INET6) + { + strncpyzt(host, (char *) inet6ntoa((char *) &addr.addr6.sin6_addr), + sizeof(host)); + } else { /* unknown address family. */ diff --git a/src/s_user.c b/src/s_user.c index 2a75ee9..17da791 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -539,8 +539,17 @@ register_user(aClient *cptr, aClient *sptr, char *nick, char *username, /* * Check that the hostname has AT LEAST ONE dot (.) in it. If * not, drop the client (spoofed host) -ThemBones + * + * allow valid IPv6 addresses, though. */ - if (!dots) + if (sptr->ip_family == AF_INET6 && + inet_pton(AF_INET6, user->host, tmpstr2) == 1) + { + bad_dns = NO; + dots = 1; + } + + if (!dots) { sendto_realops("Invalid hostname for %s, dumping user %s", sptr->hostip, sptr->name); diff --git a/src/support.c b/src/support.c index 280f7d0..ebfd144 100644 --- a/src/support.c +++ b/src/support.c @@ -24,6 +24,7 @@ #include "h.h" #include "numeric.h" #include "memcount.h" +#include "inet.h" #define FOREVER for(;;) @@ -130,13 +131,35 @@ char *inetntoa(char *in) return buf; } +/* inet6ntoa - return the string notation of a given IPv6 address. */ +char *inet6ntoa(char *in) +{ + static char buf[HOSTIPLEN + 2]; + + buf[1] = '\0'; + if (inet_ntop(AF_INET6, in, buf + 1, sizeof(buf) - 1)) + { + /* addresses should not start with a ':' character */ + if (buf[1] == ':') + { + buf[0] = '0'; + return buf; + } + } + return buf + 1; +} + /* cipntoa - Return the client IP address as a string. */ char *cipntoa(aClient *cptr) { if (cptr->hostip[0] != '\0') return cptr->hostip; + else if (cptr->ip_family == AF_INET) + return inetntoa((char *)&cptr->ip.ip4); + else if (cptr->ip_family == AF_INET6) + return inet6ntoa((char *)&cptr->ip.ip6); else - return inetntoa((char *)&cptr->ip); + return "invalid.address.family.invalid"; } #if !defined( HAVE_INET_NETOF ) -- 1.7.2.3
participants (1)
-
Ned T. Crigler