Lines Matching +full:non +full:- +full:sticky

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) in in6_delayed_cksum()
201 offset += m->m_pkthdr.csum_data; /* checksum offset */ in in6_delayed_cksum()
203 if (offset + sizeof(csum) > m->m_len) in in6_delayed_cksum()
219 in6_delayed_cksum(m, plen - optlen, in ip6_output_delayed_csum()
221 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6; in ip6_output_delayed_csum()
226 m->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6; in ip6_output_delayed_csum()
240 int tlen = m0->m_pkthdr.len; in ip6_fragment()
246 mnext = &m->m_nextpkt; in ip6_fragment()
269 mnext = &m->m_nextpkt; in ip6_fragment()
270 m->m_data += max_linkhdr; in ip6_fragment()
273 m->m_len = sizeof(*mhip6); in ip6_fragment()
279 ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7)); in ip6_fragment()
281 fraglen = tlen - off; in ip6_fragment()
283 ip6f->ip6f_offlg |= IP6F_MORE_FRAG; in ip6_fragment()
284 mhip6->ip6_plen = htons((u_short)(fraglen + hlen + in ip6_fragment()
285 sizeof(*ip6f) - sizeof(struct ip6_hdr))); in ip6_fragment()
291 m->m_pkthdr.len = fraglen + hlen + sizeof(*ip6f); in ip6_fragment()
292 ip6f->ip6f_reserved = 0; in ip6_fragment()
293 ip6f->ip6f_ident = id; in ip6_fragment()
294 ip6f->ip6f_nxt = nextproto; in ip6_fragment()
313 MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); in ip6_output_send()
323 if (m->m_next != NULL && mbuf_has_tls_session(m->m_next)) { in ip6_output_send()
324 tls = ktls_hold(m->m_next->m_epg_tls); in ip6_output_send()
325 mst = tls->snd_tag; in ip6_output_send()
345 if ((inp->inp_flags2 & INP_RATE_LIMIT_CHANGED) != 0 || in ip6_output_send()
346 (inp->inp_snd_tag != NULL && in ip6_output_send()
347 inp->inp_snd_tag->ifp != ifp)) in ip6_output_send()
350 if (inp->inp_snd_tag != NULL) in ip6_output_send()
351 mst = inp->inp_snd_tag; in ip6_output_send()
355 KASSERT(m->m_pkthdr.rcvif == NULL, in ip6_output_send()
357 if (mst->ifp != ifp) { in ip6_output_send()
364 m->m_pkthdr.snd_tag = m_snd_tag_ref(mst); in ip6_output_send()
365 m->m_pkthdr.csum_flags |= CSUM_SND_TAG; in ip6_output_send()
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; in ip6_output()
438 M_SETFIB(m, inp->inp_inc.inc_fibnum); in ip6_output()
441 m->m_pkthdr.flowid = inp->inp_flowid; in ip6_output()
442 M_HASHTYPE_SET(m, inp->inp_flowtype); in ip6_output()
444 if ((inp->inp_flags2 & INP_2PCP_SET) != 0) in ip6_output()
445 vlan_pcp = (inp->inp_flags2 & INP_2PCP_MASK) >> in ip6_output()
448 m->m_pkthdr.numa_domain = inp->inp_numa_domain; in ip6_output()
454 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && in ip6_output()
460 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) { in ip6_output()
475 optvalid = opt->ip6po_valid; in ip6_output()
477 /* Hop-by-Hop options header. */ in ip6_output()
479 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh, optlen); in ip6_output()
509 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1, in ip6_output()
514 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr, optlen); in ip6_output()
525 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2, optlen); in ip6_output()
544 m->m_pkthdr.len += optlen; in ip6_output()
545 plen = m->m_pkthdr.len - sizeof(*ip6); in ip6_output()
560 ip6->ip6_plen = 0; in ip6_output()
562 ip6->ip6_plen = htons(plen); in ip6_output()
563 nexthdrp = &ip6->ip6_nxt; in ip6_output()
592 exthdrs.ip6e_dest2->m_next = m->m_next; in ip6_output()
593 m->m_next = exthdrs.ip6e_dest2; in ip6_output()
594 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; in ip6_output()
595 ip6->ip6_nxt = IPPROTO_DSTOPTS; in ip6_output()
615 ro = &opt->ip6po_route; in ip6_output()
617 dst = (struct sockaddr_in6 *)&ro->ro_dst; in ip6_output()
620 fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m); in ip6_output()
625 * Do not override if a non-zero value is already set. in ip6_output()
636 ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20); in ip6_output()
641 ip6->ip6_hlim = opt->ip6po_hlim & 0xff; in ip6_output()
642 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { in ip6_output()
644 ip6->ip6_hlim = im6o->im6o_multicast_hlim; in ip6_output()
646 ip6->ip6_hlim = V_ip6_defmcasthlim; in ip6_output()
649 if (ro == NULL || ro->ro_nh == NULL) { in ip6_output()
651 dst->sin6_family = AF_INET6; in ip6_output()
652 dst->sin6_len = sizeof(*dst); in ip6_output()
653 dst->sin6_addr = ip6->ip6_dst; in ip6_output()
663 if (ro->ro_nh != NULL && inp != NULL) { in ip6_output()
664 ro->ro_dst.sin6_family = AF_INET6; /* XXX KASSERT? */ in ip6_output()
665 NH_VALIDATE((struct route *)ro, &inp->inp_rt_cookie, in ip6_output()
668 if (ro->ro_nh != NULL && fwd_tag == NULL && in ip6_output()
669 (!NH_IS_VALID(ro->ro_nh) || in ip6_output()
670 ro->ro_dst.sin6_family != AF_INET6 || in ip6_output()
671 !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst))) in ip6_output()
674 if (ro->ro_nh != NULL && fwd_tag == NULL && in ip6_output()
675 ro->ro_dst.sin6_family == AF_INET6 && in ip6_output()
676 IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) { in ip6_output()
678 nh = ro->ro_nh; in ip6_output()
680 if (ro->ro_lle) in ip6_output()
681 LLE_FREE(ro->ro_lle); /* zeros ro_lle */ in ip6_output()
682 ro->ro_lle = NULL; in ip6_output()
687 dst_sa.sin6_addr = ip6->ip6_dst; in ip6_output()
690 &nh, fibnum, m->m_pkthdr.flowid); in ip6_output()
699 * Can be the case when dst is multicast, link-local or in ip6_output()
710 mtu = ifp->if_mtu; in ip6_output()
712 ifp = nh->nh_ifp; in ip6_output()
713 origifp = nh->nh_aifp; in ip6_output()
714 ia = (struct in6_ifaddr *)(nh->nh_ifa); in ip6_output()
715 counter_u64_add(nh->nh_pksent, 1); in ip6_output()
726 dst_sa.sin6_addr = ip6->ip6_dst; in ip6_output()
731 (ifp = im6o->im6o_multicast_ifp) != NULL) { in ip6_output()
755 m->m_pkthdr.flowid); in ip6_output()
763 ifp = nh->nh_ifp; in ip6_output()
764 origifp = nh->nh_aifp; in ip6_output()
765 ia = ifatoia6(nh->nh_ifa); in ip6_output()
766 if (nh->nh_flags & NHF_GATEWAY) in ip6_output()
767 dst->sin6_addr = nh->gw6_sa.sin6_addr; in ip6_output()
769 dst->sin6_addr = dst_sa.sin6_addr; in ip6_output()
779 * fe80::1%em0 -> fe80::2%em0 -> ifp=em0, origifp=em0 in ip6_output()
780 * fe80::1%em0 -> fe80::1%em0 -> ifp=lo0, origifp=em0 in ip6_output()
781 * ::1 -> ::1 -> ifp=lo0, origifp=lo0 in ip6_output()
791 * FAST IPSEC: We re-injected the packet. in ip6_output()
802 ifp->if_mtu : mtu)) != 0) { in ip6_output()
816 src0 = ip6->ip6_src; in ip6_output()
820 src_sa.sin6_addr = ip6->ip6_src; in ip6_output()
822 dst0 = ip6->ip6_dst; in ip6_output()
823 /* Re-initialize to be sure. */ in ip6_output()
827 dst_sa.sin6_addr = ip6->ip6_dst; in ip6_output()
839 } else if ((origifp->if_flags & IFF_LOOPBACK) == 0 || in ip6_output()
863 if (nh && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { in ip6_output()
870 dst = (struct sockaddr_in6 *)opt->ip6po_nexthop; in ip6_output()
872 else if ((nh->nh_flags & NHF_GATEWAY)) in ip6_output()
873 dst = &nh->gw6_sa; in ip6_output()
876 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { in ip6_output()
877 m->m_flags &= ~(M_BCAST | M_MCAST); /* Just in case. */ in ip6_output()
879 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST; in ip6_output()
883 if (!(ifp->if_flags & IFF_MULTICAST)) { in ip6_output()
890 (im6o && im6o->im6o_multicast_loop)) { in ip6_output()
918 m->m_pkthdr.rcvif = NULL; in ip6_output()
929 * are not sent -- the above call to ip6_mloopback() will in ip6_output()
933 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) || in ip6_output()
934 IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) { in ip6_output()
942 * to increment per-interface statistics. in ip6_output()
948 if ((error = ip6_getpmtu(ro_pmtu, ro != ro_pmtu, ifp, &ip6->ip6_dst, in ip6_output()
970 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL) in ip6_output()
972 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && in ip6_output()
974 opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) { in ip6_output()
983 in6_clearscope(&ip6->ip6_src); in ip6_output()
984 in6_clearscope(&ip6->ip6_dst); in ip6_output()
987 * If the outgoing packet contains a hop-by-hop options header, in ip6_output()
997 if ((hbh->ip6h_len + 1) << 3 > exthdrs.ip6e_hbh->m_len) in ip6_output()
1003 * the IPv6 and the hop-by-hop options header are in ip6_output()
1006 m->m_flags |= M_LOOP; in ip6_output()
1007 m->m_pkthdr.rcvif = ifp; in ip6_output()
1009 ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh), in ip6_output()
1015 m->m_flags &= ~M_LOOP; /* XXX */ in ip6_output()
1016 m->m_pkthdr.rcvif = NULL; in ip6_output()
1023 odst = ip6->ip6_dst; in ip6_output()
1038 if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) { in ip6_output()
1039 m->m_flags |= M_SKIP_FIREWALL; in ip6_output()
1041 if (in6_localip(&ip6->ip6_dst)) { in ip6_output()
1042 m->m_flags |= M_FASTFWD_OURS; in ip6_output()
1043 if (m->m_pkthdr.rcvif == NULL) in ip6_output()
1044 m->m_pkthdr.rcvif = V_loif; in ip6_output()
1045 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { in ip6_output()
1046 m->m_pkthdr.csum_flags |= in ip6_output()
1048 m->m_pkthdr.csum_data = 0xffff; in ip6_output()
1051 if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) in ip6_output()
1052 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; in ip6_output()
1064 m->m_flags |= M_SKIP_FIREWALL; in ip6_output()
1074 if (m->m_flags & M_FASTFWD_OURS) { in ip6_output()
1075 if (m->m_pkthdr.rcvif == NULL) in ip6_output()
1076 m->m_pkthdr.rcvif = V_loif; in ip6_output()
1077 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { in ip6_output()
1078 m->m_pkthdr.csum_flags |= in ip6_output()
1080 m->m_pkthdr.csum_data = 0xffff; in ip6_output()
1083 if (m->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) in ip6_output()
1084 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; in ip6_output()
1090 if ((m->m_flags & M_IP6_NEXTHOP) && in ip6_output()
1093 dst = (struct sockaddr_in6 *)&ro->ro_dst; in ip6_output()
1097 m->m_flags |= M_SKIP_FIREWALL; in ip6_output()
1098 m->m_flags &= ~M_IP6_NEXTHOP; in ip6_output()
1104 if (vlan_pcp > -1) in ip6_output()
1108 if ((ifp->if_capenable & IFCAP_MEXTPG) == 0) { in ip6_output()
1122 * 1-a: send as is if tlen <= path mtu in ip6_output()
1123 * 1-b: fragment if tlen > path mtu in ip6_output()
1126 * 2-a: send as is if tlen <= interface mtu in ip6_output()
1127 * 2-b: error if tlen > interface mtu in ip6_output()
1135 sw_csum = m->m_pkthdr.csum_flags; in ip6_output()
1137 tso = ((sw_csum & ifp->if_hwassist & in ip6_output()
1139 sw_csum &= ~ifp->if_hwassist; in ip6_output()
1145 * XXX-BZ Need a framework to know when the NIC can handle it, even in ip6_output()
1149 /* XXX-BZ m->m_pkthdr.csum_flags &= ~ifp->if_hwassist; */ in ip6_output()
1150 tlen = m->m_pkthdr.len; in ip6_output()
1152 if ((opt && (opt->ip6po_flags & IP6PO_DONTFRAG)) || tso) in ip6_output()
1157 /* Conflicting request - can't transmit. */ in ip6_output()
1161 if (dontfrag && tlen > IN6_LINKMTU(ifp) && !tso) { /* Case 2-b. */ in ip6_output()
1177 if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* Cases 1-a and 2-a. */ in ip6_output()
1181 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); in ip6_output()
1184 counter_u64_add(ia6->ia_ifa.ifa_opackets, 1); in ip6_output()
1185 counter_u64_add(ia6->ia_ifa.ifa_obytes, in ip6_output()
1186 m->m_pkthdr.len); in ip6_output()
1193 /* Try to fragment the packet. Cases 1-b and 3. */ in ip6_output()
1199 } else if (ip6->ip6_plen == 0) { in ip6_output()
1215 len = (mtu - unfragpartlen - sizeof(struct ip6_frag)) & ~7; in ip6_output()
1225 * XXX-BZ handle the hw offloading case. Need flags. in ip6_output()
1227 ip6_output_delayed_csum(m, ifp, m->m_pkthdr.csum_flags, plen, in ip6_output()
1245 nextproto = ip6->ip6_nxt; in ip6_output()
1246 ip6->ip6_nxt = IPPROTO_FRAGMENT; in ip6_output()
1265 m = m0->m_nextpkt; in ip6_output()
1266 m0->m_nextpkt = 0; in ip6_output()
1269 m0 = m->m_nextpkt; in ip6_output()
1270 m->m_nextpkt = 0; in ip6_output()
1274 counter_u64_add(ia->ia_ifa.ifa_opackets, 1); in ip6_output()
1275 counter_u64_add(ia->ia_ifa.ifa_obytes, in ip6_output()
1276 m->m_pkthdr.len); in ip6_output()
1278 if (vlan_pcp > -1) in ip6_output()
1318 m->m_len = hlen; in ip6_copyexthdr()
1339 * If there is no hop-by-hop options header, allocate new one. in ip6_insert_jumboopt()
1344 if (exthdrs->ip6e_hbh == NULL) { in ip6_insert_jumboopt()
1348 mopt->m_len = JUMBOOPTLEN; in ip6_insert_jumboopt()
1350 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */ in ip6_insert_jumboopt()
1351 exthdrs->ip6e_hbh = mopt; in ip6_insert_jumboopt()
1355 mopt = exthdrs->ip6e_hbh; in ip6_insert_jumboopt()
1359 * - exthdrs->ip6e_hbh is not referenced from places in ip6_insert_jumboopt()
1361 * - exthdrs->ip6e_hbh is not an mbuf chain. in ip6_insert_jumboopt()
1363 int oldoptlen = mopt->m_len; in ip6_insert_jumboopt()
1380 n->m_len = oldoptlen + JUMBOOPTLEN; in ip6_insert_jumboopt()
1385 mopt = exthdrs->ip6e_hbh = n; in ip6_insert_jumboopt()
1387 optbuf = mtod(mopt, u_char *) + mopt->m_len; in ip6_insert_jumboopt()
1388 mopt->m_len += JUMBOOPTLEN; in ip6_insert_jumboopt()
1398 hbh->ip6h_len += (JUMBOOPTLEN >> 3); in ip6_insert_jumboopt()
1408 exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN; in ip6_insert_jumboopt()
1425 hlen - sizeof(struct ip6_hdr), M_NOWAIT); in ip6_insertfraghdr()
1428 m->m_next = n; in ip6_insertfraghdr()
1433 for (mlast = n; mlast->m_next; mlast = mlast->m_next) in ip6_insertfraghdr()
1440 mlast->m_len); in ip6_insertfraghdr()
1441 mlast->m_len += sizeof(struct ip6_frag); in ip6_insertfraghdr()
1442 m->m_pkthdr.len += sizeof(struct ip6_frag); in ip6_insertfraghdr()
1450 mfrg->m_len = sizeof(struct ip6_frag); in ip6_insertfraghdr()
1452 mlast->m_next = mfrg; in ip6_insertfraghdr()
1478 error = ip6_calcmtu(nh->nh_ifp, dst, nh->nh_mtu, mtup, NULL, 0); in ip6_getpmtu_ctl()
1493 * Stores mtu and always-frag value into @mtup and @alwaysfragp.
1517 sa6_dst = (struct sockaddr_in6 *)&ro_pmtu->ro_dst; in ip6_getpmtu()
1518 if (!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst)) in ip6_getpmtu()
1519 ro_pmtu->ro_mtu = 0; in ip6_getpmtu()
1523 if (ro_pmtu == NULL || ro_pmtu->ro_mtu == 0) { in ip6_getpmtu()
1525 sa6_dst->sin6_family = AF_INET6; in ip6_getpmtu()
1526 sa6_dst->sin6_len = sizeof(struct sockaddr_in6); in ip6_getpmtu()
1527 sa6_dst->sin6_addr = *dst; in ip6_getpmtu()
1532 mtu = nh->nh_mtu; in ip6_getpmtu()
1534 ro_pmtu->ro_mtu = mtu; in ip6_getpmtu()
1537 mtu = ro_pmtu->ro_mtu; in ip6_getpmtu()
1540 if (ro_pmtu != NULL && ro_pmtu->ro_nh != NULL) in ip6_getpmtu()
1541 mtu = ro_pmtu->ro_nh->nh_mtu; in ip6_getpmtu()
1549 * Stores mtu and always-frag value into @mtup and @alwaysfragp.
1631 level = sopt->sopt_level; in ip6_ctloutput()
1632 op = sopt->sopt_dir; in ip6_ctloutput()
1633 optname = sopt->sopt_name; in ip6_ctloutput()
1634 optlen = sopt->sopt_valsize; in ip6_ctloutput()
1635 td = sopt->sopt_td; in ip6_ctloutput()
1638 uproto = (int)so->so_proto->pr_protocol; in ip6_ctloutput()
1643 if (sopt->sopt_level == SOL_SOCKET && in ip6_ctloutput()
1644 sopt->sopt_dir == SOPT_SET) { in ip6_ctloutput()
1645 switch (sopt->sopt_name) { in ip6_ctloutput()
1648 inp->inp_inc.inc_fibnum = so->so_fibnum; in ip6_ctloutput()
1655 inp->inp_flags2 |= INP_RATE_LIMIT_CHANGED; in ip6_ctloutput()
1690 error = ip6_pcbopts(&inp->in6p_outputopts, m, in ip6_ctloutput()
1698 * Use of some Hop-by-Hop options or some in ip6_ctloutput()
1706 * KAME prevents non-privileged users from sending or in ip6_ctloutput()
1754 if (optval < -1 || optval >= 256) in ip6_ctloutput()
1757 /* -1 = kernel default */ in ip6_ctloutput()
1758 inp->in6p_hops = optval; in ip6_ctloutput()
1759 if ((inp->inp_vflag & in ip6_ctloutput()
1761 inp->inp_ip_ttl = optval; in ip6_ctloutput()
1768 inp->inp_flags |= (bit); \ in ip6_ctloutput()
1770 inp->inp_flags &= ~(bit); \ in ip6_ctloutput()
1776 inp->inp_flags |= IN6P_RFC2292; \ in ip6_ctloutput()
1778 inp->inp_flags |= (bit); \ in ip6_ctloutput()
1780 inp->inp_flags &= ~(bit); \ in ip6_ctloutput()
1783 #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0) in ip6_ctloutput()
1787 inp->inp_flags2 |= bit; \ in ip6_ctloutput()
1789 inp->inp_flags2 &= ~bit; \ in ip6_ctloutput()
1796 #define OPTBIT2(bit) (inp->inp_flags2 & (bit) ? 1 : 0) in ip6_ctloutput()
1804 inp->inp_flags |= (bit); \ in ip6_ctloutput()
1806 inp->inp_flags &= ~(bit); \ in ip6_ctloutput()
1825 if (inp->inp_flags & INP_DROPPED) { in ip6_ctloutput()
1829 optp = &inp->in6p_outputopts; in ip6_ctloutput()
1832 optp, (td != NULL) ? td->td_ucred : in ip6_ctloutput()
1881 if (inp->inp_lport || in ip6_ctloutput()
1882 !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { in ip6_ctloutput()
1891 inp->inp_flags |= IN6P_IPV6_V6ONLY; in ip6_ctloutput()
1892 inp->inp_vflag &= ~INP_IPV4; in ip6_ctloutput()
1894 inp->inp_flags &= ~IN6P_IPV6_V6ONLY; in ip6_ctloutput()
1895 inp->inp_vflag |= INP_IPV4; in ip6_ctloutput()
1914 if ((optval >= -1) && (optval <= in ip6_ctloutput()
1916 if (optval == -1) { in ip6_ctloutput()
1918 inp->inp_flags2 &= in ip6_ctloutput()
1924 inp->inp_flags2 |= in ip6_ctloutput()
1926 inp->inp_flags2 &= in ip6_ctloutput()
1928 inp->inp_flags2 |= in ip6_ctloutput()
1954 if (inp->inp_flags & INP_DROPPED) { in ip6_ctloutput()
1958 optp = &inp->in6p_outputopts; in ip6_ctloutput()
1961 optp, (td != NULL) ? td->td_ucred : in ip6_ctloutput()
1990 * Check super-user privilege. in ip6_ctloutput()
2043 optlen = sopt->sopt_valsize; in ip6_ctloutput()
2046 if (inp->inp_flags & INP_DROPPED) { in ip6_ctloutput()
2050 optp = &inp->in6p_outputopts; in ip6_ctloutput()
2052 optp, (td != NULL) ? td->td_ucred : NULL, in ip6_ctloutput()
2083 inp->inp_flags &= ~(INP_LOWPORT); in ip6_ctloutput()
2084 inp->inp_flags &= ~(INP_HIGHPORT); in ip6_ctloutput()
2088 inp->inp_flags &= ~(INP_LOWPORT); in ip6_ctloutput()
2089 inp->inp_flags |= INP_HIGHPORT; in ip6_ctloutput()
2093 inp->inp_flags &= ~(INP_HIGHPORT); in ip6_ctloutput()
2094 inp->inp_flags |= INP_LOWPORT; in ip6_ctloutput()
2127 * semantics of the 2292-style pktoptions. in ip6_ctloutput()
2134 sopt->sopt_valsize = 0; in ip6_ctloutput()
2173 optval = inp->in6p_hops; in ip6_ctloutput()
2199 flags = inp->inp_flags; in ip6_ctloutput()
2225 optval = inp->inp_flowid; in ip6_ctloutput()
2229 optval = inp->inp_flowtype; in ip6_ctloutput()
2238 rss_hash2bucket(inp->inp_flowid, in ip6_ctloutput()
2239 inp->inp_flowtype, in ip6_ctloutput()
2255 optval = (inp->inp_flags2 & in ip6_ctloutput()
2259 optval = -1; in ip6_ctloutput()
2276 if (!(so->so_state & SS_ISCONNECTED)) in ip6_ctloutput()
2286 bcopy(&inp->in6p_faddr, &addr, sizeof(addr)); in ip6_ctloutput()
2288 error = ip6_getpmtu_ctl(so->so_fibnum, in ip6_ctloutput()
2375 level = sopt->sopt_level; in ip6_raw_ctloutput()
2376 op = sopt->sopt_dir; in ip6_raw_ctloutput()
2377 optname = sopt->sopt_name; in ip6_raw_ctloutput()
2378 optlen = sopt->sopt_valsize; in ip6_raw_ctloutput()
2404 if (optval < -1 || (optval % 2) != 0) { in ip6_raw_ctloutput()
2406 * The API assumes non-negative even offset in ip6_raw_ctloutput()
2407 * values or -1 as a special value. in ip6_raw_ctloutput()
2410 } else if (inp->inp_ip_p == IPPROTO_ICMPV6) { in ip6_raw_ctloutput()
2414 inp->in6p_cksum = optval; in ip6_raw_ctloutput()
2418 if (inp->inp_ip_p == IPPROTO_ICMPV6) in ip6_raw_ctloutput()
2421 optval = inp->in6p_cksum; in ip6_raw_ctloutput()
2450 struct thread *td = sopt->sopt_td; in ip6_pcbopts()
2456 if (opt->ip6po_pktinfo || opt->ip6po_nexthop || in ip6_pcbopts()
2457 opt->ip6po_hbh || opt->ip6po_dest1 || opt->ip6po_dest2 || in ip6_pcbopts()
2458 opt->ip6po_rhinfo.ip6po_rhi_rthdr) in ip6_pcbopts()
2461 ip6_clearpktopts(opt, -1); in ip6_pcbopts()
2469 if (!m || m->m_len == 0) { in ip6_pcbopts()
2481 td->td_ucred : NULL, so->so_proto->pr_protocol)) != 0) { in ip6_pcbopts()
2482 ip6_clearpktopts(opt, -1); /* XXX: discard all options */ in ip6_pcbopts()
2493 * initialize ip6_pktopts. beware that there are non-zero default values in
2501 opt->ip6po_hlim = -1; /* -1 means default hop limit */ in ip6_initpktopts()
2502 opt->ip6po_tclass = -1; /* -1 means default traffic class */ in ip6_initpktopts()
2503 opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY; in ip6_initpktopts()
2504 opt->ip6po_prefer_tempaddr = IP6PO_TEMPADDR_SYSTEM; in ip6_initpktopts()
2532 if (pktopt && pktopt->field) { \
2534 optdata = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK); \
2537 if (inp->inp_flags & INP_DROPPED) { \
2542 pktopt = inp->in6p_outputopts; \
2543 if (pktopt && pktopt->field) { \
2544 optdatalen = min(lenexpr, sopt->sopt_valsize); \
2545 bcopy(pktopt->field, optdata, optdatalen); \
2555 (((struct ip6_ext *)pktopt->field)->ip6e_len + 1) << 3)
2558 pktopt->field->sa_len)
2574 pktopt = inp->in6p_outputopts; in ip6_getpcbopt()
2579 if (pktopt && pktopt->ip6po_pktinfo) { in ip6_getpcbopt()
2580 bcopy(pktopt->ip6po_pktinfo, &null_pktinfo, in ip6_getpcbopt()
2590 if (pktopt && pktopt->ip6po_tclass >= 0) in ip6_getpcbopt()
2591 deftclass = pktopt->ip6po_tclass; in ip6_getpcbopt()
2612 defminmtu = pktopt->ip6po_minmtu; in ip6_getpcbopt()
2617 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG)) in ip6_getpcbopt()
2626 defpreftemp = pktopt->ip6po_prefer_tempaddr; in ip6_getpcbopt()
2652 if (optname == -1 || optname == IPV6_PKTINFO) { in ip6_clearpktopts()
2653 if (pktopt->ip6po_pktinfo) in ip6_clearpktopts()
2654 free(pktopt->ip6po_pktinfo, M_IP6OPT); in ip6_clearpktopts()
2655 pktopt->ip6po_pktinfo = NULL; in ip6_clearpktopts()
2657 if (optname == -1 || optname == IPV6_HOPLIMIT) { in ip6_clearpktopts()
2658 pktopt->ip6po_hlim = -1; in ip6_clearpktopts()
2659 pktopt->ip6po_valid &= ~IP6PO_VALID_HLIM; in ip6_clearpktopts()
2661 if (optname == -1 || optname == IPV6_TCLASS) { in ip6_clearpktopts()
2662 pktopt->ip6po_tclass = -1; in ip6_clearpktopts()
2663 pktopt->ip6po_valid &= ~IP6PO_VALID_TC; in ip6_clearpktopts()
2665 if (optname == -1 || optname == IPV6_NEXTHOP) { in ip6_clearpktopts()
2666 if (pktopt->ip6po_nextroute.ro_nh) { in ip6_clearpktopts()
2667 NH_FREE(pktopt->ip6po_nextroute.ro_nh); in ip6_clearpktopts()
2668 pktopt->ip6po_nextroute.ro_nh = NULL; in ip6_clearpktopts()
2670 if (pktopt->ip6po_nexthop) in ip6_clearpktopts()
2671 free(pktopt->ip6po_nexthop, M_IP6OPT); in ip6_clearpktopts()
2672 pktopt->ip6po_nexthop = NULL; in ip6_clearpktopts()
2673 pktopt->ip6po_valid &= ~IP6PO_VALID_NHINFO; in ip6_clearpktopts()
2675 if (optname == -1 || optname == IPV6_HOPOPTS) { in ip6_clearpktopts()
2676 if (pktopt->ip6po_hbh) in ip6_clearpktopts()
2677 free(pktopt->ip6po_hbh, M_IP6OPT); in ip6_clearpktopts()
2678 pktopt->ip6po_hbh = NULL; in ip6_clearpktopts()
2679 pktopt->ip6po_valid &= ~IP6PO_VALID_HBH; in ip6_clearpktopts()
2681 if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) { in ip6_clearpktopts()
2682 if (pktopt->ip6po_dest1) in ip6_clearpktopts()
2683 free(pktopt->ip6po_dest1, M_IP6OPT); in ip6_clearpktopts()
2684 pktopt->ip6po_dest1 = NULL; in ip6_clearpktopts()
2685 pktopt->ip6po_valid &= ~IP6PO_VALID_DEST1; in ip6_clearpktopts()
2687 if (optname == -1 || optname == IPV6_RTHDR) { in ip6_clearpktopts()
2688 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr) in ip6_clearpktopts()
2689 free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT); in ip6_clearpktopts()
2690 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL; in ip6_clearpktopts()
2691 if (pktopt->ip6po_route.ro_nh) { in ip6_clearpktopts()
2692 NH_FREE(pktopt->ip6po_route.ro_nh); in ip6_clearpktopts()
2693 pktopt->ip6po_route.ro_nh = NULL; in ip6_clearpktopts()
2695 pktopt->ip6po_valid &= ~IP6PO_VALID_RHINFO; in ip6_clearpktopts()
2697 if (optname == -1 || optname == IPV6_DSTOPTS) { in ip6_clearpktopts()
2698 if (pktopt->ip6po_dest2) in ip6_clearpktopts()
2699 free(pktopt->ip6po_dest2, M_IP6OPT); in ip6_clearpktopts()
2700 pktopt->ip6po_dest2 = NULL; in ip6_clearpktopts()
2701 pktopt->ip6po_valid &= ~IP6PO_VALID_DEST2; in ip6_clearpktopts()
2707 if (src->type) {\
2708 int hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
2709 dst->type = malloc(hlen, M_IP6OPT, canwait);\
2710 if (dst->type == NULL)\
2712 bcopy(src->type, dst->type, hlen);\
2724 dst->ip6po_hlim = src->ip6po_hlim; in copypktopts()
2725 dst->ip6po_tclass = src->ip6po_tclass; in copypktopts()
2726 dst->ip6po_flags = src->ip6po_flags; in copypktopts()
2727 dst->ip6po_minmtu = src->ip6po_minmtu; in copypktopts()
2728 dst->ip6po_prefer_tempaddr = src->ip6po_prefer_tempaddr; in copypktopts()
2729 if (src->ip6po_pktinfo) { in copypktopts()
2730 dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo), in copypktopts()
2732 if (dst->ip6po_pktinfo == NULL) in copypktopts()
2734 *dst->ip6po_pktinfo = *src->ip6po_pktinfo; in copypktopts()
2736 if (src->ip6po_nexthop) { in copypktopts()
2737 dst->ip6po_nexthop = malloc(src->ip6po_nexthop->sa_len, in copypktopts()
2739 if (dst->ip6po_nexthop == NULL) in copypktopts()
2741 bcopy(src->ip6po_nexthop, dst->ip6po_nexthop, in copypktopts()
2742 src->ip6po_nexthop->sa_len); in copypktopts()
2748 dst->ip6po_valid = src->ip6po_valid; in copypktopts()
2752 ip6_clearpktopts(dst, -1); in copypktopts()
2782 ip6_clearpktopts(pktopt, -1); in ip6_freepcbopts()
2826 if (control->m_next) in ip6_setpktopts()
2829 for (; control->m_len > 0; control->m_data += CMSG_ALIGN(cm->cmsg_len), in ip6_setpktopts()
2830 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) { in ip6_setpktopts()
2833 if (control->m_len < CMSG_LEN(0)) in ip6_setpktopts()
2837 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len) in ip6_setpktopts()
2839 if (cm->cmsg_level != IPPROTO_IPV6) in ip6_setpktopts()
2842 error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm), in ip6_setpktopts()
2843 cm->cmsg_len - CMSG_LEN(0), opt, cred, 0, 1, uproto); in ip6_setpktopts()
2852 * Set a particular packet option, as a sticky option or an ancillary data
2853 * item. "len" can be 0 only when it's a sticky option.
2854 * We have 4 cases of combination of "sticky" and "cmsg":
2855 * "sticky=0, cmsg=0": impossible
2856 * "sticky=0, cmsg=1": RFC2292 or RFC3542 ancillary data
2857 * "sticky=1, cmsg=0": RFC3542 socket option
2858 * "sticky=1, cmsg=1": RFC2292 socket option
2862 struct ucred *cred, int sticky, int cmsg, int uproto) in ip6_setpktopt() argument
2869 if (!sticky && !cmsg) { in ip6_setpktopt()
2893 if (sticky && cmsg) { in ip6_setpktopt()
2923 * An application can clear any sticky IPV6_PKTINFO option by in ip6_setpktopt()
2928 if (optname == IPV6_PKTINFO && opt->ip6po_pktinfo && in ip6_setpktopt()
2929 pktinfo->ipi6_ifindex == 0 && in ip6_setpktopt()
2930 IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { in ip6_setpktopt()
2936 sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { in ip6_setpktopt()
2939 if (IN6_IS_ADDR_MULTICAST(&pktinfo->ipi6_addr)) in ip6_setpktopt()
2942 if (pktinfo->ipi6_ifindex) { in ip6_setpktopt()
2943 ifp = ifnet_byindex(pktinfo->ipi6_ifindex); in ip6_setpktopt()
2947 if (ifp != NULL && (ifp->if_afdata[AF_INET6] == NULL || in ip6_setpktopt()
2948 (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)) in ip6_setpktopt()
2952 !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) { in ip6_setpktopt()
2955 in6_setscope(&pktinfo->ipi6_addr, ifp, NULL); in ip6_setpktopt()
2956 ia = in6ifa_ifpwithaddr(ifp, &pktinfo->ipi6_addr); in ip6_setpktopt()
2959 ifa_free(&ia->ia_ifa); in ip6_setpktopt()
2969 * application when it is used as a sticky option. in ip6_setpktopt()
2971 if (opt->ip6po_pktinfo == NULL) { in ip6_setpktopt()
2972 opt->ip6po_pktinfo = malloc(sizeof(*pktinfo), in ip6_setpktopt()
2974 if (opt->ip6po_pktinfo == NULL) in ip6_setpktopt()
2977 bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo)); in ip6_setpktopt()
2978 opt->ip6po_valid |= IP6PO_VALID_PKTINFO; in ip6_setpktopt()
2988 * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT in ip6_setpktopt()
2991 if (optname == IPV6_HOPLIMIT && sticky) in ip6_setpktopt()
2997 if (*hlimp < -1 || *hlimp > 255) in ip6_setpktopt()
3000 opt->ip6po_hlim = *hlimp; in ip6_setpktopt()
3001 opt->ip6po_valid |= IP6PO_VALID_HLIM; in ip6_setpktopt()
3012 if (tclass < -1 || tclass > 255) in ip6_setpktopt()
3015 opt->ip6po_tclass = tclass; in ip6_setpktopt()
3016 opt->ip6po_valid |= IP6PO_VALID_TC; in ip6_setpktopt()
3037 switch (((struct sockaddr *)buf)->sa_family) { in ip6_setpktopt()
3043 if (sa6->sin6_len != sizeof(struct sockaddr_in6)) in ip6_setpktopt()
3046 if (IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) || in ip6_setpktopt()
3047 IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) { in ip6_setpktopt()
3063 opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_NOWAIT); in ip6_setpktopt()
3064 if (opt->ip6po_nexthop == NULL) in ip6_setpktopt()
3066 bcopy(buf, opt->ip6po_nexthop, *buf); in ip6_setpktopt()
3067 opt->ip6po_valid |= IP6PO_VALID_NHINFO; in ip6_setpktopt()
3077 * XXX: We don't allow a non-privileged user to set ANY HbH in ip6_setpktopt()
3078 * options, since per-option restriction has too much in ip6_setpktopt()
3096 hbhlen = (hbh->ip6h_len + 1) << 3; in ip6_setpktopt()
3102 opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT); in ip6_setpktopt()
3103 if (opt->ip6po_hbh == NULL) in ip6_setpktopt()
3105 bcopy(hbh, opt->ip6po_hbh, hbhlen); in ip6_setpktopt()
3106 opt->ip6po_valid |= IP6PO_VALID_HBH; in ip6_setpktopt()
3133 destlen = (dest->ip6d_len + 1) << 3; in ip6_setpktopt()
3155 if (opt->ip6po_rthdr == NULL) in ip6_setpktopt()
3156 newdest = &opt->ip6po_dest1; in ip6_setpktopt()
3158 newdest = &opt->ip6po_dest2; in ip6_setpktopt()
3161 newdest = &opt->ip6po_dest1; in ip6_setpktopt()
3164 newdest = &opt->ip6po_dest2; in ip6_setpktopt()
3174 if (newdest == &opt->ip6po_dest1) in ip6_setpktopt()
3175 opt->ip6po_valid |= IP6PO_VALID_DEST1; in ip6_setpktopt()
3177 opt->ip6po_valid |= IP6PO_VALID_DEST2; in ip6_setpktopt()
3197 rthlen = (rth->ip6r_len + 1) << 3; in ip6_setpktopt()
3201 switch (rth->ip6r_type) { in ip6_setpktopt()
3203 if (rth->ip6r_len == 0) /* must contain one addr */ in ip6_setpktopt()
3205 if (rth->ip6r_len % 2) /* length must be even */ in ip6_setpktopt()
3207 if (rth->ip6r_len / 2 != rth->ip6r_segleft) in ip6_setpktopt()
3216 opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT); in ip6_setpktopt()
3217 if (opt->ip6po_rthdr == NULL) in ip6_setpktopt()
3219 bcopy(rth, opt->ip6po_rthdr, rthlen); in ip6_setpktopt()
3220 opt->ip6po_valid |= IP6PO_VALID_RHINFO; in ip6_setpktopt()
3234 opt->ip6po_minmtu = minmtupolicy; in ip6_setpktopt()
3246 opt->ip6po_flags &= ~IP6PO_DONTFRAG; in ip6_setpktopt()
3248 opt->ip6po_flags |= IP6PO_DONTFRAG; in ip6_setpktopt()
3260 opt->ip6po_prefer_tempaddr = preftemp; in ip6_setpktopt()
3274 * pointer that might NOT be &loif -- easier than replicating that code here.
3287 * Make sure to deep-copy IPv6 header portion in case the data in ip6_mloopback()
3292 copym->m_len < sizeof(struct ip6_hdr)) { in ip6_mloopback()
3302 in6_clearscope(&ip6->ip6_src); in ip6_mloopback()
3303 in6_clearscope(&ip6->ip6_dst); in ip6_mloopback()
3304 if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) { in ip6_mloopback()
3305 copym->m_pkthdr.csum_flags |= CSUM_DATA_VALID_IPV6 | in ip6_mloopback()
3307 copym->m_pkthdr.csum_data = 0xffff; in ip6_mloopback()
3322 if (m->m_len > sizeof(*ip6)) { in ip6_splithdr()
3330 m->m_len -= sizeof(*ip6); in ip6_splithdr()
3331 m->m_data += sizeof(*ip6); in ip6_splithdr()
3332 mh->m_next = m; in ip6_splithdr()
3334 m->m_len = sizeof(*ip6); in ip6_splithdr()
3337 exthdrs->ip6e_ip6 = m; in ip6_splithdr()
3349 if (!inp->in6p_outputopts) in ip6_optlen()
3354 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0) in ip6_optlen()
3356 len += elen(inp->in6p_outputopts->ip6po_hbh); in ip6_optlen()
3357 if (inp->in6p_outputopts->ip6po_rthdr) in ip6_optlen()
3359 len += elen(inp->in6p_outputopts->ip6po_dest1); in ip6_optlen()
3360 len += elen(inp->in6p_outputopts->ip6po_rthdr); in ip6_optlen()
3361 len += elen(inp->in6p_outputopts->ip6po_dest2); in ip6_optlen()