^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/if_arp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <net/6lowpan.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <net/mac802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <net/ieee802154_netdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "6lowpan_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define LOWPAN_DISPATCH_FIRST 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define LOWPAN_DISPATCH_FRAG_MASK 0xf8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define LOWPAN_DISPATCH_NALP 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define LOWPAN_DISPATCH_ESC 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define LOWPAN_DISPATCH_HC1 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define LOWPAN_DISPATCH_DFF 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define LOWPAN_DISPATCH_BC0 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define LOWPAN_DISPATCH_MESH 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static int lowpan_give_skb_to_device(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) skb->protocol = htons(ETH_P_IPV6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) skb->dev->stats.rx_packets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) skb->dev->stats.rx_bytes += skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return netif_rx(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int lowpan_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) switch (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) case RX_CONTINUE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* nobody cared about this packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) net_warn_ratelimited("%s: received unknown dispatch\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) case RX_DROP_UNUSABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) case RX_DROP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return NET_RX_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case RX_QUEUED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return lowpan_give_skb_to_device(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return NET_RX_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static inline bool lowpan_is_frag1(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAG1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static inline bool lowpan_is_fragn(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return (dispatch & LOWPAN_DISPATCH_FRAG_MASK) == LOWPAN_DISPATCH_FRAGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static lowpan_rx_result lowpan_rx_h_frag(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!(lowpan_is_frag1(*skb_network_header(skb)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) lowpan_is_fragn(*skb_network_header(skb))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ret = lowpan_frag_rcv(skb, *skb_network_header(skb) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) LOWPAN_DISPATCH_FRAG_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (ret == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return RX_QUEUED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Packet is freed by lowpan_frag_rcv on error or put into the frag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * bucket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return RX_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int lowpan_iphc_decompress(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct ieee802154_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return lowpan_header_decompress(skb, skb->dev, &hdr.dest, &hdr.source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static lowpan_rx_result lowpan_rx_h_iphc(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!lowpan_is_iphc(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /* Setting datagram_offset to zero indicates non frag handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * while doing lowpan_header_decompress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) lowpan_802154_cb(skb)->d_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ret = lowpan_iphc_decompress(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return RX_DROP_UNUSABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return RX_QUEUED;
^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) lowpan_rx_result lowpan_rx_h_ipv6(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!lowpan_is_ipv6(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Pull off the 1-byte of 6lowpan header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) skb_pull(skb, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return RX_QUEUED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static inline bool lowpan_is_esc(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return dispatch == LOWPAN_DISPATCH_ESC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static lowpan_rx_result lowpan_rx_h_esc(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!lowpan_is_esc(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) net_warn_ratelimited("%s: %s\n", skb->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "6LoWPAN ESC not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return RX_DROP_UNUSABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static inline bool lowpan_is_hc1(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return dispatch == LOWPAN_DISPATCH_HC1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static lowpan_rx_result lowpan_rx_h_hc1(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!lowpan_is_hc1(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) net_warn_ratelimited("%s: %s\n", skb->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "6LoWPAN HC1 not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return RX_DROP_UNUSABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static inline bool lowpan_is_dff(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return dispatch == LOWPAN_DISPATCH_DFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static lowpan_rx_result lowpan_rx_h_dff(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!lowpan_is_dff(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) net_warn_ratelimited("%s: %s\n", skb->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "6LoWPAN DFF not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return RX_DROP_UNUSABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static inline bool lowpan_is_bc0(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return dispatch == LOWPAN_DISPATCH_BC0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static lowpan_rx_result lowpan_rx_h_bc0(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!lowpan_is_bc0(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) net_warn_ratelimited("%s: %s\n", skb->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) "6LoWPAN BC0 not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return RX_DROP_UNUSABLE;
^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) static inline bool lowpan_is_mesh(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_MESH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static lowpan_rx_result lowpan_rx_h_mesh(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!lowpan_is_mesh(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return RX_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) net_warn_ratelimited("%s: %s\n", skb->dev->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) "6LoWPAN MESH not supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return RX_DROP_UNUSABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int lowpan_invoke_rx_handlers(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) lowpan_rx_result res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #define CALL_RXH(rxh) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) res = rxh(skb); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (res != RX_CONTINUE) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) goto rxh_next; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* likely at first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) CALL_RXH(lowpan_rx_h_iphc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) CALL_RXH(lowpan_rx_h_frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) CALL_RXH(lowpan_rx_h_ipv6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) CALL_RXH(lowpan_rx_h_esc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) CALL_RXH(lowpan_rx_h_hc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) CALL_RXH(lowpan_rx_h_dff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) CALL_RXH(lowpan_rx_h_bc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) CALL_RXH(lowpan_rx_h_mesh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) rxh_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return lowpan_rx_handlers_result(skb, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #undef CALL_RXH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static inline bool lowpan_is_nalp(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return (dispatch & LOWPAN_DISPATCH_FIRST) == LOWPAN_DISPATCH_NALP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Lookup for reserved dispatch values at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * https://www.iana.org/assignments/_6lowpan-parameters/_6lowpan-parameters.xhtml#_6lowpan-parameters-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * Last Updated: 2015-01-22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static inline bool lowpan_is_reserved(u8 dispatch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return ((dispatch >= 0x44 && dispatch <= 0x4F) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) (dispatch >= 0x51 && dispatch <= 0x5F) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) (dispatch >= 0xc8 && dispatch <= 0xdf) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) dispatch >= 0xe8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* lowpan_rx_h_check checks on generic 6LoWPAN requirements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * in MAC and 6LoWPAN header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * Don't manipulate the skb here, it could be shared buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static inline bool lowpan_rx_h_check(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) __le16 fc = ieee802154_get_fc_from_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* check on ieee802154 conform 6LoWPAN header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (!ieee802154_is_data(fc) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) !ieee802154_skb_is_intra_pan_addressing(fc, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* check if we can dereference the dispatch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (unlikely(!skb->len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (lowpan_is_nalp(*skb_network_header(skb)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) lowpan_is_reserved(*skb_network_header(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) static int lowpan_rcv(struct sk_buff *skb, struct net_device *wdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) struct packet_type *pt, struct net_device *orig_wdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct net_device *ldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (wdev->type != ARPHRD_IEEE802154 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) skb->pkt_type == PACKET_OTHERHOST ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) !lowpan_rx_h_check(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ldev = wdev->ieee802154_ptr->lowpan_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!ldev || !netif_running(ldev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* Replacing skb->dev and followed rx handlers will manipulate skb. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) skb = skb_share_check(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) skb->dev = ldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* When receive frag1 it's likely that we manipulate the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * When recevie iphc we manipulate the data buffer. So we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * to unshare the buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (lowpan_is_frag1(*skb_network_header(skb)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) lowpan_is_iphc(*skb_network_header(skb))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) skb = skb_unshare(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return lowpan_invoke_rx_handlers(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return NET_RX_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static struct packet_type lowpan_packet_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .type = htons(ETH_P_IEEE802154),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .func = lowpan_rcv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) void lowpan_rx_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dev_add_pack(&lowpan_packet_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) void lowpan_rx_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dev_remove_pack(&lowpan_packet_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }