wpan.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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[MAC802154_FRAME_HARD_HEADER_LEN];
  119. u16 fc;
  120. if (!daddr)
  121. return -EINVAL;
  122. head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */
  123. fc = mac_cb_type(skb);
  124. if (!saddr) {
  125. spin_lock_bh(&priv->mib_lock);
  126. if (priv->short_addr == IEEE802154_ADDR_BROADCAST ||
  127. priv->short_addr == IEEE802154_ADDR_UNDEF ||
  128. priv->pan_id == IEEE802154_PANID_BROADCAST) {
  129. dev_addr.addr_type = IEEE802154_ADDR_LONG;
  130. memcpy(dev_addr.hwaddr, dev->dev_addr,
  131. IEEE802154_ADDR_LEN);
  132. } else {
  133. dev_addr.addr_type = IEEE802154_ADDR_SHORT;
  134. dev_addr.short_addr = priv->short_addr;
  135. }
  136. dev_addr.pan_id = priv->pan_id;
  137. saddr = &dev_addr;
  138. spin_unlock_bh(&priv->mib_lock);
  139. }
  140. if (daddr->addr_type != IEEE802154_ADDR_NONE) {
  141. fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
  142. head[pos++] = daddr->pan_id & 0xff;
  143. head[pos++] = daddr->pan_id >> 8;
  144. if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
  145. head[pos++] = daddr->short_addr & 0xff;
  146. head[pos++] = daddr->short_addr >> 8;
  147. } else {
  148. mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
  149. pos += IEEE802154_ADDR_LEN;
  150. }
  151. }
  152. if (saddr->addr_type != IEEE802154_ADDR_NONE) {
  153. fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
  154. if ((saddr->pan_id == daddr->pan_id) &&
  155. (saddr->pan_id != IEEE802154_PANID_BROADCAST)) {
  156. /* PANID compression/intra PAN */
  157. fc |= IEEE802154_FC_INTRA_PAN;
  158. } else {
  159. head[pos++] = saddr->pan_id & 0xff;
  160. head[pos++] = saddr->pan_id >> 8;
  161. }
  162. if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
  163. head[pos++] = saddr->short_addr & 0xff;
  164. head[pos++] = saddr->short_addr >> 8;
  165. } else {
  166. mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
  167. pos += IEEE802154_ADDR_LEN;
  168. }
  169. }
  170. head[0] = fc;
  171. head[1] = fc >> 8;
  172. memcpy(skb_push(skb, pos), head, pos);
  173. return pos;
  174. }
  175. static int
  176. mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  177. {
  178. const u8 *hdr = skb_mac_header(skb);
  179. const u8 *tail = skb_tail_pointer(skb);
  180. struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
  181. u16 fc;
  182. int da_type;
  183. if (hdr + 3 > tail)
  184. goto malformed;
  185. fc = hdr[0] | (hdr[1] << 8);
  186. hdr += 3;
  187. da_type = IEEE802154_FC_DAMODE(fc);
  188. addr->addr_type = IEEE802154_FC_SAMODE(fc);
  189. switch (da_type) {
  190. case IEEE802154_ADDR_NONE:
  191. if (fc & IEEE802154_FC_INTRA_PAN)
  192. goto malformed;
  193. break;
  194. case IEEE802154_ADDR_LONG:
  195. if (fc & IEEE802154_FC_INTRA_PAN) {
  196. if (hdr + 2 > tail)
  197. goto malformed;
  198. addr->pan_id = hdr[0] | (hdr[1] << 8);
  199. hdr += 2;
  200. }
  201. if (hdr + IEEE802154_ADDR_LEN > tail)
  202. goto malformed;
  203. hdr += IEEE802154_ADDR_LEN;
  204. break;
  205. case IEEE802154_ADDR_SHORT:
  206. if (fc & IEEE802154_FC_INTRA_PAN) {
  207. if (hdr + 2 > tail)
  208. goto malformed;
  209. addr->pan_id = hdr[0] | (hdr[1] << 8);
  210. hdr += 2;
  211. }
  212. if (hdr + 2 > tail)
  213. goto malformed;
  214. hdr += 2;
  215. break;
  216. default:
  217. goto malformed;
  218. }
  219. switch (addr->addr_type) {
  220. case IEEE802154_ADDR_NONE:
  221. break;
  222. case IEEE802154_ADDR_LONG:
  223. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  224. if (hdr + 2 > tail)
  225. goto malformed;
  226. addr->pan_id = hdr[0] | (hdr[1] << 8);
  227. hdr += 2;
  228. }
  229. if (hdr + IEEE802154_ADDR_LEN > tail)
  230. goto malformed;
  231. mac802154_haddr_copy_swap(addr->hwaddr, hdr);
  232. hdr += IEEE802154_ADDR_LEN;
  233. break;
  234. case IEEE802154_ADDR_SHORT:
  235. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  236. if (hdr + 2 > tail)
  237. goto malformed;
  238. addr->pan_id = hdr[0] | (hdr[1] << 8);
  239. hdr += 2;
  240. }
  241. if (hdr + 2 > tail)
  242. goto malformed;
  243. addr->short_addr = hdr[0] | (hdr[1] << 8);
  244. hdr += 2;
  245. break;
  246. default:
  247. goto malformed;
  248. }
  249. return sizeof(struct ieee802154_addr);
  250. malformed:
  251. pr_debug("malformed packet\n");
  252. return 0;
  253. }
  254. static netdev_tx_t
  255. mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
  256. {
  257. struct mac802154_sub_if_data *priv;
  258. u8 chan, page;
  259. priv = netdev_priv(dev);
  260. spin_lock_bh(&priv->mib_lock);
  261. chan = priv->chan;
  262. page = priv->page;
  263. spin_unlock_bh(&priv->mib_lock);
  264. if (chan == MAC802154_CHAN_NONE ||
  265. page >= WPAN_NUM_PAGES ||
  266. chan >= WPAN_NUM_CHANNELS) {
  267. kfree_skb(skb);
  268. return NETDEV_TX_OK;
  269. }
  270. skb->skb_iif = dev->ifindex;
  271. dev->stats.tx_packets++;
  272. dev->stats.tx_bytes += skb->len;
  273. return mac802154_tx(priv->hw, skb, page, chan);
  274. }
  275. static struct header_ops mac802154_header_ops = {
  276. .create = mac802154_header_create,
  277. .parse = mac802154_header_parse,
  278. };
  279. static const struct net_device_ops mac802154_wpan_ops = {
  280. .ndo_open = mac802154_slave_open,
  281. .ndo_stop = mac802154_slave_close,
  282. .ndo_start_xmit = mac802154_wpan_xmit,
  283. .ndo_do_ioctl = mac802154_wpan_ioctl,
  284. .ndo_set_mac_address = mac802154_wpan_mac_addr,
  285. };
  286. void mac802154_wpan_setup(struct net_device *dev)
  287. {
  288. struct mac802154_sub_if_data *priv;
  289. dev->addr_len = IEEE802154_ADDR_LEN;
  290. memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
  291. dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
  292. dev->header_ops = &mac802154_header_ops;
  293. dev->needed_tailroom = 2; /* FCS */
  294. dev->mtu = IEEE802154_MTU;
  295. dev->tx_queue_len = 10;
  296. dev->type = ARPHRD_IEEE802154;
  297. dev->flags = IFF_NOARP | IFF_BROADCAST;
  298. dev->watchdog_timeo = 0;
  299. dev->destructor = free_netdev;
  300. dev->netdev_ops = &mac802154_wpan_ops;
  301. dev->ml_priv = &mac802154_mlme_wpan;
  302. priv = netdev_priv(dev);
  303. priv->type = IEEE802154_DEV_WPAN;
  304. priv->chan = MAC802154_CHAN_NONE;
  305. priv->page = 0;
  306. spin_lock_init(&priv->mib_lock);
  307. get_random_bytes(&priv->bsn, 1);
  308. get_random_bytes(&priv->dsn, 1);
  309. priv->pan_id = IEEE802154_PANID_BROADCAST;
  310. priv->short_addr = IEEE802154_ADDR_BROADCAST;
  311. }
  312. static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
  313. {
  314. return netif_rx_ni(skb);
  315. }
  316. static int
  317. mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
  318. {
  319. pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
  320. spin_lock_bh(&sdata->mib_lock);
  321. switch (mac_cb(skb)->da.addr_type) {
  322. case IEEE802154_ADDR_NONE:
  323. if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE)
  324. /* FIXME: check if we are PAN coordinator */
  325. skb->pkt_type = PACKET_OTHERHOST;
  326. else
  327. /* ACK comes with both addresses empty */
  328. skb->pkt_type = PACKET_HOST;
  329. break;
  330. case IEEE802154_ADDR_LONG:
  331. if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
  332. mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
  333. skb->pkt_type = PACKET_OTHERHOST;
  334. else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr,
  335. IEEE802154_ADDR_LEN))
  336. skb->pkt_type = PACKET_HOST;
  337. else
  338. skb->pkt_type = PACKET_OTHERHOST;
  339. break;
  340. case IEEE802154_ADDR_SHORT:
  341. if (mac_cb(skb)->da.pan_id != sdata->pan_id &&
  342. mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST)
  343. skb->pkt_type = PACKET_OTHERHOST;
  344. else if (mac_cb(skb)->da.short_addr == sdata->short_addr)
  345. skb->pkt_type = PACKET_HOST;
  346. else if (mac_cb(skb)->da.short_addr ==
  347. IEEE802154_ADDR_BROADCAST)
  348. skb->pkt_type = PACKET_BROADCAST;
  349. else
  350. skb->pkt_type = PACKET_OTHERHOST;
  351. break;
  352. default:
  353. break;
  354. }
  355. spin_unlock_bh(&sdata->mib_lock);
  356. skb->dev = sdata->dev;
  357. sdata->dev->stats.rx_packets++;
  358. sdata->dev->stats.rx_bytes += skb->len;
  359. switch (mac_cb_type(skb)) {
  360. case IEEE802154_FC_TYPE_DATA:
  361. return mac802154_process_data(sdata->dev, skb);
  362. default:
  363. pr_warning("ieee802154: bad frame received (type = %d)\n",
  364. mac_cb_type(skb));
  365. kfree_skb(skb);
  366. return NET_RX_DROP;
  367. }
  368. }
  369. static int mac802154_parse_frame_start(struct sk_buff *skb)
  370. {
  371. u8 *head = skb->data;
  372. u16 fc;
  373. if (mac802154_fetch_skb_u16(skb, &fc) ||
  374. mac802154_fetch_skb_u8(skb, &(mac_cb(skb)->seq)))
  375. goto err;
  376. pr_debug("fc: %04x dsn: %02x\n", fc, head[2]);
  377. mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc);
  378. mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc);
  379. mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc);
  380. if (fc & IEEE802154_FC_INTRA_PAN)
  381. mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN;
  382. if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) {
  383. if (mac802154_fetch_skb_u16(skb, &(mac_cb(skb)->da.pan_id)))
  384. goto err;
  385. /* source PAN id compression */
  386. if (mac_cb_is_intrapan(skb))
  387. mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id;
  388. pr_debug("dest PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
  389. if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) {
  390. u16 *da = &(mac_cb(skb)->da.short_addr);
  391. if (mac802154_fetch_skb_u16(skb, da))
  392. goto err;
  393. pr_debug("destination address is short: %04x\n",
  394. mac_cb(skb)->da.short_addr);
  395. } else {
  396. if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
  397. goto err;
  398. mac802154_haddr_copy_swap(mac_cb(skb)->da.hwaddr,
  399. skb->data);
  400. skb_pull(skb, IEEE802154_ADDR_LEN);
  401. pr_debug("destination address is hardware\n");
  402. }
  403. }
  404. if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) {
  405. /* non PAN-compression, fetch source address id */
  406. if (!(mac_cb_is_intrapan(skb))) {
  407. u16 *sa_pan = &(mac_cb(skb)->sa.pan_id);
  408. if (mac802154_fetch_skb_u16(skb, sa_pan))
  409. goto err;
  410. }
  411. pr_debug("source PAN addr: %04x\n", mac_cb(skb)->da.pan_id);
  412. if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) {
  413. u16 *sa = &(mac_cb(skb)->sa.short_addr);
  414. if (mac802154_fetch_skb_u16(skb, sa))
  415. goto err;
  416. pr_debug("source address is short: %04x\n",
  417. mac_cb(skb)->sa.short_addr);
  418. } else {
  419. if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN))
  420. goto err;
  421. mac802154_haddr_copy_swap(mac_cb(skb)->sa.hwaddr,
  422. skb->data);
  423. skb_pull(skb, IEEE802154_ADDR_LEN);
  424. pr_debug("source address is hardware\n");
  425. }
  426. }
  427. return 0;
  428. err:
  429. return -EINVAL;
  430. }
  431. void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
  432. {
  433. int ret;
  434. struct sk_buff *sskb;
  435. struct mac802154_sub_if_data *sdata;
  436. ret = mac802154_parse_frame_start(skb);
  437. if (ret) {
  438. pr_debug("got invalid frame\n");
  439. return;
  440. }
  441. rcu_read_lock();
  442. list_for_each_entry_rcu(sdata, &priv->slaves, list) {
  443. if (sdata->type != IEEE802154_DEV_WPAN)
  444. continue;
  445. sskb = skb_clone(skb, GFP_ATOMIC);
  446. if (sskb)
  447. mac802154_subif_frame(sdata, sskb);
  448. }
  449. rcu_read_unlock();
  450. }