Beispiel #1
0
/* Called from if_up(). */
void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
{
	struct prefix_ipv4 p;

	if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
		return;

	PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));

	/* Apply mask to the network. */
	apply_mask_ipv4(&p);

	/* In case of connected address is 0.0.0.0/0 we treat it tunnel
	   address. */
	if (prefix_ipv4_any(&p))
		return;

	rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
		     RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);

	rib_add_ipv4(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
		     RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);

	rib_update();
}
Beispiel #2
0
void handle_route_entry (mib2_ipRouteEntry_t *routeEntry)
{
	struct prefix_ipv4	prefix;
 	struct in_addr		tmpaddr, gateway;
	u_char			zebra_flags = 0;

	if (routeEntry->ipRouteInfo.re_ire_type & IRE_CACHETABLE)
		return;

	if (routeEntry->ipRouteInfo.re_ire_type & IRE_HOST_REDIRECT)
		zebra_flags |= ZEBRA_FLAG_SELFROUTE;

	prefix.family = AF_INET;

	tmpaddr.s_addr = routeEntry->ipRouteDest;
	prefix.prefix = tmpaddr;

	tmpaddr.s_addr = routeEntry->ipRouteMask;
	prefix.prefixlen = ip_masklen (tmpaddr);

	gateway.s_addr = routeEntry->ipRouteNextHop;

	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &prefix,
		      &gateway, 0, 0, 0, 0);
}
/* Kernel routing table read up by /proc filesystem. */
int
proc_route_read ()
{
  FILE *fp;
  char buf[RT_BUFSIZ];
  char iface[INTERFACE_NAMSIZ], dest[9], gate[9], mask[9];
  int flags, refcnt, use, metric, mtu, window, rtt;

  /* Open /proc filesystem */
  fp = fopen (_PATH_PROCNET_ROUTE, "r");
  if (fp == NULL)
    {
      zlog_warn ("Can't open %s : %s\n", _PATH_PROCNET_ROUTE, strerror (errno));
      return -1;
    }
  
  /* Drop first label line. */
  fgets (buf, RT_BUFSIZ, fp);

  while (fgets (buf, RT_BUFSIZ, fp) != NULL)
    {
      int n;
      struct prefix_ipv4 p;
      struct in_addr tmpmask;
      struct in_addr gateway;
      u_char zebra_flags = 0;

      n = sscanf (buf, "%s %s %s %x %d %d %d %s %d %d %d",
		  iface, dest, gate, &flags, &refcnt, &use, &metric, 
		  mask, &mtu, &window, &rtt);
      if (n != 11)
	{	
	  zlog_warn ("can't read all of routing information\n");
	  continue;
	}
      if (! (flags & RTF_UP))
	continue;
      if (! (flags & RTF_GATEWAY))
	continue;

      if (flags & RTF_DYNAMIC)
	zebra_flags |= ZEBRA_FLAG_SELFROUTE;

      p.family = AF_INET;
      sscanf (dest, "%lX", (unsigned long *)&p.prefix);
      sscanf (mask, "%lX", (unsigned long *)&tmpmask);
      p.prefixlen = ip_masklen (tmpmask);
      sscanf (gate, "%lX", (unsigned long *)&gateway);

      //2006/4/13 trenchen : when kernel route, save metric info.
      //rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0, 0, 0);
      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0, metric, 0);
    }

  return 0;
}
Beispiel #4
0
/* Called from if_up(). */
void
connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
{
  struct prefix_ipv4 p;
  struct prefix_ipv4 *addr;
  struct prefix_ipv4 *dest;

  if (IS_ZEBRA_DEBUG_RIB)
    zlog_debug ("%s: start", __func__);


 /* if(product != NULL)*/
  if(product != NULL && product->board_type != BOARD_IS_ACTIVE_MASTER)/*gjd : change for active master 在删除ip时,直连路由没删除,因为重复添加,导致refcnt不为0释放不掉*/
  	goto skip;
  if(product != NULL && product->board_type == BOARD_IS_ACTIVE_MASTER &&CHECK_FLAG(ifp->if_scope, INTERFACE_LOCAL))
  	goto skip;/*local interface , skip the check the ifc->conf, because the ip address not install in the kernel .*/

  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
    return;

 skip:

  addr = (struct prefix_ipv4 *) ifc->address;
  dest = (struct prefix_ipv4 *) ifc->destination;

  memset (&p, 0, sizeof (struct prefix_ipv4));
  p.family = AF_INET;
  p.prefixlen = addr->prefixlen;

  /* Point-to-point check. */
  if (CONNECTED_POINTOPOINT_HOST(ifc))
    p.prefix = dest->prefix;
  else
    p.prefix = addr->prefix;

  /* Apply mask to the network. */
  apply_mask_ipv4 (&p);

  /* In case of connected address is 0.0.0.0/0 we treat it tunnel
     address. */
  if (prefix_ipv4_any (&p))
    return;

  rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, 
                ifp->metric, 0);

  if (IS_ZEBRA_DEBUG_RIB)
    zlog_debug ("%s: goto rib_update ", __func__);
  rib_update ();
}
/* Called from if_up(). */
void
connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
{
  struct prefix_ipv4 p;
  struct prefix_ipv4 *addr;
  struct prefix_ipv4 *dest;

  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
    return;

  addr = (struct prefix_ipv4 *) ifc->address;
  dest = (struct prefix_ipv4 *) ifc->destination;

  memset (&p, 0, sizeof (struct prefix_ipv4));
  p.family = AF_INET;
  p.prefixlen = addr->prefixlen;

  /* Point-to-point check. */
  if (CONNECTED_POINTOPOINT_HOST(ifc))
    p.prefix = dest->prefix;
  else
    p.prefix = addr->prefix;

  /* Apply mask to the network. */
  apply_mask_ipv4 (&p);

  /* In case of connected address is 0.0.0.0/0 we treat it tunnel
     address. */
  if (prefix_ipv4_any (&p))
    return;

  rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, 
                ifp->metric, 0);

  rib_update ();
}
Beispiel #6
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 */
}
Beispiel #7
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 */
}
Beispiel #8
0
/* Routing information change from the kernel. */
int
netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct rtmsg *rtm;
    struct rtattr *tb [RTA_MAX + 1];

    char anyaddr[16] = {0};

    int index;
    int table;
    void *dest;
    void *gate;

    rtm = NLMSG_DATA (h);

    if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
    {
        /* If this is not route add/delete message print warning. */
        zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
        return 0;
    }

    /* Connected route. */
    if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_info ("%s %s %s proto %s",
                   h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
                   rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
                   rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
                   lookup (rtproto_str, rtm->rtm_protocol));

    if (rtm->rtm_type != RTN_UNICAST)
    {
        return 0;
    }

    table = rtm->rtm_table;
    if (table != RT_TABLE_MAIN && table != rtm_table_default)
    {
        return 0;
    }

    len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
    if (len < 0)
        return -1;

    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);

    if (rtm->rtm_flags & RTM_F_CLONED)
        return 0;
    if (rtm->rtm_protocol == RTPROT_REDIRECT)
        return 0;
    if (rtm->rtm_protocol == RTPROT_KERNEL)
        return 0;

    if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
        return 0;

    if (rtm->rtm_src_len != 0)
    {
        zlog_warn ("netlink_route_change(): no src len");
        return 0;
    }

    index = 0;
    dest = NULL;
    gate = NULL;

    if (tb[RTA_OIF])
        index = *(int *) RTA_DATA (tb[RTA_OIF]);

    if (tb[RTA_DST])
        dest = RTA_DATA (tb[RTA_DST]);
    else
        dest = anyaddr;

    if (tb[RTA_GATEWAY])
        gate = RTA_DATA (tb[RTA_GATEWAY]);

    if (rtm->rtm_family == AF_INET)
    {
        struct prefix_ipv4 p;
        p.family = AF_INET;
        memcpy (&p.prefix, dest, 4);
        p.prefixlen = rtm->rtm_dst_len;

        if (IS_ZEBRA_DEBUG_KERNEL)
        {
            if (h->nlmsg_type == RTM_NEWROUTE)
                zlog_info ("RTM_NEWROUTE %s/%d",
                           inet_ntoa (p.prefix), p.prefixlen);
            else
                zlog_info ("RTM_DELROUTE %s/%d",
                           inet_ntoa (p.prefix), p.prefixlen);
        }

        if (h->nlmsg_type == RTM_NEWROUTE)
            rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
        else
            rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
    }

