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);
}
Exemplo n.º 2
0
Arquivo: util.c Projeto: aosm/bootp
/* 
 * 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);
}