#include "zebra/rt_netlink.h"
#include "zebra/rib.h"
-int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; }
-int kernel_update_ipv4 (struct prefix *a, struct rib *b) { return 0; }
-int kernel_delete_ipv4 (struct prefix *a, struct rib *b) { return 0; }
-
-int kernel_add_ipv6 (struct prefix *a, struct rib *b) { return 0; }
-int kernel_update_ipv6 (struct prefix *a, struct rib *b) { return 0; }
-int kernel_delete_ipv6 (struct prefix *a, struct rib *b) { return 0; }
+int kernel_route_rib (struct prefix *a, struct rib *old, struct rib *new) { return 0; }
int kernel_address_add_ipv4 (struct interface *a, struct connected *b)
{
return;
#endif
- if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
+ if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) && ! (flags & RTF_UP))
return;
/* This is connected route. */
ifp = if_lookup_by_index (index);
- if (gate && message == RTM_ADD)
+ if (gate && (message == RTM_ADD || message == RTM_CHANGE))
msg.rtm.rtm_flags |= RTF_GATEWAY;
/* When RTF_CLONING is unavailable on BSD, should we set some
* other flag instead?
*/
#ifdef RTF_CLONING
- if (! gate && message == RTM_ADD && ifp &&
+ if (! gate && (message == RTM_ADD || message == RTM_CHANGE) && ifp &&
(ifp->flags & IFF_POINTOPOINT) == 0)
msg.rtm.rtm_flags |= RTF_CLONING;
#endif /* RTF_CLONING */
if (mask)
msg.rtm.rtm_addrs |= RTA_NETMASK;
- else if (message == RTM_ADD)
+ else if (message == RTM_ADD || message == RTM_CHANGE)
msg.rtm.rtm_flags |= RTF_HOST;
#ifdef __OpenBSD__
#include "zebra/zebra_ns.h"
#include "zebra/zebra_mpls.h"
-extern int kernel_add_ipv4 (struct prefix *, struct rib *);
-extern int kernel_update_ipv4 (struct prefix *, struct rib *);
-extern int kernel_delete_ipv4 (struct prefix *, struct rib *);
+extern int kernel_route_rib (struct prefix *, struct rib *, struct rib *);
extern int kernel_address_add_ipv4 (struct interface *, struct connected *);
extern int kernel_address_delete_ipv4 (struct interface *, struct connected *);
extern int kernel_neigh_update (int, int, uint32_t, char *, int);
-extern int kernel_add_ipv6 (struct prefix *, struct rib *);
-extern int kernel_update_ipv6 (struct prefix *, struct rib *);
-extern int kernel_delete_ipv6 (struct prefix *, struct rib *);
-
extern int kernel_add_lsp (zebra_lsp_t *);
extern int kernel_upd_lsp (zebra_lsp_t *);
extern int kernel_del_lsp (zebra_lsp_t *);
/* Update flag indicates whether this is a "replace" or not. */
static int
netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
- int family, int update)
+ int update)
{
int bytelen;
struct sockaddr_nl snl;
int recursing;
int nexthop_num;
int discard;
+ int family = PREFIX_FAMILY(p);
const char *routedesc;
int setsrc = 0;
union g_addr src;
}
int
-kernel_add_ipv4 (struct prefix *p, struct rib *rib)
+kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
{
- return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET, 0);
-}
-
-int
-kernel_update_ipv4 (struct prefix *p, struct rib *rib)
-{
- return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET, 1);
-}
-
-int
-kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
-{
- return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET, 0);
-}
-
-#ifdef HAVE_IPV6
-int
-kernel_add_ipv6 (struct prefix *p, struct rib *rib)
-{
- {
- return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6, 0);
- }
-}
+ if (!old && new)
+ return netlink_route_multipath (RTM_NEWROUTE, p, new, 0);
+ if (old && !new)
+ return netlink_route_multipath (RTM_DELROUTE, p, old, 0);
-int
-kernel_update_ipv6 (struct prefix *p, struct rib *rib)
-{
-#if defined (HAVE_V6_RR_SEMANTICS)
- return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6, 1);
-#else
- kernel_delete_ipv6 (p, rib);
- return kernel_add_ipv6 (p, rib);
-#endif
+ return netlink_route_multipath (RTM_NEWROUTE, p, new, 1);
}
-int
-kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
-{
- {
- return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6, 0);
- }
-}
-#endif /* HAVE_IPV6 */
-
int
kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
{
return 0; /*XXX*/
}
-int
-kernel_add_ipv4 (struct prefix *p, struct rib *rib)
-{
- int route;
-
- if (zserv_privs.change(ZPRIVS_RAISE))
- zlog (NULL, LOG_ERR, "Can't raise privileges");
- route = kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog (NULL, LOG_ERR, "Can't lower privileges");
-
- return route;
-}
-
-int
-kernel_update_ipv4 (struct prefix *p, struct rib *rib)
-{
- kernel_delete_ipv4 (p, rib);
- return kernel_add_ipv4 (p, rib);
-}
-
-int
-kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
-{
- int route;
-
- if (zserv_privs.change(ZPRIVS_RAISE))
- zlog (NULL, LOG_ERR, "Can't raise privileges");
- route = kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog (NULL, LOG_ERR, "Can't lower privileges");
-
- return route;
-}
-
-#ifdef HAVE_IPV6
-
#ifdef SIN6_LEN
/* Calculate sin6_len value for netmask socket value. */
static int
/* Interface between zebra message and rtm message. */
static int
-kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
- int family)
+kernel_rtm_ipv6 (int cmd, struct prefix *p, struct rib *rib, int family)
{
struct sockaddr_in6 *mask;
struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
#if 0
if (error)
{
- zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
+ zlog_info ("kernel_rtm_ipv6(): nexthop %d add error=%d.",
nexthop_num, error);
}
#else
if (nexthop_num == 0)
{
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug ("kernel_rtm_ipv6_multipath(): No useful nexthop.");
+ zlog_debug ("kernel_rtm_ipv6(): No useful nexthop.");
return 0;
}
}
int
-kernel_add_ipv6 (struct prefix *p, struct rib *rib)
+kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new)
{
- int route;
-
- if (zserv_privs.change(ZPRIVS_RAISE))
- zlog (NULL, LOG_ERR, "Can't raise privileges");
- route = kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog (NULL, LOG_ERR, "Can't lower privileges");
-
- return route;
-}
+ struct rib *rib;
+ int route = 0, cmd;
-int
-kernel_update_ipv6 (struct prefix *p, struct rib *rib)
-{
- kernel_delete_ipv6 (p, rib);
- return kernel_add_ipv6 (p, rib);
-}
+ if (!old && new)
+ cmd = RTM_ADD;
+ else if (old && !new)
+ cmd = RTM_DELETE;
+ else
+ cmd = RTM_CHANGE;
-int
-kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
-{
- int route;
+ rib = new ? new : old;
if (zserv_privs.change(ZPRIVS_RAISE))
zlog (NULL, LOG_ERR, "Can't raise privileges");
- route = kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
+
+ switch (PREFIX_FAMILY(p))
+ {
+ case AF_INET:
+ route = kernel_rtm_ipv4 (cmd, p, rib, AF_INET);
+ break;
+ case AF_INET6:
+ route = kernel_rtm_ipv6 (cmd, p, rib, AF_INET6);
+ break;
+ }
+
if (zserv_privs.change(ZPRIVS_LOWER))
zlog (NULL, LOG_ERR, "Can't lower privileges");
return route;
}
-#endif /* HAVE_IPV6 */
int
kernel_neigh_update (int add, int ifindex, uint32_t addr, char *lla, int llalen)
* the kernel.
*/
zfpm_trigger_update (rn, "installing in kernel");
- switch (PREFIX_FAMILY (&rn->p))
- {
- case AF_INET:
- if (update)
- ret = kernel_update_ipv4 (&rn->p, rib);
- else
- ret = kernel_add_ipv4 (&rn->p, rib);
- break;
- case AF_INET6:
- if (update)
- ret = kernel_update_ipv6 (&rn->p, rib);
- else
- ret = kernel_add_ipv6 (&rn->p, rib);
- break;
- }
+ ret = kernel_route_rib (&rn->p, update ? rib : NULL, rib);
/* If install succeeds, update FIB flag for nexthops. */
if (!ret)
* the kernel.
*/
zfpm_trigger_update (rn, "uninstalling from kernel");
-
- switch (PREFIX_FAMILY (&rn->p))
- {
- case AF_INET:
- ret = kernel_delete_ipv4 (&rn->p, rib);
- break;
- case AF_INET6:
- ret = kernel_delete_ipv6 (&rn->p, rib);
- break;
- }
+ ret = kernel_route_rib (&rn->p, rib, NULL);
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);