aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc/llcp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 16:38:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-02 16:38:27 -0400
commitaecdc33e111b2c447b622e287c6003726daa1426 (patch)
tree3e7657eae4b785e1a1fb5dfb225dbae0b2f0cfc6 /net/nfc/llcp
parenta20acf99f75e49271381d65db097c9763060a1e8 (diff)
parenta3a6cab5ea10cca64d036851fe0d932448f2fe4f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: 1) GRE now works over ipv6, from Dmitry Kozlov. 2) Make SCTP more network namespace aware, from Eric Biederman. 3) TEAM driver now works with non-ethernet devices, from Jiri Pirko. 4) Make openvswitch network namespace aware, from Pravin B Shelar. 5) IPV6 NAT implementation, from Patrick McHardy. 6) Server side support for TCP Fast Open, from Jerry Chu and others. 7) Packet BPF filter supports MOD and XOR, from Eric Dumazet and Daniel Borkmann. 8) Increate the loopback default MTU to 64K, from Eric Dumazet. 9) Use a per-task rather than per-socket page fragment allocator for outgoing networking traffic. This benefits processes that have very many mostly idle sockets, which is quite common. From Eric Dumazet. 10) Use up to 32K for page fragment allocations, with fallbacks to smaller sizes when higher order page allocations fail. Benefits are a) less segments for driver to process b) less calls to page allocator c) less waste of space. From Eric Dumazet. 11) Allow GRO to be used on GRE tunnels, from Eric Dumazet. 12) VXLAN device driver, one way to handle VLAN issues such as the limitation of 4096 VLAN IDs yet still have some level of isolation. From Stephen Hemminger. 13) As usual there is a large boatload of driver changes, with the scale perhaps tilted towards the wireless side this time around. Fix up various fairly trivial conflicts, mostly caused by the user namespace changes. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1012 commits) hyperv: Add buffer for extended info after the RNDIS response message. hyperv: Report actual status in receive completion packet hyperv: Remove extra allocated space for recv_pkt_list elements hyperv: Fix page buffer handling in rndis_filter_send_request() hyperv: Fix the missing return value in rndis_filter_set_packet_filter() hyperv: Fix the max_xfer_size in RNDIS initialization vxlan: put UDP socket in correct namespace vxlan: Depend on CONFIG_INET sfc: Fix the reported priorities of different filter types sfc: Remove EFX_FILTER_FLAG_RX_OVERRIDE_IP sfc: Fix loopback self-test with separate_tx_channels=1 sfc: Fix MCDI structure field lookup sfc: Add parentheses around use of bitfield macro arguments sfc: Fix null function pointer in efx_sriov_channel_type vxlan: virtual extensible lan igmp: export symbol ip_mc_leave_group netlink: add attributes to fdb interface tg3: unconditionally select HWMON support when tg3 is enabled. Revert "net: ti cpsw ethernet: allow reading phy interface mode from DT" gre: fix sparse warning ...
Diffstat (limited to 'net/nfc/llcp')
-rw-r--r--net/nfc/llcp/commands.c2
-rw-r--r--net/nfc/llcp/llcp.c131
-rw-r--r--net/nfc/llcp/llcp.h6
-rw-r--r--net/nfc/llcp/sock.c93
4 files changed, 161 insertions, 71 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index b982b5b890d7..c45ccd6c094c 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -312,6 +312,8 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
312 312
313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM); 313 skb = llcp_add_header(skb, 0, 0, LLCP_PDU_SYMM);
314 314
315 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_TX);
316
315 return nfc_data_exchange(dev, local->target_idx, skb, 317 return nfc_data_exchange(dev, local->target_idx, skb,
316 nfc_llcp_recv, local); 318 nfc_llcp_recv, local);
317} 319}
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 82f0f7588b46..c12c5ef3d036 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -56,7 +56,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
56 sk_for_each_safe(sk, node, tmp, &local->sockets.head) { 56 sk_for_each_safe(sk, node, tmp, &local->sockets.head) {
57 llcp_sock = nfc_llcp_sock(sk); 57 llcp_sock = nfc_llcp_sock(sk);
58 58
59 lock_sock(sk); 59 bh_lock_sock(sk);
60 60
61 if (sk->sk_state == LLCP_CONNECTED) 61 if (sk->sk_state == LLCP_CONNECTED)
62 nfc_put_device(llcp_sock->dev); 62 nfc_put_device(llcp_sock->dev);
@@ -68,26 +68,26 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
68 list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, 68 list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
69 accept_queue) { 69 accept_queue) {
70 accept_sk = &lsk->sk; 70 accept_sk = &lsk->sk;
71 lock_sock(accept_sk); 71 bh_lock_sock(accept_sk);
72 72
73 nfc_llcp_accept_unlink(accept_sk); 73 nfc_llcp_accept_unlink(accept_sk);
74 74
75 accept_sk->sk_state = LLCP_CLOSED; 75 accept_sk->sk_state = LLCP_CLOSED;
76 76
77 release_sock(accept_sk); 77 bh_unlock_sock(accept_sk);
78 78
79 sock_orphan(accept_sk); 79 sock_orphan(accept_sk);
80 } 80 }
81 81
82 if (listen == true) { 82 if (listen == true) {
83 release_sock(sk); 83 bh_unlock_sock(sk);
84 continue; 84 continue;
85 } 85 }
86 } 86 }
87 87
88 sk->sk_state = LLCP_CLOSED; 88 sk->sk_state = LLCP_CLOSED;
89 89
90 release_sock(sk); 90 bh_unlock_sock(sk);
91 91
92 sock_orphan(sk); 92 sock_orphan(sk);
93 93
@@ -114,9 +114,9 @@ static void local_release(struct kref *ref)
114 nfc_llcp_socket_release(local, false); 114 nfc_llcp_socket_release(local, false);
115 del_timer_sync(&local->link_timer); 115 del_timer_sync(&local->link_timer);
116 skb_queue_purge(&local->tx_queue); 116 skb_queue_purge(&local->tx_queue);
117 destroy_workqueue(local->tx_wq); 117 cancel_work_sync(&local->tx_work);
118 destroy_workqueue(local->rx_wq); 118 cancel_work_sync(&local->rx_work);
119 destroy_workqueue(local->timeout_wq); 119 cancel_work_sync(&local->timeout_work);
120 kfree_skb(local->rx_pending); 120 kfree_skb(local->rx_pending);
121 kfree(local); 121 kfree(local);
122} 122}
@@ -181,7 +181,7 @@ static void nfc_llcp_symm_timer(unsigned long data)
181 181
182 pr_err("SYMM timeout\n"); 182 pr_err("SYMM timeout\n");
183 183
184 queue_work(local->timeout_wq, &local->timeout_work); 184 queue_work(system_nrt_wq, &local->timeout_work);
185} 185}
186 186
187struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) 187struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
@@ -426,6 +426,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
426 u8 *miux_tlv, miux_length; 426 u8 *miux_tlv, miux_length;
427 __be16 miux; 427 __be16 miux;
428 u8 gb_len = 0; 428 u8 gb_len = 0;
429 int ret = 0;
429 430
430 version = LLCP_VERSION_11; 431 version = LLCP_VERSION_11;
431 version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version, 432 version_tlv = nfc_llcp_build_tlv(LLCP_TLV_VERSION, &version,
@@ -450,8 +451,8 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
450 gb_len += ARRAY_SIZE(llcp_magic); 451 gb_len += ARRAY_SIZE(llcp_magic);
451 452
452 if (gb_len > NFC_MAX_GT_LEN) { 453 if (gb_len > NFC_MAX_GT_LEN) {
453 kfree(version_tlv); 454 ret = -EINVAL;
454 return -EINVAL; 455 goto out;
455 } 456 }
456 457
457 gb_cur = local->gb; 458 gb_cur = local->gb;
@@ -471,12 +472,15 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local)
471 memcpy(gb_cur, miux_tlv, miux_length); 472 memcpy(gb_cur, miux_tlv, miux_length);
472 gb_cur += miux_length; 473 gb_cur += miux_length;
473 474
475 local->gb_len = gb_len;
476
477out:
474 kfree(version_tlv); 478 kfree(version_tlv);
475 kfree(lto_tlv); 479 kfree(lto_tlv);
480 kfree(wks_tlv);
481 kfree(miux_tlv);
476 482
477 local->gb_len = gb_len; 483 return ret;
478
479 return 0;
480} 484}
481 485
482u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) 486u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
@@ -554,6 +558,46 @@ static void nfc_llcp_set_nrns(struct nfc_llcp_sock *sock, struct sk_buff *pdu)
554 sock->recv_ack_n = (sock->recv_n - 1) % 16; 558 sock->recv_ack_n = (sock->recv_n - 1) % 16;
555} 559}
556 560
561void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
562 struct sk_buff *skb, u8 direction)
563{
564 struct hlist_node *node;
565 struct sk_buff *skb_copy = NULL, *nskb;
566 struct sock *sk;
567 u8 *data;
568
569 read_lock(&local->raw_sockets.lock);
570
571 sk_for_each(sk, node, &local->raw_sockets.head) {
572 if (sk->sk_state != LLCP_BOUND)
573 continue;
574
575 if (skb_copy == NULL) {
576 skb_copy = __pskb_copy(skb, NFC_LLCP_RAW_HEADER_SIZE,
577 GFP_ATOMIC);
578
579 if (skb_copy == NULL)
580 continue;
581
582 data = skb_push(skb_copy, NFC_LLCP_RAW_HEADER_SIZE);
583
584 data[0] = local->dev ? local->dev->idx : 0xFF;
585 data[1] = direction;
586 }
587
588 nskb = skb_clone(skb_copy, GFP_ATOMIC);
589 if (!nskb)
590 continue;
591
592 if (sock_queue_rcv_skb(sk, nskb))
593 kfree_skb(nskb);
594 }
595
596 read_unlock(&local->raw_sockets.lock);
597
598 kfree_skb(skb_copy);
599}
600
557static void nfc_llcp_tx_work(struct work_struct *work) 601static void nfc_llcp_tx_work(struct work_struct *work)
558{ 602{
559 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local, 603 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
@@ -574,6 +618,9 @@ static void nfc_llcp_tx_work(struct work_struct *work)
574 DUMP_PREFIX_OFFSET, 16, 1, 618 DUMP_PREFIX_OFFSET, 16, 1,
575 skb->data, skb->len, true); 619 skb->data, skb->len, true);
576 620
621 nfc_llcp_send_to_raw_sock(local, skb,
622 NFC_LLCP_DIRECTION_TX);
623
577 ret = nfc_data_exchange(local->dev, local->target_idx, 624 ret = nfc_data_exchange(local->dev, local->target_idx,
578 skb, nfc_llcp_recv, local); 625 skb, nfc_llcp_recv, local);
579 626
@@ -1018,6 +1065,8 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1018 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET, 1065 print_hex_dump(KERN_DEBUG, "LLCP Rx: ", DUMP_PREFIX_OFFSET,
1019 16, 1, skb->data, skb->len, true); 1066 16, 1, skb->data, skb->len, true);
1020 1067
1068 nfc_llcp_send_to_raw_sock(local, skb, NFC_LLCP_DIRECTION_RX);
1069
1021 switch (ptype) { 1070 switch (ptype) {
1022 case LLCP_PDU_SYMM: 1071 case LLCP_PDU_SYMM:
1023 pr_debug("SYMM\n"); 1072 pr_debug("SYMM\n");
@@ -1052,7 +1101,7 @@ static void nfc_llcp_rx_work(struct work_struct *work)
1052 1101
1053 } 1102 }
1054 1103
1055 queue_work(local->tx_wq, &local->tx_work); 1104 queue_work(system_nrt_wq, &local->tx_work);
1056 kfree_skb(local->rx_pending); 1105 kfree_skb(local->rx_pending);
1057 local->rx_pending = NULL; 1106 local->rx_pending = NULL;
1058 1107
@@ -1071,7 +1120,7 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err)
1071 1120
1072 local->rx_pending = skb_get(skb); 1121 local->rx_pending = skb_get(skb);
1073 del_timer(&local->link_timer); 1122 del_timer(&local->link_timer);
1074 queue_work(local->rx_wq, &local->rx_work); 1123 queue_work(system_nrt_wq, &local->rx_work);
1075 1124
1076 return; 1125 return;
1077} 1126}
@@ -1086,7 +1135,7 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
1086 1135
1087 local->rx_pending = skb_get(skb); 1136 local->rx_pending = skb_get(skb);
1088 del_timer(&local->link_timer); 1137 del_timer(&local->link_timer);
1089 queue_work(local->rx_wq, &local->rx_work); 1138 queue_work(system_nrt_wq, &local->rx_work);
1090 1139
1091 return 0; 1140 return 0;
1092} 1141}
@@ -1121,7 +1170,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
1121 if (rf_mode == NFC_RF_INITIATOR) { 1170 if (rf_mode == NFC_RF_INITIATOR) {
1122 pr_debug("Queueing Tx work\n"); 1171 pr_debug("Queueing Tx work\n");
1123 1172
1124 queue_work(local->tx_wq, &local->tx_work); 1173 queue_work(system_nrt_wq, &local->tx_work);
1125 } else { 1174 } else {
1126 mod_timer(&local->link_timer, 1175 mod_timer(&local->link_timer,
1127 jiffies + msecs_to_jiffies(local->remote_lto)); 1176 jiffies + msecs_to_jiffies(local->remote_lto));
@@ -1130,10 +1179,7 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
1130 1179
1131int nfc_llcp_register_device(struct nfc_dev *ndev) 1180int nfc_llcp_register_device(struct nfc_dev *ndev)
1132{ 1181{
1133 struct device *dev = &ndev->dev;
1134 struct nfc_llcp_local *local; 1182 struct nfc_llcp_local *local;
1135 char name[32];
1136 int err;
1137 1183
1138 local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL); 1184 local = kzalloc(sizeof(struct nfc_llcp_local), GFP_KERNEL);
1139 if (local == NULL) 1185 if (local == NULL)
@@ -1149,41 +1195,15 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1149 1195
1150 skb_queue_head_init(&local->tx_queue); 1196 skb_queue_head_init(&local->tx_queue);
1151 INIT_WORK(&local->tx_work, nfc_llcp_tx_work); 1197 INIT_WORK(&local->tx_work, nfc_llcp_tx_work);
1152 snprintf(name, sizeof(name), "%s_llcp_tx_wq", dev_name(dev));
1153 local->tx_wq =
1154 alloc_workqueue(name,
1155 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
1156 1);
1157 if (local->tx_wq == NULL) {
1158 err = -ENOMEM;
1159 goto err_local;
1160 }
1161 1198
1162 local->rx_pending = NULL; 1199 local->rx_pending = NULL;
1163 INIT_WORK(&local->rx_work, nfc_llcp_rx_work); 1200 INIT_WORK(&local->rx_work, nfc_llcp_rx_work);
1164 snprintf(name, sizeof(name), "%s_llcp_rx_wq", dev_name(dev));
1165 local->rx_wq =
1166 alloc_workqueue(name,
1167 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
1168 1);
1169 if (local->rx_wq == NULL) {
1170 err = -ENOMEM;
1171 goto err_tx_wq;
1172 }
1173 1201
1174 INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work); 1202 INIT_WORK(&local->timeout_work, nfc_llcp_timeout_work);
1175 snprintf(name, sizeof(name), "%s_llcp_timeout_wq", dev_name(dev));
1176 local->timeout_wq =
1177 alloc_workqueue(name,
1178 WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM,
1179 1);
1180 if (local->timeout_wq == NULL) {
1181 err = -ENOMEM;
1182 goto err_rx_wq;
1183 }
1184 1203
1185 local->sockets.lock = __RW_LOCK_UNLOCKED(local->sockets.lock); 1204 rwlock_init(&local->sockets.lock);
1186 local->connecting_sockets.lock = __RW_LOCK_UNLOCKED(local->connecting_sockets.lock); 1205 rwlock_init(&local->connecting_sockets.lock);
1206 rwlock_init(&local->raw_sockets.lock);
1187 1207
1188 nfc_llcp_build_gb(local); 1208 nfc_llcp_build_gb(local);
1189 1209
@@ -1193,17 +1213,6 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1193 list_add(&llcp_devices, &local->list); 1213 list_add(&llcp_devices, &local->list);
1194 1214
1195 return 0; 1215 return 0;
1196
1197err_rx_wq:
1198 destroy_workqueue(local->rx_wq);
1199
1200err_tx_wq:
1201 destroy_workqueue(local->tx_wq);
1202
1203err_local:
1204 kfree(local);
1205
1206 return 0;
1207} 1216}
1208 1217
1209void nfc_llcp_unregister_device(struct nfc_dev *dev) 1218void nfc_llcp_unregister_device(struct nfc_dev *dev)
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index 83b8bba5a280..fdb2d24e60bd 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -56,12 +56,9 @@ struct nfc_llcp_local {
56 56
57 struct timer_list link_timer; 57 struct timer_list link_timer;
58 struct sk_buff_head tx_queue; 58 struct sk_buff_head tx_queue;
59 struct workqueue_struct *tx_wq;
60 struct work_struct tx_work; 59 struct work_struct tx_work;
61 struct workqueue_struct *rx_wq;
62 struct work_struct rx_work; 60 struct work_struct rx_work;
63 struct sk_buff *rx_pending; 61 struct sk_buff *rx_pending;
64 struct workqueue_struct *timeout_wq;
65 struct work_struct timeout_work; 62 struct work_struct timeout_work;
66 63
67 u32 target_idx; 64 u32 target_idx;
@@ -89,6 +86,7 @@ struct nfc_llcp_local {
89 /* sockets array */ 86 /* sockets array */
90 struct llcp_sock_list sockets; 87 struct llcp_sock_list sockets;
91 struct llcp_sock_list connecting_sockets; 88 struct llcp_sock_list connecting_sockets;
89 struct llcp_sock_list raw_sockets;
92}; 90};
93 91
94struct nfc_llcp_sock { 92struct nfc_llcp_sock {
@@ -187,6 +185,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
187u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local); 185u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);
188void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap); 186void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap);
189int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock); 187int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock);
188void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
189 struct sk_buff *skb, u8 direction);
190 190
191/* Sock API */ 191/* Sock API */
192struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp); 192struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index ddeb9aa398f0..40f056debf9a 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -142,6 +142,60 @@ error:
142 return ret; 142 return ret;
143} 143}
144 144
145static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
146 int alen)
147{
148 struct sock *sk = sock->sk;
149 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
150 struct nfc_llcp_local *local;
151 struct nfc_dev *dev;
152 struct sockaddr_nfc_llcp llcp_addr;
153 int len, ret = 0;
154
155 if (!addr || addr->sa_family != AF_NFC)
156 return -EINVAL;
157
158 pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
159
160 memset(&llcp_addr, 0, sizeof(llcp_addr));
161 len = min_t(unsigned int, sizeof(llcp_addr), alen);
162 memcpy(&llcp_addr, addr, len);
163
164 lock_sock(sk);
165
166 if (sk->sk_state != LLCP_CLOSED) {
167 ret = -EBADFD;
168 goto error;
169 }
170
171 dev = nfc_get_device(llcp_addr.dev_idx);
172 if (dev == NULL) {
173 ret = -ENODEV;
174 goto error;
175 }
176
177 local = nfc_llcp_find_local(dev);
178 if (local == NULL) {
179 ret = -ENODEV;
180 goto put_dev;
181 }
182
183 llcp_sock->dev = dev;
184 llcp_sock->local = nfc_llcp_local_get(local);
185 llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
186
187 nfc_llcp_sock_link(&local->raw_sockets, sk);
188
189 sk->sk_state = LLCP_BOUND;
190
191put_dev:
192 nfc_put_device(dev);
193
194error:
195 release_sock(sk);
196 return ret;
197}
198
145static int llcp_sock_listen(struct socket *sock, int backlog) 199static int llcp_sock_listen(struct socket *sock, int backlog)
146{ 200{
147 struct sock *sk = sock->sk; 201 struct sock *sk = sock->sk;
@@ -300,9 +354,6 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *uaddr,
300 pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx, 354 pr_debug("%p %d %d %d\n", sk, llcp_sock->target_idx,
301 llcp_sock->dsap, llcp_sock->ssap); 355 llcp_sock->dsap, llcp_sock->ssap);
302 356
303 if (llcp_sock == NULL || llcp_sock->dev == NULL)
304 return -EBADFD;
305
306 uaddr->sa_family = AF_NFC; 357 uaddr->sa_family = AF_NFC;
307 358
308 *len = sizeof(struct sockaddr_nfc_llcp); 359 *len = sizeof(struct sockaddr_nfc_llcp);
@@ -421,7 +472,10 @@ static int llcp_sock_release(struct socket *sock)
421 472
422 release_sock(sk); 473 release_sock(sk);
423 474
424 nfc_llcp_sock_unlink(&local->sockets, sk); 475 if (sock->type == SOCK_RAW)
476 nfc_llcp_sock_unlink(&local->raw_sockets, sk);
477 else
478 nfc_llcp_sock_unlink(&local->sockets, sk);
425 479
426out: 480out:
427 sock_orphan(sk); 481 sock_orphan(sk);
@@ -617,7 +671,7 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
617 if (!(flags & MSG_PEEK)) { 671 if (!(flags & MSG_PEEK)) {
618 672
619 /* SOCK_STREAM: re-queue skb if it contains unreceived data */ 673 /* SOCK_STREAM: re-queue skb if it contains unreceived data */
620 if (sk->sk_type == SOCK_STREAM) { 674 if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) {
621 skb_pull(skb, copied); 675 skb_pull(skb, copied);
622 if (skb->len) { 676 if (skb->len) {
623 skb_queue_head(&sk->sk_receive_queue, skb); 677 skb_queue_head(&sk->sk_receive_queue, skb);
@@ -658,6 +712,26 @@ static const struct proto_ops llcp_sock_ops = {
658 .mmap = sock_no_mmap, 712 .mmap = sock_no_mmap,
659}; 713};
660 714
715static const struct proto_ops llcp_rawsock_ops = {
716 .family = PF_NFC,
717 .owner = THIS_MODULE,
718 .bind = llcp_raw_sock_bind,
719 .connect = sock_no_connect,
720 .release = llcp_sock_release,
721 .socketpair = sock_no_socketpair,
722 .accept = sock_no_accept,
723 .getname = llcp_sock_getname,
724 .poll = llcp_sock_poll,
725 .ioctl = sock_no_ioctl,
726 .listen = sock_no_listen,
727 .shutdown = sock_no_shutdown,
728 .setsockopt = sock_no_setsockopt,
729 .getsockopt = sock_no_getsockopt,
730 .sendmsg = sock_no_sendmsg,
731 .recvmsg = llcp_sock_recvmsg,
732 .mmap = sock_no_mmap,
733};
734
661static void llcp_sock_destruct(struct sock *sk) 735static void llcp_sock_destruct(struct sock *sk)
662{ 736{
663 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 737 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
@@ -735,10 +809,15 @@ static int llcp_sock_create(struct net *net, struct socket *sock,
735 809
736 pr_debug("%p\n", sock); 810 pr_debug("%p\n", sock);
737 811
738 if (sock->type != SOCK_STREAM && sock->type != SOCK_DGRAM) 812 if (sock->type != SOCK_STREAM &&
813 sock->type != SOCK_DGRAM &&
814 sock->type != SOCK_RAW)
739 return -ESOCKTNOSUPPORT; 815 return -ESOCKTNOSUPPORT;
740 816
741 sock->ops = &llcp_sock_ops; 817 if (sock->type == SOCK_RAW)
818 sock->ops = &llcp_rawsock_ops;
819 else
820 sock->ops = &llcp_sock_ops;
742 821
743 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC); 822 sk = nfc_llcp_sock_alloc(sock, sock->type, GFP_ATOMIC);
744 if (sk == NULL) 823 if (sk == NULL)