wpan.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  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 (mac_cb_is_ackreq(skb))
  125. fc |= IEEE802154_FC_ACK_REQ;
  126. if (!saddr) {
  127. spin_lock_bh(&priv->mib_lock);
  128. if (priv->short_addr == IEEE802154_ADDR_BROADCAST ||
  129. priv->short_addr == IEEE802154_ADDR_UNDEF ||
  130. priv->pan_id == IEEE802154_PANID_BROADCAST) {
  131. dev_addr.addr_type = IEEE802154_ADDR_LONG;
  132. memcpy(dev_addr.hwaddr, dev->dev_addr,
  133. IEEE802154_ADDR_LEN);
  134. } else {
  135. dev_addr.addr_type = IEEE802154_ADDR_SHORT;
  136. dev_addr.short_addr = priv->short_addr;
  137. }
  138. dev_addr.pan_id = priv->pan_id;
  139. saddr = &dev_addr;
  140. spin_unlock_bh(&priv->mib_lock);
  141. }
  142. if (daddr->addr_type != IEEE802154_ADDR_NONE) {
  143. fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT);
  144. head[pos++] = daddr->pan_id & 0xff;
  145. head[pos++] = daddr->pan_id >> 8;
  146. if (daddr->addr_type == IEEE802154_ADDR_SHORT) {
  147. head[pos++] = daddr->short_addr & 0xff;
  148. head[pos++] = daddr->short_addr >> 8;
  149. } else {
  150. mac802154_haddr_copy_swap(head + pos, daddr->hwaddr);
  151. pos += IEEE802154_ADDR_LEN;
  152. }
  153. }
  154. if (saddr->addr_type != IEEE802154_ADDR_NONE) {
  155. fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT);
  156. if ((saddr->pan_id == daddr->pan_id) &&
  157. (saddr->pan_id != IEEE802154_PANID_BROADCAST)) {
  158. /* PANID compression/intra PAN */
  159. fc |= IEEE802154_FC_INTRA_PAN;
  160. } else {
  161. head[pos++] = saddr->pan_id & 0xff;
  162. head[pos++] = saddr->pan_id >> 8;
  163. }
  164. if (saddr->addr_type == IEEE802154_ADDR_SHORT) {
  165. head[pos++] = saddr->short_addr & 0xff;
  166. head[pos++] = saddr->short_addr >> 8;
  167. } else {
  168. mac802154_haddr_copy_swap(head + pos, saddr->hwaddr);
  169. pos += IEEE802154_ADDR_LEN;
  170. }
  171. }
  172. head[0] = fc;
  173. head[1] = fc >> 8;
  174. memcpy(skb_push(skb, pos), head, pos);
  175. return pos;
  176. }
  177. static int
  178. mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
  179. {
  180. const u8 *hdr = skb_mac_header(skb);
  181. const u8 *tail = skb_tail_pointer(skb);
  182. struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
  183. u16 fc;
  184. int da_type;
  185. if (hdr + 3 > tail)
  186. goto malformed;
  187. fc = hdr[0] | (hdr[1] << 8);
  188. hdr += 3;
  189. da_type = IEEE802154_FC_DAMODE(fc);
  190. addr->addr_type = IEEE802154_FC_SAMODE(fc);
  191. switch (da_type) {
  192. case IEEE802154_ADDR_NONE:
  193. if (fc & IEEE802154_FC_INTRA_PAN)
  194. goto malformed;
  195. break;
  196. case IEEE802154_ADDR_LONG:
  197. if (fc & IEEE802154_FC_INTRA_PAN) {
  198. if (hdr + 2 > tail)
  199. goto malformed;
  200. addr->pan_id = hdr[0] | (hdr[1] << 8);
  201. hdr += 2;
  202. }
  203. if (hdr + IEEE802154_ADDR_LEN > tail)
  204. goto malformed;
  205. hdr += IEEE802154_ADDR_LEN;
  206. break;
  207. case IEEE802154_ADDR_SHORT:
  208. if (fc & IEEE802154_FC_INTRA_PAN) {
  209. if (hdr + 2 > tail)
  210. goto malformed;
  211. addr->pan_id = hdr[0] | (hdr[1] << 8);
  212. hdr += 2;
  213. }
  214. if (hdr + 2 > tail)
  215. goto malformed;
  216. hdr += 2;
  217. break;
  218. default:
  219. goto malformed;
  220. }
  221. switch (addr->addr_type) {
  222. case IEEE802154_ADDR_NONE:
  223. break;
  224. case IEEE802154_ADDR_LONG:
  225. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  226. if (hdr + 2 > tail)
  227. goto malformed;
  228. addr->pan_id = hdr[0] | (hdr[1] << 8);
  229. hdr += 2;
  230. }
  231. if (hdr + IEEE802154_ADDR_LEN > tail)
  232. goto malformed;
  233. mac802154_haddr_copy_swap(addr->hwaddr, hdr);
  234. hdr += IEEE802154_ADDR_LEN;
  235. break;
  236. case IEEE802154_ADDR_SHORT:
  237. if (!(fc & IEEE802154_FC_INTRA_PAN)) {
  238. if (hdr + 2 > tail)
  239. goto malformed;
  240. addr->pan_id = hdr[0] | (hdr[1] << 8);
  241. hdr += 2;
  242. }
  243. if (hdr + 2 > tail)
  244. goto malformed;
  245. addr->short_addr = hdr[0] | (hdr[1] << 8);
  246. hdr += 2;
  247. break;
  248. default:
  249. goto malformed;
  250. }
  251. return sizeof(struct ieee802154_addr);
  252. malformed:
  253. pr_debug("malformed packet\n");
  254. return 0;
  255. }
  256. static netdev_tx_t
  257. mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
  258. {
  259. struct mac802154_sub_if_data *priv;
  260. u8 chan, page;
  261. priv = netdev_priv(dev);
  262. spin_lock_bh(&priv->mib_lock);
  263. chan = priv->chan;
  264. page = priv->page;
  265. spin_unlock_bh(&priv->mib_lock);
  266. if (chan == MAC802154_CHAN_NONE ||
  267. page >= WPAN_NUM_PAGES ||
  268. chan >= WPAN_NUM_CHANNELS) {
  269. kfree_skb(skb);
  270. return NETDEV_TX_OK;
  271. }
  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 = 300;
  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_ni(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. }