diff options
Diffstat (limited to 'zebra/if_ioctl.c')
| -rw-r--r-- | zebra/if_ioctl.c | 487 | 
1 files changed, 237 insertions, 250 deletions
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 73da049655..2d5d604a8b 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -38,306 +38,293 @@  #include <ifaddrs.h>  /* Interface looking up using infamous SIOCGIFCONF. */ -static int -interface_list_ioctl (void) +static int interface_list_ioctl(void)  { -  int ret; -  int sock; +	int ret; +	int sock;  #define IFNUM_BASE 32 -  int ifnum; -  struct ifreq *ifreq; -  struct ifconf ifconf; -  struct interface *ifp; -  int n; -  int lastlen; - -  /* Normally SIOCGIFCONF works with AF_INET socket. */ -  sock = socket (AF_INET, SOCK_DGRAM, 0); -  if (sock < 0)  -    { -      zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno)); -      return -1; -    } - -  /* Set initial ifreq count.  This will be double when SIOCGIFCONF -     fail.  Solaris has SIOCGIFNUM. */ +	int ifnum; +	struct ifreq *ifreq; +	struct ifconf ifconf; +	struct interface *ifp; +	int n; +	int lastlen; + +	/* Normally SIOCGIFCONF works with AF_INET socket. */ +	sock = socket(AF_INET, SOCK_DGRAM, 0); +	if (sock < 0) { +		zlog_warn("Can't make AF_INET socket stream: %s", +			  safe_strerror(errno)); +		return -1; +	} + +/* Set initial ifreq count.  This will be double when SIOCGIFCONF +   fail.  Solaris has SIOCGIFNUM. */  #ifdef SIOCGIFNUM -  ret = ioctl (sock, SIOCGIFNUM, &ifnum); -  if (ret < 0) -    ifnum = IFNUM_BASE; -  else -    ifnum++; +	ret = ioctl(sock, SIOCGIFNUM, &ifnum); +	if (ret < 0) +		ifnum = IFNUM_BASE; +	else +		ifnum++;  #else -  ifnum = IFNUM_BASE; +	ifnum = IFNUM_BASE;  #endif /* SIOCGIFNUM */ -  ifconf.ifc_buf = NULL; - -  lastlen = 0; -  /* Loop until SIOCGIFCONF success. */ -  for (;;)  -    { -      ifconf.ifc_len = sizeof (struct ifreq) * ifnum; -      ifconf.ifc_buf = XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); - -      ret = ioctl(sock, SIOCGIFCONF, &ifconf); - -      if (ret < 0)  -	{ -	  zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno)); -	  goto end; -	} -      /* Repeatedly get info til buffer fails to grow. */ -      if (ifconf.ifc_len > lastlen) -	{ -          lastlen = ifconf.ifc_len; -	  ifnum += 10; -	  continue; +	ifconf.ifc_buf = NULL; + +	lastlen = 0; +	/* Loop until SIOCGIFCONF success. */ +	for (;;) { +		ifconf.ifc_len = sizeof(struct ifreq) * ifnum; +		ifconf.ifc_buf = +			XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len); + +		ret = ioctl(sock, SIOCGIFCONF, &ifconf); + +		if (ret < 0) { +			zlog_warn("SIOCGIFCONF: %s", safe_strerror(errno)); +			goto end; +		} +		/* Repeatedly get info til buffer fails to grow. */ +		if (ifconf.ifc_len > lastlen) { +			lastlen = ifconf.ifc_len; +			ifnum += 10; +			continue; +		} +		/* Success. */ +		break;  	} -      /* Success. */ -      break; -    } -  /* Allocate interface. */ -  ifreq = ifconf.ifc_req; +	/* Allocate interface. */ +	ifreq = ifconf.ifc_req;  #ifdef OPEN_BSD -  for (n = 0; n < ifconf.ifc_len; ) -    { -      unsigned int size; - -      ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n); -      ifp = if_get_by_name_len(ifreq->ifr_name, -			       strnlen(ifreq->ifr_name, -				       sizeof(ifreq->ifr_name)), -                               VRF_DEFAULT, 0); -      if_add_update (ifp); -      size = ifreq->ifr_addr.sa_len; -      if (size < sizeof (ifreq->ifr_addr)) -	size = sizeof (ifreq->ifr_addr); -      size += sizeof (ifreq->ifr_name); -      n += size; -    } +	for (n = 0; n < ifconf.ifc_len;) { +		unsigned int size; + +		ifreq = (struct ifreq *)((caddr_t)ifconf.ifc_req + n); +		ifp = if_get_by_name_len( +			ifreq->ifr_name, +			strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), +			VRF_DEFAULT, 0); +		if_add_update(ifp); +		size = ifreq->ifr_addr.sa_len; +		if (size < sizeof(ifreq->ifr_addr)) +			size = sizeof(ifreq->ifr_addr); +		size += sizeof(ifreq->ifr_name); +		n += size; +	}  #else -  for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) -    { -      ifp = if_get_by_name_len(ifreq->ifr_name, -			       strnlen(ifreq->ifr_name, -				       sizeof(ifreq->ifr_name)), -                               VRF_DEFAULT, 0); -      if_add_update (ifp); -      ifreq++; -    } +	for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) { +		ifp = if_get_by_name_len( +			ifreq->ifr_name, +			strnlen(ifreq->ifr_name, sizeof(ifreq->ifr_name)), +			VRF_DEFAULT, 0); +		if_add_update(ifp); +		ifreq++; +	}  #endif /* OPEN_BSD */ - end: -  close (sock); -  XFREE (MTYPE_TMP, ifconf.ifc_buf); +end: +	close(sock); +	XFREE(MTYPE_TMP, ifconf.ifc_buf); -  return ret; +	return ret;  }  /* Get interface's index by ioctl. */ -static int -if_get_index (struct interface *ifp) +static int if_get_index(struct interface *ifp)  { -  ifp->ifindex = if_nametoindex(ifp->name); -  return ifp->ifindex; +	ifp->ifindex = if_nametoindex(ifp->name); +	return ifp->ifindex;  }  #ifdef SIOCGIFHWADDR -static int -if_get_hwaddr (struct interface *ifp) +static int if_get_hwaddr(struct interface *ifp)  { -  int ret; -  struct ifreq ifreq; -  int i; - -  strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); -  ifreq.ifr_addr.sa_family = AF_INET; - -  /* Fetch Hardware address if available. */ -  ret = if_ioctl (SIOCGIFHWADDR, (caddr_t) &ifreq); -  if (ret < 0) -    ifp->hw_addr_len = 0; -  else -    { -      memcpy (ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); - -      for (i = 0; i < 6; i++) -	if (ifp->hw_addr[i] != 0) -	  break; - -      if (i == 6) -	ifp->hw_addr_len = 0; -      else -	ifp->hw_addr_len = 6; -    } -  return 0; +	int ret; +	struct ifreq ifreq; +	int i; + +	strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); +	ifreq.ifr_addr.sa_family = AF_INET; + +	/* Fetch Hardware address if available. */ +	ret = if_ioctl(SIOCGIFHWADDR, (caddr_t)&ifreq); +	if (ret < 0) +		ifp->hw_addr_len = 0; +	else { +		memcpy(ifp->hw_addr, ifreq.ifr_hwaddr.sa_data, 6); + +		for (i = 0; i < 6; i++) +			if (ifp->hw_addr[i] != 0) +				break; + +		if (i == 6) +			ifp->hw_addr_len = 0; +		else +			ifp->hw_addr_len = 6; +	} +	return 0;  }  #endif /* SIOCGIFHWADDR */ -static int -if_getaddrs (void) +static int if_getaddrs(void)  { -  int ret; -  struct ifaddrs *ifap; -  struct ifaddrs *ifapfree; -  struct interface *ifp; -  int prefixlen; - -  ret = getifaddrs (&ifap);  -  if (ret != 0) -    { -      zlog_err ("getifaddrs(): %s", safe_strerror (errno)); -      return -1; -    } - -  for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) -    { -      if (ifap->ifa_addr == NULL) -        { -          zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", -                    __func__, (ifap->ifa_name ? ifap->ifa_name : "(null)")); -          continue; -        } -        -      ifp = if_lookup_by_name (ifap->ifa_name, VRF_DEFAULT); -      if (ifp == NULL) -	{ -	  zlog_err ("if_getaddrs(): Can't lookup interface %s\n", -		    ifap->ifa_name); -	  continue; +	int ret; +	struct ifaddrs *ifap; +	struct ifaddrs *ifapfree; +	struct interface *ifp; +	int prefixlen; + +	ret = getifaddrs(&ifap); +	if (ret != 0) { +		zlog_err("getifaddrs(): %s", safe_strerror(errno)); +		return -1;  	} -      if (ifap->ifa_addr->sa_family == AF_INET) -	{ -	  struct sockaddr_in *addr; -	  struct sockaddr_in *mask; -	  struct sockaddr_in *dest; -	  struct in_addr *dest_pnt; -	  int flags = 0; - -	  addr = (struct sockaddr_in *) ifap->ifa_addr; -	  mask = (struct sockaddr_in *) ifap->ifa_netmask; -	  prefixlen = ip_masklen (mask->sin_addr); - -	  dest_pnt = NULL; - -	  if (ifap->ifa_dstaddr && -	      !IPV4_ADDR_SAME(&addr->sin_addr, -			      &((struct sockaddr_in *) -			      	ifap->ifa_dstaddr)->sin_addr)) -	    { -	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr; -	      dest_pnt = &dest->sin_addr; -	      flags = ZEBRA_IFA_PEER; -	    } -	  else if (ifap->ifa_broadaddr && -		   !IPV4_ADDR_SAME(&addr->sin_addr, -				   &((struct sockaddr_in *) -				     ifap->ifa_broadaddr)->sin_addr)) -	    { -	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr; -	      dest_pnt = &dest->sin_addr; -	    } - -	  connected_add_ipv4 (ifp, flags, &addr->sin_addr, -			      prefixlen, dest_pnt, NULL); -	} -      if (ifap->ifa_addr->sa_family == AF_INET6) -	{ -	  struct sockaddr_in6 *addr; -	  struct sockaddr_in6 *mask; -	  struct sockaddr_in6 *dest; -	  struct in6_addr *dest_pnt; -	  int flags = 0; - -	  addr = (struct sockaddr_in6 *) ifap->ifa_addr; -	  mask = (struct sockaddr_in6 *) ifap->ifa_netmask; -	  prefixlen = ip6_masklen (mask->sin6_addr); - -	  dest_pnt = NULL; - -	  if (ifap->ifa_dstaddr && -	      !IPV6_ADDR_SAME(&addr->sin6_addr, -			      &((struct sockaddr_in6 *) -			      	ifap->ifa_dstaddr)->sin6_addr)) -	    { -	      dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr; -	      dest_pnt = &dest->sin6_addr; -	      flags = ZEBRA_IFA_PEER; -	    } -	  else if (ifap->ifa_broadaddr && -		   !IPV6_ADDR_SAME(&addr->sin6_addr, -				   &((struct sockaddr_in6 *) -				     ifap->ifa_broadaddr)->sin6_addr)) -	    { -	      dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr; -	      dest_pnt = &dest->sin6_addr; -	    } +	for (ifapfree = ifap; ifap; ifap = ifap->ifa_next) { +		if (ifap->ifa_addr == NULL) { +			zlog_err( +				"%s: nonsensical ifaddr with NULL ifa_addr, ifname %s", +				__func__, +				(ifap->ifa_name ? ifap->ifa_name : "(null)")); +			continue; +		} + +		ifp = if_lookup_by_name(ifap->ifa_name, VRF_DEFAULT); +		if (ifp == NULL) { +			zlog_err("if_getaddrs(): Can't lookup interface %s\n", +				 ifap->ifa_name); +			continue; +		} + +		if (ifap->ifa_addr->sa_family == AF_INET) { +			struct sockaddr_in *addr; +			struct sockaddr_in *mask; +			struct sockaddr_in *dest; +			struct in_addr *dest_pnt; +			int flags = 0; + +			addr = (struct sockaddr_in *)ifap->ifa_addr; +			mask = (struct sockaddr_in *)ifap->ifa_netmask; +			prefixlen = ip_masklen(mask->sin_addr); + +			dest_pnt = NULL; + +			if (ifap->ifa_dstaddr +			    && !IPV4_ADDR_SAME(&addr->sin_addr, +					       &((struct sockaddr_in *) +							 ifap->ifa_dstaddr) +							->sin_addr)) { +				dest = (struct sockaddr_in *)ifap->ifa_dstaddr; +				dest_pnt = &dest->sin_addr; +				flags = ZEBRA_IFA_PEER; +			} else if (ifap->ifa_broadaddr +				   && !IPV4_ADDR_SAME( +					      &addr->sin_addr, +					      &((struct sockaddr_in *) +							ifap->ifa_broadaddr) +						       ->sin_addr)) { +				dest = (struct sockaddr_in *) +					       ifap->ifa_broadaddr; +				dest_pnt = &dest->sin_addr; +			} + +			connected_add_ipv4(ifp, flags, &addr->sin_addr, +					   prefixlen, dest_pnt, NULL); +		} +		if (ifap->ifa_addr->sa_family == AF_INET6) { +			struct sockaddr_in6 *addr; +			struct sockaddr_in6 *mask; +			struct sockaddr_in6 *dest; +			struct in6_addr *dest_pnt; +			int flags = 0; + +			addr = (struct sockaddr_in6 *)ifap->ifa_addr; +			mask = (struct sockaddr_in6 *)ifap->ifa_netmask; +			prefixlen = ip6_masklen(mask->sin6_addr); + +			dest_pnt = NULL; + +			if (ifap->ifa_dstaddr +			    && !IPV6_ADDR_SAME(&addr->sin6_addr, +					       &((struct sockaddr_in6 *) +							 ifap->ifa_dstaddr) +							->sin6_addr)) { +				dest = (struct sockaddr_in6 *)ifap->ifa_dstaddr; +				dest_pnt = &dest->sin6_addr; +				flags = ZEBRA_IFA_PEER; +			} else if (ifap->ifa_broadaddr +				   && !IPV6_ADDR_SAME( +					      &addr->sin6_addr, +					      &((struct sockaddr_in6 *) +							ifap->ifa_broadaddr) +						       ->sin6_addr)) { +				dest = (struct sockaddr_in6 *) +					       ifap->ifa_broadaddr; +				dest_pnt = &dest->sin6_addr; +			}  #if defined(KAME) -	  if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))  -	    { -	      addr->sin6_scope_id = -			ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]); -	      addr->sin6_addr.s6_addr[2] = addr->sin6_addr.s6_addr[3] = 0; -	    }	 -#endif           - -	  connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen,  -	                      dest_pnt, NULL); +			if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) { +				addr->sin6_scope_id = +					ntohs(*(u_int16_t *)&addr->sin6_addr +						       .s6_addr[2]); +				addr->sin6_addr.s6_addr[2] = +					addr->sin6_addr.s6_addr[3] = 0; +			} +#endif + +			connected_add_ipv6(ifp, flags, &addr->sin6_addr, +					   prefixlen, dest_pnt, NULL); +		}  	} -    } -  freeifaddrs (ifapfree); +	freeifaddrs(ifapfree); -  return 0;  +	return 0;  }  /* Fetch interface information via ioctl(). */ -static void -interface_info_ioctl () +static void interface_info_ioctl()  { -  struct listnode *node, *nnode; -  struct interface *ifp; -   -  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp)) -    { -      if_get_index (ifp); +	struct listnode *node, *nnode; +	struct interface *ifp; + +	for (ALL_LIST_ELEMENTS(vrf_iflist(VRF_DEFAULT), node, nnode, ifp)) { +		if_get_index(ifp);  #ifdef SIOCGIFHWADDR -      if_get_hwaddr (ifp); +		if_get_hwaddr(ifp);  #endif /* SIOCGIFHWADDR */ -      if_get_flags (ifp); -      if_get_mtu (ifp); -      if_get_metric (ifp); -    } +		if_get_flags(ifp); +		if_get_mtu(ifp); +		if_get_metric(ifp); +	}  }  /* Lookup all interface information. */ -void -interface_list (struct zebra_ns *zns) +void interface_list(struct zebra_ns *zns)  { -  zlog_info ("interface_list: NS %u", zns->ns_id); +	zlog_info("interface_list: NS %u", zns->ns_id); -  /* Linux can do both proc & ioctl, ioctl is the only way to get -     interface aliases in 2.2 series kernels. */ +/* Linux can do both proc & ioctl, ioctl is the only way to get +   interface aliases in 2.2 series kernels. */  #ifdef HAVE_PROC_NET_DEV -  interface_list_proc (); +	interface_list_proc();  #endif /* HAVE_PROC_NET_DEV */ -  interface_list_ioctl (); +	interface_list_ioctl(); -  /* After listing is done, get index, address, flags and other -     interface's information. */ -  interface_info_ioctl (); +	/* After listing is done, get index, address, flags and other +	   interface's information. */ +	interface_info_ioctl(); -  if_getaddrs (); +	if_getaddrs();  #if defined(HAVE_PROC_NET_IF_INET6) -  /* Linux provides interface's IPv6 address via -     /proc/net/if_inet6. */ -  ifaddr_proc_ipv6 (); +	/* Linux provides interface's IPv6 address via +	   /proc/net/if_inet6. */ +	ifaddr_proc_ipv6();  #endif /* HAVE_PROC_NET_IF_INET6 */  }  | 
