Ejemplo n.º 1
0
struct interface *
zebra_interface_add_read (struct stream *s)
{
  struct interface *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

  /* Read interface name. */
  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);

  /* Lookup/create interface by name. */
  ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getq (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
#ifdef HAVE_SOCKADDR_DL
  stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
#else
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_SOCKADDR_DL */
  
  return ifp;
}
Ejemplo n.º 2
0
struct interface *
zebra_interface_add_read (struct stream *s)
{
  struct interface *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

  /* Read interface name. */
  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);

  /* Lookup/create interface by name. */
  ifp = if_get_by_name_len (ifname_tmp, strnlen(ifname_tmp, INTERFACE_NAMSIZ));

  zebra_interface_if_set_value (s, ifp);

  return ifp;
}
Ejemplo n.º 3
0
/* Interface adding function */
static int
ifan_read (struct if_announcemsghdr *ifan)
{
  struct interface *ifp;
  
  ifp = if_lookup_by_index (ifan->ifan_index);
  
  if (ifp)
    assert ( (ifp->ifindex == ifan->ifan_index) 
             || (ifp->ifindex == IFINDEX_INTERNAL) );

  if ( (ifp == NULL) 
      || ((ifp->ifindex == IFINDEX_INTERNAL)
          && (ifan->ifan_what == IFAN_ARRIVAL)) )
    {
      if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_debug ("%s: creating interface for ifindex %d, name %s",
                    __func__, ifan->ifan_index, ifan->ifan_name);
      
      /* Create Interface */
      ifp = if_get_by_name_len(ifan->ifan_name,
			       strnlen(ifan->ifan_name,
				       sizeof(ifan->ifan_name)));
      ifp->ifindex = ifan->ifan_index;

      if_add_update (ifp);
    }
  else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
    if_delete_update (ifp);

  if_get_flags (ifp);
  if_get_mtu (ifp);
  if_get_metric (ifp);

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: interface %s index %d", 
                __func__, ifan->ifan_name, ifan->ifan_index);

  return 0;
}
Ejemplo n.º 4
0
/* Interface looking up using infamous SIOCGIFCONF. */
static int
interface_list_ioctl (void)
{
  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. */
#ifdef SIOCGIFNUM
  ret = ioctl (sock, SIOCGIFNUM, &ifnum);
  if (ret < 0)
    ifnum = IFNUM_BASE;
  else
    ifnum++;
#else
  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;
	}
      /* Success. */
      break;
    }

  /* Allocate interface. */
  ifreq = ifconf.ifc_req;

#ifdef OPEN_BSD
  for (n = 0; n < ifconf.ifc_len; )
    {
      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)));
      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)));
      if_add_update (ifp);
      ifreq++;
    }
