interface_t * ifl_find_subnet(interface_list_t * list_p, struct in_addr iaddr) { int i; u_long addr_hl = iptohl(iaddr); for (i = 0; i < list_p->count; i++) { interface_t * if_p = list_p->list + i; int j; for (j = 0; j < dynarray_count(&if_p->inet); j++) { inet_addrinfo_t * info = dynarray_element(&if_p->inet, j); u_long ifnetaddr_hl = iptohl(info->netaddr); u_long ifmask_hl = iptohl(info->mask); if ((addr_hl & ifmask_hl) == ifnetaddr_hl) return (if_p); } } return (NULL); }
/* * Function: nbits_host * Purpose: * Return the number of bits of host address */ PRIVATE_EXTERN int nbits_host(struct in_addr mask) { u_long l = iptohl(mask); int i; for (i = 0; i < 32; i++) { if (l & (1 << i)) return (32 - i); } return (32); }
static boolean_t S_build_interface_list(interface_list_t * interfaces) { struct ifaddrs * addrs = NULL; struct ifaddrs * ifap = NULL; struct ifmediareq ifmr; int s = -1; int size; boolean_t success = FALSE; if (getifaddrs(&addrs) < 0) { goto done; } size = count_ifaddrs(addrs); interfaces->list = (interface_t *)malloc(size * sizeof(*(interfaces->list))); if (interfaces->list == NULL) { goto done; } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { goto done; } interfaces->count = 0; interfaces->size = size; for (ifap = addrs; ifap != NULL; ifap = ifap->ifa_next) { const char * name; if (ifap->ifa_addr == NULL) { continue; } name = ifap->ifa_name; switch (ifap->ifa_addr->sa_family) { case AF_INET: { inet_addrinfo_t info; interface_t * entry; entry = ifl_find_name(interfaces, name); if (entry == NULL) { /* new entry */ entry = S_next_entry(interfaces, name); if (entry == NULL) { /* NOT REACHED */ IPConfigLog(LOG_ERR, "interfaces: S_next_entry returns NULL"); continue; } entry->flags = ifap->ifa_flags; } bzero(&info, sizeof(info)); /* ALIGN: getifaddrs should align, cast ok. */ info.addr = ((struct sockaddr_in *) (void *)ifap->ifa_addr)->sin_addr; if (ifap->ifa_netmask != NULL) { /* ALIGN: getifaddrs should align, cast ok. */ info.mask = ((struct sockaddr_in *) (void *)ifap->ifa_netmask)->sin_addr; } if (entry->flags & IFF_BROADCAST && ifap->ifa_broadaddr != NULL) { /* ALIGN: getifaddrs should align, cast ok. */ info.broadcast = ((struct sockaddr_in *)(void *) ifap->ifa_broadaddr)->sin_addr; } info.netaddr.s_addr = htonl(iptohl(info.addr) & iptohl(info.mask)); dynarray_add(&entry->inet, inet_addrinfo_copy(&info)); break; } case AF_LINK: { struct sockaddr_dl * dl_p; interface_t * entry; struct if_data * if_data; /* ALIGN: getifaddrs should align, cast ok. */ dl_p = (struct sockaddr_dl *) (void *)ifap->ifa_addr; entry = ifl_find_name(interfaces, name); if (entry == NULL) { /* new entry */ entry = S_next_entry(interfaces, name); if (entry == NULL) { /* NOT REACHED */ IPConfigLog(LOG_ERR, "interfaces: S_next_entry returns NULL"); continue; } entry->flags = ifap->ifa_flags; } if (dl_p->sdl_alen > sizeof(entry->link_address.addr)) { IPConfigLog(LOG_ERR, "%s: link type %d address length %d > %ld", name, dl_p->sdl_type, dl_p->sdl_alen, sizeof(entry->link_address.addr)); entry->link_address.length = sizeof(entry->link_address.addr); } else { entry->link_address.length = dl_p->sdl_alen; } bcopy(dl_p->sdl_data + dl_p->sdl_nlen, entry->link_address.addr, entry->link_address.length); entry->link_address.type = dl_p->sdl_type; entry->link_address.index = dl_p->sdl_index; if_data = (struct if_data *)ifap->ifa_data; if (if_data != NULL) { entry->type = if_data->ifi_type; } else { entry->type = dl_p->sdl_type; } if (S_get_ifmediareq_s(s, name, &ifmr)) { if (entry->type == IFT_ETHER) { if (S_ifmediareq_get_is_wireless(&ifmr)) { entry->type_flags |= kInterfaceTypeFlagIsWireless; if (S_is_awdl(s, name)) { entry->type_flags |= kInterfaceTypeFlagIsAWDL; } } } entry->link_status = S_ifmediareq_get_link_status(&ifmr); } break; } } } /* make it the "right" size (plus 1 more in case it's 0) */ interfaces->list = (interface_t *) realloc(interfaces->list, sizeof(*(interfaces->list)) * (interfaces->count + 1)); success = TRUE; done: if (addrs != NULL) { freeifaddrs(addrs); } if (success == FALSE) { if (interfaces->list != NULL) { free(interfaces->list); } interfaces->list = NULL; } if (s >= 0) { close(s); } return (success); }