#ifdef HAVE_IPV6
    if (rtm->rtm_family == AF_INET6)
    {
        struct prefix_ipv6 p;
        char buf[BUFSIZ];

        p.family = AF_INET6;
        memcpy (&p.prefix, dest, 16);
        p.prefixlen = rtm->rtm_dst_len;

        if (IS_ZEBRA_DEBUG_KERNEL)
        {
            if (h->nlmsg_type == RTM_NEWROUTE)
                zlog_info ("RTM_NEWROUTE %s/%d",
                           inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
                           p.prefixlen);
            else
                zlog_info ("RTM_DELROUTE %s/%d",
                           inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
                           p.prefixlen);
        }

        if (h->nlmsg_type == RTM_NEWROUTE)
            rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
        else
            rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
    }
#endif /* HAVE_IPV6 */

    return 0;
}
Beispiel #9
0
/* Looking up routing table by netlink interface. */
int
netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct rtmsg *rtm;
    struct rtattr *tb [RTA_MAX + 1];
    u_char flags = 0;

    char anyaddr[16] = {0};

    int index;
    int table;
    void *dest;
    void *gate;

    rtm = NLMSG_DATA (h);

    if (h->nlmsg_type != RTM_NEWROUTE)
        return 0;
    if (rtm->rtm_type != RTN_UNICAST)
        return 0;

    table = rtm->rtm_table;
