IP_GLOBAL void
ipnet_rtnetlink_route_change(Ipnet_route_entry *rt)
{
    if (ipnet_rtnetlink_neigh_is(rt))
        ipnet_rtnetlink_neigh_change(rt);
    else
    {
        ipnet_rtnetlink_route_event(rt, IP_RTM_NEWROUTE);
    }
}
IP_GLOBAL void
ipnet_rtnetlink_route_del(Ipnet_route_entry *rt)
{
    if (ipnet_rtnetlink_neigh_is(rt))
        ipnet_rtnetlink_neigh_del(rt);
    else
    {
        ipnet_rtnetlink_route_event(rt, IP_RTM_DELROUTE);
    }
}
/*
 *===========================================================================
 *                    ipnet_rtnetlink_route_foreach_vr
 *===========================================================================
 * Description: Hash table foreach callback. Called once for each virtual
 *              router that exists in the system.
 * Parameters:  rtab  - route table
 *              param - callback parameters.
 * Returns:     -
 *
 */
IP_STATIC void
ipnet_rtnetlink_neigh_foreach_vr_family(Ipcom_route *rtab, Ipnet_rtnetlink_neigh_family_t *param)
{
    Ip_u16             vr       = IPNET_ROUTE_GET_VR(rtab);
    Ipnet_route_entry  *rt      = IP_NULL;

    /* This traversal is already aborted */
    if (param->state.aborted)
        return;

    /* Only handle rtabs of selected address family */
    if (param->family != IP_AF_UNSPEC && IPNET_ROUTE_GET_FAMILY(rtab) != param->family)
        return;

    /* We only have neigh values in the default table */
    if (IPNET_ROUTE_GET_TABLE(rtab) != IPCOM_ROUTE_TABLE_DEFAULT)
        return;

    /* Check if specific VR shall be dumped */
    if (IP_BIT_ISFALSE(param->nlmsg->nlmsg_flags, IP_NLM_F_VR_UNSPEC) && (param->mem->vr != IPCOM_VR_ANY) && (param->mem->vr != vr))
        return;

    /*
     * If this is a trailer message buffer, make sure it
     * starts dumping where the last message ended
     */
    if (param->state.cont)
    {
        Ipnet_route_entry  *rtt = (Ipnet_route_entry*)(*param->state.rt);

        /* Verify current state */
        if (*param->state.vr != vr)
            return;

        if (rtt != IP_NULL)
        {
            rt = ipnet_route_first_entry(IPNET_ROUTE_GET_FAMILY(rtab),
                                         vr,
                                         IPNET_ROUTE_GET_TABLE(rtab));
            while (rt != IP_NULL)
            {
                if (rt == rtt)
                    break;
                rt = ipnet_route_next_entry(rt);
            }
        }
    }


    /* Reset the continue variable; we're on the move again */
    param->state.cont = 0;

    /* Get first unless we've found one to continue from */
    if (rt == IP_NULL)
        rt = ipnet_route_first_entry(IPNET_ROUTE_GET_FAMILY(rtab),
                                     vr,
                                     IPNET_ROUTE_GET_TABLE(rtab));

    /* */
    while (rt)
    {
        do
        {
            if (ipnet_rtnetlink_neigh_is(rt))
                break;
            rt = ipnet_route_next_entry(rt);
        } while (rt != IP_NULL);

        if (rt != IP_NULL)
        {
            int ret = 0;
            /* Verify this particular NC entry */
#ifdef IPCOM_USE_INET
            if (IPNET_ROUTE_GET_FAMILY(rtab) == IP_AF_INET)
                ret = ipnet_rtnetlink_ip4_neigh_fill_info(param->mem, rt, param->nlmsg->nlmsg_seq, IP_RTM_NEWNEIGH, IP_NLM_F_MULTI);
#endif
#ifdef IPCOM_USE_INET6
            if (IPNET_ROUTE_GET_FAMILY(rtab) == IP_AF_INET6)
                ret = ipnet_rtnetlink_ip6_neigh_fill_info(param->mem, rt, param->nlmsg->nlmsg_seq, IP_RTM_NEWNEIGH, IP_NLM_F_MULTI);
#endif
            if (ret < 0)
                goto aborted;

            /* Get next */
            rt = ipnet_route_next_entry(rt);
        }
    }

    return;

aborted:
    param->state.aborted = 1;
    *param->state.rt     = (Ip_ptrdiff_t)rt;
    *param->state.vr     = (Ip_ptrdiff_t)vr;
}