version 1.1.1.1, 2012/02/21 17:26:11
|
version 1.1.1.2, 2016/11/02 10:09:10
|
Line 41 extern int rtm_write (int message, union sockunion *de
|
Line 41 extern int rtm_write (int message, union sockunion *de
|
union sockunion *mask, union sockunion *gate, |
union sockunion *mask, union sockunion *gate, |
unsigned int index, int zebra_flags, int metric); |
unsigned int index, int zebra_flags, int metric); |
|
|
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
/* Adjust netmask socket length. Return value is a adjusted sin_len |
/* Adjust netmask socket length. Return value is a adjusted sin_len |
value. */ |
value. */ |
static int |
static int |
Line 63 sin_masklen (struct in_addr mask)
|
Line 64 sin_masklen (struct in_addr mask)
|
len--; |
len--; |
return len; |
return len; |
} |
} |
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
|
|
/* Interface between zebra message and rtm message. */ |
/* Interface between zebra message and rtm message. */ |
static int |
static int |
kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family) | kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib) |
|
|
{ |
{ |
struct sockaddr_in *mask = NULL; |
struct sockaddr_in *mask = NULL; |
struct sockaddr_in sin_dest, sin_mask, sin_gate; |
struct sockaddr_in sin_dest, sin_mask, sin_gate; |
struct nexthop *nexthop; | struct nexthop *nexthop, *tnexthop; |
| int recursing; |
int nexthop_num = 0; |
int nexthop_num = 0; |
unsigned int ifindex = 0; | ifindex_t ifindex = 0; |
int gate = 0; |
int gate = 0; |
int error; |
int error; |
char prefix_buf[INET_ADDRSTRLEN]; | char prefix_buf[PREFIX_STRLEN]; |
|
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); | prefix2str (p, prefix_buf, sizeof(prefix_buf)); |
memset (&sin_dest, 0, sizeof (struct sockaddr_in)); |
memset (&sin_dest, 0, sizeof (struct sockaddr_in)); |
sin_dest.sin_family = AF_INET; |
sin_dest.sin_family = AF_INET; |
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
Line 96 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 99 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
|
|
/* Make gateway. */ |
/* Make gateway. */ |
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) | for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) |
{ |
{ |
|
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) |
|
continue; |
|
|
gate = 0; |
gate = 0; |
char gate_buf[INET_ADDRSTRLEN] = "NULL"; |
char gate_buf[INET_ADDRSTRLEN] = "NULL"; |
|
|
Line 112 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 118 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) |
)) |
)) |
{ |
{ |
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) | if (nexthop->type == NEXTHOP_TYPE_IPV4 || |
| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) |
{ |
{ |
if (nexthop->rtype == NEXTHOP_TYPE_IPV4 || | sin_gate.sin_addr = nexthop->gate.ipv4; |
nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) | gate = 1; |
{ | |
sin_gate.sin_addr = nexthop->rgate.ipv4; | |
gate = 1; | |
} | |
if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX | |
|| nexthop->rtype == NEXTHOP_TYPE_IFNAME | |
|| nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) | |
ifindex = nexthop->rifindex; | |
} |
} |
else | if (nexthop->type == NEXTHOP_TYPE_IFINDEX |
| || nexthop->type == NEXTHOP_TYPE_IFNAME |
| || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) |
| ifindex = nexthop->ifindex; |
| if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) |
{ |
{ |
if (nexthop->type == NEXTHOP_TYPE_IPV4 || | struct in_addr loopback; |
nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) | loopback.s_addr = htonl (INADDR_LOOPBACK); |
{ | sin_gate.sin_addr = loopback; |
sin_gate.sin_addr = nexthop->gate.ipv4; | gate = 1; |
gate = 1; | |
} | |
if (nexthop->type == NEXTHOP_TYPE_IFINDEX | |
|| nexthop->type == NEXTHOP_TYPE_IFNAME | |
|| nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) | |
ifindex = nexthop->ifindex; | |
if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) | |
{ | |
struct in_addr loopback; | |
loopback.s_addr = htonl (INADDR_LOOPBACK); | |
sin_gate.sin_addr = loopback; | |
gate = 1; | |
} | |
} |
} |
|
|
if (gate && p->prefixlen == 32) |
if (gate && p->prefixlen == 32) |
Line 170 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 160 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
{ |
{ |
if (!gate) |
if (!gate) |
{ |
{ |
zlog_debug ("%s: %s/%d: attention! gate not found for rib %p", | zlog_debug ("%s: %s: attention! gate not found for rib %p", |
__func__, prefix_buf, p->prefixlen, rib); | __func__, prefix_buf, rib); |
rib_dump (__func__, (struct prefix_ipv4 *)p, rib); | rib_dump (p, rib); |
} |
} |
else |
else |
inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); |
inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); |
Line 184 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 174 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
case ZEBRA_ERR_NOERROR: |
case ZEBRA_ERR_NOERROR: |
nexthop_num++; |
nexthop_num++; |
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: %s/%d: successfully did NH %s", | zlog_debug ("%s: %s: successfully did NH %s", |
__func__, prefix_buf, p->prefixlen, gate_buf); | __func__, prefix_buf, gate_buf); |
if (cmd == RTM_ADD) |
if (cmd == RTM_ADD) |
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); |
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); |
break; |
break; |
Line 207 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 197 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
case ZEBRA_ERR_RTNOEXIST: |
case ZEBRA_ERR_RTNOEXIST: |
case ZEBRA_ERR_RTUNREACH: |
case ZEBRA_ERR_RTUNREACH: |
default: |
default: |
/* This point is reachable regardless of debugging mode. */ | zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s", |
if (!IS_ZEBRA_DEBUG_RIB) | __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)), |
inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); | error, lookup (rtm_type_str, cmd)); |
zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s", | |
__func__, prefix_buf, p->prefixlen, error, lookup (rtm_type_str, cmd)); | |
break; |
break; |
} |
} |
} /* if (cmd and flags make sense) */ |
} /* if (cmd and flags make sense) */ |
Line 219 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 207 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
if (IS_ZEBRA_DEBUG_RIB) |
if (IS_ZEBRA_DEBUG_RIB) |
zlog_debug ("%s: odd command %s for flags %d", |
zlog_debug ("%s: odd command %s for flags %d", |
__func__, lookup (rtm_type_str, cmd), nexthop->flags); |
__func__, lookup (rtm_type_str, cmd), nexthop->flags); |
} /* for (nexthop = ... */ | } /* for (ALL_NEXTHOPS_RO(...))*/ |
|
|
/* If there was no useful nexthop, then complain. */ |
/* If there was no useful nexthop, then complain. */ |
if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) |
if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) |
Line 228 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
Line 216 kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib
|
return 0; /*XXX*/ |
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_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 HAVE_IPV6 |
|
|
|
#ifdef SIN6_LEN |
/* Calculate sin6_len value for netmask socket value. */ |
/* Calculate sin6_len value for netmask socket value. */ |
static int |
static int |
sin6_masklen (struct in6_addr mask) |
sin6_masklen (struct in6_addr mask) |
Line 266 sin6_masklen (struct in6_addr mask)
|
Line 227 sin6_masklen (struct in6_addr mask)
|
char *p, *lim; |
char *p, *lim; |
int len; |
int len; |
|
|
#if defined (INRIA) |
|
if (IN_ANYADDR6 (mask)) |
|
return sizeof (long); |
|
#else /* ! INRIA */ |
|
if (IN6_IS_ADDR_UNSPECIFIED (&mask)) |
if (IN6_IS_ADDR_UNSPECIFIED (&mask)) |
return sizeof (long); |
return sizeof (long); |
#endif /* ! INRIA */ |
|
|
|
sin6.sin6_addr = mask; |
sin6.sin6_addr = mask; |
len = sizeof (struct sockaddr_in6); |
len = sizeof (struct sockaddr_in6); |
Line 285 sin6_masklen (struct in6_addr mask)
|
Line 241 sin6_masklen (struct in6_addr mask)
|
|
|
return len; |
return len; |
} |
} |
|
|
/* Interface between zebra message and rtm message. */ |
|
static int |
|
kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest, |
|
struct in6_addr *gate, int index, int flags) |
|
{ |
|
struct sockaddr_in6 *mask; |
|
struct sockaddr_in6 sin_dest, sin_mask, sin_gate; |
|
|
|
memset (&sin_dest, 0, sizeof (struct sockaddr_in6)); |
|
sin_dest.sin6_family = AF_INET6; |
|
#ifdef SIN6_LEN |
|
sin_dest.sin6_len = sizeof (struct sockaddr_in6); |
|
#endif /* SIN6_LEN */ |
#endif /* SIN6_LEN */ |
|
|
memset (&sin_mask, 0, sizeof (struct sockaddr_in6)); |
|
|
|
memset (&sin_gate, 0, sizeof (struct sockaddr_in6)); |
|
sin_gate.sin6_family = AF_INET6; |
|
#ifdef SIN6_LEN |
|
sin_gate.sin6_len = sizeof (struct sockaddr_in6); |
|
#endif /* SIN6_LEN */ |
|
|
|
sin_dest.sin6_addr = dest->prefix; |
|
|
|
if (gate) |
|
memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr)); |
|
|
|
/* Under kame set interface index to link local address. */ |
|
#ifdef KAME |
|
|
|
#define SET_IN6_LINKLOCAL_IFINDEX(a, i) \ |
|
do { \ |
|
(a).s6_addr[2] = ((i) >> 8) & 0xff; \ |
|
(a).s6_addr[3] = (i) & 0xff; \ |
|
} while (0) |
|
|
|
if (gate && IN6_IS_ADDR_LINKLOCAL(gate)) |
|
SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index); |
|
#endif /* KAME */ |
|
|
|
if (gate && dest->prefixlen == 128) |
|
mask = NULL; |
|
else |
|
{ |
|
masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr); |
|
sin_mask.sin6_family = AF_INET6; |
|
#ifdef SIN6_LEN |
|
sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr); |
|
#endif /* SIN6_LEN */ |
|
mask = &sin_mask; |
|
} |
|
|
|
return rtm_write (message, |
|
(union sockunion *) &sin_dest, |
|
(union sockunion *) mask, |
|
gate ? (union sockunion *)&sin_gate : NULL, |
|
index, |
|
flags, |
|
0); |
|
} |
|
|
|
/* Interface between zebra message and rtm message. */ |
/* Interface between zebra message and rtm message. */ |
static int |
static int |
kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib, | kernel_rtm_ipv6 (int cmd, struct prefix *p, struct rib *rib) |
int family) | |
{ |
{ |
struct sockaddr_in6 *mask; |
struct sockaddr_in6 *mask; |
struct sockaddr_in6 sin_dest, sin_mask, sin_gate; |
struct sockaddr_in6 sin_dest, sin_mask, sin_gate; |
struct nexthop *nexthop; | struct nexthop *nexthop, *tnexthop; |
| int recursing; |
int nexthop_num = 0; |
int nexthop_num = 0; |
unsigned int ifindex = 0; | ifindex_t ifindex = 0; |
int gate = 0; |
int gate = 0; |
int error; |
int error; |
|
|
Line 376 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
Line 272 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
|
|
/* Make gateway. */ |
/* Make gateway. */ |
for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) | for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) |
{ |
{ |
|
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) |
|
continue; |
|
|
gate = 0; |
gate = 0; |
|
|
if ((cmd == RTM_ADD |
if ((cmd == RTM_ADD |
Line 388 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
Line 287 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
#endif |
#endif |
)) |
)) |
{ |
{ |
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) | if (nexthop->type == NEXTHOP_TYPE_IPV6 |
| || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME |
| || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) |
{ |
{ |
if (nexthop->rtype == NEXTHOP_TYPE_IPV6 | sin_gate.sin6_addr = nexthop->gate.ipv6; |
|| nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME | gate = 1; |
|| nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX) | |
{ | |
sin_gate.sin6_addr = nexthop->rgate.ipv6; | |
gate = 1; | |
} | |
if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX | |
|| nexthop->rtype == NEXTHOP_TYPE_IFNAME | |
|| nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME | |
|| nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX) | |
ifindex = nexthop->rifindex; | |
} |
} |
else | if (nexthop->type == NEXTHOP_TYPE_IFINDEX |
{ | || nexthop->type == NEXTHOP_TYPE_IFNAME |
if (nexthop->type == NEXTHOP_TYPE_IPV6 | || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME |
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME | || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) |
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) | ifindex = nexthop->ifindex; |
{ | |
sin_gate.sin6_addr = nexthop->gate.ipv6; | |
gate = 1; | |
} | |
if (nexthop->type == NEXTHOP_TYPE_IFINDEX | |
|| nexthop->type == NEXTHOP_TYPE_IFNAME | |
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME | |
|| nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) | |
ifindex = nexthop->ifindex; | |
} | |
|
|
if (cmd == RTM_ADD) |
if (cmd == RTM_ADD) |
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); |
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); |
Line 459 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
Line 340 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
#if 0 |
#if 0 |
if (error) |
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); |
nexthop_num, error); |
} |
} |
|
#else |
|
(void)error; |
#endif |
#endif |
|
|
nexthop_num++; |
nexthop_num++; |
Line 471 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
Line 354 kernel_rtm_ipv6_multipath (int cmd, struct prefix *p,
|
if (nexthop_num == 0) |
if (nexthop_num == 0) |
{ |
{ |
if (IS_ZEBRA_DEBUG_KERNEL) |
if (IS_ZEBRA_DEBUG_KERNEL) |
zlog_debug ("kernel_rtm_ipv6_multipath(): No useful nexthop."); | zlog_debug ("kernel_rtm_ipv6(): No useful nexthop."); |
return 0; |
return 0; |
} |
} |
|
|
return 0; /*XXX*/ |
return 0; /*XXX*/ |
} |
} |
|
|
int | #endif |
kernel_add_ipv6 (struct prefix *p, struct rib *rib) | |
{ | |
int route; | |
|
|
if (zserv_privs.change(ZPRIVS_RAISE)) | static int |
zlog (NULL, LOG_ERR, "Can't raise privileges"); | kernel_rtm (int cmd, struct prefix *p, struct rib *rib) |
route = kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6); | { |
if (zserv_privs.change(ZPRIVS_LOWER)) | switch (PREFIX_FAMILY(p)) |
zlog (NULL, LOG_ERR, "Can't lower privileges"); | { |
| case AF_INET: |
return route; | return kernel_rtm_ipv4 (cmd, p, rib); |
| case AF_INET6: |
| return kernel_rtm_ipv6 (cmd, p, rib); |
| } |
| return 0; |
} |
} |
|
|
int |
int |
kernel_delete_ipv6 (struct prefix *p, struct rib *rib) | kernel_route_rib (struct prefix *p, struct rib *old, struct rib *new) |
{ |
{ |
int route; | int route = 0; |
|
|
if (zserv_privs.change(ZPRIVS_RAISE)) |
if (zserv_privs.change(ZPRIVS_RAISE)) |
zlog (NULL, LOG_ERR, "Can't raise privileges"); |
zlog (NULL, LOG_ERR, "Can't raise privileges"); |
route = kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6); |
|
if (zserv_privs.change(ZPRIVS_LOWER)) |
|
zlog (NULL, LOG_ERR, "Can't lower privileges"); |
|
|
|
return route; | if (old) |
} | route |= kernel_rtm (RTM_DELETE, p, old); |
|
|
/* Delete IPv6 route from the kernel. */ | if (new) |
int | route |= kernel_rtm (RTM_ADD, p, new); |
kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, | |
unsigned int index, int flags, int table) | |
{ | |
int route; | |
|
|
if (zserv_privs.change(ZPRIVS_RAISE)) |
|
zlog (NULL, LOG_ERR, "Can't raise privileges"); |
|
route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags); |
|
if (zserv_privs.change(ZPRIVS_LOWER)) |
if (zserv_privs.change(ZPRIVS_LOWER)) |
zlog (NULL, LOG_ERR, "Can't lower privileges"); |
zlog (NULL, LOG_ERR, "Can't lower privileges"); |
|
|
return route; |
return route; |
} |
} |
#endif /* HAVE_IPV6 */ |
|