diff --git a/minissdpd/Changelog.txt b/minissdpd/Changelog.txt index 4c5ac27..3abba01 100644 --- a/minissdpd/Changelog.txt +++ b/minissdpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.25 2012/05/02 10:30:40 nanard Exp $ +$Id: Changelog.txt,v 1.26 2012/05/15 22:02:23 nanard Exp $ + +2012/05/15: + Improve ProcessInterfaceWatch() under linux. 2012/05/02: Clean CLFAGS in Makefile. diff --git a/minissdpd/ifacewatch.c b/minissdpd/ifacewatch.c index a70ad9e..8acfa7d 100644 --- a/minissdpd/ifacewatch.c +++ b/minissdpd/ifacewatch.c @@ -1,12 +1,13 @@ -/* $Id: ifacewatch.c,v 1.4 2012/04/09 21:50:18 nanard Exp $ */ +/* $Id: ifacewatch.c,v 1.7 2012/05/15 22:02:23 nanard Exp $ */ /* MiniUPnP project - * (c) 2011 Thomas Bernard + * (c) 2011-2012 Thomas Bernard * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include "config.h" #include +#include #include #include #include @@ -73,6 +74,8 @@ ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6, struct msghdr hdr; struct nlmsghdr *nlhdr; struct ifaddrmsg *ifa; + struct rtattr *rta; + int ifa_len; iov.iov_base = buffer; iov.iov_len = sizeof(buffer); @@ -90,27 +93,72 @@ ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6, for(nlhdr = (struct nlmsghdr *)buffer; NLMSG_OK(nlhdr, len); nlhdr = NLMSG_NEXT(nlhdr, len)) { - syslog(LOG_DEBUG, "nlmsg_type=%d", nlhdr->nlmsg_type); + int is_del = 0; + char address[48]; + char ifname[IFNAMSIZ]; + address[0] = '\0'; + ifname[0] = '\0'; if(nlhdr->nlmsg_type == NLMSG_DONE) break; - if(nlhdr->nlmsg_type == RTM_NEWADDR) { + switch(nlhdr->nlmsg_type) { + /* case RTM_NEWLINK: */ + /* case RTM_DELLINK: */ + case RTM_DELADDR: + is_del = 1; + case RTM_NEWADDR: + /* http://linux-hacks.blogspot.fr/2009/01/sample-code-to-learn-netlink.html */ ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr); - syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifa->ifa_index); + rta = (struct rtattr *)IFA_RTA(ifa); + ifa_len = IFA_PAYLOAD(nlhdr); + syslog(LOG_DEBUG, "%s %s index=%d fam=%d prefixlen=%d flags=%d scope=%d", + "ProcessInterfaceWatchNotify", is_del ? "RTM_DELADDR" : "RTM_NEWADDR", + ifa->ifa_index, ifa->ifa_family, ifa->ifa_prefixlen, + ifa->ifa_flags, ifa->ifa_scope); + for(;RTA_OK(rta, ifa_len); rta = RTA_NEXT(rta, ifa_len)) { + /*RTA_DATA(rta)*/ + /*rta_type : IFA_ADDRESS, IFA_LOCAL, etc. */ + char tmp[128]; + memset(tmp, 0, sizeof(tmp)); + switch(rta->rta_type) { + case IFA_ADDRESS: + case IFA_LOCAL: + case IFA_BROADCAST: + case IFA_ANYCAST: + inet_ntop(ifa->ifa_family, RTA_DATA(rta), tmp, sizeof(tmp)); + if(rta->rta_type == IFA_ADDRESS) + strncpy(address, tmp, sizeof(address)); + break; + case IFA_LABEL: + strncpy(tmp, RTA_DATA(rta), sizeof(tmp)); + strncpy(ifname, tmp, sizeof(ifname)); + break; + case IFA_CACHEINFO: + { + struct ifa_cacheinfo *cache_info; + cache_info = RTA_DATA(rta); + snprintf(tmp, sizeof(tmp), "valid=%u prefered=%u", + cache_info->ifa_valid, cache_info->ifa_prefered); + } + break; + default: + strncpy(tmp, "*unknown*", sizeof(tmp)); + } + syslog(LOG_DEBUG, " rta_len=%d rta_type=%d '%s'", rta->rta_len, rta->rta_type, tmp); + } for(i = 0; i < n_if_addr; i++) { - if(ifa->ifa_index == if_nametoindex(if_addr[i])) { - AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0); - break; - } - } - } else if(nlhdr->nlmsg_type == RTM_DELADDR) { - ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr); - syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifa->ifa_index); - for(i = 0; i < n_if_addr; i++) { - if(ifa->ifa_index == if_nametoindex(if_addr[i])) { - AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1); + if((0 == strcmp(address, if_addr[i])) || + (0 == strcmp(ifname, if_addr[i])) || + (ifa->ifa_index == if_nametoindex(if_addr[i]))) { + if(ifa->ifa_family == AF_INET && address[0] != '\0') + AddDropMulticastMembership(s_ssdp, address, 0, is_del); + else if(ifa->ifa_family == AF_INET6) + AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, is_del); break; } } + break; + default: + syslog(LOG_DEBUG, "unknown nlmsg_type=%d", nlhdr->nlmsg_type); } } #else /* __linux__ */ @@ -119,28 +167,32 @@ ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6, len = recv(s, buffer, sizeof(buffer), 0); if(len < 0) { - syslog(LOG_ERR, "ProcessInterfaceWatchNotify recv: %m"); + syslog(LOG_ERR, "%s recv: %m", "ProcessInterfaceWatchNotify"); return -1; } rtm = (struct rt_msghdr *)buffer; switch(rtm->rtm_type) { case RTM_NEWADDR: ifam = (struct ifa_msghdr *)buffer; - syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR index=%d", ifam->ifam_index); + syslog(LOG_DEBUG, "%s %s index=%d", + "ProcessInterfaceWatchNotify", "RTM_NEWADDR", ifam->ifam_index); for(i = 0; i < n_if_addr; i++) { if(ifam->ifam_index == if_nametoindex(if_addr[i])) { AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 0); + AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, 0); break; } } break; case RTM_DELADDR: ifam = (struct ifa_msghdr *)buffer; - syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR index=%d", ifam->ifam_index); + syslog(LOG_DEBUG, "%s %s index=%d", + "ProcessInterfaceWatchNotify", "RTM_DELADDR", ifam->ifam_index); for(i = 0; i < n_if_addr; i++) { if(ifam->ifam_index == if_nametoindex(if_addr[i])) { /* I dont think it is useful */ /*AddDropMulticastMembership(s_ssdp, if_addr[i], 0, 1);*/ + /*AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, 1);*/ break; } }