Esempio n. 1
0
/* Interface's address information get. */
int
ifam_read (struct ifa_msghdr *ifam)
{
  struct interface *ifp;
  union sockunion addr, mask, gate;

  /* Check does this interface exist or not. */
  ifp = if_lookup_by_index (ifam->ifam_index);
  if (ifp == NULL) 
    {
      zlog_warn ("no interface for index %d", ifam->ifam_index); 
      return -1;
    }

  /* Allocate and read address information. */
  ifam_read_mesg (ifam, &addr, &mask, &gate);

  /* Check interface flag for implicit up of the interface. */
  if_refresh (ifp);

  /* Add connected address. */
  switch (sockunion_family (&addr))
    {
    case AF_INET:
      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr, 
			    ip_masklen (mask.sin.sin_addr),
			    &gate.sin.sin_addr, NULL);
      else
	connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr, 
			       ip_masklen (mask.sin.sin_addr),
			       &gate.sin.sin_addr, NULL);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      /* Unset interface index from link-local address when IPv6 stack
	 is KAME. */
      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);

      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv6 (ifp,
			    &addr.sin6.sin6_addr, 
			    ip6_masklen (mask.sin6.sin6_addr),
			    &gate.sin6.sin6_addr);
      else
	connected_delete_ipv6 (ifp,
			       &addr.sin6.sin6_addr, 
			       ip6_masklen (mask.sin6.sin6_addr),
			       &gate.sin6.sin6_addr);
      break;
#endif /* HAVE_IPV6 */
    default:
      /* Unsupported family silently ignore... */
      break;
    }
  return 0;
}
Esempio n. 2
0
/* Utility function of convert between struct prefix <=> union sockunion.
 * FIXME This function isn't used anywhere. */
struct prefix *
sockunion2prefix (const union sockunion *dest,
		  const union sockunion *mask)
{
  if (dest->sa.sa_family == AF_INET)
    {
      struct prefix_ipv4 *p;

      p = prefix_ipv4_new ();
      p->family = AF_INET;
      p->prefix = dest->sin.sin_addr;
      p->prefixlen = ip_masklen (mask->sin.sin_addr);
      return (struct prefix *) p;
    }
#ifdef HAVE_IPV6
  if (dest->sa.sa_family == AF_INET6)
    {
      struct prefix_ipv6 *p;

      p = prefix_ipv6_new ();
      p->family = AF_INET6;
      p->prefixlen = ip6_masklen (mask->sin6.sin6_addr);
      memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr));
      return (struct prefix *) p;
    }
#endif /* HAVE_IPV6 */
  return NULL;
}
Esempio n. 3
0
void
rtm_read (struct rt_msghdr *rtm)
{
  int flags;
  u_char zebra_flags;
  union sockunion dest, mask, gate;

  zebra_flags = 0;

  /* Discard self send message. */
  if (rtm->rtm_type != RTM_GET 
      && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid))
    return;

  /* Read destination and netmask and gateway from rtm message
     structure. */
  flags = rtm_read_mesg (rtm, &dest, &mask, &gate);

#ifdef RTF_CLONED	/*bsdi, netbsd 1.6*/
  if (flags & RTF_CLONED)
    return;
#endif
#ifdef RTF_WASCLONED	/*freebsd*/
  if (flags & RTF_WASCLONED)
    return;
#endif

  if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
    return;

  /* Ignore route which has both HOST and GATEWAY attribute. */
  if ((flags & RTF_GATEWAY) && (flags & RTF_HOST))
    return;

  /* This is connected route. */
  if (! (flags & RTF_GATEWAY))
      return;

  if (flags & RTF_PROTO1)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);

  /* This is persistent route. */
  if (flags & RTF_STATIC)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);

  if (dest.sa.sa_family == AF_INET)
    {
      struct prefix_ipv4 p;

      p.family = AF_INET;
      p.prefix = dest.sin.sin_addr;
      p.prefixlen = ip_masklen (mask.sin.sin_addr);

      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
		      &p, &gate.sin.sin_addr, 0, 0, 0, 0);
      else
	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
		      &p, &gate.sin.sin_addr, 0, 0);
    }
