Le lundi 10 octobre 2011 00:15:15, Thomas Preud'homme a écrit : > Le dimanche 9 octobre 2011 19:16:58, Thomas Preud'homme a écrit : > > Le dimanche 9 octobre 2011 15:11:10, Julien Valroff a écrit : > > > Hi, > > > > > > Here is an attempt to fix Debian bug #644794 [0] stating the logged > > > IPv6 addresses are truncated. > > > > > > Cheers, > > > Julien > > > > I would like to propose a patch myself too. Size of ip array should be > > 128 but I'm thinking about replacing this array by a more appropriate > > structure (like union of struct in_addr or struct in6_addr). but I want > > to check it's adequate first. > > > > Congrats for your quick reaction Julien. > > Ok, it will take more time than expected because there is also some other > place in the code which I believe assume IPv4. > > egrep -In "\[32\]" **/*.c | wc -l gives 11 > > One exemple is in src/daemon.c around line 250. I transformed local_addr > and remote_addr in an union of sockaddr_in and sockaddr_in6 but then the > code needs to be adapted. I will try to finish the patch tomorrow.
The patch is not completely finished but I'm going in holidays for a week so I prefer to post it. I didn't changed the handling of remote_addr in THREAD_CTX structure. Also I didn't try to compile so there is probably lots of mistake left. I discovered while writing the last part in daemon.c that IPv4 can be handled transparently through IPv6 API so probably some simplification can be done in dspam.c Anyway, it's better than nothing. Best regards.
diff --git a/src/daemon.c b/src/daemon.c index 1464a0c..f559b97 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -88,7 +88,7 @@ */ int daemon_listen(DRIVER_CTX *DTX) { - struct sockaddr_in local_addr, remote_addr; + struct sockaddr_in6 local_addr, remote_addr; THREAD_CTX *TTX = NULL; fd_set master, read_fds; pthread_attr_t attr; @@ -146,13 +146,13 @@ int daemon_listen(DRIVER_CTX *DTX) { len = sizeof(saun.sun_family) + strlen(saun.sun_path) + 1; LOGDEBUG(INFO_DAEMON_DOMAINSOCK, address); - + if (bind(listener, (struct sockaddr *) &saun, len)<0) { close(listener); LOG(LOG_CRIT, INFO_DAEMON_DOMAINSOCK, address, strerror(errno)); umask (mask); return EFAILURE; - } + } umask (mask); @@ -171,20 +171,23 @@ int daemon_listen(DRIVER_CTX *DTX) { return(EFAILURE); } - memset(&local_addr, 0, sizeof(struct sockaddr_in)); - local_addr.sin_family = AF_INET; - local_addr.sin_port = htons(port); + memset(&local_addr, 0, sizeof(local_addr)); + local_addr.sin6_family = AF_INET6; + local_addr.sin6_port = htons(port); if (_ds_read_attribute(agent_config, "ServerHost")) { char *host = _ds_read_attribute(agent_config, "ServerHost"); - local_addr.sin_addr.s_addr = inet_addr(host); + if (!inet_pton(AF_INET6, host, &local_addr.sin6_addr.s_addr)) { + LOG(LOG_CRIT, ERR_DAEMON_PTON, host); + return(EFAILURE); + } LOGDEBUG(INFO_DAEMON_BIND, host, port); } else { - local_addr.sin_addr.s_addr = INADDR_ANY; + local_addr.sin6_addr.s_addr = IN6ADDR_ANY_INIT; LOGDEBUG(INFO_DAEMON_BIND, "*", port); } - if (bind(listener, (struct sockaddr *)&local_addr, - sizeof(struct sockaddr)) == -1) + if (bind(listener, (struct sockaddr *)&local_addr, + sizeof(local_addr)) == -1) { close(listener); LOG(LOG_CRIT, ERR_DAEMON_BIND, port, strerror(errno)); @@ -232,22 +235,21 @@ int daemon_listen(DRIVER_CTX *DTX) { int newfd; int addrlen = sizeof(remote_addr); - if ((newfd = accept(listener, - (struct sockaddr *)&remote_addr, + if ((newfd = accept(listener, + (struct sockaddr *)&remote_addr, (socklen_t *) &addrlen)) == -1) { LOG(LOG_WARNING, ERR_DAEMON_ACCEPT, strerror(errno)); continue; #ifdef DEBUG } else if (!domain) { - char buff[32]; - LOGDEBUG("connection id %d from %s.", newfd, -#ifdef HAVE_INET_NTOA_R_2 - inet_ntoa_r(remote_addr.sin_addr, buff) -#else - inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff)) -#endif - ); + char buff[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, (struct sockaddr_in6) remote_addr.sin6_addr, + buff, sizeof(buff)); + if (!strncmp(buff, "::ffff:", 7)) + LOGDEBUG("connection id %d from %s.", newfd, buf + 7); + else + LOGDEBUG("connection id %d from %s.", newfd, buf); #endif } fcntl(newfd, F_SETFL, O_RDWR); diff --git a/src/daemon.h b/src/daemon.h index fa045af..d3cd83c 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -51,7 +51,7 @@ typedef struct { int sockfd; char authenticated; pthread_t thread; - struct sockaddr_in remote_addr; + struct sockaddr_in6 remote_addr; buffer *packet_buffer; DRIVER_CTX *DTX; } THREAD_CTX; diff --git a/src/dspam.c b/src/dspam.c index 26266c9..0ddadce 100644 --- a/src/dspam.c +++ b/src/dspam.c @@ -409,7 +409,7 @@ process_message ( strcmp(_ds_pref_val(ATX->PTX, "optOutClamAV"), "on")) { if (has_virus(message)) { - char ip[32]; + char ip[INET6_ADDRSTRLEN]; CTX->result = DSR_ISSPAM; CTX->probability = 1.0; CTX->confidence = 1.0; @@ -3814,7 +3814,7 @@ MEM_ALLOC: */ int tracksource(DSPAM_CTX *CTX) { - char ip[32]; + char ip[INET6_ADDRSTRLEN]; if (!dspam_getsource (CTX, ip, sizeof (ip))) { @@ -4001,53 +4001,50 @@ int is_blacklisted(DSPAM_CTX *CTX, AGENT_CTX *ATX) { /* No cygwin support for IP Blacklisting */ return 0; #else - char ip[32]; + char ip[INET6_ADDRSTRLEN]; int bad = 0; struct attribute *attrib; struct addrinfo *res = NULL; - struct sockaddr_in saddr; - char host[32]; + char host[INET6_ADDRSTRLEN]; char lookup[256]; - char *ptr; - char *octet[4]; - int i = 3; - octet[0] = octet[1] = octet[2] = octet[3] = NULL; if (!dspam_getsource (CTX, ip, sizeof (ip))) { - host[0] = 0; - ptr = strtok(ip, "."); - while(ptr != NULL && i>=0 && i<4) { - octet[i] = ptr; - ptr = strtok(NULL, "."); - if (ptr == NULL && i!=0) - return 0; - i--; + struct addrinfo *unused_addr, hint = { + .ai_flags = AI_NUMERICHOST; + .ai_family = AF_UNSPEC; + .ai_socktype = .ai_protocol = 0; } - if (octet[0] == NULL || octet[1] == NULL || octet[2] == NULL || octet[3] == NULL) + host[0] = 0; + if (getaddrinfo(ip, NULL, &hint, &unused_addr)) return 0; - snprintf(host, sizeof(host), "%s.%s.%s.%s.", octet[0], octet[1], octet[2], octet[3]); + free(unused_addr); + snprintf(host, sizeof(host), "%s", ip); attrib = _ds_find_attribute(agent_config, "Lookup"); while(attrib != NULL) { int error; - snprintf(lookup, sizeof(lookup), "%s%s", host, attrib->value); + snprintf(lookup, sizeof(lookup), "%s.%s", host, attrib->value); error = getaddrinfo(lookup, NULL, NULL, &res); if (!error) { - char buff[128]; if (!bad) { - memcpy(&saddr, res->ai_addr, sizeof(struct sockaddr)); -#ifdef HAVE_INET_NTOA_R_2 - inet_ntoa_r(saddr.sin_addr, buff); -#else - inet_ntoa_r(saddr.sin_addr, buff, sizeof(buff)); -#endif - if (strncmp(buff, "127.0.0.", 8) == 0) { - STATUS("Blacklisted (%s)", attrib->value); - bad = 1; - freeaddrinfo(res); - break; + if (res->ai_family == AF_INET) { + struct sockaddr_in *saddr = res->ai_addr; + + if (saddr->sin_addr.s_addr & htonl(0xFF000000) == 127) { + STATUS("Blacklisted (%s)", attrib->value); + bad = 1; + freeaddrinfo(res); + } + } else { + struct sockaddr_in6 *saddr = res->ai_addr; + + if (saddr->sin6_addr == in6addr_loopback) { + STATUS("Blacklisted (%s)", attrib->value); + bad = 1; + freeaddrinfo(res); + } } } freeaddrinfo(res); diff --git a/src/language.h b/src/language.h index ed33188..7edab53 100644 --- a/src/language.h +++ b/src/language.h @@ -122,6 +122,7 @@ user, e.g.. root or Trusted User [uid=%d(%s)]" #define ERR_DAEMON_NO_SUPPORT "DSPAM was not compiled with daemon support" #define ERR_DAEMON_BIND "Could not bind to :%d: %s" +#define ERR_DAEMON_PTON "Could not bind to :%s" #define ERR_DAEMON_DOMAINBIND "Could not bind to %s: %s" #define ERR_DAEMON_SOCKET "Could not create socket: %s" #define ERR_DAEMON_SOCKOPT "Could not set sockopt %s: %s"
signature.asc
Description: This is a digitally signed message part.