#endif /* OPEN_BSD */

 end:
  close (sock);
  XFREE (MTYPE_TMP, ifconf.ifc_buf);

  return ret;
}
Ejemplo n.º 5
0
static int
interface_list_ioctl (int af)
{
  int ret;
  int sock;
#define IFNUM_BASE 32
  struct lifnum lifn;
  int ifnum;
  struct lifreq *lifreq;
  struct lifconf lifconf;
  struct interface *ifp;
  int n;
  int save_errno;
  size_t needed, lastneeded = 0;
  char *buf = NULL;

  if (zserv_privs.change(ZPRIVS_RAISE))
    zlog (NULL, LOG_ERR, "Can't raise privileges");
  
  sock = socket (af, SOCK_DGRAM, 0);
  if (sock < 0)
    {
      zlog_warn ("Can't make %s socket stream: %s",
                 (af == AF_INET ? "AF_INET" : "AF_INET6"), safe_strerror (errno));
                 
      if (zserv_privs.change(ZPRIVS_LOWER))
        zlog (NULL, LOG_ERR, "Can't lower privileges");
        
      return -1;
    }

calculate_lifc_len:     /* must hold privileges to enter here */
  lifn.lifn_family = af;
  lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */
  ret = ioctl (sock, SIOCGLIFNUM, &lifn);
  save_errno = errno;
  
  if (zserv_privs.change(ZPRIVS_LOWER))
    zlog (NULL, LOG_ERR, "Can't lower privileges");
 
  if (ret < 0)
    {
      zlog_warn ("interface_list_ioctl: SIOCGLIFNUM failed %s",
                 safe_strerror (save_errno));
      close (sock);
      return -1;
    }
  ifnum = lifn.lifn_count;

  /*
   * When calculating the buffer size needed, add a small number
   * of interfaces to those we counted.  We do this to capture
   * the interface status of potential interfaces which may have
   * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
   */
  needed = (ifnum + 4) * sizeof (struct lifreq);
  if (needed > lastneeded || needed < lastneeded / 2)
    {
      if (buf != NULL)
        XFREE (MTYPE_TMP, buf);
      if ((buf = XMALLOC (MTYPE_TMP, needed)) == NULL)
        {
          zlog_warn ("interface_list_ioctl: malloc failed");
          close (sock);
          return -1;
        }
    }
  lastneeded = needed;

  lifconf.lifc_family = af;
  lifconf.lifc_flags = LIFC_NOXMIT;
  lifconf.lifc_len = needed;
  lifconf.lifc_buf = buf;

  if (zserv_privs.change(ZPRIVS_RAISE))
    zlog (NULL, LOG_ERR, "Can't raise privileges");
    
  ret = ioctl (sock, SIOCGLIFCONF, &lifconf);

  if (ret < 0)
    {
      if (errno == EINVAL)
        goto calculate_lifc_len; /* deliberately hold privileges */

      zlog_warn ("SIOCGLIFCONF: %s", safe_strerror (errno));

      if (zserv_privs.change(ZPRIVS_LOWER))
        zlog (NULL, LOG_ERR, "Can't lower privileges");

      goto end;
    }

  if (zserv_privs.change(ZPRIVS_LOWER))
    zlog (NULL, LOG_ERR, "Can't lower privileges");
    
  /* Allocate interface. */
  lifreq = lifconf.lifc_req;

  for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq))
    {
      /* we treat Solaris logical interfaces as addresses, because that is
       * how PF_ROUTE on Solaris treats them. Hence we can not directly use
       * the lifreq_name to get the ifp.  We need to normalise the name
       * before attempting get.
       *
       * Solaris logical interface names are in the form of:
       * <interface name>:<logical interface id>
       */
      unsigned int normallen = 0;
      uint64_t lifflags;
      
      /* We should exclude ~IFF_UP interfaces, as we'll find out about them
       * coming up later through RTM_NEWADDR message on the route socket.
       */
      if (if_get_flags_direct (lifreq->lifr_name, &lifflags,
                           lifreq->lifr_addr.ss_family)
          || !CHECK_FLAG (lifflags, IFF_UP))
        {
          lifreq++;
          continue;
        }
      
      /* Find the normalised name */
      while ( (normallen < sizeof(lifreq->lifr_name))
             && ( *(lifreq->lifr_name + normallen) != '\0')
             && ( *(lifreq->lifr_name + normallen) != ':') )
        normallen++;
      
      ifp = if_get_by_name_len(lifreq->lifr_name, normallen);

      if (lifreq->lifr_addr.ss_family == AF_INET)
        ifp->flags |= IFF_IPV4;

      if (lifreq->lifr_addr.ss_family == AF_INET6)
        {
#ifdef HAVE_IPV6
          ifp->flags |= IFF_IPV6;
#else
          lifreq++;
          continue;
#endif /* HAVE_IPV6 */
        }
        
      if_add_update (ifp);

      interface_info_ioctl (ifp);
      
      /* If a logical interface pass the full name so it can be
       * as a label on the address
       */
      if ( *(lifreq->lifr_name + normallen) != '\0')
        if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr,
                     lifreq->lifr_name);
      else
        if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL);
        
      /* Poke the interface flags. Lets IFF_UP mangling kick in */
      if_flags_update (ifp, ifp->flags);
      
      lifreq++;
    }

end:
  close (sock);
  XFREE (MTYPE_TMP, lifconf.lifc_buf);
  return ret;
}