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