Пример #1
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 */
}
Пример #2
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 */
}
Пример #3
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 */
}