wpan.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Copyright 2007-2012 Siemens AG
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * Written by:
  18. * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  19. * Sergey Lapin <slapin@ossfans.org>
  20. * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
  21. * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
  22. */
  23. #include <linux/netdevice.h>
  24. #include <linux/module.h>
  25. #include <linux/if_arp.h>
  26. #include <net/rtnetlink.h>
  27. #include <linux/nl802154.h>
  28. #include <net/af_ieee802154.h>
  29. #include <net/mac802154.h>
  30. #include <net/ieee802154_netdev.h>
  31. #include <net/ieee802154.h>
  32. #include <net/wpan-phy.h>
  33. #include "mac802154.h"
  34. static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val)
  35. {
  36. if (unlikely(!pskb_may_pull(skb, 1)))
  37. return -EINVAL;
  38. *val = skb->data[0];
  39. skb_pull(skb, 1);
  40. return 0;
  41. }
  42. static inline int mac802154_fetch_skb_u16(struct sk_buff *skb, u16 *val)
  43. {
  44. if (unlikely(!pskb_may_pull(skb, 2)))
  45. return -EINVAL;
  46. *val = skb->data[0] | (skb->data[1] << 8);
  47. skb_pull(skb, 2);
  48. return 0;
  49. }
  50. static inline void mac802154_haddr_copy_swap(u8 *dest, const u8 *src)
  51. {
  52. int i;
  53. for (i = 0; i < IEEE802154_ADDR_LEN; i++)
  54. dest[IEEE802154_ADDR_LEN - i - 1] = src[i];
  55. }
  56. static int
  57. mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  58. {
  59. struct mac802154_sub_if_data *priv = netdev_priv(dev);
  60. struct sockaddr_ieee802154 *sa =
  61. (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
  62. int err = -ENOIOCTLCMD;
  63. spin_lock_bh(&priv->mib_lock);
  64. switch (cmd) {
  65. case SIOCGIFADDR:
  66. if (priv->pan_id == IEEE802154_PANID_BROADCAST ||
  67. priv->short_addr == IEEE802154_ADDR_BROADCAST) {
  68. err = -EADDRNOTAVAIL;
  69. break;
  70. }
  71. sa->family = AF_IEEE802154;
  72. sa->addr.addr_type = IEEE802154_ADDR_SHORT;
  73. sa->addr.pan_id = priv->pan_id;
  74. sa->addr.short_addr = priv->short_addr;
  75. err = 0;
  76. break;
  77. case SIOCSIFADDR:
  78. dev_warn(&dev->dev,
  79. "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n");
  80. if (sa->family != AF_IEEE802154 ||
  81. sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
  82. sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
  83. sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
  84. sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
  85. err = -EINVAL;
  86. break;
  87. }
  88. priv->pan_id = sa->addr.pan_id;
  89. priv->short_addr = sa->addr.short_addr;
  90. err = 0;
  91. break;
  92. }
  93. spin_unlock_bh(&priv->mib_lock);
  94. return err;
  95. }
  96. static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
  97. {
  98. struct sockaddr *addr = p;
  99. if (netif_running(dev))
  100. return -EBUSY;
  101. /* FIXME: validate addr */
  102. memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
  103. mac802154_dev_set_ieee_addr(dev);
  104. return 0;
  105. }
  106. static int mac802154_header_create(struct sk_buff *skb,
  107. struct net_device *dev,
  108. unsigned short type,
  109. const void *_daddr,
  110. const void *_saddr,
  111. unsigned len)
  112. {
  113. const struct ieee802154_addr *saddr = _saddr;
  114. const struct ieee802154_addr *daddr = _daddr;
  115. struct ieee802154_addr dev_addr;
  116. struct mac802154_sub_if_data *priv = netdev_priv(dev);
  117. int pos = 2;
  118. u8 *head;
  119. u16 fc;
  120. if (!daddr)
  121. return -EINVAL;
  122. head = kzalloc(MAC802154_FRAME_HARD_HEADER_LEN, GFP_KERNEL);
  123. if (head == NULL)
  124. return -ENOMEM;
  125. head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
  126. fc = mac_cb_type(skb);
  127. if (!saddr) {
  128. spin_lock_bh(&priv->mib_lock);
  129. if (priv->short_addr == IEEE802154_ADDR_BROADCAST ||
  130. priv->short_addr == IEEE802154_ADDR_UNDEF ||
  131. priv->pan_id == IEEE802154_PANID_BROADCAST) {
  132. dev_addr.addr_type = IEEE802154_ADDR_LONG;
  133. memcpy(dev_addr.hwaddr, dev->dev_addr,
  134. IEEE802154_ADDR_LEN);
  135. } else {
  136. dev_addr.addr_type = IEEE802154_ADDR_SHORT;
  137. dev_addr.short_addr = priv->short_addr;
  138. }
  139. dev_addr.pan_id = priv->pan_id;
  140. saddr = &dev_addr;
  141. spin_unlock_bh(&priv->mib_lock);
  142. }
  143. if (daddr->addr_type != IEEE802154_ADDR_NONE) {
  144. fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
  145. head[pos++] = daddr->pan_id & 0xff;
  146. head[pos++] = daddr->pan_id >> 8;
  147. if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
  148. head[pos++] = daddr->short_addr & 0xff;
  149. head[pos++] = daddr->short_addr >> 8;
  150. } else {
  151. mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
  152. pos += IEEE802154_ADDR_LEN;
  153. }
  154. }
  155. if (saddr->addr_type != IEEE802154_ADDR_NONE) {
  156. fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
  157. if ((saddr->pan_id == daddr->pan_id) &&
  158. (saddr->pan_id != IEEE802154_PANID_BROADCAST)) {
  159. /* PANID compression/intra PAN */
  160. fc |= IEEE802154_FC_INTRA_PAN;
  161. } else {
  162. head[pos++] = saddr->pan_id & 0xff;
  163. head[pos++] = saddr->pan_id >> 8;
  164. }
  165. if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
  166. head[pos++] = saddr->short_addr & 0xff;
  167. head[pos++] = saddr->short_addr >> 8;
  168. } else {
  169. mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
  170. pos += IEEE802154_ADDR_LEN;
  171. }
  172. }
  173. head[0] = fc;
  174. head[1] = fc >> 8;
  175. memcpy(skb_push(skb, pos), head, pos);
  176. kfree(head);
  177. return pos;
  178. }
  179. static int
  180. mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  181. {
  182. const u8 *hdr = skb_mac_header(skb);
  183. const u8 *tail = skb_tail_pointer(skb);
  184. struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
  185. u16 fc;
  186. int da_type;
  187. if (hdr + 3 > tail)
  188. goto malformed;
  189. fc = hdr[0] | (hdr[1] << 8);
  190. hdr += 3;
  191. da_type = IEEE802154_FC_DAMODE(fc);
  192. addr->addr_type = IEEE802154_FC_SAMODE(fc);
  193. switch (da_type) {
  194. case IEEE802154_ADDR_NONE:
  195. if (fc & IEEE802154_FC_INTRA_PAN)
  196. goto malformed;
  197. break;
  198. case IEEE802154_ADDR_LONG:
  199. if (fc & IEEE802154_FC_INTRA_PAN) {
  200. if (hdr + 2 > tail)
  201. goto malformed;
  202. addr->pan_id = hdr[0] | (hdr[1] << 8);
  203. hdr += 2;
  204. }
  205. if (hdr + IEEE802154_ADDR_LEN > tail)
  206. goto malformed;
  207. hdr += IEEE802154_ADDR_LEN;
  208. break;
  209. case IEEE802154_ADDR_SHORT:
  210. if (fc & IEEE802154_FC_INTRA_PAN) {
  211. if (hdr + 2 > tail)
  212. goto malformed;
  213. addr->pan_id = hdr[0] | (hdr[1] << 8);
  214. hdr += 2;
  215. }
  216. if (hdr + 2 > tail)
  217. goto malformed;
  218. hdr += 2;
  219. break;
  220. default:
  221. goto malformed;
  222. }
  223. switch (addr->addr_type) {
  224. case IEEE802154_ADDR_NONE:
  225. break;
  226. case IEEE802154_ADDR_LONG:
  227. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  228. if (hdr + 2 > tail)
  229. goto malformed;
  230. addr->pan_id = hdr[0] | (hdr[1] << 8);
  231. hdr += 2;
  232. }
  233. if (hdr + IEEE802154_ADDR_LEN > tail)
  234. goto malformed;
  235. mac802154_haddr_copy_swap(addr->hwaddr, hdr);
  236. hdr += IEEE802154_ADDR_LEN;
  237. break;
  238. case IEEE802154_ADDR_SHORT:
  239. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  240. if (hdr + 2 > tail)
  241. goto malformed;
  242. addr->pan_id = hdr[0] | (hdr[1] << 8);
  243. hdr += 2;
  244. }
  245. if (hdr + 2 > tail)
  246. goto malformed;
  247. addr->short_addr = hdr[0] | (hdr[1] << 8);
  248. hdr += 2;
  249. break;
  250. default:
  251. goto malformed;
  252. }
  253. return sizeof(struct ieee802154_addr);
  254. malformed:
  255. pr_debug("malformed packet\n");
  256. return 0;
  257. }
  258. static netdev_tx_t
  259. mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
  260. {
  261. struct mac802154_sub_if_data *priv;
  262. u8 chan, page;
  263. priv = netdev_priv(dev);
  264. spin_lock_bh(&priv->mib_lock);
  265. chan = priv->chan;
  266. page = priv->page;
  267. spin_unlock_bh(&priv->mib_lock);
  268. if (chan == MAC802154_CHAN_NONE ||
  269. page >= WPAN_NUM_PAGES ||
  270. chan >= WPAN_NUM_CHANNELS)
  271. return NETDEV_TX_OK;
  272. skb->skb_iif = dev->ifindex;
  273. dev->stats.tx_packets++;
  274. dev->stats.tx_bytes += skb->len;
  275. return mac802154_tx(priv->hw, skb, page, chan);
  276. }
  277. static struct header_ops mac802154_header_ops = {
  278. .create = mac802154_header_create,
  279. .parse = mac802154_header_parse,
  280. };
  281. static const struct net_device_ops mac802154_wpan_ops = {
  282. .ndo_open = mac802154_slave_open,
  283. .ndo_stop = mac802154_slave_close,
  284. .ndo_start_xmit = mac802154_wpan_xmit,
  285. .ndo_do_ioctl = mac802154_wpan_ioctl,
  286. .ndo_set_mac_address = mac802154_wpan_mac_addr,
  287. };
  288. void mac802154_wpan_setup(struct net_device *dev)
  289. {
  290. struct mac802154_sub_if_data *priv;
  291. dev->addr_len = IEEE802154_ADDR_LEN;
  292. memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
  293. dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
  294. dev->header_ops = &mac802154_header_ops;
  295. dev->needed_tailroom = 2; /* FCS */
  296. dev->mtu = IEEE802154_MTU;
  297. dev->tx_queue_len = 10;
  298. dev->type = ARPHRD_IEEE802154;
  299. dev->flags = IFF_NOARP | IFF_BROADCAST;
  300. dev->watchdog_timeo = 0;
  301. dev->destructor = free_netdev;
  302. dev->netdev_ops = &mac802154_wpan_ops;
  303. dev->ml_priv = &mac802154_mlme_wpan;
  304. priv = netdev_priv(dev);
  305. priv->type = IEEE802154_DEV_WPAN;
  306. priv->chan = MAC802154_CHAN_NONE;
  307. priv->page = 0;
  308. spin_lock_init(&priv->mib_lock);
  309. get_random_bytes(&priv->bsn, 1);
  310. get_random_bytes(&priv->dsn, 1);
  311. priv->pan_id = IEEE802154_PANID_BROADCAST;
  312. priv->short_addr = IEEE802154_ADDR_BROADCAST;
  313. }
  314. static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
  315. {
  316. return netif_rx(skb);
  317. }
  318. static int
  319. mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
  320. {
  321. pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
  322. spin_lock_bh(&sdata->mib_lock);
  323. switch (mac_cb(skb)->da.addr_type) {
  324. case IEEE802154_ADDR_NONE:
  325. if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE)
  326. /* FIXME: check if we are PAN coordinator */
  327. skb->pkt_type = PACKET_OTHERHOST;
  328. else
  329. /* ACK comes with both addresses empty */
  330. skb->pkt_type = PACKET_HOST;
  331. break;
  332. case IEEE802154_ADDR_LONG:
  333. if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
  334. mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
  335. skb->pkt_type = PACKET_OTHERHOST;
  336. else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr,
  337. IEEE802154_ADDR_LEN))
  338. skb->pkt_type = PACKET_HOST;
  339. else
  340. skb->pkt_type = PACKET_OTHERHOST;
  341. break;
  342. case IEEE802154_ADDR_SHORT:
  343. if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
  344. mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
  345. skb->pkt_type = PACKET_OTHERHOST;
  346. else if (mac_cb(skb)->da.short_addr == sdata->short_addr)
  347. skb->pkt_type = PACKET_HOST;
  348. else if (mac_cb(skb)->da.short_addr ==
  349. IEEE802154_ADDR_BROADCAST)
  350. skb->pkt_type = PACKET_BROADCAST;
  351. else
  352. skb->pkt_type = PACKET_OTHERHOST;
  353. break;
  354. default:
  355. break;
  356. }
  357. spin_unlock_bh(&sdata->mib_lock);
  358. skb->dev = sdata->dev;
  359. sdata->dev->stats.rx_packets++;
  360. sdata->dev->stats.rx_bytes += skb->len;
  361. switch (mac_cb_type(skb)) {
  362. case IEEE802154_FC_TYPE_DATA:
  363. return mac802154_process_data(sdata->dev, skb);
  364. default:
  365. pr_warning("ieee802154: bad frame received (type = %d)\n",
  366. mac_cb_type(skb));
  367. kfree_skb(skb);
  368. return NET_RX_DROP;
  369. }
  370. }
  371. static int mac802154_parse_frame_start(struct sk_buff *skb)
  372. {
  373. u8 *head = skb->data;
  374. u16 fc;
  375. if (mac802154_fetch_skb_u16(skb, &fc) ||
  376. mac802154_fetch_skb_u8(skb, &(mac_cb(skb)->seq)))
  377. goto err;
  378. pr_debug("fc: %04x dsn: %02x\n", fc, head[2]);
  379. mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc);
  380. mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
  381. mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
  382. if (fc & IEEE802154_FC_INTRA_PAN)
  383. mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN;
  384. if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) {
  385. if (mac802154_fetch_skb_u16(skb, &(mac_cb(skb)->da.pan_id)))
  386. goto err;
  387. /* source PAN id compression */
  388. if (mac_cb_is_intrapan(skb))
  389. mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
  390. pr_debug("dest PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
  391. if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) {
  392. u16 *da = &(mac_cb(skb)->da.short_addr);
  393. if (mac802154_fetch_skb_u16(skb, da))
  394. goto err;
  395. pr_debug("destination address is short: %04x\n",
  396. mac_cb(skb)->da.short_addr);
  397. } else {
  398. if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
  399. goto err;
  400. mac802154_haddr_copy_swap(mac_cb(skb)->da.hwaddr,
  401. skb->data);
  402. skb_pull(skb, IEEE802154_ADDR_LEN);
  403. pr_debug("destination address is hardware\n");
  404. }
  405. }
  406. if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) {
  407. /* non PAN-compression, fetch source address id */
  408. if (!(mac_cb_is_intrapan(skb))) {
  409. u16 *sa_pan = &(mac_cb(skb)->sa.pan_id);
  410. if (mac802154_fetch_skb_u16(skb, sa_pan))
  411. goto err;
  412. }
  413. pr_debug("source PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
  414. if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
  415. u16 *sa = &(mac_cb(skb)->sa.short_addr);
  416. if (mac802154_fetch_skb_u16(skb, sa))
  417. goto err;
  418. pr_debug("source address is short: %04x\n",
  419. mac_cb(skb)->sa.short_addr);
  420. } else {
  421. if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
  422. goto err;
  423. mac802154_haddr_copy_swap(mac_cb(skb)->sa.hwaddr,
  424. skb->data);
  425. skb_pull(skb, IEEE802154_ADDR_LEN);
  426. pr_debug("source address is hardware\n");
  427. }
  428. }
  429. return 0;
  430. err:
  431. return -EINVAL;
  432. }
  433. void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
  434. {
  435. int ret;
  436. struct sk_buff *sskb;
  437. struct mac802154_sub_if_data *sdata;
  438. ret = mac802154_parse_frame_start(skb);
  439. if (ret) {
  440. pr_debug("got invalid frame\n");
  441. return;
  442. }
  443. rcu_read_lock();
  444. list_for_each_entry_rcu(sdata, &priv->slaves, list) {
  445. if (sdata->type != IEEE802154_DEV_WPAN)
  446. continue;
  447. sskb = skb_clone(skb, GFP_ATOMIC);
  448. if (sskb)
  449. mac802154_subif_frame(sdata, sskb);
  450. }
  451. rcu_read_unlock();
  452. }