#ifdef HAVE_IPV6
  if (dest.sa.sa_family == AF_INET6)
    {
      struct prefix_ipv6 p;
      unsigned int ifindex = 0;

      p.family = AF_INET6;
      p.prefix = dest.sin6.sin6_addr;
      p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);

#ifdef KAME
      if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
	{
	  ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
	  SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
	}
#endif /* KAME */

      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
		      &p, &gate.sin6.sin6_addr, ifindex, 0);
      else
	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
			 &p, &gate.sin6.sin6_addr, ifindex, 0);
    }
#endif /* HAVE_IPV6 */
}
Esempio n. 4
0
void
rtm_read (struct rt_msghdr *rtm)
{
  int flags;
  u_char zebra_flags;
  union sockunion dest, mask, gate;
  char ifname[INTERFACE_NAMSIZ + 1];
  short ifnlen = 0;

  zebra_flags = 0;

  /* Read destination and netmask and gateway from rtm message
     structure. */
  flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);
  if (!(flags & RTF_DONE))
    return;
  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: got rtm of type %d (%s)", __func__, rtm->rtm_type,
      lookup (rtm_type_str, rtm->rtm_type));

#ifdef RTF_CLONED	/*bsdi, netbsd 1.6*/
  if (flags & RTF_CLONED)
    return;
#endif
#ifdef RTF_WASCLONED	/*freebsd*/
  if (flags & RTF_WASCLONED)
    return;
#endif

  if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
    return;

  /* This is connected route. */
  if (! (flags & RTF_GATEWAY))
      return;

  if (flags & RTF_PROTO1)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);

  /* This is persistent route. */
  if (flags & RTF_STATIC)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);

  /* This is a reject or blackhole route */
  if (flags & RTF_REJECT)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
  if (flags & RTF_BLACKHOLE)
    SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);

  if (dest.sa.sa_family == AF_INET)
    {
      struct prefix_ipv4 p;

      p.family = AF_INET;
      p.prefix = dest.sin.sin_addr;
      if (flags & RTF_HOST)
	p.prefixlen = IPV4_MAX_PREFIXLEN;
      else
	p.prefixlen = ip_masklen (mask.sin.sin_addr);
      
      /* Catch self originated messages and match them against our current RIB.
       * At the same time, ignore unconfirmed messages, they should be tracked
       * by rtm_write() and kernel_rtm_ipv4().
       */
      if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
      {
        char buf[INET_ADDRSTRLEN], gate_buf[INET_ADDRSTRLEN];
        int ret;
        if (! IS_ZEBRA_DEBUG_RIB)
          return;
        ret = rib_lookup_ipv4_route (&p, &gate); 
        inet_ntop (AF_INET, &p.prefix, buf, INET_ADDRSTRLEN);
        switch (rtm->rtm_type)
        {
          case RTM_ADD:
          case RTM_GET:
          case RTM_CHANGE:
            /* The kernel notifies us about a new route in FIB created by us.
               Do we have a correspondent entry in our RIB? */
            switch (ret)
            {
              case ZEBRA_RIB_NOTFOUND:
                zlog_debug ("%s: %s %s/%d: desync: RR isn't yet in RIB, while already in FIB",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
                break;
              case ZEBRA_RIB_FOUND_CONNECTED:
              case ZEBRA_RIB_FOUND_NOGATE:
                inet_ntop (AF_INET, &gate.sin.sin_addr, gate_buf, INET_ADDRSTRLEN);
                zlog_debug ("%s: %s %s/%d: desync: RR is in RIB, but gate differs (ours is %s)",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen, gate_buf);
                break;
              case ZEBRA_RIB_FOUND_EXACT: /* RIB RR == FIB RR */
                zlog_debug ("%s: %s %s/%d: done Ok",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
                rib_lookup_and_dump (&p);
                return;
                break;
            }
            break;
          case RTM_DELETE:
            /* The kernel notifies us about a route deleted by us. Do we still
               have it in the RIB? Do we have anything instead? */
            switch (ret)
            {
              case ZEBRA_RIB_FOUND_EXACT:
                zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, while already not in FIB",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
                rib_lookup_and_dump (&p);
                break;
              case ZEBRA_RIB_FOUND_CONNECTED:
              case ZEBRA_RIB_FOUND_NOGATE:
                zlog_debug ("%s: %s %s/%d: desync: RR is still in RIB, plus gate differs",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
                rib_lookup_and_dump (&p);
                break;
              case ZEBRA_RIB_NOTFOUND: /* RIB RR == FIB RR */
                zlog_debug ("%s: %s %s/%d: done Ok",
                  __func__, lookup (rtm_type_str, rtm->rtm_type), buf, p.prefixlen);
                rib_lookup_and_dump (&p);
                return;
                break;
            }
            break;
          default:
            zlog_debug ("%s: %s/%d: warning: loopback RTM of type %s received",
              __func__, buf, p.prefixlen, lookup (rtm_type_str, rtm->rtm_type));
        }
        return;
      }

      /* Change, delete the old prefix, we have no further information
       * to specify the route really
       */
      if (rtm->rtm_type == RTM_CHANGE)
        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
                         NULL, 0, 0);
      
      if (rtm->rtm_type == RTM_GET 
          || rtm->rtm_type == RTM_ADD
          || rtm->rtm_type == RTM_CHANGE)
	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
		      &p, &gate.sin.sin_addr, NULL, 0, 0, 0, 0, rtm->rtm_protocol);
      else
	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, 
		      &p, &gate.sin.sin_addr, 0, 0);
    }
