int scope6_get(struct ifnet *ifp, struct scope6_id *idlist) { struct scope6_id *sid; /* We only need to lock the interface's afdata for SID() to work. */ IF_AFDATA_RLOCK(ifp); sid = SID(ifp); if (sid == NULL) { /* paranoid? */ IF_AFDATA_RUNLOCK(ifp); return (EINVAL); } *idlist = *sid; IF_AFDATA_RUNLOCK(ifp); return (0); }
/* * Determine the appropriate scope zone ID for in6 and ifp. If ret_id is * non NULL, it is set to the zone ID. If the zone ID needs to be embedded * in the in6_addr structure, in6 will be modified. * * ret_id - unnecessary? */ int in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id) { int scope; u_int32_t zoneid = 0; struct scope6_id *sid; /* * special case: the loopback address can only belong to a loopback * interface. */ if (IN6_IS_ADDR_LOOPBACK(in6)) { if (!(ifp->if_flags & IFF_LOOPBACK)) return (EINVAL); } else { scope = in6_addrscope(in6); if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL || scope == IPV6_ADDR_SCOPE_LINKLOCAL) { /* * Currently we use interface indeces as the * zone IDs for interface-local and link-local * scopes. */ zoneid = ifp->if_index; in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */ } else if (scope != IPV6_ADDR_SCOPE_GLOBAL) { IF_AFDATA_RLOCK(ifp); sid = SID(ifp); zoneid = sid->s6id_list[scope]; IF_AFDATA_RUNLOCK(ifp); } } if (ret_id != NULL) *ret_id = zoneid; return (0); }
/* * Original (hw independent) Link layer output routine is wrapped by * mpls_output, if focussed Link layer interface remains in MPLS enabled * state. Original output routine is hooked by mpls_ifinfo{} and called * by mpls_output. * * Any by protocol layer above transmitted mbuf(9) containing Protocol * Data Uniit (pdu) must pass MPLS layer, if for transmission used interface * on link-layer remains in MPLS enabled state. * * I/O Path, IPv4: * * rip_input() +{ socket layer }+ rip_output() * / \ * / \ * +-->+ ip_input() +-->+ ip_forward() +-->+ ip_output() * / \ \ * / \ + * + +<------+ | * | \ v * + mpls_input() +--->+ mpls_forward() +------>+ mpls_output() * |\ /| * | \ +<-------+ | * | \ / | * | +<-----------+ if_simloop() +<-----------+ if_output() * | | * + if_input() | * A | * | V * */ int mpls_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { struct mpls_ifinfo *mii; struct mpls_ro mplsroute; struct mpls_ro *mro; struct sockaddr *gw; int error = 0; #ifdef MPLS_DEBUG struct shim_hdr *shim; #endif /* MPLS_DEBUG */ if ((ifp->if_flags & IFF_MPLS) == 0) { /* * Any pdu originates MPLS-layer are looped back into its * domain, if for transmission used interface cannot accept * by MPLS-layer processed pdu. * * See net/if_ethersubr.c and net/if_loop.c for further details. */ if (dst->sa_family == AF_MPLS) if_simloop(ifp, m, dst->sa_family, 0); else error = (*ifp->if_output)(ifp, m, dst, ro); goto out; } IF_AFDATA_RLOCK(ifp); mii = MPLS_IFINFO(ifp); IF_AFDATA_RUNLOCK(ifp); mro = &mplsroute; bzero(mro, sizeof(*mro)); if (ro == NULL) ro = (struct route *)mro; if (ro->ro_rt != NULL) { /* * If route exists, three cases are considered: * * (a) held route denotes fastpath. * (b) held route denotes ilm, * * or * * (c) held route originates not AF_MPLS domain. */ if (ro->ro_rt->rt_flags & RTF_MPE) { gw = ro->ro_rt->rt_gateway; if ((m = mpls_encap(m, gw, mro)) == NULL) { error = ECONNABORTED; goto done; } gw = (struct sockaddr *)&mro->mro_gw; } else gw = (struct sockaddr *)dst; } else gw = (struct sockaddr *)dst; if (m->m_flags & M_MPLS) { /* * Bypass tagging, if mbuf(9) was cached by MPLS_ARP. */ m->m_flags &= ~M_MPLS; } else if (mii->mii_nhlfe != NULL) { /* * Otherwise, mbuf(9) must pass mpls_encap, if * interface is bound by MPLS label binding on * per-interface MPLS label space. */ mro->mro_ifa = mii->mii_nhlfe; gw = mro->mro_ifa->ifa_dstaddr; /* * Per interface MPLS label space. */ if ((m = mpls_encap(m, gw, mro)) == NULL) { error = ECONNABORTED; goto done; } gw = (struct sockaddr *)&mro->mro_gw; } if (gw->sa_family == AF_MPLS) { /* * Defines iap for pfil(9) processing. */ if (PFIL_HOOKED(&V_inet_pfil_hook) #ifdef INET6 || PFIL_HOOKED(&V_inet6_pfil_hook) #endif ) { if (mpls_pfil(&m, ifp, PFIL_OUT) != 0) goto done; if (m == NULL) goto done; } #ifdef MPLS_DEBUG shim = mtod(m, struct shim_hdr *); (void)printf("%s: on %s label %d ttl %d bos %d\n", __func__, ifp->if_xname, MPLS_LABEL_GET(shim->shim_label), MPLS_TTL_GET(shim->shim_label), MPLS_BOS(shim->shim_label)); #endif /* MPLS_DEBUG */ m->m_flags &= ~(M_BCAST|M_MCAST); } error = (*mii->mii_output)(ifp, m, gw, ro); done: if (mro != NULL) mpls_rtfree(mro); out: return (error); }