Example #1
0
void
connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
{
  struct prefix_ipv6 p;
  struct prefix_ipv6 *addr;
  struct prefix_ipv6 *dest;

  if(product != NULL && product->board_type != BOARD_IS_ACTIVE_MASTER)
   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_ipv6 *) ifc->address;
  dest = (struct prefix_ipv6 *) ifc->destination;

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

  if (if_is_pointopoint (ifp) && dest)
    {
      if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
	p.prefix = addr->prefix;
      else
	p.prefix = dest->prefix;
    }
  else
    p.prefix = addr->prefix;

  apply_mask_ipv6 (&p);

  if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
    return;

  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);

  rib_update ();
}
Example #2
0
void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
{
	struct prefix_ipv6 p;

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

	PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));

	apply_mask_ipv6(&p);

	if (IN6_IS_ADDR_UNSPECIFIED(&p.prefix))
		return;

	rib_delete_ipv6(ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0,
			SAFI_UNICAST);

	rib_update();
}
Example #3
0
File: zserv.c Project: OPSF/uClinux
void
zebra_read_ipv6 (int command, struct zserv *client, u_short length)
{
  u_char type;
  u_char flags;
  struct in6_addr nexthop, *gate;
  u_char *lim;
  u_char *pnt;
  unsigned int ifindex;

  pnt = stream_pnt (client->ibuf);
  lim = pnt + length;

  type = stream_getc (client->ibuf);
  flags = stream_getc (client->ibuf);
  stream_get (&nexthop, client->ibuf, sizeof (struct in6_addr));
  
  while (stream_pnt (client->ibuf) < lim)
    {
      int size;
      struct prefix_ipv6 p;
      
      ifindex = stream_getl (client->ibuf);

      memset (&p, 0, sizeof (struct prefix_ipv6));
      p.family = AF_INET6;
      p.prefixlen = stream_getc (client->ibuf);
      size = PSIZE(p.prefixlen);
      stream_get (&p.prefix, client->ibuf, size);

      if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
        gate = NULL;
      else
        gate = &nexthop;

      if (command == ZEBRA_IPV6_ROUTE_ADD)
        rib_add_ipv6 (type, flags, &p, gate, ifindex, 0, 0, 0);
      else
        rib_delete_ipv6 (type, flags, &p, gate, ifindex, 0);
    }
}
void
connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
{
  struct prefix_ipv6 p;
  struct prefix_ipv6 *addr;
  struct prefix_ipv6 *dest;

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

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

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

  if (if_is_pointopoint (ifp) && dest)
    {
      if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
	p.prefix = addr->prefix;
      else
	p.prefix = dest->prefix;
    }
  else
    p.prefix = addr->prefix;

  apply_mask_ipv6 (&p);

  if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
    return;

  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);

  rib_update ();
}
Example #5
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 */
}
Example #6
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 */
}
Example #7
0
File: zserv.c Project: OPSF/uClinux
/* Zebra server IPv6 prefix delete function. */
static void
zread_ipv6_delete (struct zserv *client, u_short length)
{
  int i;
  struct stream *s;
  struct zapi_ipv6 api;
  struct in6_addr nexthop;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  
  s = client->ibuf;
  ifindex = 0;
  memset (&nexthop, 0, sizeof (struct in6_addr));

  /* Type, flags, message. */
  api.type = stream_getc (s);
  api.flags = stream_getc (s);
  api.message = stream_getc (s);

  /* IPv4 prefix. */
  memset (&p, 0, sizeof (struct prefix_ipv6));
  p.family = AF_INET6;
  p.prefixlen = stream_getc (s);
  stream_get (&p.prefix, s, PSIZE (p.prefixlen));

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      u_char nexthop_type;

      api.nexthop_num = stream_getc (s);
      for (i = 0; i < api.nexthop_num; i++)
	{
	  nexthop_type = stream_getc (s);

	  switch (nexthop_type)
	    {
	    case ZEBRA_NEXTHOP_IPV6:
	      stream_get (&nexthop, s, 16);
	      break;
	    case ZEBRA_NEXTHOP_IFINDEX:
	      ifindex = stream_getl (s);
	      break;
	    }
	}
    }

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;
    
  if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
    rib_delete_ipv6 (api.type, api.flags, &p, NULL, ifindex, 0);
  else
    rib_delete_ipv6 (api.type, api.flags, &p, &nexthop, ifindex, 0);
}
Example #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;
}
Example #9
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 */
}