#ifdef HAVE_IPV6
  if (dest.sa.sa_family == AF_INET6)
    {
      /* One day we might have a debug section here like one in the
       * IPv4 case above. Just ignore own messages at the moment.
       */
      if (rtm->rtm_type != RTM_GET && rtm->rtm_pid == pid)
        return;
      struct prefix_ipv6 p;
      unsigned int ifindex = 0;

      p.family = AF_INET6;
      p.prefix = dest.sin6.sin6_addr;
      if (flags & RTF_HOST)
	p.prefixlen = IPV6_MAX_PREFIXLEN;
      else
	p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);

#ifdef KAME
      if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
	{
	  ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
	  SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
	}
#endif /* KAME */

      /* CHANGE: delete the old prefix, we have no further information
       * to specify the route really
       */
      if (rtm->rtm_type == RTM_CHANGE)
        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
                         NULL, 0, 0);
      
      if (rtm->rtm_type == RTM_GET 
          || rtm->rtm_type == RTM_ADD
          || rtm->rtm_type == RTM_CHANGE)
	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
		      &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0);
      else
	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
			 &p, &gate.sin6.sin6_addr, ifindex, 0);
    }
#endif /* HAVE_IPV6 */
}
Esempio n. 5
0
/* Interface's address information get. */
int
ifam_read (struct ifa_msghdr *ifam)
{
  struct interface *ifp = NULL;
  union sockunion addr, mask, brd;
  char ifname[INTERFACE_NAMSIZ];
  short ifnlen = 0;
  char isalias = 0;
  int flags = 0;
  
  ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
  
  /* Allocate and read address information. */
  ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
  
  if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
    {
      zlog_warn ("%s: no interface for ifname %s, index %d", 
                 __func__, ifname, ifam->ifam_index);
      return -1;
    }
  
  if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
    isalias = 1;
  
  /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
     field contains a broadcast address or a peer address, so we are forced to
     rely upon the interface type. */
  if (if_is_pointopoint(ifp))
    SET_FLAG(flags, ZEBRA_IFA_PEER);

#if 0
  /* it might seem cute to grab the interface metric here, however
   * we're processing an address update message, and so some systems
   * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
   * in deliberately, as comment.
   */
  ifp->metric = ifam->ifam_metric;
#endif

  /* Add connected address. */
  switch (sockunion_family (&addr))
    {
    case AF_INET:
      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			    ip_masklen (mask.sin.sin_addr),
			    &brd.sin.sin_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			       ip_masklen (mask.sin.sin_addr),
			       &brd.sin.sin_addr);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      /* Unset interface index from link-local address when IPv6 stack
	 is KAME. */
      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);

      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, 
			    ip6_masklen (mask.sin6.sin6_addr),
			    &brd.sin6.sin6_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv6 (ifp,
			       &addr.sin6.sin6_addr, 
			       ip6_masklen (mask.sin6.sin6_addr),
			       &brd.sin6.sin6_addr);
      break;
