Lines Matching +full:coexist +full:- +full:support

1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
34 /*-
164 ((eh)->ip6e_len + 1) << 3); \
167 (_ol) += (*(mp))->m_len; \
187 (m)->m_next = (mp)->m_next;\
188 (mp)->m_next = (m);\
199 if (m->m_pkthdr.csum_flags & CSUM_UDP_IPV6 && csum == 0)
201 offset += m->m_pkthdr.csum_data; /* checksum offset */
203 if (offset + sizeof(csum) > m->m_len)
219 in6_delayed_cksum(m, plen - optlen,
221 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
226 m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
240 int tlen = m0->m_pkthdr.len;
246 mnext = &m->m_nextpkt;
269 mnext = &m->m_nextpkt;
270 m->m_data += max_linkhdr;
273 m->m_len = sizeof(*mhip6);
279 ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7));
281 fraglen = tlen - off;
283 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
284 mhip6->ip6_plen = htons((u_short)(fraglen + hlen +
285 sizeof(*ip6f) - sizeof(struct ip6_hdr)));
291 m->m_pkthdr.len = fraglen + hlen + sizeof(*ip6f);
292 ip6f->ip6f_reserved = 0;
293 ip6f->ip6f_ident = id;
294 ip6f->ip6f_nxt = nextproto;
313 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0);
323 if (m->m_next != NULL && mbuf_has_tls_session(m->m_next)) {
324 tls = ktls_hold(m->m_next->m_epg_tls);
325 mst = tls->snd_tag;
345 if ((inp->inp_flags2 & INP_RATE_LIMIT_CHANGED) != 0 ||
346 (inp->inp_snd_tag != NULL &&
347 inp->inp_snd_tag->ifp != ifp))
350 if (inp->inp_snd_tag != NULL)
351 mst = inp->inp_snd_tag;
355 KASSERT(m->m_pkthdr.rcvif == NULL,
357 if (mst->ifp != ifp) {
364 m->m_pkthdr.snd_tag = m_snd_tag_ref(mst);
365 m->m_pkthdr.csum_flags |= CSUM_SND_TAG;
394 * skipped and ro->ro_nh would be used. If ro is present but ro->ro_nh is NULL,
395 * then result of route lookup is stored in ro->ro_nh.
400 * ifpp - XXX: just for statistics
418 int vlan_pcp = -1;
438 M_SETFIB(m, inp->inp_inc.inc_fibnum);
441 m->m_pkthdr.flowid = inp->inp_flowid;
442 M_HASHTYPE_SET(m, inp->inp_flowtype);
444 if ((inp->inp_flags2 & INP_2PCP_SET) != 0)
445 vlan_pcp = (inp->inp_flags2 & INP_2PCP_MASK) >>
448 m->m_pkthdr.numa_domain = inp->inp_numa_domain;
454 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
460 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
475 optvalid = opt->ip6po_valid;
477 /* Hop-by-Hop options header. */
479 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh, optlen);
487 * currently support RH2/3/4.
490 * The moment we do support any routing header (again)
504 * way to make the advanced API coexist with MIP6
509 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1,
514 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr, optlen);
525 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2, optlen);
544 m->m_pkthdr.len += optlen;
545 plen = m->m_pkthdr.len - sizeof(*ip6);
560 ip6->ip6_plen = 0;
562 ip6->ip6_plen = htons(plen);
563 nexthdrp = &ip6->ip6_nxt;
592 exthdrs.ip6e_dest2->m_next = m->m_next;
593 m->m_next = exthdrs.ip6e_dest2;
594 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
595 ip6->ip6_nxt = IPPROTO_DSTOPTS;
615 ro = &opt->ip6po_route;
617 dst = (struct sockaddr_in6 *)&ro->ro_dst;
620 fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
625 * Do not override if a non-zero value is already set.
636 ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
641 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
642 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
644 ip6->ip6_hlim = im6o->im6o_multicast_hlim;
646 ip6->ip6_hlim = V_ip6_defmcasthlim;
649 if (ro == NULL || ro->ro_nh == NULL) {
651 dst->sin6_family = AF_INET6;
652 dst->sin6_len = sizeof(*dst);
653 dst->sin6_addr = ip6->ip6_dst;
663 if (ro->ro_nh != NULL && inp != NULL) {
664 ro->ro_dst.sin6_family = AF_INET6; /* XXX KASSERT? */
665 NH_VALIDATE((struct route *)ro, &inp->inp_rt_cookie,
668 if (ro->ro_nh != NULL && fwd_tag == NULL &&
669 (!NH_IS_VALID(ro->ro_nh) ||
670 ro->ro_dst.sin6_family != AF_INET6 ||
671 !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)))
674 if (ro->ro_nh != NULL && fwd_tag == NULL &&
675 ro->ro_dst.sin6_family == AF_INET6 &&
676 IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
678 nh = ro->ro_nh;
680 if (ro->ro_lle)
681 LLE_FREE(ro->ro_lle); /* zeros ro_lle */
682 ro->ro_lle = NULL;
687 dst_sa.sin6_addr = ip6->ip6_dst;
690 &nh, fibnum, m->m_pkthdr.flowid);
699 * Can be the case when dst is multicast, link-local or
710 mtu = ifp->if_mtu;
712 ifp = nh->nh_ifp;
713 origifp = nh->nh_aifp;
714 ia = (struct in6_ifaddr *)(nh->nh_ifa);
715 counter_u64_add(nh->nh_pksent, 1);
726 dst_sa.sin6_addr = ip6->ip6_dst;
731 (ifp = im6o->im6o_multicast_ifp) != NULL) {
755 m->m_pkthdr.flowid);
763 ifp = nh->nh_ifp;
764 origifp = nh->nh_aifp;
765 ia = ifatoia6(nh->nh_ifa);
766 if (nh->nh_flags & NHF_GATEWAY)
767 dst->sin6_addr = nh->gw6_sa.sin6_addr;
769 dst->sin6_addr = dst_sa.sin6_addr;
779 * fe80::1%em0 -> fe80::2%em0 -> ifp=em0, origifp=em0
780 * fe80::1%em0 -> fe80::1%em0 -> ifp=lo0, origifp=em0
781 * ::1 -> ::1 -> ifp=lo0, origifp=lo0
791 * FAST IPSEC: We re-injected the packet.
796 ifp->if_mtu : mtu)) != 0) {
810 src0 = ip6->ip6_src;
814 src_sa.sin6_addr = ip6->ip6_src;
816 dst0 = ip6->ip6_dst;
817 /* Re-initialize to be sure. */
821 dst_sa.sin6_addr = ip6->ip6_dst;
833 } else if ((origifp->if_flags & IFF_LOOPBACK) == 0 ||
857 if (nh && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
864 dst = (struct sockaddr_in6 *)opt->ip6po_nexthop;
866 else if ((nh->nh_flags & NHF_GATEWAY))
867 dst = &nh->gw6_sa;
870 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
871 m->m_flags &= ~(M_BCAST | M_MCAST); /* Just in case. */
873 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
877 if (!(ifp->if_flags & IFF_MULTICAST)) {
884 (im6o && im6o->im6o_multicast_loop)) {
912 m->m_pkthdr.rcvif = NULL;
923 * are not sent -- the above call to ip6_mloopback() will
927 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) ||
928 IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
936 * to increment per-interface statistics.
942 if ((error = ip6_getpmtu(ro_pmtu, ro != ro_pmtu, ifp, &ip6->ip6_dst,
964 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
966 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
968 opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
977 in6_clearscope(&ip6->ip6_src);
978 in6_clearscope(&ip6->ip6_dst);
981 * If the outgoing packet contains a hop-by-hop options header,
991 if ((hbh->ip6h_len + 1) << 3 > exthdrs.ip6e_hbh->m_len)
997 * the IPv6 and the hop-by-hop options header are
1000 m->m_flags |= M_LOOP;
1001 m->m_pkthdr.rcvif = ifp;
1003 ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
1009 m->m_flags &= ~M_LOOP; /* XXX */
1010 m->m_pkthdr.rcvif = NULL;
1017 odst = ip6->ip6_dst;
1032 if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
1033 m->m_flags |= M_SKIP_FIREWALL;
1035 if (in6_localip(&ip6->ip6_dst)) {
1036 m->m_flags |= M_FASTFWD_OURS;
1037 if (m->m_pkthdr.rcvif == NULL)
1038 m->m_pkthdr.rcvif = V_loif;
1039 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
1040 m->m_pkthdr.csum_flags |=
1042 m->m_pkthdr.csum_data = 0xffff;
1045 if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
1046 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
1058 m->m_flags |= M_SKIP_FIREWALL;
1068 if (m->m_flags & M_FASTFWD_OURS) {
1069 if (m->m_pkthdr.rcvif == NULL)
1070 m->m_pkthdr.rcvif = V_loif;
1071 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
1072 m->m_pkthdr.csum_flags |=
1074 m->m_pkthdr.csum_data = 0xffff;
1077 if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6)
1078 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
1084 if ((m->m_flags & M_IP6_NEXTHOP) &&
1087 dst = (struct sockaddr_in6 *)&ro->ro_dst;
1091 m->m_flags |= M_SKIP_FIREWALL;
1092 m->m_flags &= ~M_IP6_NEXTHOP;
1098 if (vlan_pcp > -1)
1102 if ((ifp->if_capenable & IFCAP_MEXTPG) == 0) {
1126 * 1-a: send as is if tlen <= path mtu
1127 * 1-b: fragment if tlen > path mtu
1130 * 2-a: send as is if tlen <= interface mtu
1131 * 2-b: error if tlen > interface mtu
1139 sw_csum = m->m_pkthdr.csum_flags;
1141 tso = ((sw_csum & ifp->if_hwassist &
1143 sw_csum &= ~ifp->if_hwassist;
1149 * XXX-BZ Need a framework to know when the NIC can handle it, even
1153 /* XXX-BZ m->m_pkthdr.csum_flags &= ~ifp->if_hwassist; */
1154 tlen = m->m_pkthdr.len;
1156 if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso)
1161 /* Conflicting request - can't transmit. */
1165 if (dontfrag && tlen > IN6_LINKMTU(ifp) && !tso) { /* Case 2-b. */
1181 if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* Cases 1-a and 2-a. */
1185 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
1188 counter_u64_add(ia6->ia_ifa.ifa_opackets, 1);
1189 counter_u64_add(ia6->ia_ifa.ifa_obytes,
1190 m->m_pkthdr.len);
1197 /* Try to fragment the packet. Cases 1-b and 3. */
1203 } else if (ip6->ip6_plen == 0) {
1219 len = (mtu - unfragpartlen - sizeof(struct ip6_frag)) & ~7;
1229 * XXX-BZ handle the hw offloading case. Need flags.
1231 ip6_output_delayed_csum(m, ifp, m->m_pkthdr.csum_flags, plen,
1249 nextproto = ip6->ip6_nxt;
1250 ip6->ip6_nxt = IPPROTO_FRAGMENT;
1269 m = m0->m_nextpkt;
1270 m0->m_nextpkt = 0;
1273 m0 = m->m_nextpkt;
1274 m->m_nextpkt = 0;
1278 counter_u64_add(ia->ia_ifa.ifa_opackets, 1);
1279 counter_u64_add(ia->ia_ifa.ifa_obytes,
1280 m->m_pkthdr.len);
1282 if (vlan_pcp > -1)
1322 m->m_len = hlen;
1343 * If there is no hop-by-hop options header, allocate new one.
1348 if (exthdrs->ip6e_hbh == NULL) {
1352 mopt->m_len = JUMBOOPTLEN;
1354 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
1355 exthdrs->ip6e_hbh = mopt;
1359 mopt = exthdrs->ip6e_hbh;
1363 * - exthdrs->ip6e_hbh is not referenced from places
1365 * - exthdrs->ip6e_hbh is not an mbuf chain.
1367 int oldoptlen = mopt->m_len;
1384 n->m_len = oldoptlen + JUMBOOPTLEN;
1389 mopt = exthdrs->ip6e_hbh = n;
1391 optbuf = mtod(mopt, u_char *) + mopt->m_len;
1392 mopt->m_len += JUMBOOPTLEN;
1402 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
1412 exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
1429 hlen - sizeof(struct ip6_hdr), M_NOWAIT);
1432 m->m_next = n;
1437 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1444 mlast->m_len);
1445 mlast->m_len += sizeof(struct ip6_frag);
1446 m->m_pkthdr.len += sizeof(struct ip6_frag);
1454 mfrg->m_len = sizeof(struct ip6_frag);
1456 mlast->m_next = mfrg;
1482 error = ip6_calcmtu(nh->nh_ifp, dst, nh->nh_mtu, mtup, NULL, 0);
1497 * Stores mtu and always-frag value into @mtup and @alwaysfragp.
1521 sa6_dst = (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
1522 if (!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))
1523 ro_pmtu->ro_mtu = 0;
1527 if (ro_pmtu == NULL || ro_pmtu->ro_mtu == 0) {
1529 sa6_dst->sin6_family = AF_INET6;
1530 sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
1531 sa6_dst->sin6_addr = *dst;
1536 mtu = nh->nh_mtu;
1538 ro_pmtu->ro_mtu = mtu;
1541 mtu = ro_pmtu->ro_mtu;
1544 if (ro_pmtu != NULL && ro_pmtu->ro_nh != NULL)
1545 mtu = ro_pmtu->ro_nh->nh_mtu;
1553 * Stores mtu and always-frag value into @mtup and @alwaysfragp.
1635 level = sopt->sopt_level;
1636 op = sopt->sopt_dir;
1637 optname = sopt->sopt_name;
1638 optlen = sopt->sopt_valsize;
1639 td = sopt->sopt_td;
1642 uproto = (int)so->so_proto->pr_protocol;
1647 if (sopt->sopt_level == SOL_SOCKET &&
1648 sopt->sopt_dir == SOPT_SET) {
1649 switch (sopt->sopt_name) {
1652 inp->inp_inc.inc_fibnum = so->so_fibnum;
1659 inp->inp_flags2 |= INP_RATE_LIMIT_CHANGED;
1694 error = ip6_pcbopts(&inp->in6p_outputopts, m,
1702 * Use of some Hop-by-Hop options or some
1710 * KAME prevents non-privileged users from sending or
1758 if (optval < -1 || optval >= 256)
1761 /* -1 = kernel default */
1762 inp->in6p_hops = optval;
1763 if ((inp->inp_vflag &
1765 inp->inp_ip_ttl = optval;
1772 inp->inp_flags |= (bit); \
1774 inp->inp_flags &= ~(bit); \
1780 inp->inp_flags |= IN6P_RFC2292; \
1782 inp->inp_flags |= (bit); \
1784 inp->inp_flags &= ~(bit); \
1787 #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0)
1791 inp->inp_flags2 |= bit; \
1793 inp->inp_flags2 &= ~bit; \
1800 #define OPTBIT2(bit) (inp->inp_flags2 & (bit) ? 1 : 0)
1808 inp->inp_flags |= (bit); \
1810 inp->inp_flags &= ~(bit); \
1829 if (inp->inp_flags & INP_DROPPED) {
1833 optp = &inp->in6p_outputopts;
1836 optp, (td != NULL) ? td->td_ucred :
1885 if (inp->inp_lport ||
1886 !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
1895 inp->inp_flags |= IN6P_IPV6_V6ONLY;
1896 inp->inp_vflag &= ~INP_IPV4;
1898 inp->inp_flags &= ~IN6P_IPV6_V6ONLY;
1899 inp->inp_vflag |= INP_IPV4;
1918 if ((optval >= -1) && (optval <=
1920 if (optval == -1) {
1922 inp->inp_flags2 &=
1928 inp->inp_flags2 |=
1930 inp->inp_flags2 &=
1932 inp->inp_flags2 |=
1958 if (inp->inp_flags & INP_DROPPED) {
1962 optp = &inp->in6p_outputopts;
1965 optp, (td != NULL) ? td->td_ucred :
1994 * Check super-user privilege.
2047 optlen = sopt->sopt_valsize;
2050 if (inp->inp_flags & INP_DROPPED) {
2054 optp = &inp->in6p_outputopts;
2056 optp, (td != NULL) ? td->td_ucred : NULL,
2087 inp->inp_flags &= ~(INP_LOWPORT);
2088 inp->inp_flags &= ~(INP_HIGHPORT);
2092 inp->inp_flags &= ~(INP_LOWPORT);
2093 inp->inp_flags |= INP_HIGHPORT;
2097 inp->inp_flags &= ~(INP_HIGHPORT);
2098 inp->inp_flags |= INP_LOWPORT;
2131 * semantics of the 2292-style pktoptions.
2138 sopt->sopt_valsize = 0;
2177 optval = inp->in6p_hops;
2203 flags = inp->inp_flags;
2229 optval = inp->inp_flowid;
2233 optval = inp->inp_flowtype;
2242 rss_hash2bucket(inp->inp_flowid,
2243 inp->inp_flowtype,
2259 optval = (inp->inp_flags2 &
2263 optval = -1;
2280 if (!(so->so_state & SS_ISCONNECTED))
2290 bcopy(&inp->in6p_faddr, &addr, sizeof(addr));
2292 error = ip6_getpmtu_ctl(so->so_fibnum,
2379 level = sopt->sopt_level;
2380 op = sopt->sopt_dir;
2381 optname = sopt->sopt_name;
2382 optlen = sopt->sopt_valsize;
2408 if (optval < -1 || (optval % 2) != 0) {
2410 * The API assumes non-negative even offset
2411 * values or -1 as a special value.
2414 } else if (inp->inp_ip_p == IPPROTO_ICMPV6) {
2418 inp->in6p_cksum = optval;
2422 if (inp->inp_ip_p == IPPROTO_ICMPV6)
2425 optval = inp->in6p_cksum;
2454 struct thread *td = sopt->sopt_td;
2460 if (opt->ip6po_pktinfo || opt->ip6po_nexthop ||
2461 opt->ip6po_hbh || opt->ip6po_dest1 || opt->ip6po_dest2 ||
2462 opt->ip6po_rhinfo.ip6po_rhi_rthdr)
2465 ip6_clearpktopts(opt, -1);
2473 if (!m || m->m_len == 0) {
2485 td->td_ucred : NULL, so->so_proto->pr_protocol)) != 0) {
2486 ip6_clearpktopts(opt, -1); /* XXX: discard all options */
2497 * initialize ip6_pktopts. beware that there are non-zero default values in
2505 opt->ip6po_hlim = -1; /* -1 means default hop limit */
2506 opt->ip6po_tclass = -1; /* -1 means default traffic class */
2507 opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY;
2508 opt->ip6po_prefer_tempaddr = IP6PO_TEMPADDR_SYSTEM;
2536 if (pktopt && pktopt->field) { \
2538 optdata = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK); \
2541 if (inp->inp_flags & INP_DROPPED) { \
2546 pktopt = inp->in6p_outputopts; \
2547 if (pktopt && pktopt->field) { \
2548 optdatalen = min(lenexpr, sopt->sopt_valsize); \
2549 bcopy(pktopt->field, optdata, optdatalen); \
2559 (((struct ip6_ext *)pktopt->field)->ip6e_len + 1) << 3)
2562 pktopt->field->sa_len)
2578 pktopt = inp->in6p_outputopts;
2583 if (pktopt && pktopt->ip6po_pktinfo) {
2584 bcopy(pktopt->ip6po_pktinfo, &null_pktinfo,
2594 if (pktopt && pktopt->ip6po_tclass >= 0)
2595 deftclass = pktopt->ip6po_tclass;
2616 defminmtu = pktopt->ip6po_minmtu;
2621 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG))
2630 defpreftemp = pktopt->ip6po_prefer_tempaddr;
2656 if (optname == -1 || optname == IPV6_PKTINFO) {
2657 if (pktopt->ip6po_pktinfo)
2658 free(pktopt->ip6po_pktinfo, M_IP6OPT);
2659 pktopt->ip6po_pktinfo = NULL;
2661 if (optname == -1 || optname == IPV6_HOPLIMIT) {
2662 pktopt->ip6po_hlim = -1;
2663 pktopt->ip6po_valid &= ~IP6PO_VALID_HLIM;
2665 if (optname == -1 || optname == IPV6_TCLASS) {
2666 pktopt->ip6po_tclass = -1;
2667 pktopt->ip6po_valid &= ~IP6PO_VALID_TC;
2669 if (optname == -1 || optname == IPV6_NEXTHOP) {
2670 if (pktopt->ip6po_nextroute.ro_nh) {
2671 NH_FREE(pktopt->ip6po_nextroute.ro_nh);
2672 pktopt->ip6po_nextroute.ro_nh = NULL;
2674 if (pktopt->ip6po_nexthop)
2675 free(pktopt->ip6po_nexthop, M_IP6OPT);
2676 pktopt->ip6po_nexthop = NULL;
2677 pktopt->ip6po_valid &= ~IP6PO_VALID_NHINFO;
2679 if (optname == -1 || optname == IPV6_HOPOPTS) {
2680 if (pktopt->ip6po_hbh)
2681 free(pktopt->ip6po_hbh, M_IP6OPT);
2682 pktopt->ip6po_hbh = NULL;
2683 pktopt->ip6po_valid &= ~IP6PO_VALID_HBH;
2685 if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
2686 if (pktopt->ip6po_dest1)
2687 free(pktopt->ip6po_dest1, M_IP6OPT);
2688 pktopt->ip6po_dest1 = NULL;
2689 pktopt->ip6po_valid &= ~IP6PO_VALID_DEST1;
2691 if (optname == -1 || optname == IPV6_RTHDR) {
2692 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
2693 free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
2694 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
2695 if (pktopt->ip6po_route.ro_nh) {
2696 NH_FREE(pktopt->ip6po_route.ro_nh);
2697 pktopt->ip6po_route.ro_nh = NULL;
2699 pktopt->ip6po_valid &= ~IP6PO_VALID_RHINFO;
2701 if (optname == -1 || optname == IPV6_DSTOPTS) {
2702 if (pktopt->ip6po_dest2)
2703 free(pktopt->ip6po_dest2, M_IP6OPT);
2704 pktopt->ip6po_dest2 = NULL;
2705 pktopt->ip6po_valid &= ~IP6PO_VALID_DEST2;
2711 if (src->type) {\
2712 int hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
2713 dst->type = malloc(hlen, M_IP6OPT, canwait);\
2714 if (dst->type == NULL)\
2716 bcopy(src->type, dst->type, hlen);\
2728 dst->ip6po_hlim = src->ip6po_hlim;
2729 dst->ip6po_tclass = src->ip6po_tclass;
2730 dst->ip6po_flags = src->ip6po_flags;
2731 dst->ip6po_minmtu = src->ip6po_minmtu;
2732 dst->ip6po_prefer_tempaddr = src->ip6po_prefer_tempaddr;
2733 if (src->ip6po_pktinfo) {
2734 dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
2736 if (dst->ip6po_pktinfo == NULL)
2738 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
2740 if (src->ip6po_nexthop) {
2741 dst->ip6po_nexthop = malloc(src->ip6po_nexthop->sa_len,
2743 if (dst->ip6po_nexthop == NULL)
2745 bcopy(src->ip6po_nexthop, dst->ip6po_nexthop,
2746 src->ip6po_nexthop->sa_len);
2752 dst->ip6po_valid = src->ip6po_valid;
2756 ip6_clearpktopts(dst, -1);
2786 ip6_clearpktopts(pktopt, -1);
2830 if (control->m_next)
2833 for (; control->m_len > 0; control->m_data += CMSG_ALIGN(cm->cmsg_len),
2834 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
2837 if (control->m_len < CMSG_LEN(0))
2841 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
2843 if (cm->cmsg_level != IPPROTO_IPV6)
2846 error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
2847 cm->cmsg_len - CMSG_LEN(0), opt, cred, 0, 1, uproto);
2932 if (optname == IPV6_PKTINFO && opt->ip6po_pktinfo &&
2933 pktinfo->ipi6_ifindex == 0 &&
2934 IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
2940 sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
2943 if (IN6_IS_ADDR_MULTICAST(&pktinfo->ipi6_addr))
2946 if (pktinfo->ipi6_ifindex) {
2947 ifp = ifnet_byindex(pktinfo->ipi6_ifindex);
2951 if (ifp != NULL && (ifp->if_afdata[AF_INET6] == NULL ||
2952 (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0))
2956 !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
2959 in6_setscope(&pktinfo->ipi6_addr, ifp, NULL);
2960 ia = in6ifa_ifpwithaddr(ifp, &pktinfo->ipi6_addr);
2963 ifa_free(&ia->ia_ifa);
2975 if (opt->ip6po_pktinfo == NULL) {
2976 opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
2978 if (opt->ip6po_pktinfo == NULL)
2981 bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
2982 opt->ip6po_valid |= IP6PO_VALID_PKTINFO;
3001 if (*hlimp < -1 || *hlimp > 255)
3004 opt->ip6po_hlim = *hlimp;
3005 opt->ip6po_valid |= IP6PO_VALID_HLIM;
3016 if (tclass < -1 || tclass > 255)
3019 opt->ip6po_tclass = tclass;
3020 opt->ip6po_valid |= IP6PO_VALID_TC;
3041 switch (((struct sockaddr *)buf)->sa_family) {
3047 if (sa6->sin6_len != sizeof(struct sockaddr_in6))
3050 if (IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) ||
3051 IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
3067 opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_NOWAIT);
3068 if (opt->ip6po_nexthop == NULL)
3070 bcopy(buf, opt->ip6po_nexthop, *buf);
3071 opt->ip6po_valid |= IP6PO_VALID_NHINFO;
3081 * XXX: We don't allow a non-privileged user to set ANY HbH
3082 * options, since per-option restriction has too much
3100 hbhlen = (hbh->ip6h_len + 1) << 3;
3106 opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT);
3107 if (opt->ip6po_hbh == NULL)
3109 bcopy(hbh, opt->ip6po_hbh, hbhlen);
3110 opt->ip6po_valid |= IP6PO_VALID_HBH;
3137 destlen = (dest->ip6d_len + 1) << 3;
3159 if (opt->ip6po_rthdr == NULL)
3160 newdest = &opt->ip6po_dest1;
3162 newdest = &opt->ip6po_dest2;
3165 newdest = &opt->ip6po_dest1;
3168 newdest = &opt->ip6po_dest2;
3178 if (newdest == &opt->ip6po_dest1)
3179 opt->ip6po_valid |= IP6PO_VALID_DEST1;
3181 opt->ip6po_valid |= IP6PO_VALID_DEST2;
3201 rthlen = (rth->ip6r_len + 1) << 3;
3205 switch (rth->ip6r_type) {
3207 if (rth->ip6r_len == 0) /* must contain one addr */
3209 if (rth->ip6r_len % 2) /* length must be even */
3211 if (rth->ip6r_len / 2 != rth->ip6r_segleft)
3220 opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT);
3221 if (opt->ip6po_rthdr == NULL)
3223 bcopy(rth, opt->ip6po_rthdr, rthlen);
3224 opt->ip6po_valid |= IP6PO_VALID_RHINFO;
3238 opt->ip6po_minmtu = minmtupolicy;
3250 opt->ip6po_flags &= ~IP6PO_DONTFRAG;
3252 opt->ip6po_flags |= IP6PO_DONTFRAG;
3264 opt->ip6po_prefer_tempaddr = preftemp;
3278 * pointer that might NOT be &loif -- easier than replicating that code here.
3291 * Make sure to deep-copy IPv6 header portion in case the data
3296 copym->m_len < sizeof(struct ip6_hdr)) {
3306 in6_clearscope(&ip6->ip6_src);
3307 in6_clearscope(&ip6->ip6_dst);
3308 if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
3309 copym->m_pkthdr.csum_flags |= CSUM_DATA_VALID_IPV6 |
3311 copym->m_pkthdr.csum_data = 0xffff;
3326 if (m->m_len > sizeof(*ip6)) {
3334 m->m_len -= sizeof(*ip6);
3335 m->m_data += sizeof(*ip6);
3336 mh->m_next = m;
3338 m->m_len = sizeof(*ip6);
3341 exthdrs->ip6e_ip6 = m;
3353 if (!inp->in6p_outputopts)
3358 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
3360 len += elen(inp->in6p_outputopts->ip6po_hbh);
3361 if (inp->in6p_outputopts->ip6po_rthdr)
3363 len += elen(inp->in6p_outputopts->ip6po_dest1);
3364 len += elen(inp->in6p_outputopts->ip6po_rthdr);
3365 len += elen(inp->in6p_outputopts->ip6po_dest2);