diff --git a/Makefile.defs b/Makefile.defs index 2e9f0817a3f..e922ad90bca 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -1785,7 +1785,7 @@ ifeq ($(CC_NAME), suncc) endif OLD_SOLARIS= $(shell echo "$(OSREL)" | \ sed -e 's/^5\.[0-6][^0-9]*$$/yes/' ) - LIBS+= -L$(LOCALBASE)/lib -lxnet -lnsl + LIBS+= -L$(LOCALBASE)/lib -lxnet -lsocket -lnsl ifeq ($(OLD_SOLARIS), yes) LIBS+=-lposix4 else diff --git a/socket_info.c b/socket_info.c index 678b6d85679..e2d914734dc 100644 --- a/socket_info.c +++ b/socket_info.c @@ -41,6 +41,7 @@ #include #include +#include #ifdef HAVE_SYS_SOCKIO_H #include #endif @@ -1129,7 +1130,8 @@ static int build_iface_list(void) return -1; } -/* add all family type addresses of interface if_to the socket_info array +/* add all family type addresses of interface if_name to the socket_info array + * if family ==0, uses all families * if if_name==0, adds all addresses on all interfaces * uses RTNETLINK sockets to get addresses on the present interface on LINUX * return: -1 on error, 0 on success @@ -1160,7 +1162,7 @@ int add_interfaces_via_netlink(char* if_name, int family, unsigned short port, LM_DBG("in add_iface_via_netlink Name %s Address %s\n", ifaces[i].name, tmp->addr); /* match family */ - if (family == tmp->family){ + if (family && family == tmp->family){ /* check if loopback */ if (ifaces[i].flags & IFF_LOOPBACK){ LM_DBG("INTERFACE %s is loopback", ifaces[i].name); @@ -1182,129 +1184,49 @@ int add_interfaces_via_netlink(char* if_name, int family, unsigned short port, #endif /* __OS_linux */ /* add all family type addresses of interface if_name to the socket_info array + * if family ==0, uses all families * if if_name==0, adds all addresses on all interfaces - * WARNING: it only works with ipv6 addresses on FreeBSD * return: -1 on error, 0 on success */ int add_interfaces(char* if_name, int family, unsigned short port, unsigned short proto, struct addr_info** ai_l) { - struct ifconf ifc; - struct ifreq ifr; - struct ifreq ifrcopy; - char* last; - char* p; - int size; - int lastlen; - int s; char* tmp; struct ip_addr addr; - int ret; + int ret = -1; enum si_flags flags; + struct ifaddrs *ifap, *ifa; -#ifdef HAVE_SOCKADDR_SA_LEN - #ifndef MAX - #define MAX(a,b) ( ((a)>(b))?(a):(b)) - #endif -#endif - /* ipv4 or ipv6 only*/ - flags=SI_NONE; - s=socket(family, SOCK_DGRAM, 0); - ret=-1; - lastlen=0; - ifc.ifc_req=0; - for (size=100; ; size*=2){ - ifc.ifc_len=size*sizeof(struct ifreq); - ifc.ifc_req=(struct ifreq*) pkg_malloc(size*sizeof(struct ifreq)); - if (ifc.ifc_req==0){ - LM_ERR("memory allocation failure\n"); - goto error; - } - if (ioctl(s, SIOCGIFCONF, &ifc)==-1){ - if(errno==EBADF) return 0; /* invalid descriptor => no such ifs*/ - LM_ERR("ioctl failed: %s\n", strerror(errno)); - goto error; - } - if ((lastlen) && (ifc.ifc_len==lastlen)) break; /*success, - len not changed*/ - lastlen=ifc.ifc_len; - /* try a bigger array*/ - pkg_free(ifc.ifc_req); - } - - last=(char*)ifc.ifc_req+ifc.ifc_len; - for(p=(char*)ifc.ifc_req; pifa_next) { - /* copy contents into ifr structure - * warning: it might be longer (e.g. ipv6 address) */ - memcpy(&ifr, p, sizeof(ifr)); - if (ifr.ifr_addr.sa_family!=family){ - /*printf("strange family %d skipping...\n", - ifr->ifr_addr.sa_family);*/ + if (if_name && strcmp(if_name, ifa->ifa_name)) continue; + if (family && family != ifa->ifa_addr->sa_family) + continue; + sockaddr2ip_addr(&addr, (struct sockaddr*)ifa->ifa_addr); + tmp=ip_addr2a(&addr); + if (ifa->ifa_flags & IFF_LOOPBACK) + flags = SI_IS_LO; + else + flags = SI_NONE; + if (new_addr_info2list(tmp, flags, ai_l)!=0) + { + LM_ERR("new_addr_info2list failed\n"); + ret = -1; + break; } - - /*get flags*/ - ifrcopy=ifr; - if (ioctl(s, SIOCGIFFLAGS, &ifrcopy)!=-1){ /* ignore errors */ - /* ignore down ifs only if listening on all of them*/ - if (if_name==0){ - /* if if not up, skip it*/ - if (!(ifrcopy.ifr_flags & IFF_UP)) continue; - } - } - - - - if ((if_name==0)|| - (strncmp(if_name, ifr.ifr_name, sizeof(ifr.ifr_name))==0)){ - - /*add address*/ - sockaddr2ip_addr(&addr, - (struct sockaddr*)(p+(long)&((struct ifreq*)0)->ifr_addr)); - if ((tmp=ip_addr2a(&addr))==0) goto error; - /* check if loopback */ - if (ifrcopy.ifr_flags & IFF_LOOPBACK) - flags|=SI_IS_LO; - /* save the info */ - if (new_addr_info2list(tmp, flags, ai_l)!=0){ - LM_ERR("new_addr_info2list failed\n"); - goto error; - } - ret=0; - } - /* - printf("%s:\n", ifr->ifr_name); - printf(" "); - print_sockaddr(&(ifr->ifr_addr)); - printf(" "); - ls_ifflags(ifr->ifr_name, family, options); - printf("\n");*/ + LM_DBG("If: %8s Fam: %8x Flg: %16lx Adr: %s\n", ifa->ifa_name, ifa->ifa_addr->sa_family, ifa->ifa_flags, tmp); + + ret = 0; } - pkg_free(ifc.ifc_req); /*clean up*/ - close(s); + freeifaddrs(ifap); return ret; -error: - if (ifc.ifc_req) pkg_free(ifc.ifc_req); - close(s); - return -1; } @@ -1474,7 +1396,7 @@ static int fix_socket_list(struct socket_info **list, int* type_flags) for (si=*list;si;){ next=si->next; ai_lst=0; - if (add_interfaces(si->name.s, AF_INET, si->port_no, + if (add_interfaces(si->name.s, 0, si->port_no, si->proto, &ai_lst)!=-1){ if (si->flags & SI_IS_MHOMED){ if((new_si=new_sock2list_after(ai_lst->name.s, 0, si->port_no,