/* 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) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; unsigned int ifindex = 0; int gate = 0; int error; 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 */ sin_dest.sin6_addr = p->u.prefix6; memset(&sin_mask, 0, sizeof(struct sockaddr_in6)); memset(&sin_gate, 0, sizeof(struct sockaddr_in6)); sin_gate.sin6_family = AF_INET6; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sin_gate.sin6_len = sizeof(struct sockaddr_in6); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Make gateway. */ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; gate = 0; if ((cmd == RTM_ADD && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) || (cmd == RTM_DELETE #if 0 && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) #endif )) { 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 (cmd == RTM_ADD) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); } /* 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(&sin_gate.sin6_addr)) SET_IN6_LINKLOCAL_IFINDEX(sin_gate.sin6_addr, ifindex); #endif /* KAME */ if (gate && p->prefixlen == 128) mask = NULL; else { masklen2ip6(p->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; } error = rtm_write(cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, ifindex, rib->flags, rib->metric); #if 0 if (error) { zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.", nexthop_num, error); } #endif nexthop_num++; } /* If there is no useful nexthop then return. */ if (nexthop_num == 0) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("kernel_rtm_ipv6_multipath(): No useful nexthop."); return 0; } return 0; /*XXX*/}