#endif /* HAVE_IPV6 */
    default:
      /* Unsupported family silently ignore... */
      break;
    }
  
  /* Check interface flag for implicit up of the interface. */
  if_refresh (ifp);

#ifdef SUNOS_5
  /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. 
   * See comments for SUNOS_5 in interface.c::if_flags_mangle.
   * 
   * Here we take care of case where the real IFF_UP was previously
   * unset (as kept in struct zebra_if.primary_state) and the mangled
   * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
   * to unset due to the lost non-primary address having DELADDR'd.
   *
   * we must delete the interface, because in between here and next
   * event for this interface-name the administrator could unplumb
   * and replumb the interface.
   */
  if (!if_is_up (ifp))
    if_delete_update (ifp);
#endif /* SUNOS_5 */
  
  return 0;
}
Esempio n. 6
0
/* Address read from struct ifa_msghdr. */
static void
ifam_read_mesg (struct ifa_msghdr *ifm,
		union sockunion *addr,
		union sockunion *mask,
		union sockunion *brd,
		char *ifname,
		short *ifnlen)
{
  caddr_t pnt, end;
  union sockunion dst;
  union sockunion gateway;

  pnt = (caddr_t)(ifm + 1);
  end = ((caddr_t)ifm) + ifm->ifam_msglen;

  /* Be sure structure is cleared */
  memset (mask, 0, sizeof (union sockunion));
  memset (addr, 0, sizeof (union sockunion));
  memset (brd, 0, sizeof (union sockunion));
  memset (&dst, 0, sizeof (union sockunion));
  memset (&gateway, 0, sizeof (union sockunion));

  /* We fetch each socket variable into sockunion. */
  RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
  RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
  RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
  RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);

  if (IS_ZEBRA_DEBUG_KERNEL)
    {
      switch (sockunion_family(addr))
        {
	case AF_INET:
	  {
	    char buf[4][INET_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index,
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET,&addr->sin.sin_addr,
			          buf[0],sizeof(buf[0])),
			ip_masklen(mask->sin.sin_addr),
			inet_ntop(AF_INET,&brd->sin.sin_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET,&dst.sin.sin_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET,&gateway.sin.sin_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#ifdef HAVE_IPV6
	case AF_INET6:
	  {
	    char buf[4][INET6_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index, 
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET6,&addr->sin6.sin6_addr,
			          buf[0],sizeof(buf[0])),
			ip6_masklen(mask->sin6.sin6_addr),
			inet_ntop(AF_INET6,&brd->sin6.sin6_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET6,&dst.sin6.sin6_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET6,&gateway.sin6.sin6_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#endif /* HAVE_IPV6 */
        default:
	  zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
		      __func__, ifm->ifam_index, 
		      (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
	  break;
        }
    }

  /* Assert read up end point matches to end point */
  if (pnt != end)
    zlog_warn ("ifam_read() does't read all socket data");
}
Esempio n. 7
0
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);
      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;

	  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_flags & IFF_POINTOPOINT) 
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  connected_add_ipv4 (ifp, 0, &addr->sin_addr,
			      prefixlen, dest_pnt, NULL);
	}
#ifdef HAVE_IPV6
      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;

	  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_flags & IFF_POINTOPOINT) 
	    {
	      if (ifap->ifa_dstaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      if (ifap->ifa_broadaddr)
		{
		  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, &addr->sin6_addr, prefixlen, 
	                      dest_pnt, NULL);
	}
#endif /* HAVE_IPV6 */
    }

  freeifaddrs (ifapfree);

  return 0; 
}
Esempio n. 8
0
void
rtm_read (struct rt_msghdr *rtm)
{
    int flags;
    u_char zebra_flags;
    union sockunion dest, mask, gate;
    char ifname[INTERFACE_NAMSIZ + 1];
    short ifnlen = 0;

    zebra_flags = 0;

    /* Discard self send message. */
    if (rtm->rtm_type != RTM_GET
            && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid))
        return;

    /* Read destination and netmask and gateway from rtm message
       structure. */
    flags = rtm_read_mesg (rtm, &dest, &mask, &gate, ifname, &ifnlen);