#if 0		/* we weed them out later in rib_weed_tables () */
    if (table != RT_TABLE_MAIN && table != rtm_table_default)
        return 0;
#endif

    len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
    if (len < 0)
        return -1;

    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);

    if (rtm->rtm_flags & RTM_F_CLONED)
        return 0;
    if (rtm->rtm_protocol == RTPROT_REDIRECT)
        return 0;
    if (rtm->rtm_protocol == RTPROT_KERNEL)
        return 0;

    if (rtm->rtm_src_len != 0)
        return 0;

    /* Route which inserted by Zebra. */
    if (rtm->rtm_protocol == RTPROT_ZEBRA)
        flags |= ZEBRA_FLAG_SELFROUTE;

    index = 0;
    dest = NULL;
    gate = NULL;

    if (tb[RTA_OIF])
        index = *(int *) RTA_DATA (tb[RTA_OIF]);

    if (tb[RTA_DST])
        dest = RTA_DATA (tb[RTA_DST]);
    else
        dest = anyaddr;

    /* Multipath treatment is needed. */
    if (tb[RTA_GATEWAY])
        gate = RTA_DATA (tb[RTA_GATEWAY]);

    if (rtm->rtm_family == AF_INET)
    {
        struct prefix_ipv4 p;
        p.family = AF_INET;
        memcpy (&p.prefix, dest, 4);
        p.prefixlen = rtm->rtm_dst_len;

        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);
    }
#ifdef HAVE_IPV6
    if (rtm->rtm_family == AF_INET6)
    {
        struct prefix_ipv6 p;
        p.family = AF_INET6;
        memcpy (&p.prefix, dest, 16);
        p.prefixlen = rtm->rtm_dst_len;

        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
    }
#endif /* HAVE_IPV6 */

    return 0;
}
Beispiel #10
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 */
}