@@ -131,6 +131,44 @@ int nfc_llcp_local_put(struct nfc_llcp_local *local)
131
131
return kref_put (& local -> ref , local_release );
132
132
}
133
133
134
+ static struct nfc_llcp_sock * nfc_llcp_sock_get (struct nfc_llcp_local * local ,
135
+ u8 ssap , u8 dsap )
136
+ {
137
+ struct sock * sk ;
138
+ struct hlist_node * node ;
139
+ struct nfc_llcp_sock * llcp_sock ;
140
+
141
+ pr_debug ("ssap dsap %d %d\n" , ssap , dsap );
142
+
143
+ if (ssap == 0 && dsap == 0 )
144
+ return NULL ;
145
+
146
+ read_lock (& local -> sockets .lock );
147
+
148
+ llcp_sock = NULL ;
149
+
150
+ sk_for_each (sk , node , & local -> sockets .head ) {
151
+ llcp_sock = nfc_llcp_sock (sk );
152
+
153
+ if (llcp_sock -> ssap == ssap && llcp_sock -> dsap == dsap )
154
+ break ;
155
+ }
156
+
157
+ read_unlock (& local -> sockets .lock );
158
+
159
+ if (llcp_sock == NULL )
160
+ return NULL ;
161
+
162
+ sock_hold (& llcp_sock -> sk );
163
+
164
+ return llcp_sock ;
165
+ }
166
+
167
+ static void nfc_llcp_sock_put (struct nfc_llcp_sock * sock )
168
+ {
169
+ sock_put (& sock -> sk );
170
+ }
171
+
134
172
static void nfc_llcp_timeout_work (struct work_struct * work )
135
173
{
136
174
struct nfc_llcp_local * local = container_of (work , struct nfc_llcp_local ,
@@ -191,6 +229,51 @@ static int nfc_llcp_wks_sap(char *service_name, size_t service_name_len)
191
229
return - EINVAL ;
192
230
}
193
231
232
+ static
233
+ struct nfc_llcp_sock * nfc_llcp_sock_from_sn (struct nfc_llcp_local * local ,
234
+ u8 * sn , size_t sn_len )
235
+ {
236
+ struct sock * sk ;
237
+ struct hlist_node * node ;
238
+ struct nfc_llcp_sock * llcp_sock , * tmp_sock ;
239
+
240
+ pr_debug ("sn %zd %p\n" , sn_len , sn );
241
+
242
+ if (sn == NULL || sn_len == 0 )
243
+ return NULL ;
244
+
245
+ read_lock (& local -> sockets .lock );
246
+
247
+ llcp_sock = NULL ;
248
+
249
+ sk_for_each (sk , node , & local -> sockets .head ) {
250
+ tmp_sock = nfc_llcp_sock (sk );
251
+
252
+ pr_debug ("llcp sock %p\n" , tmp_sock );
253
+
254
+ if (tmp_sock -> sk .sk_state != LLCP_LISTEN )
255
+ continue ;
256
+
257
+ if (tmp_sock -> service_name == NULL ||
258
+ tmp_sock -> service_name_len == 0 )
259
+ continue ;
260
+
261
+ if (tmp_sock -> service_name_len != sn_len )
262
+ continue ;
263
+
264
+ if (memcmp (sn , tmp_sock -> service_name , sn_len ) == 0 ) {
265
+ llcp_sock = tmp_sock ;
266
+ break ;
267
+ }
268
+ }
269
+
270
+ read_unlock (& local -> sockets .lock );
271
+
272
+ pr_debug ("Found llcp sock %p\n" , llcp_sock );
273
+
274
+ return llcp_sock ;
275
+ }
276
+
194
277
u8 nfc_llcp_get_sdp_ssap (struct nfc_llcp_local * local ,
195
278
struct nfc_llcp_sock * sock )
196
279
{
@@ -217,22 +300,19 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
217
300
}
218
301
219
302
/*
220
- * This is not a well known service,
221
- * we should try to find a local SDP free spot
303
+ * Check if there already is a non WKS socket bound
304
+ * to this service name.
222
305
*/
223
- ssap = find_first_zero_bit ( & local -> local_sdp , LLCP_SDP_NUM_SAP );
224
- if ( ssap == LLCP_SDP_NUM_SAP ) {
306
+ if ( nfc_llcp_sock_from_sn ( local , sock -> service_name ,
307
+ sock -> service_name_len ) != NULL ) {
225
308
mutex_unlock (& local -> sdp_lock );
226
309
227
310
return LLCP_SAP_MAX ;
228
311
}
229
312
230
- pr_debug ("SDP ssap %d\n" , LLCP_WKS_NUM_SAP + ssap );
231
-
232
- set_bit (ssap , & local -> local_sdp );
233
313
mutex_unlock (& local -> sdp_lock );
234
314
235
- return LLCP_WKS_NUM_SAP + ssap ;
315
+ return LLCP_SDP_UNBOUND ;
236
316
237
317
} else if (sock -> ssap != 0 && sock -> ssap < LLCP_WKS_NUM_SAP ) {
238
318
if (!test_bit (sock -> ssap , & local -> local_wks )) {
@@ -276,8 +356,34 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
276
356
local_ssap = ssap ;
277
357
sdp = & local -> local_wks ;
278
358
} else if (ssap < LLCP_LOCAL_NUM_SAP ) {
359
+ atomic_t * client_cnt ;
360
+
279
361
local_ssap = ssap - LLCP_WKS_NUM_SAP ;
280
362
sdp = & local -> local_sdp ;
363
+ client_cnt = & local -> local_sdp_cnt [local_ssap ];
364
+
365
+ pr_debug ("%d clients\n" , atomic_read (client_cnt ));
366
+
367
+ mutex_lock (& local -> sdp_lock );
368
+
369
+ if (atomic_dec_and_test (client_cnt )) {
370
+ struct nfc_llcp_sock * l_sock ;
371
+
372
+ pr_debug ("No more clients for SAP %d\n" , ssap );
373
+
374
+ clear_bit (local_ssap , sdp );
375
+
376
+ /* Find the listening sock and set it back to UNBOUND */
377
+ l_sock = nfc_llcp_sock_get (local , ssap , LLCP_SAP_SDP );
378
+ if (l_sock ) {
379
+ l_sock -> ssap = LLCP_SDP_UNBOUND ;
380
+ nfc_llcp_sock_put (l_sock );
381
+ }
382
+ }
383
+
384
+ mutex_unlock (& local -> sdp_lock );
385
+
386
+ return ;
281
387
} else if (ssap < LLCP_MAX_SAP ) {
282
388
local_ssap = ssap - LLCP_LOCAL_NUM_SAP ;
283
389
sdp = & local -> local_sap ;
@@ -292,6 +398,28 @@ void nfc_llcp_put_ssap(struct nfc_llcp_local *local, u8 ssap)
292
398
mutex_unlock (& local -> sdp_lock );
293
399
}
294
400
401
+ static u8 nfc_llcp_reserve_sdp_ssap (struct nfc_llcp_local * local )
402
+ {
403
+ u8 ssap ;
404
+
405
+ mutex_lock (& local -> sdp_lock );
406
+
407
+ ssap = find_first_zero_bit (& local -> local_sdp , LLCP_SDP_NUM_SAP );
408
+ if (ssap == LLCP_SDP_NUM_SAP ) {
409
+ mutex_unlock (& local -> sdp_lock );
410
+
411
+ return LLCP_SAP_MAX ;
412
+ }
413
+
414
+ pr_debug ("SDP ssap %d\n" , LLCP_WKS_NUM_SAP + ssap );
415
+
416
+ set_bit (ssap , & local -> local_sdp );
417
+
418
+ mutex_unlock (& local -> sdp_lock );
419
+
420
+ return LLCP_WKS_NUM_SAP + ssap ;
421
+ }
422
+
295
423
static int nfc_llcp_build_gb (struct nfc_llcp_local * local )
296
424
{
297
425
u8 * gb_cur , * version_tlv , version , version_length ;
@@ -493,74 +621,12 @@ static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local
493
621
return llcp_sock ;
494
622
}
495
623
496
- static struct nfc_llcp_sock * nfc_llcp_sock_get (struct nfc_llcp_local * local ,
497
- u8 ssap , u8 dsap )
498
- {
499
- struct sock * sk ;
500
- struct hlist_node * node ;
501
- struct nfc_llcp_sock * llcp_sock ;
502
-
503
- pr_debug ("ssap dsap %d %d\n" , ssap , dsap );
504
-
505
- if (ssap == 0 && dsap == 0 )
506
- return NULL ;
507
-
508
- read_lock (& local -> sockets .lock );
509
-
510
- llcp_sock = NULL ;
511
-
512
- sk_for_each (sk , node , & local -> sockets .head ) {
513
- llcp_sock = nfc_llcp_sock (sk );
514
-
515
- if (llcp_sock -> ssap == ssap &&
516
- llcp_sock -> dsap == dsap )
517
- break ;
518
- }
519
-
520
- read_unlock (& local -> sockets .lock );
521
-
522
- if (llcp_sock == NULL )
523
- return NULL ;
524
-
525
- sock_hold (& llcp_sock -> sk );
526
-
527
- return llcp_sock ;
528
- }
529
-
530
624
static struct nfc_llcp_sock * nfc_llcp_sock_get_sn (struct nfc_llcp_local * local ,
531
625
u8 * sn , size_t sn_len )
532
626
{
533
- struct sock * sk ;
534
- struct hlist_node * node ;
535
627
struct nfc_llcp_sock * llcp_sock ;
536
628
537
- pr_debug ("sn %zd\n" , sn_len );
538
-
539
- if (sn == NULL || sn_len == 0 )
540
- return NULL ;
541
-
542
- read_lock (& local -> sockets .lock );
543
-
544
- llcp_sock = NULL ;
545
-
546
- sk_for_each (sk , node , & local -> sockets .head ) {
547
- llcp_sock = nfc_llcp_sock (sk );
548
-
549
- if (llcp_sock -> sk .sk_state != LLCP_LISTEN )
550
- continue ;
551
-
552
- if (llcp_sock -> service_name == NULL ||
553
- llcp_sock -> service_name_len == 0 )
554
- continue ;
555
-
556
- if (llcp_sock -> service_name_len != sn_len )
557
- continue ;
558
-
559
- if (memcmp (sn , llcp_sock -> service_name , sn_len ) == 0 )
560
- break ;
561
- }
562
-
563
- read_unlock (& local -> sockets .lock );
629
+ llcp_sock = nfc_llcp_sock_from_sn (local , sn , sn_len );
564
630
565
631
if (llcp_sock == NULL )
566
632
return NULL ;
@@ -570,11 +636,6 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
570
636
return llcp_sock ;
571
637
}
572
638
573
- static void nfc_llcp_sock_put (struct nfc_llcp_sock * sock )
574
- {
575
- sock_put (& sock -> sk );
576
- }
577
-
578
639
static u8 * nfc_llcp_connect_sn (struct sk_buff * skb , size_t * sn_len )
579
640
{
580
641
u8 * tlv = & skb -> data [2 ], type , length ;
@@ -646,6 +707,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
646
707
goto fail ;
647
708
}
648
709
710
+ if (sock -> ssap == LLCP_SDP_UNBOUND ) {
711
+ u8 ssap = nfc_llcp_reserve_sdp_ssap (local );
712
+
713
+ pr_debug ("First client, reserving %d\n" , ssap );
714
+
715
+ if (ssap == LLCP_SAP_MAX ) {
716
+ reason = LLCP_DM_REJ ;
717
+ release_sock (& sock -> sk );
718
+ sock_put (& sock -> sk );
719
+ goto fail ;
720
+ }
721
+
722
+ sock -> ssap = ssap ;
723
+ }
724
+
649
725
new_sk = nfc_llcp_sock_alloc (NULL , parent -> sk_type , GFP_ATOMIC );
650
726
if (new_sk == NULL ) {
651
727
reason = LLCP_DM_REJ ;
@@ -659,10 +735,21 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
659
735
new_sock -> local = nfc_llcp_local_get (local );
660
736
new_sock -> miu = local -> remote_miu ;
661
737
new_sock -> nfc_protocol = sock -> nfc_protocol ;
662
- new_sock -> ssap = sock -> ssap ;
663
738
new_sock -> dsap = ssap ;
664
739
new_sock -> target_idx = local -> target_idx ;
665
740
new_sock -> parent = parent ;
741
+ new_sock -> ssap = sock -> ssap ;
742
+ if (sock -> ssap < LLCP_LOCAL_NUM_SAP && sock -> ssap >= LLCP_WKS_NUM_SAP ) {
743
+ atomic_t * client_count ;
744
+
745
+ pr_debug ("reserved_ssap %d for %p\n" , sock -> ssap , new_sock );
746
+
747
+ client_count =
748
+ & local -> local_sdp_cnt [sock -> ssap - LLCP_WKS_NUM_SAP ];
749
+
750
+ atomic_inc (client_count );
751
+ new_sock -> reserved_ssap = sock -> ssap ;
752
+ }
666
753
667
754
nfc_llcp_parse_connection_tlv (new_sock , & skb -> data [LLCP_HEADER_SIZE ],
668
755
skb -> len - LLCP_HEADER_SIZE );
0 commit comments