aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-07-08 12:36:30 -0400
committerDavid S. Miller <davem@davemloft.net>2011-07-08 12:36:30 -0400
commita05e42c27f80d341a5ec2053b041e24231a002e2 (patch)
tree371ae025e2a8c8b2828648d64a12774fbb6789f4 /net
parent0a0e2344a62ce9e7fac6129d6292e59aecfceced (diff)
parent204d1641d200709c759d8c269458cbc7de378c40 (diff)
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/core/sock.c6
-rw-r--r--net/mac80211/cfg.c16
-rw-r--r--net/mac80211/driver-ops.h10
-rw-r--r--net/mac80211/driver-trace.h49
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/key.c96
-rw-r--r--net/mac80211/mesh_pathtbl.c4
-rw-r--r--net/mac80211/mlme.c4
-rw-r--r--net/mac80211/pm.c16
-rw-r--r--net/mac80211/tx.c14
-rw-r--r--net/nfc/Kconfig16
-rw-r--r--net/nfc/Makefile7
-rw-r--r--net/nfc/af_nfc.c98
-rw-r--r--net/nfc/core.c468
-rw-r--r--net/nfc/netlink.c537
-rw-r--r--net/nfc/nfc.h117
-rw-r--r--net/nfc/rawsock.c354
-rw-r--r--net/wireless/mlme.c11
-rw-r--r--net/wireless/nl80211.c113
-rw-r--r--net/wireless/nl80211.h4
-rw-r--r--net/wireless/scan.c5
23 files changed, 1924 insertions, 26 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 878151c772c9..a07314844238 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -322,6 +322,7 @@ source "net/rfkill/Kconfig"
322source "net/9p/Kconfig" 322source "net/9p/Kconfig"
323source "net/caif/Kconfig" 323source "net/caif/Kconfig"
324source "net/ceph/Kconfig" 324source "net/ceph/Kconfig"
325source "net/nfc/Kconfig"
325 326
326 327
327endif # if NET 328endif # if NET
diff --git a/net/Makefile b/net/Makefile
index a51d9465e628..acdde4950de4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -68,3 +68,4 @@ obj-$(CONFIG_WIMAX) += wimax/
68obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/ 68obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/
69obj-$(CONFIG_CEPH_LIB) += ceph/ 69obj-$(CONFIG_CEPH_LIB) += ceph/
70obj-$(CONFIG_BATMAN_ADV) += batman-adv/ 70obj-$(CONFIG_BATMAN_ADV) += batman-adv/
71obj-$(CONFIG_NFC) += nfc/
diff --git a/net/core/sock.c b/net/core/sock.c
index 76c403146750..bc745d00ea4d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -160,7 +160,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
160 "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , 160 "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" ,
161 "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , 161 "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" ,
162 "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" , 162 "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG" ,
163 "sk_lock-AF_MAX" 163 "sk_lock-AF_NFC" , "sk_lock-AF_MAX"
164}; 164};
165static const char *const af_family_slock_key_strings[AF_MAX+1] = { 165static const char *const af_family_slock_key_strings[AF_MAX+1] = {
166 "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , 166 "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" ,
@@ -176,7 +176,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
176 "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , 176 "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" ,
177 "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , 177 "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" ,
178 "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" , 178 "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG" ,
179 "slock-AF_MAX" 179 "slock-AF_NFC" , "slock-AF_MAX"
180}; 180};
181static const char *const af_family_clock_key_strings[AF_MAX+1] = { 181static const char *const af_family_clock_key_strings[AF_MAX+1] = {
182 "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , 182 "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" ,
@@ -192,7 +192,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
192 "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , 192 "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" ,
193 "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , 193 "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" ,
194 "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" , 194 "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG" ,
195 "clock-AF_MAX" 195 "clock-AF_NFC" , "clock-AF_MAX"
196}; 196};
197 197
198/* 198/*
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9fe22cc393c8..295ab747663f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2101,6 +2101,21 @@ static void ieee80211_get_ringparam(struct wiphy *wiphy,
2101 drv_get_ringparam(local, tx, tx_max, rx, rx_max); 2101 drv_get_ringparam(local, tx, tx_max, rx, rx_max);
2102} 2102}
2103 2103
2104static int ieee80211_set_rekey_data(struct wiphy *wiphy,
2105 struct net_device *dev,
2106 struct cfg80211_gtk_rekey_data *data)
2107{
2108 struct ieee80211_local *local = wiphy_priv(wiphy);
2109 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2110
2111 if (!local->ops->set_rekey_data)
2112 return -EOPNOTSUPP;
2113
2114 drv_set_rekey_data(local, sdata, data);
2115
2116 return 0;
2117}
2118
2104struct cfg80211_ops mac80211_config_ops = { 2119struct cfg80211_ops mac80211_config_ops = {
2105 .add_virtual_intf = ieee80211_add_iface, 2120 .add_virtual_intf = ieee80211_add_iface,
2106 .del_virtual_intf = ieee80211_del_iface, 2121 .del_virtual_intf = ieee80211_del_iface,
@@ -2163,4 +2178,5 @@ struct cfg80211_ops mac80211_config_ops = {
2163 .get_antenna = ieee80211_get_antenna, 2178 .get_antenna = ieee80211_get_antenna,
2164 .set_ringparam = ieee80211_set_ringparam, 2179 .set_ringparam = ieee80211_set_ringparam,
2165 .get_ringparam = ieee80211_get_ringparam, 2180 .get_ringparam = ieee80211_get_ringparam,
2181 .set_rekey_data = ieee80211_set_rekey_data,
2166}; 2182};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 0e7e4268ddf6..edd2dd79c9be 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -647,4 +647,14 @@ static inline int drv_set_bitrate_mask(struct ieee80211_local *local,
647 return ret; 647 return ret;
648} 648}
649 649
650static inline void drv_set_rekey_data(struct ieee80211_local *local,
651 struct ieee80211_sub_if_data *sdata,
652 struct cfg80211_gtk_rekey_data *data)
653{
654 trace_drv_set_rekey_data(local, sdata, data);
655 if (local->ops->set_rekey_data)
656 local->ops->set_rekey_data(&local->hw, &sdata->vif, data);
657 trace_drv_return_void(local);
658}
659
650#endif /* __MAC80211_DRIVER_OPS */ 660#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 3cb6795e926d..31a9dfa81f65 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -1024,6 +1024,34 @@ TRACE_EVENT(drv_set_bitrate_mask,
1024 ) 1024 )
1025); 1025);
1026 1026
1027TRACE_EVENT(drv_set_rekey_data,
1028 TP_PROTO(struct ieee80211_local *local,
1029 struct ieee80211_sub_if_data *sdata,
1030 struct cfg80211_gtk_rekey_data *data),
1031
1032 TP_ARGS(local, sdata, data),
1033
1034 TP_STRUCT__entry(
1035 LOCAL_ENTRY
1036 VIF_ENTRY
1037 __array(u8, kek, NL80211_KEK_LEN)
1038 __array(u8, kck, NL80211_KCK_LEN)
1039 __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
1040 ),
1041
1042 TP_fast_assign(
1043 LOCAL_ASSIGN;
1044 VIF_ASSIGN;
1045 memcpy(__entry->kek, data->kek, NL80211_KEK_LEN);
1046 memcpy(__entry->kck, data->kck, NL80211_KCK_LEN);
1047 memcpy(__entry->replay_ctr, data->replay_ctr,
1048 NL80211_REPLAY_CTR_LEN);
1049 ),
1050
1051 TP_printk(LOCAL_PR_FMT VIF_PR_FMT,
1052 LOCAL_PR_ARG, VIF_PR_ARG)
1053);
1054
1027/* 1055/*
1028 * Tracing for API calls that drivers call. 1056 * Tracing for API calls that drivers call.
1029 */ 1057 */
@@ -1293,6 +1321,27 @@ DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired,
1293 TP_ARGS(local) 1321 TP_ARGS(local)
1294); 1322);
1295 1323
1324TRACE_EVENT(api_gtk_rekey_notify,
1325 TP_PROTO(struct ieee80211_sub_if_data *sdata,
1326 const u8 *bssid, const u8 *replay_ctr),
1327
1328 TP_ARGS(sdata, bssid, replay_ctr),
1329
1330 TP_STRUCT__entry(
1331 VIF_ENTRY
1332 __array(u8, bssid, ETH_ALEN)
1333 __array(u8, replay_ctr, NL80211_REPLAY_CTR_LEN)
1334 ),
1335
1336 TP_fast_assign(
1337 VIF_ASSIGN;
1338 memcpy(__entry->bssid, bssid, ETH_ALEN);
1339 memcpy(__entry->replay_ctr, replay_ctr, NL80211_REPLAY_CTR_LEN);
1340 ),
1341
1342 TP_printk(VIF_PR_FMT, VIF_PR_ARG)
1343);
1344
1296/* 1345/*
1297 * Tracing for internal functions 1346 * Tracing for internal functions
1298 * (which may also be called in response to driver calls) 1347 * (which may also be called in response to driver calls)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 25c15cc63319..4f2e424e8b1b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -544,6 +544,9 @@ struct ieee80211_sub_if_data {
544 /* keys */ 544 /* keys */
545 struct list_head key_list; 545 struct list_head key_list;
546 546
547 /* count for keys needing tailroom space allocation */
548 int crypto_tx_tailroom_needed_cnt;
549
547 struct net_device *dev; 550 struct net_device *dev;
548 struct ieee80211_local *local; 551 struct ieee80211_local *local;
549 552
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index f825e2f0a57e..1208a7878bfd 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -61,6 +61,36 @@ static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
61 return NULL; 61 return NULL;
62} 62}
63 63
64static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
65{
66 /*
67 * When this count is zero, SKB resizing for allocating tailroom
68 * for IV or MMIC is skipped. But, this check has created two race
69 * cases in xmit path while transiting from zero count to one:
70 *
71 * 1. SKB resize was skipped because no key was added but just before
72 * the xmit key is added and SW encryption kicks off.
73 *
74 * 2. SKB resize was skipped because all the keys were hw planted but
75 * just before xmit one of the key is deleted and SW encryption kicks
76 * off.
77 *
78 * In both the above case SW encryption will find not enough space for
79 * tailroom and exits with WARN_ON. (See WARN_ONs at wpa.c)
80 *
81 * Solution has been explained at
82 * http://mid.gmane.org/1308590980.4322.19.camel@jlt3.sipsolutions.net
83 */
84
85 if (!sdata->crypto_tx_tailroom_needed_cnt++) {
86 /*
87 * Flush all XMIT packets currently using HW encryption or no
88 * encryption at all if the count transition is from 0 -> 1.
89 */
90 synchronize_net();
91 }
92}
93
64static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 94static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
65{ 95{
66 struct ieee80211_sub_if_data *sdata; 96 struct ieee80211_sub_if_data *sdata;
@@ -101,6 +131,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
101 131
102 if (!ret) { 132 if (!ret) {
103 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 133 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
134
135 if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
136 (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
137 sdata->crypto_tx_tailroom_needed_cnt--;
138
104 return 0; 139 return 0;
105 } 140 }
106 141
@@ -142,6 +177,10 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
142 sta = get_sta_for_key(key); 177 sta = get_sta_for_key(key);
143 sdata = key->sdata; 178 sdata = key->sdata;
144 179
180 if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
181 (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
182 increment_tailroom_need_count(sdata);
183
145 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 184 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
146 sdata = container_of(sdata->bss, 185 sdata = container_of(sdata->bss,
147 struct ieee80211_sub_if_data, 186 struct ieee80211_sub_if_data,
@@ -394,8 +433,10 @@ static void __ieee80211_key_destroy(struct ieee80211_key *key)
394 ieee80211_aes_key_free(key->u.ccmp.tfm); 433 ieee80211_aes_key_free(key->u.ccmp.tfm);
395 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 434 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC)
396 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 435 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
397 if (key->local) 436 if (key->local) {
398 ieee80211_debugfs_key_remove(key); 437 ieee80211_debugfs_key_remove(key);
438 key->sdata->crypto_tx_tailroom_needed_cnt--;
439 }
399 440
400 kfree(key); 441 kfree(key);
401} 442}
@@ -452,6 +493,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
452 else 493 else
453 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); 494 old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
454 495
496 increment_tailroom_need_count(sdata);
497
455 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); 498 __ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
456 __ieee80211_key_destroy(old_key); 499 __ieee80211_key_destroy(old_key);
457 500
@@ -498,12 +541,49 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
498 541
499 mutex_lock(&sdata->local->key_mtx); 542 mutex_lock(&sdata->local->key_mtx);
500 543
501 list_for_each_entry(key, &sdata->key_list, list) 544 sdata->crypto_tx_tailroom_needed_cnt = 0;
545
546 list_for_each_entry(key, &sdata->key_list, list) {
547 increment_tailroom_need_count(sdata);
502 ieee80211_key_enable_hw_accel(key); 548 ieee80211_key_enable_hw_accel(key);
549 }
503 550
504 mutex_unlock(&sdata->local->key_mtx); 551 mutex_unlock(&sdata->local->key_mtx);
505} 552}
506 553
554void ieee80211_iter_keys(struct ieee80211_hw *hw,
555 struct ieee80211_vif *vif,
556 void (*iter)(struct ieee80211_hw *hw,
557 struct ieee80211_vif *vif,
558 struct ieee80211_sta *sta,
559 struct ieee80211_key_conf *key,
560 void *data),
561 void *iter_data)
562{
563 struct ieee80211_local *local = hw_to_local(hw);
564 struct ieee80211_key *key;
565 struct ieee80211_sub_if_data *sdata;
566
567 ASSERT_RTNL();
568
569 mutex_lock(&local->key_mtx);
570 if (vif) {
571 sdata = vif_to_sdata(vif);
572 list_for_each_entry(key, &sdata->key_list, list)
573 iter(hw, &sdata->vif,
574 key->sta ? &key->sta->sta : NULL,
575 &key->conf, iter_data);
576 } else {
577 list_for_each_entry(sdata, &local->interfaces, list)
578 list_for_each_entry(key, &sdata->key_list, list)
579 iter(hw, &sdata->vif,
580 key->sta ? &key->sta->sta : NULL,
581 &key->conf, iter_data);
582 }
583 mutex_unlock(&local->key_mtx);
584}
585EXPORT_SYMBOL(ieee80211_iter_keys);
586
507void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 587void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
508{ 588{
509 struct ieee80211_key *key; 589 struct ieee80211_key *key;
@@ -533,3 +613,15 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
533 613
534 mutex_unlock(&sdata->local->key_mtx); 614 mutex_unlock(&sdata->local->key_mtx);
535} 615}
616
617
618void ieee80211_gtk_rekey_notify(struct ieee80211_vif *vif, const u8 *bssid,
619 const u8 *replay_ctr, gfp_t gfp)
620{
621 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
622
623 trace_api_gtk_rekey_notify(sdata, bssid, replay_ctr);
624
625 cfg80211_gtk_rekey_notify(sdata->dev, bssid, replay_ctr, gfp);
626}
627EXPORT_SYMBOL_GPL(ieee80211_gtk_rekey_notify);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 0d2faacc3e87..068ee6518254 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -647,12 +647,12 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
647 mpath = node->mpath; 647 mpath = node->mpath;
648 if (mpath->sdata == sdata && 648 if (mpath->sdata == sdata &&
649 memcmp(addr, mpath->dst, ETH_ALEN) == 0) { 649 memcmp(addr, mpath->dst, ETH_ALEN) == 0) {
650 spin_lock_bh(&mpath->state_lock); 650 spin_lock(&mpath->state_lock);
651 mpath->flags |= MESH_PATH_RESOLVING; 651 mpath->flags |= MESH_PATH_RESOLVING;
652 hlist_del_rcu(&node->list); 652 hlist_del_rcu(&node->list);
653 call_rcu(&node->rcu, mesh_path_node_reclaim); 653 call_rcu(&node->rcu, mesh_path_node_reclaim);
654 atomic_dec(&tbl->entries); 654 atomic_dec(&tbl->entries);
655 spin_unlock_bh(&mpath->state_lock); 655 spin_unlock(&mpath->state_lock);
656 goto enddel; 656 goto enddel;
657 } 657 }
658 } 658 }
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b87420088c33..182cda66ebef 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -749,7 +749,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
749 container_of(work, struct ieee80211_local, 749 container_of(work, struct ieee80211_local,
750 dynamic_ps_enable_work); 750 dynamic_ps_enable_work);
751 struct ieee80211_sub_if_data *sdata = local->ps_sdata; 751 struct ieee80211_sub_if_data *sdata = local->ps_sdata;
752 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 752 struct ieee80211_if_managed *ifmgd;
753 unsigned long flags; 753 unsigned long flags;
754 int q; 754 int q;
755 755
@@ -757,6 +757,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
757 if (!sdata) 757 if (!sdata)
758 return; 758 return;
759 759
760 ifmgd = &sdata->u.mgd;
761
760 if (local->hw.conf.flags & IEEE80211_CONF_PS) 762 if (local->hw.conf.flags & IEEE80211_CONF_PS)
761 return; 763 return;
762 764
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 67839eb90cc1..f87e993e713b 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -72,15 +72,19 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
72 local->wowlan = wowlan && local->open_count; 72 local->wowlan = wowlan && local->open_count;
73 if (local->wowlan) { 73 if (local->wowlan) {
74 int err = drv_suspend(local, wowlan); 74 int err = drv_suspend(local, wowlan);
75 if (err) { 75 if (err < 0) {
76 local->quiescing = false; 76 local->quiescing = false;
77 return err; 77 return err;
78 } else if (err > 0) {
79 WARN_ON(err != 1);
80 local->wowlan = false;
81 } else {
82 list_for_each_entry(sdata, &local->interfaces, list) {
83 cancel_work_sync(&sdata->work);
84 ieee80211_quiesce(sdata);
85 }
86 goto suspend;
78 } 87 }
79 list_for_each_entry(sdata, &local->interfaces, list) {
80 cancel_work_sync(&sdata->work);
81 ieee80211_quiesce(sdata);
82 }
83 goto suspend;
84 } 88 }
85 89
86 /* disable keys */ 90 /* disable keys */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3104c844b544..e8d0d2d22665 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1474,18 +1474,14 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
1474 1474
1475/* device xmit handlers */ 1475/* device xmit handlers */
1476 1476
1477static int ieee80211_skb_resize(struct ieee80211_local *local, 1477static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
1478 struct sk_buff *skb, 1478 struct sk_buff *skb,
1479 int head_need, bool may_encrypt) 1479 int head_need, bool may_encrypt)
1480{ 1480{
1481 struct ieee80211_local *local = sdata->local;
1481 int tail_need = 0; 1482 int tail_need = 0;
1482 1483
1483 /* 1484 if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
1484 * This could be optimised, devices that do full hardware
1485 * crypto (including TKIP MMIC) need no tailroom... But we
1486 * have no drivers for such devices currently.
1487 */
1488 if (may_encrypt) {
1489 tail_need = IEEE80211_ENCRYPT_TAILROOM; 1485 tail_need = IEEE80211_ENCRYPT_TAILROOM;
1490 tail_need -= skb_tailroom(skb); 1486 tail_need -= skb_tailroom(skb);
1491 tail_need = max_t(int, tail_need, 0); 1487 tail_need = max_t(int, tail_need, 0);
@@ -1578,7 +1574,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1578 headroom -= skb_headroom(skb); 1574 headroom -= skb_headroom(skb);
1579 headroom = max_t(int, 0, headroom); 1575 headroom = max_t(int, 0, headroom);
1580 1576
1581 if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { 1577 if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
1582 dev_kfree_skb(skb); 1578 dev_kfree_skb(skb);
1583 rcu_read_unlock(); 1579 rcu_read_unlock();
1584 return; 1580 return;
@@ -1945,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
1945 head_need += IEEE80211_ENCRYPT_HEADROOM; 1941 head_need += IEEE80211_ENCRYPT_HEADROOM;
1946 head_need += local->tx_headroom; 1942 head_need += local->tx_headroom;
1947 head_need = max_t(int, 0, head_need); 1943 head_need = max_t(int, 0, head_need);
1948 if (ieee80211_skb_resize(local, skb, head_need, true)) 1944 if (ieee80211_skb_resize(sdata, skb, head_need, true))
1949 goto fail; 1945 goto fail;
1950 } 1946 }
1951 1947
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
new file mode 100644
index 000000000000..33e095b124b3
--- /dev/null
+++ b/net/nfc/Kconfig
@@ -0,0 +1,16 @@
1#
2# NFC sybsystem configuration
3#
4
5menuconfig NFC
6 depends on NET && EXPERIMENTAL
7 tristate "NFC subsystem support (EXPERIMENTAL)"
8 default n
9 help
10 Say Y here if you want to build support for NFC (Near field
11 communication) devices.
12
13 To compile this support as a module, choose M here: the module will
14 be called nfc.
15
16source "drivers/nfc/Kconfig"
diff --git a/net/nfc/Makefile b/net/nfc/Makefile
new file mode 100644
index 000000000000..16250c353851
--- /dev/null
+++ b/net/nfc/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the Linux NFC subsystem.
3#
4
5obj-$(CONFIG_NFC) += nfc.o
6
7nfc-objs := core.o netlink.o af_nfc.o rawsock.o
diff --git a/net/nfc/af_nfc.c b/net/nfc/af_nfc.c
new file mode 100644
index 000000000000..e982cef8f49d
--- /dev/null
+++ b/net/nfc/af_nfc.c
@@ -0,0 +1,98 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
6 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/nfc.h>
25
26#include "nfc.h"
27
28static DEFINE_RWLOCK(proto_tab_lock);
29static const struct nfc_protocol *proto_tab[NFC_SOCKPROTO_MAX];
30
31static int nfc_sock_create(struct net *net, struct socket *sock, int proto,
32 int kern)
33{
34 int rc = -EPROTONOSUPPORT;
35
36 if (net != &init_net)
37 return -EAFNOSUPPORT;
38
39 if (proto < 0 || proto >= NFC_SOCKPROTO_MAX)
40 return -EINVAL;
41
42 read_lock(&proto_tab_lock);
43 if (proto_tab[proto] && try_module_get(proto_tab[proto]->owner)) {
44 rc = proto_tab[proto]->create(net, sock, proto_tab[proto]);
45 module_put(proto_tab[proto]->owner);
46 }
47 read_unlock(&proto_tab_lock);
48
49 return rc;
50}
51
52static struct net_proto_family nfc_sock_family_ops = {
53 .owner = THIS_MODULE,
54 .family = PF_NFC,
55 .create = nfc_sock_create,
56};
57
58int nfc_proto_register(const struct nfc_protocol *nfc_proto)
59{
60 int rc;
61
62 if (nfc_proto->id < 0 || nfc_proto->id >= NFC_SOCKPROTO_MAX)
63 return -EINVAL;
64
65 rc = proto_register(nfc_proto->proto, 0);
66 if (rc)
67 return rc;
68
69 write_lock(&proto_tab_lock);
70 if (proto_tab[nfc_proto->id])
71 rc = -EBUSY;
72 else
73 proto_tab[nfc_proto->id] = nfc_proto;
74 write_unlock(&proto_tab_lock);
75
76 return rc;
77}
78EXPORT_SYMBOL(nfc_proto_register);
79
80void nfc_proto_unregister(const struct nfc_protocol *nfc_proto)
81{
82 write_lock(&proto_tab_lock);
83 proto_tab[nfc_proto->id] = NULL;
84 write_unlock(&proto_tab_lock);
85
86 proto_unregister(nfc_proto->proto);
87}
88EXPORT_SYMBOL(nfc_proto_unregister);
89
90int __init af_nfc_init(void)
91{
92 return sock_register(&nfc_sock_family_ops);
93}
94
95void af_nfc_exit(void)
96{
97 sock_unregister(PF_NFC);
98}
diff --git a/net/nfc/core.c b/net/nfc/core.c
new file mode 100644
index 000000000000..b6fd4e1f2057
--- /dev/null
+++ b/net/nfc/core.c
@@ -0,0 +1,468 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
6 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <linux/init.h>
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/slab.h>
28
29#include "nfc.h"
30
31#define VERSION "0.1"
32
33int nfc_devlist_generation;
34DEFINE_MUTEX(nfc_devlist_mutex);
35
36int nfc_printk(const char *level, const char *format, ...)
37{
38 struct va_format vaf;
39 va_list args;
40 int r;
41
42 va_start(args, format);
43
44 vaf.fmt = format;
45 vaf.va = &args;
46
47 r = printk("%sNFC: %pV\n", level, &vaf);
48
49 va_end(args);
50
51 return r;
52}
53EXPORT_SYMBOL(nfc_printk);
54
55/**
56 * nfc_start_poll - start polling for nfc targets
57 *
58 * @dev: The nfc device that must start polling
59 * @protocols: bitset of nfc protocols that must be used for polling
60 *
61 * The device remains polling for targets until a target is found or
62 * the nfc_stop_poll function is called.
63 */
64int nfc_start_poll(struct nfc_dev *dev, u32 protocols)
65{
66 int rc;
67
68 nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols);
69
70 if (!protocols)
71 return -EINVAL;
72
73 device_lock(&dev->dev);
74
75 if (!device_is_registered(&dev->dev)) {
76 rc = -ENODEV;
77 goto error;
78 }
79
80 if (dev->polling) {
81 rc = -EBUSY;
82 goto error;
83 }
84
85 rc = dev->ops->start_poll(dev, protocols);
86 if (!rc)
87 dev->polling = true;
88
89error:
90 device_unlock(&dev->dev);
91 return rc;
92}
93
94/**
95 * nfc_stop_poll - stop polling for nfc targets
96 *
97 * @dev: The nfc device that must stop polling
98 */
99int nfc_stop_poll(struct nfc_dev *dev)
100{
101 int rc = 0;
102
103 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
104
105 device_lock(&dev->dev);
106
107 if (!device_is_registered(&dev->dev)) {
108 rc = -ENODEV;
109 goto error;
110 }
111
112 if (!dev->polling) {
113 rc = -EINVAL;
114 goto error;
115 }
116
117 dev->ops->stop_poll(dev);
118 dev->polling = false;
119
120error:
121 device_unlock(&dev->dev);
122 return rc;
123}
124
125/**
126 * nfc_activate_target - prepare the target for data exchange
127 *
128 * @dev: The nfc device that found the target
129 * @target_idx: index of the target that must be activated
130 * @protocol: nfc protocol that will be used for data exchange
131 */
132int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol)
133{
134 int rc;
135
136 nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev),
137 target_idx, protocol);
138
139 device_lock(&dev->dev);
140
141 if (!device_is_registered(&dev->dev)) {
142 rc = -ENODEV;
143 goto error;
144 }
145
146 rc = dev->ops->activate_target(dev, target_idx, protocol);
147
148error:
149 device_unlock(&dev->dev);
150 return rc;
151}
152
153/**
154 * nfc_deactivate_target - deactivate a nfc target
155 *
156 * @dev: The nfc device that found the target
157 * @target_idx: index of the target that must be deactivated
158 */
159int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx)
160{
161 int rc = 0;
162
163 nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx);
164
165 device_lock(&dev->dev);
166
167 if (!device_is_registered(&dev->dev)) {
168 rc = -ENODEV;
169 goto error;
170 }
171
172 dev->ops->deactivate_target(dev, target_idx);
173
174error:
175 device_unlock(&dev->dev);
176 return rc;
177}
178
179/**
180 * nfc_data_exchange - transceive data
181 *
182 * @dev: The nfc device that found the target
183 * @target_idx: index of the target
184 * @skb: data to be sent
185 * @cb: callback called when the response is received
186 * @cb_context: parameter for the callback function
187 *
188 * The user must wait for the callback before calling this function again.
189 */
190int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
191 struct sk_buff *skb,
192 data_exchange_cb_t cb,
193 void *cb_context)
194{
195 int rc;
196
197 nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev),
198 target_idx, skb->len);
199
200 device_lock(&dev->dev);
201
202 if (!device_is_registered(&dev->dev)) {
203 rc = -ENODEV;
204 kfree_skb(skb);
205 goto error;
206 }
207
208 rc = dev->ops->data_exchange(dev, target_idx, skb, cb, cb_context);
209
210error:
211 device_unlock(&dev->dev);
212 return rc;
213}
214
215/**
216 * nfc_alloc_skb - allocate a skb for data exchange responses
217 *
218 * @size: size to allocate
219 * @gfp: gfp flags
220 */
221struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp)
222{
223 struct sk_buff *skb;
224 unsigned int total_size;
225
226 total_size = size + 1;
227 skb = alloc_skb(total_size, gfp);
228
229 if (skb)
230 skb_reserve(skb, 1);
231
232 return skb;
233}
234EXPORT_SYMBOL(nfc_alloc_skb);
235
236/**
237 * nfc_targets_found - inform that targets were found
238 *
239 * @dev: The nfc device that found the targets
240 * @targets: array of nfc targets found
241 * @ntargets: targets array size
242 *
243 * The device driver must call this function when one or many nfc targets
244 * are found. After calling this function, the device driver must stop
245 * polling for targets.
246 */
247int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
248 int n_targets)
249{
250 int i;
251
252 nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets);
253
254 dev->polling = false;
255
256 for (i = 0; i < n_targets; i++)
257 targets[i].idx = dev->target_idx++;
258
259 spin_lock_bh(&dev->targets_lock);
260
261 dev->targets_generation++;
262
263 kfree(dev->targets);
264 dev->targets = kmemdup(targets, n_targets * sizeof(struct nfc_target),
265 GFP_ATOMIC);
266
267 if (!dev->targets) {
268 dev->n_targets = 0;
269 spin_unlock_bh(&dev->targets_lock);
270 return -ENOMEM;
271 }
272
273 dev->n_targets = n_targets;
274 spin_unlock_bh(&dev->targets_lock);
275
276 nfc_genl_targets_found(dev);
277
278 return 0;
279}
280EXPORT_SYMBOL(nfc_targets_found);
281
282static void nfc_release(struct device *d)
283{
284 struct nfc_dev *dev = to_nfc_dev(d);
285
286 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
287
288 nfc_genl_data_exit(&dev->genl_data);
289 kfree(dev->targets);
290 kfree(dev);
291}
292
293struct class nfc_class = {
294 .name = "nfc",
295 .dev_release = nfc_release,
296};
297EXPORT_SYMBOL(nfc_class);
298
299static int match_idx(struct device *d, void *data)
300{
301 struct nfc_dev *dev = to_nfc_dev(d);
302 unsigned *idx = data;
303
304 return dev->idx == *idx;
305}
306
307struct nfc_dev *nfc_get_device(unsigned idx)
308{
309 struct device *d;
310
311 d = class_find_device(&nfc_class, NULL, &idx, match_idx);
312 if (!d)
313 return NULL;
314
315 return to_nfc_dev(d);
316}
317
318/**
319 * nfc_allocate_device - allocate a new nfc device
320 *
321 * @ops: device operations
322 * @supported_protocols: NFC protocols supported by the device
323 */
324struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
325 u32 supported_protocols)
326{
327 static atomic_t dev_no = ATOMIC_INIT(0);
328 struct nfc_dev *dev;
329
330 if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
331 !ops->deactivate_target || !ops->data_exchange)
332 return NULL;
333
334 if (!supported_protocols)
335 return NULL;
336
337 dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL);
338 if (!dev)
339 return NULL;
340
341 dev->dev.class = &nfc_class;
342 dev->idx = atomic_inc_return(&dev_no) - 1;
343 dev_set_name(&dev->dev, "nfc%d", dev->idx);
344 device_initialize(&dev->dev);
345
346 dev->ops = ops;
347 dev->supported_protocols = supported_protocols;
348
349 spin_lock_init(&dev->targets_lock);
350 nfc_genl_data_init(&dev->genl_data);
351
352 /* first generation must not be 0 */
353 dev->targets_generation = 1;
354
355 return dev;
356}
357EXPORT_SYMBOL(nfc_allocate_device);
358
359/**
360 * nfc_register_device - register a nfc device in the nfc subsystem
361 *
362 * @dev: The nfc device to register
363 */
364int nfc_register_device(struct nfc_dev *dev)
365{
366 int rc;
367
368 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
369
370 mutex_lock(&nfc_devlist_mutex);
371 nfc_devlist_generation++;
372 rc = device_add(&dev->dev);
373 mutex_unlock(&nfc_devlist_mutex);
374
375 if (rc < 0)
376 return rc;
377
378 rc = nfc_genl_device_added(dev);
379 if (rc)
380 nfc_dbg("The userspace won't be notified that the device %s was"
381 " added", dev_name(&dev->dev));
382
383
384 return 0;
385}
386EXPORT_SYMBOL(nfc_register_device);
387
388/**
389 * nfc_unregister_device - unregister a nfc device in the nfc subsystem
390 *
391 * @dev: The nfc device to unregister
392 */
393void nfc_unregister_device(struct nfc_dev *dev)
394{
395 int rc;
396
397 nfc_dbg("dev_name=%s", dev_name(&dev->dev));
398
399 mutex_lock(&nfc_devlist_mutex);
400 nfc_devlist_generation++;
401
402 /* lock to avoid unregistering a device while an operation
403 is in progress */
404 device_lock(&dev->dev);
405 device_del(&dev->dev);
406 device_unlock(&dev->dev);
407
408 mutex_unlock(&nfc_devlist_mutex);
409
410 rc = nfc_genl_device_removed(dev);
411 if (rc)
412 nfc_dbg("The userspace won't be notified that the device %s"
413 " was removed", dev_name(&dev->dev));
414
415}
416EXPORT_SYMBOL(nfc_unregister_device);
417
418static int __init nfc_init(void)
419{
420 int rc;
421
422 nfc_info("NFC Core ver %s", VERSION);
423
424 rc = class_register(&nfc_class);
425 if (rc)
426 return rc;
427
428 rc = nfc_genl_init();
429 if (rc)
430 goto err_genl;
431
432 /* the first generation must not be 0 */
433 nfc_devlist_generation = 1;
434
435 rc = rawsock_init();
436 if (rc)
437 goto err_rawsock;
438
439 rc = af_nfc_init();
440 if (rc)
441 goto err_af_nfc;
442
443 return 0;
444
445err_af_nfc:
446 rawsock_exit();
447err_rawsock:
448 nfc_genl_exit();
449err_genl:
450 class_unregister(&nfc_class);
451 return rc;
452}
453
454static void __exit nfc_exit(void)
455{
456 af_nfc_exit();
457 rawsock_exit();
458 nfc_genl_exit();
459 class_unregister(&nfc_class);
460}
461
462subsys_initcall(nfc_init);
463module_exit(nfc_exit);
464
465MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>");
466MODULE_DESCRIPTION("NFC Core ver " VERSION);
467MODULE_VERSION(VERSION);
468MODULE_LICENSE("GPL");
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
new file mode 100644
index 000000000000..ccdff7953f7d
--- /dev/null
+++ b/net/nfc/netlink.c
@@ -0,0 +1,537 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
6 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <net/genetlink.h>
25#include <linux/nfc.h>
26#include <linux/slab.h>
27
28#include "nfc.h"
29
30static struct genl_multicast_group nfc_genl_event_mcgrp = {
31 .name = NFC_GENL_MCAST_EVENT_NAME,
32};
33
34struct genl_family nfc_genl_family = {
35 .id = GENL_ID_GENERATE,
36 .hdrsize = 0,
37 .name = NFC_GENL_NAME,
38 .version = NFC_GENL_VERSION,
39 .maxattr = NFC_ATTR_MAX,
40};
41
42static const struct nla_policy nfc_genl_policy[NFC_ATTR_MAX + 1] = {
43 [NFC_ATTR_DEVICE_INDEX] = { .type = NLA_U32 },
44 [NFC_ATTR_DEVICE_NAME] = { .type = NLA_STRING,
45 .len = NFC_DEVICE_NAME_MAXSIZE },
46 [NFC_ATTR_PROTOCOLS] = { .type = NLA_U32 },
47};
48
49static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target,
50 struct netlink_callback *cb, int flags)
51{
52 void *hdr;
53
54 nfc_dbg("entry");
55
56 hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
57 &nfc_genl_family, flags, NFC_CMD_GET_TARGET);
58 if (!hdr)
59 return -EMSGSIZE;
60
61 genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
62
63 NLA_PUT_U32(msg, NFC_ATTR_TARGET_INDEX, target->idx);
64 NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS,
65 target->supported_protocols);
66 NLA_PUT_U16(msg, NFC_ATTR_TARGET_SENS_RES, target->sens_res);
67 NLA_PUT_U8(msg, NFC_ATTR_TARGET_SEL_RES, target->sel_res);
68
69 return genlmsg_end(msg, hdr);
70
71nla_put_failure:
72 genlmsg_cancel(msg, hdr);
73 return -EMSGSIZE;
74}
75
76static struct nfc_dev *__get_device_from_cb(struct netlink_callback *cb)
77{
78 struct nfc_dev *dev;
79 int rc;
80 u32 idx;
81
82 rc = nlmsg_parse(cb->nlh, GENL_HDRLEN + nfc_genl_family.hdrsize,
83 nfc_genl_family.attrbuf,
84 nfc_genl_family.maxattr,
85 nfc_genl_policy);
86 if (rc < 0)
87 return ERR_PTR(rc);
88
89 if (!nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX])
90 return ERR_PTR(-EINVAL);
91
92 idx = nla_get_u32(nfc_genl_family.attrbuf[NFC_ATTR_DEVICE_INDEX]);
93
94 dev = nfc_get_device(idx);
95 if (!dev)
96 return ERR_PTR(-ENODEV);
97
98 return dev;
99}
100
101static int nfc_genl_dump_targets(struct sk_buff *skb,
102 struct netlink_callback *cb)
103{
104 int i = cb->args[0];
105 struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
106 int rc;
107
108 nfc_dbg("entry");
109
110 if (!dev) {
111 dev = __get_device_from_cb(cb);
112 if (IS_ERR(dev))
113 return PTR_ERR(dev);
114
115 cb->args[1] = (long) dev;
116 }
117
118 spin_lock_bh(&dev->targets_lock);
119
120 cb->seq = dev->targets_generation;
121
122 while (i < dev->n_targets) {
123 rc = nfc_genl_send_target(skb, &dev->targets[i], cb,
124 NLM_F_MULTI);
125 if (rc < 0)
126 break;
127
128 i++;
129 }
130
131 spin_unlock_bh(&dev->targets_lock);
132
133 cb->args[0] = i;
134
135 return skb->len;
136}
137
138static int nfc_genl_dump_targets_done(struct netlink_callback *cb)
139{
140 struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
141
142 nfc_dbg("entry");
143
144 if (dev)
145 nfc_put_device(dev);
146
147 return 0;
148}
149
150int nfc_genl_targets_found(struct nfc_dev *dev)
151{
152 struct sk_buff *msg;
153 void *hdr;
154
155 nfc_dbg("entry");
156
157 dev->genl_data.poll_req_pid = 0;
158
159 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
160 if (!msg)
161 return -ENOMEM;
162
163 hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
164 NFC_EVENT_TARGETS_FOUND);
165 if (!hdr)
166 goto free_msg;
167
168 NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
169
170 genlmsg_end(msg, hdr);
171
172 return genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_ATOMIC);
173
174nla_put_failure:
175 genlmsg_cancel(msg, hdr);
176free_msg:
177 nlmsg_free(msg);
178 return -EMSGSIZE;
179}
180
181int nfc_genl_device_added(struct nfc_dev *dev)
182{
183 struct sk_buff *msg;
184 void *hdr;
185
186 nfc_dbg("entry");
187
188 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
189 if (!msg)
190 return -ENOMEM;
191
192 hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
193 NFC_EVENT_DEVICE_ADDED);
194 if (!hdr)
195 goto free_msg;
196
197 NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
198 NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
199 NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
200
201 genlmsg_end(msg, hdr);
202
203 genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
204
205 return 0;
206
207nla_put_failure:
208 genlmsg_cancel(msg, hdr);
209free_msg:
210 nlmsg_free(msg);
211 return -EMSGSIZE;
212}
213
214int nfc_genl_device_removed(struct nfc_dev *dev)
215{
216 struct sk_buff *msg;
217 void *hdr;
218
219 nfc_dbg("entry");
220
221 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
222 if (!msg)
223 return -ENOMEM;
224
225 hdr = genlmsg_put(msg, 0, 0, &nfc_genl_family, 0,
226 NFC_EVENT_DEVICE_REMOVED);
227 if (!hdr)
228 goto free_msg;
229
230 NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
231
232 genlmsg_end(msg, hdr);
233
234 genlmsg_multicast(msg, 0, nfc_genl_event_mcgrp.id, GFP_KERNEL);
235
236 return 0;
237
238nla_put_failure:
239 genlmsg_cancel(msg, hdr);
240free_msg:
241 nlmsg_free(msg);
242 return -EMSGSIZE;
243}
244
245static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev,
246 u32 pid, u32 seq,
247 struct netlink_callback *cb,
248 int flags)
249{
250 void *hdr;
251
252 nfc_dbg("entry");
253
254 hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags,
255 NFC_CMD_GET_DEVICE);
256 if (!hdr)
257 return -EMSGSIZE;
258
259 if (cb)
260 genl_dump_check_consistent(cb, hdr, &nfc_genl_family);
261
262 NLA_PUT_STRING(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev));
263 NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx);
264 NLA_PUT_U32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols);
265
266 return genlmsg_end(msg, hdr);
267
268nla_put_failure:
269 genlmsg_cancel(msg, hdr);
270 return -EMSGSIZE;
271}
272
273static int nfc_genl_dump_devices(struct sk_buff *skb,
274 struct netlink_callback *cb)
275{
276 struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
277 struct nfc_dev *dev = (struct nfc_dev *) cb->args[1];
278 bool first_call = false;
279
280 nfc_dbg("entry");
281
282 if (!iter) {
283 first_call = true;
284 iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL);
285 if (!iter)
286 return -ENOMEM;
287 cb->args[0] = (long) iter;
288 }
289
290 mutex_lock(&nfc_devlist_mutex);
291
292 cb->seq = nfc_devlist_generation;
293
294 if (first_call) {
295 nfc_device_iter_init(iter);
296 dev = nfc_device_iter_next(iter);
297 }
298
299 while (dev) {
300 int rc;
301
302 rc = nfc_genl_send_device(skb, dev, NETLINK_CB(cb->skb).pid,
303 cb->nlh->nlmsg_seq,
304 cb, NLM_F_MULTI);
305 if (rc < 0)
306 break;
307
308 dev = nfc_device_iter_next(iter);
309 }
310
311 mutex_unlock(&nfc_devlist_mutex);
312
313 cb->args[1] = (long) dev;
314
315 return skb->len;
316}
317
318static int nfc_genl_dump_devices_done(struct netlink_callback *cb)
319{
320 struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0];
321
322 nfc_dbg("entry");
323
324 nfc_device_iter_exit(iter);
325 kfree(iter);
326
327 return 0;
328}
329
330static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info)
331{
332 struct sk_buff *msg;
333 struct nfc_dev *dev;
334 u32 idx;
335 int rc = -ENOBUFS;
336
337 nfc_dbg("entry");
338
339 if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
340 return -EINVAL;
341
342 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
343
344 dev = nfc_get_device(idx);
345 if (!dev)
346 return -ENODEV;
347
348 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
349 if (!msg) {
350 rc = -ENOMEM;
351 goto out_putdev;
352 }
353
354 rc = nfc_genl_send_device(msg, dev, info->snd_pid, info->snd_seq,
355 NULL, 0);
356 if (rc < 0)
357 goto out_free;
358
359 nfc_put_device(dev);
360
361 return genlmsg_reply(msg, info);
362
363out_free:
364 nlmsg_free(msg);
365out_putdev:
366 nfc_put_device(dev);
367 return rc;
368}
369
370static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info)
371{
372 struct nfc_dev *dev;
373 int rc;
374 u32 idx;
375 u32 protocols;
376
377 nfc_dbg("entry");
378
379 if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
380 !info->attrs[NFC_ATTR_PROTOCOLS])
381 return -EINVAL;
382
383 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
384 protocols = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
385
386 dev = nfc_get_device(idx);
387 if (!dev)
388 return -ENODEV;
389
390 mutex_lock(&dev->genl_data.genl_data_mutex);
391
392 rc = nfc_start_poll(dev, protocols);
393 if (!rc)
394 dev->genl_data.poll_req_pid = info->snd_pid;
395
396 mutex_unlock(&dev->genl_data.genl_data_mutex);
397
398 nfc_put_device(dev);
399 return rc;
400}
401
402static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info)
403{
404 struct nfc_dev *dev;
405 int rc;
406 u32 idx;
407
408 nfc_dbg("entry");
409
410 if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
411 return -EINVAL;
412
413 idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
414
415 dev = nfc_get_device(idx);
416 if (!dev)
417 return -ENODEV;
418
419 mutex_lock(&dev->genl_data.genl_data_mutex);
420
421 if (dev->genl_data.poll_req_pid != info->snd_pid) {
422 rc = -EBUSY;
423 goto out;
424 }
425
426 rc = nfc_stop_poll(dev);
427 dev->genl_data.poll_req_pid = 0;
428
429out:
430 mutex_unlock(&dev->genl_data.genl_data_mutex);
431 nfc_put_device(dev);
432 return rc;
433}
434
435static struct genl_ops nfc_genl_ops[] = {
436 {
437 .cmd = NFC_CMD_GET_DEVICE,
438 .doit = nfc_genl_get_device,
439 .dumpit = nfc_genl_dump_devices,
440 .done = nfc_genl_dump_devices_done,
441 .policy = nfc_genl_policy,
442 },
443 {
444 .cmd = NFC_CMD_START_POLL,
445 .doit = nfc_genl_start_poll,
446 .policy = nfc_genl_policy,
447 },
448 {
449 .cmd = NFC_CMD_STOP_POLL,
450 .doit = nfc_genl_stop_poll,
451 .policy = nfc_genl_policy,
452 },
453 {
454 .cmd = NFC_CMD_GET_TARGET,
455 .dumpit = nfc_genl_dump_targets,
456 .done = nfc_genl_dump_targets_done,
457 .policy = nfc_genl_policy,
458 },
459};
460
461static int nfc_genl_rcv_nl_event(struct notifier_block *this,
462 unsigned long event, void *ptr)
463{
464 struct netlink_notify *n = ptr;
465 struct class_dev_iter iter;
466 struct nfc_dev *dev;
467
468 if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)
469 goto out;
470
471 nfc_dbg("NETLINK_URELEASE event from id %d", n->pid);
472
473 nfc_device_iter_init(&iter);
474 dev = nfc_device_iter_next(&iter);
475
476 while (dev) {
477 mutex_lock(&dev->genl_data.genl_data_mutex);
478 if (dev->genl_data.poll_req_pid == n->pid) {
479 nfc_stop_poll(dev);
480 dev->genl_data.poll_req_pid = 0;
481 }
482 mutex_unlock(&dev->genl_data.genl_data_mutex);
483 dev = nfc_device_iter_next(&iter);
484 }
485
486 nfc_device_iter_exit(&iter);
487
488out:
489 return NOTIFY_DONE;
490}
491
492void nfc_genl_data_init(struct nfc_genl_data *genl_data)
493{
494 genl_data->poll_req_pid = 0;
495 mutex_init(&genl_data->genl_data_mutex);
496}
497
498void nfc_genl_data_exit(struct nfc_genl_data *genl_data)
499{
500 mutex_destroy(&genl_data->genl_data_mutex);
501}
502
503static struct notifier_block nl_notifier = {
504 .notifier_call = nfc_genl_rcv_nl_event,
505};
506
507/**
508 * nfc_genl_init() - Initialize netlink interface
509 *
510 * This initialization function registers the nfc netlink family.
511 */
512int __init nfc_genl_init(void)
513{
514 int rc;
515
516 rc = genl_register_family_with_ops(&nfc_genl_family, nfc_genl_ops,
517 ARRAY_SIZE(nfc_genl_ops));
518 if (rc)
519 return rc;
520
521 rc = genl_register_mc_group(&nfc_genl_family, &nfc_genl_event_mcgrp);
522
523 netlink_register_notifier(&nl_notifier);
524
525 return rc;
526}
527
528/**
529 * nfc_genl_exit() - Deinitialize netlink interface
530 *
531 * This exit function unregisters the nfc netlink family.
532 */
533void nfc_genl_exit(void)
534{
535 netlink_unregister_notifier(&nl_notifier);
536 genl_unregister_family(&nfc_genl_family);
537}
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h
new file mode 100644
index 000000000000..aaf9832298f3
--- /dev/null
+++ b/net/nfc/nfc.h
@@ -0,0 +1,117 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
6 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#ifndef __LOCAL_NFC_H
25#define __LOCAL_NFC_H
26
27#include <net/nfc.h>
28#include <net/sock.h>
29
30__attribute__((format (printf, 2, 3)))
31int nfc_printk(const char *level, const char *fmt, ...);
32
33#define nfc_info(fmt, arg...) nfc_printk(KERN_INFO, fmt, ##arg)
34#define nfc_err(fmt, arg...) nfc_printk(KERN_ERR, fmt, ##arg)
35#define nfc_dbg(fmt, arg...) pr_debug(fmt "\n", ##arg)
36
37struct nfc_protocol {
38 int id;
39 struct proto *proto;
40 struct module *owner;
41 int (*create)(struct net *net, struct socket *sock,
42 const struct nfc_protocol *nfc_proto);
43};
44
45struct nfc_rawsock {
46 struct sock sk;
47 struct nfc_dev *dev;
48 u32 target_idx;
49 struct work_struct tx_work;
50 bool tx_work_scheduled;
51};
52#define nfc_rawsock(sk) ((struct nfc_rawsock *) sk)
53#define to_rawsock_sk(_tx_work) \
54 ((struct sock *) container_of(_tx_work, struct nfc_rawsock, tx_work))
55
56int __init rawsock_init(void);
57void rawsock_exit(void);
58
59int __init af_nfc_init(void);
60void af_nfc_exit(void);
61int nfc_proto_register(const struct nfc_protocol *nfc_proto);
62void nfc_proto_unregister(const struct nfc_protocol *nfc_proto);
63
64extern int nfc_devlist_generation;
65extern struct mutex nfc_devlist_mutex;
66
67int __init nfc_genl_init(void);
68void nfc_genl_exit(void);
69
70void nfc_genl_data_init(struct nfc_genl_data *genl_data);
71void nfc_genl_data_exit(struct nfc_genl_data *genl_data);
72
73int nfc_genl_targets_found(struct nfc_dev *dev);
74
75int nfc_genl_device_added(struct nfc_dev *dev);
76int nfc_genl_device_removed(struct nfc_dev *dev);
77
78struct nfc_dev *nfc_get_device(unsigned idx);
79
80static inline void nfc_put_device(struct nfc_dev *dev)
81{
82 put_device(&dev->dev);
83}
84
85static inline void nfc_device_iter_init(struct class_dev_iter *iter)
86{
87 class_dev_iter_init(iter, &nfc_class, NULL, NULL);
88}
89
90static inline struct nfc_dev *nfc_device_iter_next(struct class_dev_iter *iter)
91{
92 struct device *d = class_dev_iter_next(iter);
93 if (!d)
94 return NULL;
95
96 return to_nfc_dev(d);
97}
98
99static inline void nfc_device_iter_exit(struct class_dev_iter *iter)
100{
101 class_dev_iter_exit(iter);
102}
103
104int nfc_start_poll(struct nfc_dev *dev, u32 protocols);
105
106int nfc_stop_poll(struct nfc_dev *dev);
107
108int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol);
109
110int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx);
111
112int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx,
113 struct sk_buff *skb,
114 data_exchange_cb_t cb,
115 void *cb_context);
116
117#endif /* __LOCAL_NFC_H */
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
new file mode 100644
index 000000000000..52de84a55115
--- /dev/null
+++ b/net/nfc/rawsock.c
@@ -0,0 +1,354 @@
1/*
2 * Copyright (C) 2011 Instituto Nokia de Tecnologia
3 *
4 * Authors:
5 * Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
6 * Lauro Ramos Venancio <lauro.venancio@openbossa.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc.,
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24#include <net/tcp_states.h>
25#include <linux/nfc.h>
26
27#include "nfc.h"
28
29static void rawsock_write_queue_purge(struct sock *sk)
30{
31 nfc_dbg("sk=%p", sk);
32
33 spin_lock_bh(&sk->sk_write_queue.lock);
34 __skb_queue_purge(&sk->sk_write_queue);
35 nfc_rawsock(sk)->tx_work_scheduled = false;
36 spin_unlock_bh(&sk->sk_write_queue.lock);
37}
38
39static void rawsock_report_error(struct sock *sk, int err)
40{
41 nfc_dbg("sk=%p err=%d", sk, err);
42
43 sk->sk_shutdown = SHUTDOWN_MASK;
44 sk->sk_err = -err;
45 sk->sk_error_report(sk);
46
47 rawsock_write_queue_purge(sk);
48}
49
50static int rawsock_release(struct socket *sock)
51{
52 struct sock *sk = sock->sk;
53
54 nfc_dbg("sock=%p", sock);
55
56 sock_orphan(sk);
57 sock_put(sk);
58
59 return 0;
60}
61
62static int rawsock_connect(struct socket *sock, struct sockaddr *_addr,
63 int len, int flags)
64{
65 struct sock *sk = sock->sk;
66 struct sockaddr_nfc *addr = (struct sockaddr_nfc *)_addr;
67 struct nfc_dev *dev;
68 int rc = 0;
69
70 nfc_dbg("sock=%p sk=%p flags=%d", sock, sk, flags);
71
72 if (!addr || len < sizeof(struct sockaddr_nfc) ||
73 addr->sa_family != AF_NFC)
74 return -EINVAL;
75
76 nfc_dbg("addr dev_idx=%u target_idx=%u protocol=%u", addr->dev_idx,
77 addr->target_idx, addr->nfc_protocol);
78
79 lock_sock(sk);
80
81 if (sock->state == SS_CONNECTED) {
82 rc = -EISCONN;
83 goto error;
84 }
85
86 dev = nfc_get_device(addr->dev_idx);
87 if (!dev) {
88 rc = -ENODEV;
89 goto error;
90 }
91
92 if (addr->target_idx > dev->target_idx - 1 ||
93 addr->target_idx < dev->target_idx - dev->n_targets) {
94 rc = -EINVAL;
95 goto error;
96 }
97
98 if (addr->target_idx > dev->target_idx - 1 ||
99 addr->target_idx < dev->target_idx - dev->n_targets) {
100 rc = -EINVAL;
101 goto error;
102 }
103
104 rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol);
105 if (rc)
106 goto put_dev;
107
108 nfc_rawsock(sk)->dev = dev;
109 nfc_rawsock(sk)->target_idx = addr->target_idx;
110 sock->state = SS_CONNECTED;
111 sk->sk_state = TCP_ESTABLISHED;
112 sk->sk_state_change(sk);
113
114 release_sock(sk);
115 return 0;
116
117put_dev:
118 nfc_put_device(dev);
119error:
120 release_sock(sk);
121 return rc;
122}
123
124static int rawsock_add_header(struct sk_buff *skb)
125{
126
127 if (skb_cow_head(skb, 1))
128 return -ENOMEM;
129
130 *skb_push(skb, 1) = 0;
131
132 return 0;
133}
134
135static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb,
136 int err)
137{
138 struct sock *sk = (struct sock *) context;
139
140 BUG_ON(in_irq());
141
142 nfc_dbg("sk=%p err=%d", sk, err);
143
144 if (err)
145 goto error;
146
147 err = rawsock_add_header(skb);
148 if (err)
149 goto error;
150
151 err = sock_queue_rcv_skb(sk, skb);
152 if (err)
153 goto error;
154
155 spin_lock_bh(&sk->sk_write_queue.lock);
156 if (!skb_queue_empty(&sk->sk_write_queue))
157 schedule_work(&nfc_rawsock(sk)->tx_work);
158 else
159 nfc_rawsock(sk)->tx_work_scheduled = false;
160 spin_unlock_bh(&sk->sk_write_queue.lock);
161
162 sock_put(sk);
163 return;
164
165error:
166 rawsock_report_error(sk, err);
167 sock_put(sk);
168}
169
170static void rawsock_tx_work(struct work_struct *work)
171{
172 struct sock *sk = to_rawsock_sk(work);
173 struct nfc_dev *dev = nfc_rawsock(sk)->dev;
174 u32 target_idx = nfc_rawsock(sk)->target_idx;
175 struct sk_buff *skb;
176 int rc;
177
178 nfc_dbg("sk=%p target_idx=%u", sk, target_idx);
179
180 if (sk->sk_shutdown & SEND_SHUTDOWN) {
181 rawsock_write_queue_purge(sk);
182 return;
183 }
184
185 skb = skb_dequeue(&sk->sk_write_queue);
186
187 sock_hold(sk);
188 rc = nfc_data_exchange(dev, target_idx, skb,
189 rawsock_data_exchange_complete, sk);
190 if (rc) {
191 rawsock_report_error(sk, rc);
192 sock_put(sk);
193 }
194}
195
196static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,
197 struct msghdr *msg, size_t len)
198{
199 struct sock *sk = sock->sk;
200 struct sk_buff *skb;
201 int rc;
202
203 nfc_dbg("sock=%p sk=%p len=%zu", sock, sk, len);
204
205 if (msg->msg_namelen)
206 return -EOPNOTSUPP;
207
208 if (sock->state != SS_CONNECTED)
209 return -ENOTCONN;
210
211 skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT,
212 &rc);
213 if (!skb)
214 return rc;
215
216 rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
217 if (rc < 0) {
218 kfree_skb(skb);
219 return rc;
220 }
221
222 spin_lock_bh(&sk->sk_write_queue.lock);
223 __skb_queue_tail(&sk->sk_write_queue, skb);
224 if (!nfc_rawsock(sk)->tx_work_scheduled) {
225 schedule_work(&nfc_rawsock(sk)->tx_work);
226 nfc_rawsock(sk)->tx_work_scheduled = true;
227 }
228 spin_unlock_bh(&sk->sk_write_queue.lock);
229
230 return len;
231}
232
233static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock,
234 struct msghdr *msg, size_t len, int flags)
235{
236 int noblock = flags & MSG_DONTWAIT;
237 struct sock *sk = sock->sk;
238 struct sk_buff *skb;
239 int copied;
240 int rc;
241
242 nfc_dbg("sock=%p sk=%p len=%zu flags=%d", sock, sk, len, flags);
243
244 skb = skb_recv_datagram(sk, flags, noblock, &rc);
245 if (!skb)
246 return rc;
247
248 msg->msg_namelen = 0;
249
250 copied = skb->len;
251 if (len < copied) {
252 msg->msg_flags |= MSG_TRUNC;
253 copied = len;
254 }
255
256 rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
257
258 skb_free_datagram(sk, skb);
259
260 return rc ? : copied;
261}
262
263
264static const struct proto_ops rawsock_ops = {
265 .family = PF_NFC,
266 .owner = THIS_MODULE,
267 .release = rawsock_release,
268 .bind = sock_no_bind,
269 .connect = rawsock_connect,
270 .socketpair = sock_no_socketpair,
271 .accept = sock_no_accept,
272 .getname = sock_no_getname,
273 .poll = datagram_poll,
274 .ioctl = sock_no_ioctl,
275 .listen = sock_no_listen,
276 .shutdown = sock_no_shutdown,
277 .setsockopt = sock_no_setsockopt,
278 .getsockopt = sock_no_getsockopt,
279 .sendmsg = rawsock_sendmsg,
280 .recvmsg = rawsock_recvmsg,
281 .mmap = sock_no_mmap,
282};
283
284static void rawsock_destruct(struct sock *sk)
285{
286 nfc_dbg("sk=%p", sk);
287
288 if (sk->sk_state == TCP_ESTABLISHED) {
289 nfc_deactivate_target(nfc_rawsock(sk)->dev,
290 nfc_rawsock(sk)->target_idx);
291 nfc_put_device(nfc_rawsock(sk)->dev);
292 }
293
294 skb_queue_purge(&sk->sk_receive_queue);
295
296 if (!sock_flag(sk, SOCK_DEAD)) {
297 nfc_err("Freeing alive NFC raw socket %p", sk);
298 return;
299 }
300}
301
302static int rawsock_create(struct net *net, struct socket *sock,
303 const struct nfc_protocol *nfc_proto)
304{
305 struct sock *sk;
306
307 nfc_dbg("sock=%p", sock);
308
309 if (sock->type != SOCK_SEQPACKET)
310 return -ESOCKTNOSUPPORT;
311
312 sock->ops = &rawsock_ops;
313
314 sk = sk_alloc(net, PF_NFC, GFP_KERNEL, nfc_proto->proto);
315 if (!sk)
316 return -ENOMEM;
317
318 sock_init_data(sock, sk);
319 sk->sk_protocol = nfc_proto->id;
320 sk->sk_destruct = rawsock_destruct;
321 sock->state = SS_UNCONNECTED;
322
323 INIT_WORK(&nfc_rawsock(sk)->tx_work, rawsock_tx_work);
324 nfc_rawsock(sk)->tx_work_scheduled = false;
325
326 return 0;
327}
328
329static struct proto rawsock_proto = {
330 .name = "NFC_RAW",
331 .owner = THIS_MODULE,
332 .obj_size = sizeof(struct nfc_rawsock),
333};
334
335static const struct nfc_protocol rawsock_nfc_proto = {
336 .id = NFC_SOCKPROTO_RAW,
337 .proto = &rawsock_proto,
338 .owner = THIS_MODULE,
339 .create = rawsock_create
340};
341
342int __init rawsock_init(void)
343{
344 int rc;
345
346 rc = nfc_proto_register(&rawsock_nfc_proto);
347
348 return rc;
349}
350
351void rawsock_exit(void)
352{
353 nfc_proto_unregister(&rawsock_nfc_proto);
354}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 3633ab6af184..832f6574e4ed 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1084,3 +1084,14 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
1084 nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp); 1084 nl80211_send_cqm_pktloss_notify(rdev, dev, peer, num_packets, gfp);
1085} 1085}
1086EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify); 1086EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
1087
1088void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
1089 const u8 *replay_ctr, gfp_t gfp)
1090{
1091 struct wireless_dev *wdev = dev->ieee80211_ptr;
1092 struct wiphy *wiphy = wdev->wiphy;
1093 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1094
1095 nl80211_gtk_rekey_notify(rdev, dev, bssid, replay_ctr, gfp);
1096}
1097EXPORT_SYMBOL(cfg80211_gtk_rekey_notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 50ff82aa4890..491b0ba40c43 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -176,6 +176,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
176 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, 176 [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED },
177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, 177 [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, 178 [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 },
179 [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED },
179}; 180};
180 181
181/* policy for the key attributes */ 182/* policy for the key attributes */
@@ -206,6 +207,14 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = {
206 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, 207 [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED },
207}; 208};
208 209
210/* policy for GTK rekey offload attributes */
211static const struct nla_policy
212nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = {
213 [NL80211_REKEY_DATA_KEK] = { .len = NL80211_KEK_LEN },
214 [NL80211_REKEY_DATA_KCK] = { .len = NL80211_KCK_LEN },
215 [NL80211_REKEY_DATA_REPLAY_CTR] = { .len = NL80211_REPLAY_CTR_LEN },
216};
217
209/* ifidx get helper */ 218/* ifidx get helper */
210static int nl80211_get_ifidx(struct netlink_callback *cb) 219static int nl80211_get_ifidx(struct netlink_callback *cb)
211{ 220{
@@ -5408,6 +5417,57 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
5408 return err; 5417 return err;
5409} 5418}
5410 5419
5420static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
5421{
5422 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5423 struct net_device *dev = info->user_ptr[1];
5424 struct wireless_dev *wdev = dev->ieee80211_ptr;
5425 struct nlattr *tb[NUM_NL80211_REKEY_DATA];
5426 struct cfg80211_gtk_rekey_data rekey_data;
5427 int err;
5428
5429 if (!info->attrs[NL80211_ATTR_REKEY_DATA])
5430 return -EINVAL;
5431
5432 err = nla_parse(tb, MAX_NL80211_REKEY_DATA,
5433 nla_data(info->attrs[NL80211_ATTR_REKEY_DATA]),
5434 nla_len(info->attrs[NL80211_ATTR_REKEY_DATA]),
5435 nl80211_rekey_policy);
5436 if (err)
5437 return err;
5438
5439 if (nla_len(tb[NL80211_REKEY_DATA_REPLAY_CTR]) != NL80211_REPLAY_CTR_LEN)
5440 return -ERANGE;
5441 if (nla_len(tb[NL80211_REKEY_DATA_KEK]) != NL80211_KEK_LEN)
5442 return -ERANGE;
5443 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
5444 return -ERANGE;
5445
5446 memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]),
5447 NL80211_KEK_LEN);
5448 memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]),
5449 NL80211_KCK_LEN);
5450 memcpy(rekey_data.replay_ctr,
5451 nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
5452 NL80211_REPLAY_CTR_LEN);
5453
5454 wdev_lock(wdev);
5455 if (!wdev->current_bss) {
5456 err = -ENOTCONN;
5457 goto out;
5458 }
5459
5460 if (!rdev->ops->set_rekey_data) {
5461 err = -EOPNOTSUPP;
5462 goto out;
5463 }
5464
5465 err = rdev->ops->set_rekey_data(&rdev->wiphy, dev, &rekey_data);
5466 out:
5467 wdev_unlock(wdev);
5468 return err;
5469}
5470
5411#define NL80211_FLAG_NEED_WIPHY 0x01 5471#define NL80211_FLAG_NEED_WIPHY 0x01
5412#define NL80211_FLAG_NEED_NETDEV 0x02 5472#define NL80211_FLAG_NEED_NETDEV 0x02
5413#define NL80211_FLAG_NEED_RTNL 0x04 5473#define NL80211_FLAG_NEED_RTNL 0x04
@@ -5939,6 +5999,14 @@ static struct genl_ops nl80211_ops[] = {
5939 .internal_flags = NL80211_FLAG_NEED_WIPHY | 5999 .internal_flags = NL80211_FLAG_NEED_WIPHY |
5940 NL80211_FLAG_NEED_RTNL, 6000 NL80211_FLAG_NEED_RTNL,
5941 }, 6001 },
6002 {
6003 .cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
6004 .doit = nl80211_set_rekey_data,
6005 .policy = nl80211_policy,
6006 .flags = GENL_ADMIN_PERM,
6007 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
6008 NL80211_FLAG_NEED_RTNL,
6009 },
5942}; 6010};
5943 6011
5944static struct genl_multicast_group nl80211_mlme_mcgrp = { 6012static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -6883,6 +6951,51 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
6883 nlmsg_free(msg); 6951 nlmsg_free(msg);
6884} 6952}
6885 6953
6954void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
6955 struct net_device *netdev, const u8 *bssid,
6956 const u8 *replay_ctr, gfp_t gfp)
6957{
6958 struct sk_buff *msg;
6959 struct nlattr *rekey_attr;
6960 void *hdr;
6961
6962 msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
6963 if (!msg)
6964 return;
6965
6966 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_REKEY_OFFLOAD);
6967 if (!hdr) {
6968 nlmsg_free(msg);
6969 return;
6970 }
6971
6972 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
6973 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
6974 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
6975
6976 rekey_attr = nla_nest_start(msg, NL80211_ATTR_REKEY_DATA);
6977 if (!rekey_attr)
6978 goto nla_put_failure;
6979
6980 NLA_PUT(msg, NL80211_REKEY_DATA_REPLAY_CTR,
6981 NL80211_REPLAY_CTR_LEN, replay_ctr);
6982
6983 nla_nest_end(msg, rekey_attr);
6984
6985 if (genlmsg_end(msg, hdr) < 0) {
6986 nlmsg_free(msg);
6987 return;
6988 }
6989
6990 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
6991 nl80211_mlme_mcgrp.id, gfp);
6992 return;
6993
6994 nla_put_failure:
6995 genlmsg_cancel(msg, hdr);
6996 nlmsg_free(msg);
6997}
6998
6886void 6999void
6887nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, 7000nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
6888 struct net_device *netdev, const u8 *peer, 7001 struct net_device *netdev, const u8 *peer,
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2f1bfb87a651..5d69c56400ae 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -109,4 +109,8 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
109 struct net_device *netdev, const u8 *peer, 109 struct net_device *netdev, const u8 *peer,
110 u32 num_packets, gfp_t gfp); 110 u32 num_packets, gfp_t gfp);
111 111
112void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
113 struct net_device *netdev, const u8 *bssid,
114 const u8 *replay_ctr, gfp_t gfp);
115
112#endif /* __NET_WIRELESS_NL80211_H */ 116#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 7a6c67667d70..5d23503dd5e0 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -132,7 +132,6 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
132int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, 132int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
133 bool driver_initiated) 133 bool driver_initiated)
134{ 134{
135 int err;
136 struct net_device *dev; 135 struct net_device *dev;
137 136
138 ASSERT_RDEV_LOCK(rdev); 137 ASSERT_RDEV_LOCK(rdev);
@@ -143,7 +142,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
143 dev = rdev->sched_scan_req->dev; 142 dev = rdev->sched_scan_req->dev;
144 143
145 if (!driver_initiated) { 144 if (!driver_initiated) {
146 err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev); 145 int err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
147 if (err) 146 if (err)
148 return err; 147 return err;
149 } 148 }
@@ -153,7 +152,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
153 kfree(rdev->sched_scan_req); 152 kfree(rdev->sched_scan_req);
154 rdev->sched_scan_req = NULL; 153 rdev->sched_scan_req = NULL;
155 154
156 return err; 155 return 0;
157} 156}
158 157
159static void bss_release(struct kref *ref) 158static void bss_release(struct kref *ref)