/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; ifc->flags = flags; /* If we get a notification from the kernel, * we can safely assume the address is known to the kernel */ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or peer address. */ if (broad) { if (IN6_IS_ADDR_UNSPECIFIED(broad)) zlog_warn("warning: %s called for interface %s with unspecified " "destination address; ignoring!", __func__, ifp->name); else { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); p->prefixlen = prefixlen; ifc->destination = (struct prefix *) p; } } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); /* On Linux, we only get here when DAD is complete, therefore we can set * ZEBRA_IFC_REAL. * * On BSD, there currently doesn't seem to be a way to check for completion of * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD * might still be running. */ SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); connected_update(ifp, ifc); }
/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; ifc->flags = flags; /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or peer address. */ if (broad) { if (IN6_IS_ADDR_UNSPECIFIED(broad)) zlog_warn("warning: %s called for interface %s with unspecified " "destination address; ignoring!", __func__, ifp->name); else { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); p->prefixlen = prefixlen; ifc->destination = (struct prefix *) p; } } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) return; connected_announce (ifp, ifc); }
/* Utility function of convert between struct prefix <=> union sockunion. */ struct prefix * sockunion2hostprefix (const union sockunion *su) { if (su->sa.sa_family == AF_INET) { struct prefix_ipv4 *p; p = prefix_ipv4_new (); p->family = AF_INET; p->prefix = su->sin.sin_addr; p->prefixlen = IPV4_MAX_BITLEN; return (struct prefix *) p; } #ifdef HAVE_IPV6 if (su->sa.sa_family == AF_INET6) { struct prefix_ipv6 *p; p = prefix_ipv6_new (); p->family = AF_INET6; p->prefixlen = IPV6_MAX_BITLEN; memcpy (&p->prefix, &su->sin6.sin6_addr, sizeof (struct in6_addr)); return (struct prefix *) p; } #endif /* HAVE_IPV6 */ return NULL; }
/* Utility function of convert between struct prefix <=> union sockunion. * FIXME This function isn't used anywhere. */ struct prefix * sockunion2prefix (const union sockunion *dest, const union sockunion *mask) { if (dest->sa.sa_family == AF_INET) { struct prefix_ipv4 *p; p = prefix_ipv4_new (); p->family = AF_INET; p->prefix = dest->sin.sin_addr; p->prefixlen = ip_masklen (mask->sin.sin_addr); return (struct prefix *) p; } #ifdef HAVE_IPV6 if (dest->sa.sa_family == AF_INET6) { struct prefix_ipv6 *p; p = prefix_ipv6_new (); p->family = AF_INET6; p->prefixlen = ip6_masklen (mask->sin6.sin6_addr); memcpy (&p->prefix, &dest->sin6.sin6_addr, sizeof (struct in6_addr)); return (struct prefix *) p; } #endif /* HAVE_IPV6 */ return NULL; }
/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or pointopoint address. */ if (broad) { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); ifc->destination = (struct prefix *) p; } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) return; connected_announce (ifp, ifc); }