--- embedaddon/quagga/zebra/rt_socket.c 2012/02/21 17:26:11 1.1.1.1 +++ embedaddon/quagga/zebra/rt_socket.c 2016/11/02 10:09:10 1.1.1.2 @@ -41,6 +41,7 @@ extern int rtm_write (int message, union sockunion *de union sockunion *mask, union sockunion *gate, 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 value. */ static int @@ -63,23 +64,25 @@ sin_masklen (struct in_addr mask) len--; return len; } +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Interface between zebra message and rtm message. */ 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 sin_dest, sin_mask, sin_gate; - struct nexthop *nexthop; + struct nexthop *nexthop, *tnexthop; + int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; - char prefix_buf[INET_ADDRSTRLEN]; + char prefix_buf[PREFIX_STRLEN]; 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)); sin_dest.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN @@ -96,8 +99,11 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* 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; char gate_buf[INET_ADDRSTRLEN] = "NULL"; @@ -112,38 +118,22 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib && 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 || - nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) - { - 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; + sin_gate.sin_addr = nexthop->gate.ipv4; + gate = 1; } - 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 || - nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) - { - sin_gate.sin_addr = nexthop->gate.ipv4; - 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; - } + struct in_addr loopback; + loopback.s_addr = htonl (INADDR_LOOPBACK); + sin_gate.sin_addr = loopback; + gate = 1; } if (gate && p->prefixlen == 32) @@ -170,9 +160,9 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib { if (!gate) { - zlog_debug ("%s: %s/%d: attention! gate not found for rib %p", - __func__, prefix_buf, p->prefixlen, rib); - rib_dump (__func__, (struct prefix_ipv4 *)p, rib); + zlog_debug ("%s: %s: attention! gate not found for rib %p", + __func__, prefix_buf, rib); + rib_dump (p, rib); } else inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); @@ -184,8 +174,8 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib case ZEBRA_ERR_NOERROR: nexthop_num++; if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: %s/%d: successfully did NH %s", - __func__, prefix_buf, p->prefixlen, gate_buf); + zlog_debug ("%s: %s: successfully did NH %s", + __func__, prefix_buf, gate_buf); if (cmd == RTM_ADD) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); break; @@ -207,11 +197,9 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib case ZEBRA_ERR_RTNOEXIST: case ZEBRA_ERR_RTUNREACH: default: - /* This point is reachable regardless of debugging mode. */ - if (!IS_ZEBRA_DEBUG_RIB) - inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); - zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s", - __func__, prefix_buf, p->prefixlen, error, lookup (rtm_type_str, cmd)); + zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s", + __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)), + error, lookup (rtm_type_str, cmd)); break; } } /* if (cmd and flags make sense) */ @@ -219,7 +207,7 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: odd command %s for flags %d", __func__, lookup (rtm_type_str, cmd), nexthop->flags); - } /* for (nexthop = ... */ + } /* for (ALL_NEXTHOPS_RO(...))*/ /* If there was no useful nexthop, then complain. */ if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) @@ -228,36 +216,9 @@ kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib 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 SIN6_LEN /* Calculate sin6_len value for netmask socket value. */ static int sin6_masklen (struct in6_addr mask) @@ -266,13 +227,8 @@ sin6_masklen (struct in6_addr mask) char *p, *lim; int len; -#if defined (INRIA) - if (IN_ANYADDR6 (mask)) - return sizeof (long); -#else /* ! INRIA */ if (IN6_IS_ADDR_UNSPECIFIED (&mask)) return sizeof (long); -#endif /* ! INRIA */ sin6.sin6_addr = mask; len = sizeof (struct sockaddr_in6); @@ -285,78 +241,18 @@ sin6_masklen (struct in6_addr mask) 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 */ - 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. */ 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) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; - struct nexthop *nexthop; + struct nexthop *nexthop, *tnexthop; + int recursing; int nexthop_num = 0; - unsigned int ifindex = 0; + ifindex_t ifindex = 0; int gate = 0; int error; @@ -376,8 +272,11 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* 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; if ((cmd == RTM_ADD @@ -388,36 +287,18 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, #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 - || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME - || 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; + sin_gate.sin6_addr = nexthop->gate.ipv6; + gate = 1; } - else - { - if (nexthop->type == NEXTHOP_TYPE_IPV6 - || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME - || nexthop->type == NEXTHOP_TYPE_IPV6_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 (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) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); @@ -459,9 +340,11 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, #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 + (void)error; #endif nexthop_num++; @@ -471,54 +354,44 @@ kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, 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; } return 0; /*XXX*/ } -int -kernel_add_ipv6 (struct prefix *p, struct rib *rib) -{ - int route; +#endif - 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; +static int +kernel_rtm (int cmd, struct prefix *p, struct rib *rib) +{ + switch (PREFIX_FAMILY(p)) + { + case AF_INET: + return kernel_rtm_ipv4 (cmd, p, rib); + case AF_INET6: + return kernel_rtm_ipv6 (cmd, p, rib); + } + return 0; } 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)) 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. */ -int -kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) -{ - int route; + if (new) + route |= kernel_rtm (RTM_ADD, p, new); - 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)) zlog (NULL, LOG_ERR, "Can't lower privileges"); return route; } -#endif /* HAVE_IPV6 */