^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Extension Header handling for IPv6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Linux INET6 implementation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Pedro Roque <roque@di.fc.ul.pt>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Andi Kleen <ak@muc.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /* Changes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * yoshfuji : ensure not to overrun while parsing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * tlv options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * YOSHIFUJI Hideaki @USAGI Register inbound extension header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * handlers as inet6_protocol{}.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sockios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/net.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/in6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/icmpv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <net/dst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <net/snmp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <net/ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <net/protocol.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <net/transp_v6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <net/rawv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <net/ndisc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <net/ip6_route.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <net/addrconf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <net/calipso.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <net/xfrm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <linux/seg6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <net/seg6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <net/seg6_hmac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <net/rpl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Parsing tlv encoded headers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Parsing function "func" returns true, if parsing succeed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * and false, if it failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * It MUST NOT touch skb->h.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct tlvtype_proc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bool (*func)(struct sk_buff *skb, int offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*********************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) Generic functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* An unknown option is detected, decide what to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static bool ip6_tlvopt_unknown(struct sk_buff *skb, int optoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bool disallow_unknowns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (disallow_unknowns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* If unknown TLVs are disallowed by configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * then always silently drop packet. Note this also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * means no ICMP parameter problem is sent which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * could be a good property to mitigate a reflection DOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * attack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) switch ((skb_network_header(skb)[optoff] & 0xC0) >> 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case 0: /* ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case 1: /* drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) case 3: /* Send ICMP if not a multicast address and drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* Actually, it is redundant check. icmp_send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) will recheck in any case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case 2: /* send ICMP PARM PROB regardless and drop packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) icmpv6_param_prob(skb, ICMPV6_UNK_OPTION, optoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Parse tlv encoded option header (hop-by-hop or destination) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int max_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int len = (skb_transport_header(skb)[1] + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) const unsigned char *nh = skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int off = skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const struct tlvtype_proc *curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) bool disallow_unknowns = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) int tlv_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int padlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (unlikely(max_count < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) disallow_unknowns = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) max_count = -max_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (skb_transport_offset(skb) + len > skb_headlen(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) off += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int optlen, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (nh[off] == IPV6_TLV_PAD1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) padlen++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (padlen > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) off++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) len--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) optlen = nh[off + 1] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (optlen > len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (nh[off] == IPV6_TLV_PADN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* RFC 2460 states that the purpose of PadN is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * to align the containing header to multiples
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * of 8. 7 is therefore the highest valid value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * See also RFC 4942, Section 2.1.9.5.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) padlen += optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (padlen > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* RFC 4942 recommends receiving hosts to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * actively check PadN payload to contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * only zeroes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) for (i = 2; i < optlen; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (nh[off + i] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) tlv_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (tlv_count > max_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) for (curr = procs; curr->type >= 0; curr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (curr->type == nh[off]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* type specific length/alignment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) checks will be performed in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) func(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (curr->func(skb, off) == false)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (curr->type < 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) !ip6_tlvopt_unknown(skb, off, disallow_unknowns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) padlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) off += optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) len -= optlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) bad:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /*****************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) Destination options header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *****************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct ipv6_destopt_hao *hao;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct ipv6hdr *ipv6h = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (opt->dsthao) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) net_dbg_ratelimited("hao duplicated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) opt->dsthao = opt->dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) opt->dst1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) + optoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (hao->length != 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) net_dbg_ratelimited("hao invalid option length = %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) hao->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) net_dbg_ratelimited("hao is not an unicast addr: %pI6\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) &hao->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (unlikely(ret < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (skb_cloned(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto discard;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* update all variable using below by copied skbuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) hao = (struct ipv6_destopt_hao *)(skb_network_header(skb) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) optoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ipv6h = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (skb->ip_summed == CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) swap(ipv6h->saddr, hao->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (skb->tstamp == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) __net_timestamp(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) discard:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static const struct tlvtype_proc tlvprocdestopt_lst[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .type = IPV6_TLV_HAO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .func = ipv6_dest_hao,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {-1, NULL}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int ipv6_destopt_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct inet6_dev *idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) __u16 dstbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct dst_entry *dst = skb_dst(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) int extlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) !pskb_may_pull(skb, (skb_transport_offset(skb) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ((skb_transport_header(skb)[1] + 1) << 3)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) __IP6_INC_STATS(dev_net(dst->dev), idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) fail_and_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) extlen = (skb_transport_header(skb)[1] + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (extlen > net->ipv6.sysctl.max_dst_opts_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) goto fail_and_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) opt->lastopt = opt->dst1 = skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dstbuf = opt->dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (ip6_parse_tlv(tlvprocdestopt_lst, skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) net->ipv6.sysctl.max_dst_opts_cnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) skb->transport_header += extlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) opt->nhoff = dstbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) opt->nhoff = opt->dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void seg6_update_csum(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct ipv6_sr_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct in6_addr *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) __be32 from, to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* srh is at transport offset and seg_left is already decremented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * but daddr is not yet updated with next segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) addr = hdr->segments + hdr->segments_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) hdr->segments_left++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) from = *(__be32 *)hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) hdr->segments_left--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) to = *(__be32 *)hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* update skb csum with diff resulting from seg_left decrement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) update_csum_diff4(skb, from, to);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* compute csum diff between current and next segment and update */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) update_csum_diff16(skb, (__be32 *)(&ipv6_hdr(skb)->daddr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) (__be32 *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static int ipv6_srh_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) struct ipv6_sr_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct in6_addr *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int accept_seg6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) accept_seg6 = net->ipv6.devconf_all->seg6_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (accept_seg6 > idev->cnf.seg6_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) accept_seg6 = idev->cnf.seg6_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (!accept_seg6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!seg6_hmac_validate_skb(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) looped_back:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) if (hdr->segments_left == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (hdr->nexthdr == NEXTHDR_IPV6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int offset = (hdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) skb_postpull_rcsum(skb, skb_network_header(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) skb_network_header_len(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!pskb_pull(skb, offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) skb_postpull_rcsum(skb, skb_transport_header(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) skb->encapsulation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) __skb_tunnel_rx(skb, skb->dev, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) opt->srcrt = skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) opt->lastopt = opt->srcrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) skb->transport_header += (hdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (hdr->segments_left >= (hdr->hdrlen >> 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ((&hdr->segments_left) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) skb_network_header(skb)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (skb_cloned(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) hdr->segments_left--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) addr = hdr->segments + hdr->segments_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) skb_push(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (skb->ip_summed == CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) seg6_update_csum(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ipv6_hdr(skb)->daddr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ip6_route_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (skb_dst(skb)->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) if (ipv6_hdr(skb)->hop_limit <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) icmpv6_send(skb, ICMPV6_TIME_EXCEED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ICMPV6_EXC_HOPLIMIT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ipv6_hdr(skb)->hop_limit--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) skb_pull(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) goto looped_back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct ipv6_rpl_sr_hdr *hdr, *ohdr, *chdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct inet6_dev *idev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct ipv6hdr *oldhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct in6_addr addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) unsigned char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int accept_rpl_seg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) u64 n = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) accept_rpl_seg = net->ipv6.devconf_all->rpl_seg_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (accept_rpl_seg > idev->cnf.rpl_seg_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) accept_rpl_seg = idev->cnf.rpl_seg_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!accept_rpl_seg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) looped_back:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) hdr = (struct ipv6_rpl_sr_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (hdr->segments_left == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (hdr->nexthdr == NEXTHDR_IPV6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int offset = (hdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) skb_postpull_rcsum(skb, skb_network_header(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) skb_network_header_len(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (!pskb_pull(skb, offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) skb_postpull_rcsum(skb, skb_transport_header(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) skb->encapsulation = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) __skb_tunnel_rx(skb, skb->dev, net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) opt->srcrt = skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) opt->lastopt = opt->srcrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) skb->transport_header += (hdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (!pskb_may_pull(skb, sizeof(*hdr))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) n = (hdr->hdrlen << 3) - hdr->pad - (16 - hdr->cmpre);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) r = do_div(n, (16 - hdr->cmpri));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* checks if calculation was without remainder and n fits into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * unsigned char which is segments_left field. Should not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * higher than that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (r || (n + 1) > 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (hdr->segments_left > n + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) ((&hdr->segments_left) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) skb_network_header(skb)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (skb_cloned(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (pskb_expand_head(skb, IPV6_RPL_SRH_WORST_SWAP_SIZE, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) GFP_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) err = skb_cow_head(skb, IPV6_RPL_SRH_WORST_SWAP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (unlikely(err)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) hdr = (struct ipv6_rpl_sr_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (!pskb_may_pull(skb, ipv6_rpl_srh_size(n, hdr->cmpri,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) hdr->cmpre))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) hdr->segments_left--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) i = n - hdr->segments_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) buf = kcalloc(struct_size(hdr, segments.addr, n + 2), 2, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (unlikely(!buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) ohdr = (struct ipv6_rpl_sr_hdr *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ipv6_rpl_srh_decompress(ohdr, hdr, &ipv6_hdr(skb)->daddr, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) chdr = (struct ipv6_rpl_sr_hdr *)(buf + ((ohdr->hdrlen + 1) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if ((ipv6_addr_type(&ipv6_hdr(skb)->daddr) & IPV6_ADDR_MULTICAST) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) (ipv6_addr_type(&ohdr->rpl_segaddr[i]) & IPV6_ADDR_MULTICAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) err = ipv6_chk_rpl_srh_loop(net, ohdr->rpl_segaddr, n + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) icmpv6_send(skb, ICMPV6_PARAMPROB, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) addr = ipv6_hdr(skb)->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ipv6_hdr(skb)->daddr = ohdr->rpl_segaddr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ohdr->rpl_segaddr[i] = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ipv6_rpl_srh_compress(chdr, ohdr, &ipv6_hdr(skb)->daddr, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) oldhdr = ipv6_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) skb_pull(skb, ((hdr->hdrlen + 1) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) skb_postpull_rcsum(skb, oldhdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) sizeof(struct ipv6hdr) + ((hdr->hdrlen + 1) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) skb_push(skb, ((chdr->hdrlen + 1) << 3) + sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) skb_mac_header_rebuild(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) skb_set_transport_header(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) memmove(ipv6_hdr(skb), oldhdr, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) memcpy(skb_transport_header(skb), chdr, (chdr->hdrlen + 1) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) skb_postpush_rcsum(skb, ipv6_hdr(skb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) sizeof(struct ipv6hdr) + ((chdr->hdrlen + 1) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) ip6_route_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (skb_dst(skb)->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (skb_dst(skb)->dev->flags & IFF_LOOPBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) if (ipv6_hdr(skb)->hop_limit <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) icmpv6_send(skb, ICMPV6_TIME_EXCEED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) ICMPV6_EXC_HOPLIMIT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ipv6_hdr(skb)->hop_limit--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) skb_pull(skb, sizeof(struct ipv6hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) goto looped_back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /********************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) Routing header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) ********************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* called with rcu_read_lock() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static int ipv6_rthdr_rcv(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct inet6_dev *idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct in6_addr *addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) struct in6_addr daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) int n, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct ipv6_rt_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) struct rt0_hdr *rthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) int accept_source_route = net->ipv6.devconf_all->accept_source_route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) idev = __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (idev && accept_source_route > idev->cnf.accept_source_route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) accept_source_route = idev->cnf.accept_source_route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) !pskb_may_pull(skb, (skb_transport_offset(skb) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ((skb_transport_header(skb)[1] + 1) << 3)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) skb->pkt_type != PACKET_HOST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) switch (hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) case IPV6_SRCRT_TYPE_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* segment routing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) return ipv6_srh_rcv(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case IPV6_SRCRT_TYPE_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* rpl segment routing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return ipv6_rpl_srh_rcv(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) looped_back:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (hdr->segments_left == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) switch (hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) case IPV6_SRCRT_TYPE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* Silently discard type 2 header unless it was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * processed by own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) __IP6_INC_STATS(net, idev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) IPSTATS_MIB_INADDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) opt->lastopt = opt->srcrt = skb_network_header_len(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) skb->transport_header += (hdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) opt->dst0 = opt->dst1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) opt->dst1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) opt->nhoff = (&hdr->nexthdr) - skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) switch (hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) case IPV6_SRCRT_TYPE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (accept_source_route < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) goto unknown_rh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* Silently discard invalid RTH type 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) goto unknown_rh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * This is the routing header forwarding algorithm from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) * RFC 2460, page 16.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) n = hdr->hdrlen >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) if (hdr->segments_left > n) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) ((&hdr->segments_left) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) skb_network_header(skb)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) /* We are about to mangle packet header. Be careful!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) Do not damage packets queued somewhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (skb_cloned(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) /* the copy is a forwarded packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) __IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) IPSTATS_MIB_OUTDISCARDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) hdr = (struct ipv6_rt_hdr *)skb_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (skb->ip_summed == CHECKSUM_COMPLETE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) skb->ip_summed = CHECKSUM_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) i = n - --hdr->segments_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) rthdr = (struct rt0_hdr *) hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) addr = rthdr->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) addr += i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) switch (hdr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) #if IS_ENABLED(CONFIG_IPV6_MIP6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) case IPV6_SRCRT_TYPE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) IPPROTO_ROUTING) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!ipv6_chk_home_addr(dev_net(skb_dst(skb)->dev), addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (ipv6_addr_is_multicast(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INADDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) daddr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) *addr = ipv6_hdr(skb)->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) ipv6_hdr(skb)->daddr = daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) skb_dst_drop(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ip6_route_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if (skb_dst(skb)->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) skb_push(skb, skb->data - skb_network_header(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (skb_dst(skb)->dev->flags&IFF_LOOPBACK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (ipv6_hdr(skb)->hop_limit <= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) ipv6_hdr(skb)->hop_limit--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) goto looped_back;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) skb_push(skb, skb->data - skb_network_header(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) dst_input(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) unknown_rh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) (&hdr->type) - skb_network_header(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) static const struct inet6_protocol rthdr_protocol = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) .handler = ipv6_rthdr_rcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) .flags = INET6_PROTO_NOPOLICY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static const struct inet6_protocol destopt_protocol = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) .handler = ipv6_destopt_rcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) .flags = INET6_PROTO_NOPOLICY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) static const struct inet6_protocol nodata_protocol = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) .handler = dst_discard,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) .flags = INET6_PROTO_NOPOLICY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) int __init ipv6_exthdrs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) goto out_rthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) ret = inet6_add_protocol(&nodata_protocol, IPPROTO_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) goto out_destopt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) out_destopt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) out_rthdr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) void ipv6_exthdrs_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /**********************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) Hop-by-hop options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) **********************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * Note: we cannot rely on skb_dst(skb) before we assign it in ip6_route_input().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) return skb_dst(skb) ? ip6_dst_idev(skb_dst(skb)) : __in6_dev_get(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static inline struct net *ipv6_skb_net(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) return skb_dst(skb) ? dev_net(skb_dst(skb)->dev) : dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* Router Alert as of RFC 2711 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) static bool ipv6_hop_ra(struct sk_buff *skb, int optoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) const unsigned char *nh = skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (nh[optoff + 1] == 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) IP6CB(skb)->flags |= IP6SKB_ROUTERALERT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) memcpy(&IP6CB(skb)->ra, nh + optoff + 2, sizeof(IP6CB(skb)->ra));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) net_dbg_ratelimited("ipv6_hop_ra: wrong RA length %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) nh[optoff + 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* Jumbo payload */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static bool ipv6_hop_jumbo(struct sk_buff *skb, int optoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) const unsigned char *nh = skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct inet6_dev *idev = __in6_dev_get_safely(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct net *net = ipv6_skb_net(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) u32 pkt_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) net_dbg_ratelimited("ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) nh[optoff+1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (pkt_len <= IPV6_MAXPLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (ipv6_hdr(skb)->payload_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) __IP6_INC_STATS(net, idev, IPSTATS_MIB_INTRUNCATEDPKTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) IP6CB(skb)->flags |= IP6SKB_JUMBOGRAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* CALIPSO RFC 5570 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) static bool ipv6_hop_calipso(struct sk_buff *skb, int optoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) const unsigned char *nh = skb_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (nh[optoff + 1] < 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (nh[optoff + 6] * 4 + 8 > nh[optoff + 1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (!calipso_validate(skb, nh + optoff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) static const struct tlvtype_proc tlvprochopopt_lst[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) .type = IPV6_TLV_ROUTERALERT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) .func = ipv6_hop_ra,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) .type = IPV6_TLV_JUMBO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) .func = ipv6_hop_jumbo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) .type = IPV6_TLV_CALIPSO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) .func = ipv6_hop_calipso,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) { -1, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int ipv6_parse_hopopts(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct inet6_skb_parm *opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) struct net *net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) int extlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * skb_network_header(skb) is equal to skb->data, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * skb_network_header_len(skb) is always equal to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * sizeof(struct ipv6hdr) by definition of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) * hop-by-hop options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) !pskb_may_pull(skb, (sizeof(struct ipv6hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) ((skb_transport_header(skb)[1] + 1) << 3)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) fail_and_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) extlen = (skb_transport_header(skb)[1] + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (extlen > net->ipv6.sysctl.max_hbh_opts_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) goto fail_and_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) opt->flags |= IP6SKB_HOPBYHOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (ip6_parse_tlv(tlvprochopopt_lst, skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) net->ipv6.sysctl.max_hbh_opts_cnt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) skb->transport_header += extlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) opt = IP6CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) opt->nhoff = sizeof(struct ipv6hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * Creating outbound headers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * "build" functions work when skb is filled from head to tail (datagram)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * "push" functions work when headers are added from tail to head (tcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * In both cases we assume, that caller reserved enough room
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * for headers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static void ipv6_push_rthdr0(struct sk_buff *skb, u8 *proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) struct ipv6_rt_hdr *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) struct in6_addr **addr_p, struct in6_addr *saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) struct rt0_hdr *phdr, *ihdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) int hops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) ihdr = (struct rt0_hdr *) opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) phdr = skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) memcpy(phdr, ihdr, sizeof(struct rt0_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) hops = ihdr->rt_hdr.hdrlen >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (hops > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) memcpy(phdr->addr, ihdr->addr + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) (hops - 1) * sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) phdr->addr[hops - 1] = **addr_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) *addr_p = ihdr->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) phdr->rt_hdr.nexthdr = *proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) *proto = NEXTHDR_ROUTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static void ipv6_push_rthdr4(struct sk_buff *skb, u8 *proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) struct ipv6_rt_hdr *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) struct in6_addr **addr_p, struct in6_addr *saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) struct ipv6_sr_hdr *sr_phdr, *sr_ihdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) int plen, hops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) sr_ihdr = (struct ipv6_sr_hdr *)opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) plen = (sr_ihdr->hdrlen + 1) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) sr_phdr = skb_push(skb, plen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) memcpy(sr_phdr, sr_ihdr, sizeof(struct ipv6_sr_hdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) hops = sr_ihdr->first_segment + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) memcpy(sr_phdr->segments + 1, sr_ihdr->segments + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) (hops - 1) * sizeof(struct in6_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) sr_phdr->segments[0] = **addr_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) *addr_p = &sr_ihdr->segments[sr_ihdr->segments_left];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (sr_ihdr->hdrlen > hops * 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) int tlvs_offset, tlvs_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) tlvs_offset = (1 + hops * 2) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) tlvs_length = (sr_ihdr->hdrlen - hops * 2) << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) memcpy((char *)sr_phdr + tlvs_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) (char *)sr_ihdr + tlvs_offset, tlvs_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) #ifdef CONFIG_IPV6_SEG6_HMAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) if (sr_has_hmac(sr_phdr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct net *net = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (skb->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) net = dev_net(skb->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) else if (skb->sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) WARN_ON(!net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) if (net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) seg6_push_hmac(net, saddr, sr_phdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) sr_phdr->nexthdr = *proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) *proto = NEXTHDR_ROUTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) struct ipv6_rt_hdr *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct in6_addr **addr_p, struct in6_addr *saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) switch (opt->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) case IPV6_SRCRT_TYPE_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) case IPV6_SRCRT_STRICT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) case IPV6_SRCRT_TYPE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) case IPV6_SRCRT_TYPE_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) ipv6_push_rthdr4(skb, proto, opt, addr_p, saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct ipv6_opt_hdr *h = skb_push(skb, ipv6_optlen(opt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) memcpy(h, opt, ipv6_optlen(opt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) h->nexthdr = *proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) *proto = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) u8 *proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) struct in6_addr **daddr, struct in6_addr *saddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) if (opt->srcrt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) ipv6_push_rthdr(skb, proto, opt->srcrt, daddr, saddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * IPV6_RTHDRDSTOPTS is ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * unless IPV6_RTHDR is set (RFC3542).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (opt->dst0opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (opt->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (opt->dst1opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) EXPORT_SYMBOL(ipv6_push_frag_opts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct ipv6_txoptions *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) struct ipv6_txoptions *opt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (opt2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) long dif = (char *)opt2 - (char *)opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) memcpy(opt2, opt, opt->tot_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) if (opt2->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) *((char **)&opt2->hopopt) += dif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (opt2->dst0opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) *((char **)&opt2->dst0opt) += dif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (opt2->dst1opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) *((char **)&opt2->dst1opt) += dif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (opt2->srcrt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) *((char **)&opt2->srcrt) += dif;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) refcount_set(&opt2->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) return opt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) EXPORT_SYMBOL_GPL(ipv6_dup_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) static void ipv6_renew_option(int renewtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) struct ipv6_opt_hdr **dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct ipv6_opt_hdr *old,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) struct ipv6_opt_hdr *new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) int newtype, char **p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) struct ipv6_opt_hdr *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) src = (renewtype == newtype ? new : old);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (!src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) memcpy(*p, src, ipv6_optlen(src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) *dest = (struct ipv6_opt_hdr *)*p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) *p += CMSG_ALIGN(ipv6_optlen(*dest));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * ipv6_renew_options - replace a specific ext hdr with a new one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) * @sk: sock from which to allocate memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) * @opt: original options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) * @newtype: option type to replace in @opt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * @newopt: new option of type @newtype to replace (user-mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) * Returns a new set of options which is a copy of @opt with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) * option type @newtype replaced with @newopt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * @opt may be NULL, in which case a new set of options is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * containing just @newopt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * @newopt may be NULL, in which case the specified option type is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) * not copied into the new set of options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * The new set of options is allocated from the socket option memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * buffer of @sk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) struct ipv6_txoptions *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) int newtype, struct ipv6_opt_hdr *newopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) int tot_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) struct ipv6_txoptions *opt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (newtype != IPV6_HOPOPTS && opt->hopopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) if (newtype != IPV6_RTHDR && opt->srcrt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (newtype != IPV6_DSTOPTS && opt->dst1opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (newopt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) tot_len += CMSG_ALIGN(ipv6_optlen(newopt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) if (!tot_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) tot_len += sizeof(*opt2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) if (!opt2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) return ERR_PTR(-ENOBUFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) memset(opt2, 0, tot_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) refcount_set(&opt2->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) opt2->tot_len = tot_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) p = (char *)(opt2 + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) ipv6_renew_option(IPV6_HOPOPTS, &opt2->hopopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) (opt ? opt->hopopt : NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) newopt, newtype, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) ipv6_renew_option(IPV6_RTHDRDSTOPTS, &opt2->dst0opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) (opt ? opt->dst0opt : NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) newopt, newtype, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) ipv6_renew_option(IPV6_RTHDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) (struct ipv6_opt_hdr **)&opt2->srcrt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) (opt ? (struct ipv6_opt_hdr *)opt->srcrt : NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) newopt, newtype, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) ipv6_renew_option(IPV6_DSTOPTS, &opt2->dst1opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) (opt ? opt->dst1opt : NULL),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) newopt, newtype, &p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) return opt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) struct ipv6_txoptions *opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) * ignore the dest before srcrt unless srcrt is being included.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) * --yoshfuji
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) if (opt && opt->dst0opt && !opt->srcrt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (opt_space != opt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) memcpy(opt_space, opt, sizeof(*opt_space));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) opt = opt_space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) opt->dst0opt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) return opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) EXPORT_SYMBOL_GPL(ipv6_fixup_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * fl6_update_dst - update flowi destination address with info given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * by srcrt option, if any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * @fl6: flowi6 for which daddr is to be updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * @opt: struct ipv6_txoptions in which to look for srcrt opt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * @orig: copy of original daddr address if modified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) * Returns NULL if no txoptions or no srcrt, otherwise returns orig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) * and initial value of fl6->daddr set in orig
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) const struct ipv6_txoptions *opt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct in6_addr *orig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) if (!opt || !opt->srcrt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) *orig = fl6->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) switch (opt->srcrt->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) case IPV6_SRCRT_TYPE_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) case IPV6_SRCRT_STRICT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) case IPV6_SRCRT_TYPE_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) case IPV6_SRCRT_TYPE_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)opt->srcrt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) fl6->daddr = srh->segments[srh->segments_left];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) EXPORT_SYMBOL_GPL(fl6_update_dst);