#ifdef RTF_CLONED	/*bsdi, netbsd 1.6*/
    if (flags & RTF_CLONED)
        return;
#endif
#ifdef RTF_WASCLONED	/*freebsd*/
    if (flags & RTF_WASCLONED)
        return;
#endif

    if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
        return;

    /* This is connected route. */
    if (! (flags & RTF_GATEWAY))
        return;

    if (flags & RTF_PROTO1)
        SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);

    /* This is persistent route. */
    if (flags & RTF_STATIC)
        SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);

    /* This is a reject or blackhole route */
    if (flags & RTF_REJECT)
        SET_FLAG (zebra_flags, ZEBRA_FLAG_REJECT);
    if (flags & RTF_BLACKHOLE)
        SET_FLAG (zebra_flags, ZEBRA_FLAG_BLACKHOLE);

    if (dest.sa.sa_family == AF_INET)
    {
        struct prefix_ipv4 p;

        p.family = AF_INET;
        p.prefix = dest.sin.sin_addr;
        if (flags & RTF_HOST)
            p.prefixlen = IPV4_MAX_PREFIXLEN;
        else
            p.prefixlen = ip_masklen (mask.sin.sin_addr);

        /* Change, delete the old prefix, we have no further information
         * to specify the route really
         */
        if (rtm->rtm_type == RTM_CHANGE)
            rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
                             NULL, 0, 0);

        if (rtm->rtm_type == RTM_GET
                || rtm->rtm_type == RTM_ADD
                || rtm->rtm_type == RTM_CHANGE)
            rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
                          &p, &gate.sin.sin_addr, 0, 0, 0, 0);
        else
            rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
                             &p, &gate.sin.sin_addr, 0, 0);
    }
#ifdef HAVE_IPV6
    if (dest.sa.sa_family == AF_INET6)
    {
        struct prefix_ipv6 p;
        unsigned int ifindex = 0;

        p.family = AF_INET6;
        p.prefix = dest.sin6.sin6_addr;
        if (flags & RTF_HOST)
            p.prefixlen = IPV6_MAX_PREFIXLEN;
        else
            p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);

#ifdef KAME
        if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
        {
            ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
            SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
        }
#endif /* KAME */

        /* CHANGE: delete the old prefix, we have no further information
         * to specify the route really
         */
        if (rtm->rtm_type == RTM_CHANGE)
            rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
                             NULL, 0, 0);

        if (rtm->rtm_type == RTM_GET
                || rtm->rtm_type == RTM_ADD
                || rtm->rtm_type == RTM_CHANGE)
            rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
                          &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0);
        else
            rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
                             &p, &gate.sin6.sin6_addr, ifindex, 0);
    }
#endif /* HAVE_IPV6 */
}
Esempio n. 9
0
int
if_getaddrs ()
{
  int ret;
  struct ifaddrs *ifap;
  struct ifaddrs *ifapfree;
  struct interface *ifp;
  int prefixlen;

  ret = getifaddrs (&ifap); 
  if (ret != 0)
    {
#ifdef BRCM_RIP_DEBUG
      zlog_err ("getifaddrs(): %s", strerror (errno));
#endif
      return -1;
    }

  for (ifapfree = ifap; ifap; ifap = ifap->ifa_next)
    {
      ifp = if_lookup_by_name (ifap->ifa_name);
      if (ifp == NULL)
	{
#ifdef BRCM_RIP_DEBUG
	  zlog_err ("if_getaddrs(): Can't lookup interface %s\n",
		    ifap->ifa_name);
#endif
	  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;

	  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_flags & IFF_POINTOPOINT) 
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  connected_add_ipv4 (ifp, 0, &addr->sin_addr,
			      prefixlen, dest_pnt, NULL);
	}
#ifdef HAVE_IPV6
      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;

	  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_flags & IFF_POINTOPOINT) 
	    {
	      if (ifap->ifa_dstaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      if (ifap->ifa_broadaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, dest_pnt);
	}
#endif /* HAVE_IPV6 */
    }

  freeifaddrs (ifapfree);

  return 0; 
}