This not only makes possible to use generic totemip_iface_check, but also fixes some problems with previous implementation (fixed mask, not very well supported ipv6, ...) Tested on OpenIndiana 151a Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx> --- exec/totemip.c | 195 ++++++++++++++++++++++++++++++-------------------------- 1 files changed, 105 insertions(+), 90 deletions(-) diff --git a/exec/totemip.c b/exec/totemip.c index 93f933d..c6109c1 100644 --- a/exec/totemip.c +++ b/exec/totemip.c @@ -339,95 +339,7 @@ int totemip_sockaddr_to_totemip_convert(const struct sockaddr_storage *saddr, return ret; } -/* - * On Solaris, man if_tcp describes this method - */ -#if defined(COROSYNC_SOLARIS) -int totemip_iface_check(struct totem_ip_address *bindnet, - struct totem_ip_address *boundto, - int *interface_up, - int *interface_num, - int mask_high_bit) -{ - struct sockaddr_storage bindnet_ss; - struct sockaddr_in *bindnet_sin = (struct sockaddr_in *)&bindnet_ss; - struct sockaddr_in *sockaddr_in; - int id_fd; - struct lifconf lifconf; - struct lifreq *lifreq; - int numreqs = 0; - int i; - in_addr_t mask_addr; - int res = -1; - int addrlen; - - totemip_totemip_to_sockaddr_convert (bindnet, - 0, &bindnet_ss, &addrlen); - - *interface_up = 0; - id_fd = socket (AF_INET, SOCK_STREAM, 0); - lifconf.lifc_family = AF_UNSPEC; - lifconf.lifc_flags = 0; - lifconf.lifc_buf = NULL; - lifconf.lifc_len = 0; - do { - numreqs += 32; - lifconf.lifc_len = sizeof (struct lifreq) * numreqs; - lifconf.lifc_buf = (void *)realloc(lifconf.lifc_buf, lifconf.lifc_len); - res = ioctl (id_fd, SIOCGLIFCONF, &lifconf); - if (res < 0) { - close (id_fd); - return -1; - } - } while (lifconf.lifc_len == sizeof (struct lifconf) * numreqs); - res = -1; - - lifreq = (struct lifreq *)lifconf.lifc_buf; - /* - * Find interface address to bind to - */ - for (i = 0; i < lifconf.lifc_len / sizeof (struct lifreq); i++) { - sockaddr_in = (struct sockaddr_in *)&lifreq[i].lifr_addr; - mask_addr = inet_addr ("255.255.255.0"); - - if ((sockaddr_in->sin_family == AF_INET) && - (sockaddr_in->sin_addr.s_addr & mask_addr) == - (bindnet_sin->sin_addr.s_addr & mask_addr)) { - - res = i; - - /* - * Setup boundto output - */ - totemip_sockaddr_to_totemip_convert((struct sockaddr_storage *)sockaddr_in, boundto); - boundto->nodeid = sockaddr_in->sin_addr.s_addr; -#if __BYTE_ORDER == __BIG_ENDIAN - boundto->nodeid = swab32 (boundto->nodeid); -#endif - - if (ioctl(id_fd, SIOCGLIFFLAGS, &lifreq[i]) < 0) { - printf ("couldn't do ioctl\n"); - } - - *interface_up = lifreq[i].lifr_flags & IFF_UP; - - if (ioctl(id_fd, SIOCGLIFINDEX, &lifreq[i]) < 0) { - printf ("couldn't do ioctl\n"); - } - *interface_num = lifreq[i].lifr_index; - - - break; - } - } - free (lifconf.lifc_buf); - close (id_fd); - - return (res); -} -#endif - -#ifdef HAVE_GETIFADDRS +#if defined(HAVE_GETIFADDRS) int totemip_getifaddrs(struct list_head *addrs) { struct ifaddrs *ifap, *ifa; @@ -490,7 +402,110 @@ error_free_ifaddrs: freeifaddrs(ifap); return (-1); } -#else +#elif defined(SOLARIS) +/* + * On Solaris, man if_tcp describes this method + */ +int totemip_getifaddrs(struct list_head *addrs) +{ + int id_fd; + int numreqs; + int res; + struct lifconf lifconf; + struct lifreq *lifreq; + int i, j; + struct totem_ip_if_address *if_addr; + short family; + + list_init(addrs); + + for (family = 0; family < 2; family++) { + numreqs = 0; + res = -1; + + lifconf.lifc_family = (family == 0 ? AF_INET : AF_INET6); + id_fd = socket (lifconf.lifc_family, SOCK_STREAM, 0); + lifconf.lifc_flags = 0; + lifconf.lifc_buf = NULL; + lifconf.lifc_len = 0; + do { + numreqs += 32; + lifconf.lifc_len = sizeof (struct lifreq) * numreqs; + lifconf.lifc_buf = (void *)realloc(lifconf.lifc_buf, lifconf.lifc_len); + res = ioctl (id_fd, SIOCGLIFCONF, &lifconf); + if (res < 0) { + close (id_fd); + } + } while (res >= 0 && lifconf.lifc_len == sizeof (struct lifconf) * numreqs); + + if (res < 0) + continue ; + + lifreq = (struct lifreq *)lifconf.lifc_buf; + for (i = 0; i < lifconf.lifc_len / sizeof (struct lifreq); i++) { + if (ioctl(id_fd, SIOCGLIFADDR, &lifreq[i]) < 0) + continue ; + + if (lifreq[i].lifr_addr.ss_family != AF_INET && lifreq[i].lifr_addr.ss_family != AF_INET6) + continue ; + + if_addr = malloc(sizeof(struct totem_ip_if_address)); + if (if_addr == NULL) { + goto error_free_ifaddrs; + } + + memset(if_addr, 0, sizeof(struct totem_ip_if_address)); + + if_addr->name = strdup(lifreq[i].lifr_name); + if (if_addr->name == NULL) { + goto error_free_addr; + } + + if (totemip_sockaddr_to_totemip_convert(&lifreq[i].lifr_addr, &if_addr->ip_addr) == -1) { + goto error_free_addr_name; + } + + if (ioctl(id_fd, SIOCGLIFSUBNET, &lifreq[i]) < 0) + continue ; + + /* + * lifreq doesn't contain mask address. But It length of prefix in bits, + * so we can generate mask. + */ + memset(&if_addr->mask_addr, 0, sizeof(if_addr->mask_addr)); + if_addr->mask_addr.family = if_addr->ip_addr.family; + for (j = 0; j < lifreq[i].lifr_addrlen; j++) { + if_addr->mask_addr.addr[j / 8] |= 1 << (7 - (j % 8)); + } + if (ioctl(id_fd, SIOCGLIFFLAGS, &lifreq[i]) >= 0) { + if_addr->interface_up = lifreq[i].lifr_flags & IFF_UP; + } + if (ioctl(id_fd, SIOCGLIFINDEX, &lifreq[i]) >= 0) { + if_addr->interface_num = lifreq[i].lifr_index; + } + + list_add(&if_addr->list, addrs); + } + + free (lifconf.lifc_buf); + close (id_fd); + } + + return (0); + +error_free_addr_name: + free(if_addr->name); + +error_free_addr: + free(if_addr); + +error_free_ifaddrs: + totemip_freeifaddrs(addrs); + free (lifconf.lifc_buf); + close (id_fd); + + return (-1); +} #endif /* HAVE_GETIFADDRS */ void totemip_freeifaddrs(struct list_head *addrs) -- 1.7.1 _______________________________________________ discuss mailing list discuss@xxxxxxxxxxxx http://lists.corosync.org/mailman/listinfo/discuss