Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/llc/llc_conn.c
15109 views
1
/*
2
* llc_conn.c - Driver routines for connection component.
3
*
4
* Copyright (c) 1997 by Procom Technology, Inc.
5
* 2001-2003 by Arnaldo Carvalho de Melo <[email protected]>
6
*
7
* This program can be redistributed or modified under the terms of the
8
* GNU General Public License as published by the Free Software Foundation.
9
* This program is distributed without any warranty or implied warranty
10
* of merchantability or fitness for a particular purpose.
11
*
12
* See the GNU General Public License for more details.
13
*/
14
15
#include <linux/init.h>
16
#include <linux/slab.h>
17
#include <net/llc_sap.h>
18
#include <net/llc_conn.h>
19
#include <net/sock.h>
20
#include <net/tcp_states.h>
21
#include <net/llc_c_ev.h>
22
#include <net/llc_c_ac.h>
23
#include <net/llc_c_st.h>
24
#include <net/llc_pdu.h>
25
26
#if 0
27
#define dprintk(args...) printk(KERN_DEBUG args)
28
#else
29
#define dprintk(args...)
30
#endif
31
32
static int llc_find_offset(int state, int ev_type);
33
static void llc_conn_send_pdus(struct sock *sk);
34
static int llc_conn_service(struct sock *sk, struct sk_buff *skb);
35
static int llc_exec_conn_trans_actions(struct sock *sk,
36
struct llc_conn_state_trans *trans,
37
struct sk_buff *ev);
38
static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
39
struct sk_buff *skb);
40
41
/* Offset table on connection states transition diagram */
42
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
43
44
int sysctl_llc2_ack_timeout = LLC2_ACK_TIME * HZ;
45
int sysctl_llc2_p_timeout = LLC2_P_TIME * HZ;
46
int sysctl_llc2_rej_timeout = LLC2_REJ_TIME * HZ;
47
int sysctl_llc2_busy_timeout = LLC2_BUSY_TIME * HZ;
48
49
/**
50
* llc_conn_state_process - sends event to connection state machine
51
* @sk: connection
52
* @skb: occurred event
53
*
54
* Sends an event to connection state machine. After processing event
55
* (executing it's actions and changing state), upper layer will be
56
* indicated or confirmed, if needed. Returns 0 for success, 1 for
57
* failure. The socket lock has to be held before calling this function.
58
*/
59
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
60
{
61
int rc;
62
struct llc_sock *llc = llc_sk(skb->sk);
63
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
64
65
/*
66
* We have to hold the skb, because llc_conn_service will kfree it in
67
* the sending path and we need to look at the skb->cb, where we encode
68
* llc_conn_state_ev.
69
*/
70
skb_get(skb);
71
ev->ind_prim = ev->cfm_prim = 0;
72
/*
73
* Send event to state machine
74
*/
75
rc = llc_conn_service(skb->sk, skb);
76
if (unlikely(rc != 0)) {
77
printk(KERN_ERR "%s: llc_conn_service failed\n", __func__);
78
goto out_kfree_skb;
79
}
80
81
if (unlikely(!ev->ind_prim && !ev->cfm_prim)) {
82
/* indicate or confirm not required */
83
if (!skb->next)
84
goto out_kfree_skb;
85
goto out_skb_put;
86
}
87
88
if (unlikely(ev->ind_prim && ev->cfm_prim)) /* Paranoia */
89
skb_get(skb);
90
91
switch (ev->ind_prim) {
92
case LLC_DATA_PRIM:
93
llc_save_primitive(sk, skb, LLC_DATA_PRIM);
94
if (unlikely(sock_queue_rcv_skb(sk, skb))) {
95
/*
96
* shouldn't happen
97
*/
98
printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
99
__func__);
100
kfree_skb(skb);
101
}
102
break;
103
case LLC_CONN_PRIM:
104
/*
105
* Can't be sock_queue_rcv_skb, because we have to leave the
106
* skb->sk pointing to the newly created struct sock in
107
* llc_conn_handler. -acme
108
*/
109
skb_queue_tail(&sk->sk_receive_queue, skb);
110
sk->sk_state_change(sk);
111
break;
112
case LLC_DISC_PRIM:
113
sock_hold(sk);
114
if (sk->sk_type == SOCK_STREAM &&
115
sk->sk_state == TCP_ESTABLISHED) {
116
sk->sk_shutdown = SHUTDOWN_MASK;
117
sk->sk_socket->state = SS_UNCONNECTED;
118
sk->sk_state = TCP_CLOSE;
119
if (!sock_flag(sk, SOCK_DEAD)) {
120
sock_set_flag(sk, SOCK_DEAD);
121
sk->sk_state_change(sk);
122
}
123
}
124
kfree_skb(skb);
125
sock_put(sk);
126
break;
127
case LLC_RESET_PRIM:
128
/*
129
* FIXME:
130
* RESET is not being notified to upper layers for now
131
*/
132
printk(KERN_INFO "%s: received a reset ind!\n", __func__);
133
kfree_skb(skb);
134
break;
135
default:
136
if (ev->ind_prim) {
137
printk(KERN_INFO "%s: received unknown %d prim!\n",
138
__func__, ev->ind_prim);
139
kfree_skb(skb);
140
}
141
/* No indication */
142
break;
143
}
144
145
switch (ev->cfm_prim) {
146
case LLC_DATA_PRIM:
147
if (!llc_data_accept_state(llc->state))
148
sk->sk_write_space(sk);
149
else
150
rc = llc->failed_data_req = 1;
151
break;
152
case LLC_CONN_PRIM:
153
if (sk->sk_type == SOCK_STREAM &&
154
sk->sk_state == TCP_SYN_SENT) {
155
if (ev->status) {
156
sk->sk_socket->state = SS_UNCONNECTED;
157
sk->sk_state = TCP_CLOSE;
158
} else {
159
sk->sk_socket->state = SS_CONNECTED;
160
sk->sk_state = TCP_ESTABLISHED;
161
}
162
sk->sk_state_change(sk);
163
}
164
break;
165
case LLC_DISC_PRIM:
166
sock_hold(sk);
167
if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSING) {
168
sk->sk_socket->state = SS_UNCONNECTED;
169
sk->sk_state = TCP_CLOSE;
170
sk->sk_state_change(sk);
171
}
172
sock_put(sk);
173
break;
174
case LLC_RESET_PRIM:
175
/*
176
* FIXME:
177
* RESET is not being notified to upper layers for now
178
*/
179
printk(KERN_INFO "%s: received a reset conf!\n", __func__);
180
break;
181
default:
182
if (ev->cfm_prim) {
183
printk(KERN_INFO "%s: received unknown %d prim!\n",
184
__func__, ev->cfm_prim);
185
break;
186
}
187
goto out_skb_put; /* No confirmation */
188
}
189
out_kfree_skb:
190
kfree_skb(skb);
191
out_skb_put:
192
kfree_skb(skb);
193
return rc;
194
}
195
196
void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
197
{
198
/* queue PDU to send to MAC layer */
199
skb_queue_tail(&sk->sk_write_queue, skb);
200
llc_conn_send_pdus(sk);
201
}
202
203
/**
204
* llc_conn_rtn_pdu - sends received data pdu to upper layer
205
* @sk: Active connection
206
* @skb: Received data frame
207
*
208
* Sends received data pdu to upper layer (by using indicate function).
209
* Prepares service parameters (prim and prim_data). calling indication
210
* function will be done in llc_conn_state_process.
211
*/
212
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
213
{
214
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
215
216
ev->ind_prim = LLC_DATA_PRIM;
217
}
218
219
/**
220
* llc_conn_resend_i_pdu_as_cmd - resend all all unacknowledged I PDUs
221
* @sk: active connection
222
* @nr: NR
223
* @first_p_bit: p_bit value of first pdu
224
*
225
* Resend all unacknowledged I PDUs, starting with the NR; send first as
226
* command PDU with P bit equal first_p_bit; if more than one send
227
* subsequent as command PDUs with P bit equal zero (0).
228
*/
229
void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
230
{
231
struct sk_buff *skb;
232
struct llc_pdu_sn *pdu;
233
u16 nbr_unack_pdus;
234
struct llc_sock *llc;
235
u8 howmany_resend = 0;
236
237
llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
238
if (!nbr_unack_pdus)
239
goto out;
240
/*
241
* Process unack PDUs only if unack queue is not empty; remove
242
* appropriate PDUs, fix them up, and put them on mac_pdu_q.
243
*/
244
llc = llc_sk(sk);
245
246
while ((skb = skb_dequeue(&llc->pdu_unack_q)) != NULL) {
247
pdu = llc_pdu_sn_hdr(skb);
248
llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD);
249
llc_pdu_set_pf_bit(skb, first_p_bit);
250
skb_queue_tail(&sk->sk_write_queue, skb);
251
first_p_bit = 0;
252
llc->vS = LLC_I_GET_NS(pdu);
253
howmany_resend++;
254
}
255
if (howmany_resend > 0)
256
llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO;
257
/* any PDUs to re-send are queued up; start sending to MAC */
258
llc_conn_send_pdus(sk);
259
out:;
260
}
261
262
/**
263
* llc_conn_resend_i_pdu_as_rsp - Resend all unacknowledged I PDUs
264
* @sk: active connection.
265
* @nr: NR
266
* @first_f_bit: f_bit value of first pdu.
267
*
268
* Resend all unacknowledged I PDUs, starting with the NR; send first as
269
* response PDU with F bit equal first_f_bit; if more than one send
270
* subsequent as response PDUs with F bit equal zero (0).
271
*/
272
void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
273
{
274
struct sk_buff *skb;
275
u16 nbr_unack_pdus;
276
struct llc_sock *llc = llc_sk(sk);
277
u8 howmany_resend = 0;
278
279
llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
280
if (!nbr_unack_pdus)
281
goto out;
282
/*
283
* Process unack PDUs only if unack queue is not empty; remove
284
* appropriate PDUs, fix them up, and put them on mac_pdu_q
285
*/
286
while ((skb = skb_dequeue(&llc->pdu_unack_q)) != NULL) {
287
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
288
289
llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP);
290
llc_pdu_set_pf_bit(skb, first_f_bit);
291
skb_queue_tail(&sk->sk_write_queue, skb);
292
first_f_bit = 0;
293
llc->vS = LLC_I_GET_NS(pdu);
294
howmany_resend++;
295
}
296
if (howmany_resend > 0)
297
llc->vS = (llc->vS + 1) % LLC_2_SEQ_NBR_MODULO;
298
/* any PDUs to re-send are queued up; start sending to MAC */
299
llc_conn_send_pdus(sk);
300
out:;
301
}
302
303
/**
304
* llc_conn_remove_acked_pdus - Removes acknowledged pdus from tx queue
305
* @sk: active connection
306
* nr: NR
307
* how_many_unacked: size of pdu_unack_q after removing acked pdus
308
*
309
* Removes acknowledged pdus from transmit queue (pdu_unack_q). Returns
310
* the number of pdus that removed from queue.
311
*/
312
int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
313
{
314
int pdu_pos, i;
315
struct sk_buff *skb;
316
struct llc_pdu_sn *pdu;
317
int nbr_acked = 0;
318
struct llc_sock *llc = llc_sk(sk);
319
int q_len = skb_queue_len(&llc->pdu_unack_q);
320
321
if (!q_len)
322
goto out;
323
skb = skb_peek(&llc->pdu_unack_q);
324
pdu = llc_pdu_sn_hdr(skb);
325
326
/* finding position of last acked pdu in queue */
327
pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr -
328
(int)LLC_I_GET_NS(pdu)) % LLC_2_SEQ_NBR_MODULO;
329
330
for (i = 0; i < pdu_pos && i < q_len; i++) {
331
skb = skb_dequeue(&llc->pdu_unack_q);
332
kfree_skb(skb);
333
nbr_acked++;
334
}
335
out:
336
*how_many_unacked = skb_queue_len(&llc->pdu_unack_q);
337
return nbr_acked;
338
}
339
340
/**
341
* llc_conn_send_pdus - Sends queued PDUs
342
* @sk: active connection
343
*
344
* Sends queued pdus to MAC layer for transmission.
345
*/
346
static void llc_conn_send_pdus(struct sock *sk)
347
{
348
struct sk_buff *skb;
349
350
while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) {
351
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
352
353
if (LLC_PDU_TYPE_IS_I(pdu) &&
354
!(skb->dev->flags & IFF_LOOPBACK)) {
355
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
356
357
skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb);
358
if (!skb2)
359
break;
360
skb = skb2;
361
}
362
dev_queue_xmit(skb);
363
}
364
}
365
366
/**
367
* llc_conn_service - finds transition and changes state of connection
368
* @sk: connection
369
* @skb: happened event
370
*
371
* This function finds transition that matches with happened event, then
372
* executes related actions and finally changes state of connection.
373
* Returns 0 for success, 1 for failure.
374
*/
375
static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
376
{
377
int rc = 1;
378
struct llc_sock *llc = llc_sk(sk);
379
struct llc_conn_state_trans *trans;
380
381
if (llc->state > NBR_CONN_STATES)
382
goto out;
383
rc = 0;
384
trans = llc_qualify_conn_ev(sk, skb);
385
if (trans) {
386
rc = llc_exec_conn_trans_actions(sk, trans, skb);
387
if (!rc && trans->next_state != NO_STATE_CHANGE) {
388
llc->state = trans->next_state;
389
if (!llc_data_accept_state(llc->state))
390
sk->sk_state_change(sk);
391
}
392
}
393
out:
394
return rc;
395
}
396
397
/**
398
* llc_qualify_conn_ev - finds transition for event
399
* @sk: connection
400
* @skb: happened event
401
*
402
* This function finds transition that matches with happened event.
403
* Returns pointer to found transition on success, %NULL otherwise.
404
*/
405
static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
406
struct sk_buff *skb)
407
{
408
struct llc_conn_state_trans **next_trans;
409
llc_conn_ev_qfyr_t *next_qualifier;
410
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
411
struct llc_sock *llc = llc_sk(sk);
412
struct llc_conn_state *curr_state =
413
&llc_conn_state_table[llc->state - 1];
414
415
/* search thru events for this state until
416
* list exhausted or until no more
417
*/
418
for (next_trans = curr_state->transitions +
419
llc_find_offset(llc->state - 1, ev->type);
420
(*next_trans)->ev; next_trans++) {
421
if (!((*next_trans)->ev)(sk, skb)) {
422
/* got POSSIBLE event match; the event may require
423
* qualification based on the values of a number of
424
* state flags; if all qualifications are met (i.e.,
425
* if all qualifying functions return success, or 0,
426
* then this is THE event we're looking for
427
*/
428
for (next_qualifier = (*next_trans)->ev_qualifiers;
429
next_qualifier && *next_qualifier &&
430
!(*next_qualifier)(sk, skb); next_qualifier++)
431
/* nothing */;
432
if (!next_qualifier || !*next_qualifier)
433
/* all qualifiers executed successfully; this is
434
* our transition; return it so we can perform
435
* the associated actions & change the state
436
*/
437
return *next_trans;
438
}
439
}
440
return NULL;
441
}
442
443
/**
444
* llc_exec_conn_trans_actions - executes related actions
445
* @sk: connection
446
* @trans: transition that it's actions must be performed
447
* @skb: event
448
*
449
* Executes actions that is related to happened event. Returns 0 for
450
* success, 1 to indicate failure of at least one action.
451
*/
452
static int llc_exec_conn_trans_actions(struct sock *sk,
453
struct llc_conn_state_trans *trans,
454
struct sk_buff *skb)
455
{
456
int rc = 0;
457
llc_conn_action_t *next_action;
458
459
for (next_action = trans->ev_actions;
460
next_action && *next_action; next_action++) {
461
int rc2 = (*next_action)(sk, skb);
462
463
if (rc2 == 2) {
464
rc = rc2;
465
break;
466
} else if (rc2)
467
rc = 1;
468
}
469
return rc;
470
}
471
472
static inline bool llc_estab_match(const struct llc_sap *sap,
473
const struct llc_addr *daddr,
474
const struct llc_addr *laddr,
475
const struct sock *sk)
476
{
477
struct llc_sock *llc = llc_sk(sk);
478
479
return llc->laddr.lsap == laddr->lsap &&
480
llc->daddr.lsap == daddr->lsap &&
481
llc_mac_match(llc->laddr.mac, laddr->mac) &&
482
llc_mac_match(llc->daddr.mac, daddr->mac);
483
}
484
485
/**
486
* __llc_lookup_established - Finds connection for the remote/local sap/mac
487
* @sap: SAP
488
* @daddr: address of remote LLC (MAC + SAP)
489
* @laddr: address of local LLC (MAC + SAP)
490
*
491
* Search connection list of the SAP and finds connection using the remote
492
* mac, remote sap, local mac, and local sap. Returns pointer for
493
* connection found, %NULL otherwise.
494
* Caller has to make sure local_bh is disabled.
495
*/
496
static struct sock *__llc_lookup_established(struct llc_sap *sap,
497
struct llc_addr *daddr,
498
struct llc_addr *laddr)
499
{
500
struct sock *rc;
501
struct hlist_nulls_node *node;
502
int slot = llc_sk_laddr_hashfn(sap, laddr);
503
struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
504
505
rcu_read_lock();
506
again:
507
sk_nulls_for_each_rcu(rc, node, laddr_hb) {
508
if (llc_estab_match(sap, daddr, laddr, rc)) {
509
/* Extra checks required by SLAB_DESTROY_BY_RCU */
510
if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
511
goto again;
512
if (unlikely(llc_sk(rc)->sap != sap ||
513
!llc_estab_match(sap, daddr, laddr, rc))) {
514
sock_put(rc);
515
continue;
516
}
517
goto found;
518
}
519
}
520
rc = NULL;
521
/*
522
* if the nulls value we got at the end of this lookup is
523
* not the expected one, we must restart lookup.
524
* We probably met an item that was moved to another chain.
525
*/
526
if (unlikely(get_nulls_value(node) != slot))
527
goto again;
528
found:
529
rcu_read_unlock();
530
return rc;
531
}
532
533
struct sock *llc_lookup_established(struct llc_sap *sap,
534
struct llc_addr *daddr,
535
struct llc_addr *laddr)
536
{
537
struct sock *sk;
538
539
local_bh_disable();
540
sk = __llc_lookup_established(sap, daddr, laddr);
541
local_bh_enable();
542
return sk;
543
}
544
545
static inline bool llc_listener_match(const struct llc_sap *sap,
546
const struct llc_addr *laddr,
547
const struct sock *sk)
548
{
549
struct llc_sock *llc = llc_sk(sk);
550
551
return sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN &&
552
llc->laddr.lsap == laddr->lsap &&
553
llc_mac_match(llc->laddr.mac, laddr->mac);
554
}
555
556
static struct sock *__llc_lookup_listener(struct llc_sap *sap,
557
struct llc_addr *laddr)
558
{
559
struct sock *rc;
560
struct hlist_nulls_node *node;
561
int slot = llc_sk_laddr_hashfn(sap, laddr);
562
struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
563
564
rcu_read_lock();
565
again:
566
sk_nulls_for_each_rcu(rc, node, laddr_hb) {
567
if (llc_listener_match(sap, laddr, rc)) {
568
/* Extra checks required by SLAB_DESTROY_BY_RCU */
569
if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
570
goto again;
571
if (unlikely(llc_sk(rc)->sap != sap ||
572
!llc_listener_match(sap, laddr, rc))) {
573
sock_put(rc);
574
continue;
575
}
576
goto found;
577
}
578
}
579
rc = NULL;
580
/*
581
* if the nulls value we got at the end of this lookup is
582
* not the expected one, we must restart lookup.
583
* We probably met an item that was moved to another chain.
584
*/
585
if (unlikely(get_nulls_value(node) != slot))
586
goto again;
587
found:
588
rcu_read_unlock();
589
return rc;
590
}
591
592
/**
593
* llc_lookup_listener - Finds listener for local MAC + SAP
594
* @sap: SAP
595
* @laddr: address of local LLC (MAC + SAP)
596
*
597
* Search connection list of the SAP and finds connection listening on
598
* local mac, and local sap. Returns pointer for parent socket found,
599
* %NULL otherwise.
600
* Caller has to make sure local_bh is disabled.
601
*/
602
static struct sock *llc_lookup_listener(struct llc_sap *sap,
603
struct llc_addr *laddr)
604
{
605
static struct llc_addr null_addr;
606
struct sock *rc = __llc_lookup_listener(sap, laddr);
607
608
if (!rc)
609
rc = __llc_lookup_listener(sap, &null_addr);
610
611
return rc;
612
}
613
614
static struct sock *__llc_lookup(struct llc_sap *sap,
615
struct llc_addr *daddr,
616
struct llc_addr *laddr)
617
{
618
struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
619
620
return sk ? : llc_lookup_listener(sap, laddr);
621
}
622
623
/**
624
* llc_data_accept_state - designates if in this state data can be sent.
625
* @state: state of connection.
626
*
627
* Returns 0 if data can be sent, 1 otherwise.
628
*/
629
u8 llc_data_accept_state(u8 state)
630
{
631
return state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY &&
632
state != LLC_CONN_STATE_REJ;
633
}
634
635
/**
636
* llc_find_next_offset - finds offset for next category of transitions
637
* @state: state table.
638
* @offset: start offset.
639
*
640
* Finds offset of next category of transitions in transition table.
641
* Returns the start index of next category.
642
*/
643
static u16 __init llc_find_next_offset(struct llc_conn_state *state, u16 offset)
644
{
645
u16 cnt = 0;
646
struct llc_conn_state_trans **next_trans;
647
648
for (next_trans = state->transitions + offset;
649
(*next_trans)->ev; next_trans++)
650
++cnt;
651
return cnt;
652
}
653
654
/**
655
* llc_build_offset_table - builds offset table of connection
656
*
657
* Fills offset table of connection state transition table
658
* (llc_offset_table).
659
*/
660
void __init llc_build_offset_table(void)
661
{
662
struct llc_conn_state *curr_state;
663
int state, ev_type, next_offset;
664
665
for (state = 0; state < NBR_CONN_STATES; state++) {
666
curr_state = &llc_conn_state_table[state];
667
next_offset = 0;
668
for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {
669
llc_offset_table[state][ev_type] = next_offset;
670
next_offset += llc_find_next_offset(curr_state,
671
next_offset) + 1;
672
}
673
}
674
}
675
676
/**
677
* llc_find_offset - finds start offset of category of transitions
678
* @state: state of connection
679
* @ev_type: type of happened event
680
*
681
* Finds start offset of desired category of transitions. Returns the
682
* desired start offset.
683
*/
684
static int llc_find_offset(int state, int ev_type)
685
{
686
int rc = 0;
687
/* at this stage, llc_offset_table[..][2] is not important. it is for
688
* init_pf_cycle and I don't know what is it.
689
*/
690
switch (ev_type) {
691
case LLC_CONN_EV_TYPE_PRIM:
692
rc = llc_offset_table[state][0]; break;
693
case LLC_CONN_EV_TYPE_PDU:
694
rc = llc_offset_table[state][4]; break;
695
case LLC_CONN_EV_TYPE_SIMPLE:
696
rc = llc_offset_table[state][1]; break;
697
case LLC_CONN_EV_TYPE_P_TMR:
698
case LLC_CONN_EV_TYPE_ACK_TMR:
699
case LLC_CONN_EV_TYPE_REJ_TMR:
700
case LLC_CONN_EV_TYPE_BUSY_TMR:
701
rc = llc_offset_table[state][3]; break;
702
}
703
return rc;
704
}
705
706
/**
707
* llc_sap_add_socket - adds a socket to a SAP
708
* @sap: SAP
709
* @sk: socket
710
*
711
* This function adds a socket to the hash tables of a SAP.
712
*/
713
void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
714
{
715
struct llc_sock *llc = llc_sk(sk);
716
struct hlist_head *dev_hb = llc_sk_dev_hash(sap, llc->dev->ifindex);
717
struct hlist_nulls_head *laddr_hb = llc_sk_laddr_hash(sap, &llc->laddr);
718
719
llc_sap_hold(sap);
720
llc_sk(sk)->sap = sap;
721
722
spin_lock_bh(&sap->sk_lock);
723
sap->sk_count++;
724
sk_nulls_add_node_rcu(sk, laddr_hb);
725
hlist_add_head(&llc->dev_hash_node, dev_hb);
726
spin_unlock_bh(&sap->sk_lock);
727
}
728
729
/**
730
* llc_sap_remove_socket - removes a socket from SAP
731
* @sap: SAP
732
* @sk: socket
733
*
734
* This function removes a connection from the hash tables of a SAP if
735
* the connection was in this list.
736
*/
737
void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
738
{
739
struct llc_sock *llc = llc_sk(sk);
740
741
spin_lock_bh(&sap->sk_lock);
742
sk_nulls_del_node_init_rcu(sk);
743
hlist_del(&llc->dev_hash_node);
744
sap->sk_count--;
745
spin_unlock_bh(&sap->sk_lock);
746
llc_sap_put(sap);
747
}
748
749
/**
750
* llc_conn_rcv - sends received pdus to the connection state machine
751
* @sk: current connection structure.
752
* @skb: received frame.
753
*
754
* Sends received pdus to the connection state machine.
755
*/
756
static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
757
{
758
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
759
760
ev->type = LLC_CONN_EV_TYPE_PDU;
761
ev->reason = 0;
762
return llc_conn_state_process(sk, skb);
763
}
764
765
static struct sock *llc_create_incoming_sock(struct sock *sk,
766
struct net_device *dev,
767
struct llc_addr *saddr,
768
struct llc_addr *daddr)
769
{
770
struct sock *newsk = llc_sk_alloc(sock_net(sk), sk->sk_family, GFP_ATOMIC,
771
sk->sk_prot);
772
struct llc_sock *newllc, *llc = llc_sk(sk);
773
774
if (!newsk)
775
goto out;
776
newllc = llc_sk(newsk);
777
memcpy(&newllc->laddr, daddr, sizeof(newllc->laddr));
778
memcpy(&newllc->daddr, saddr, sizeof(newllc->daddr));
779
newllc->dev = dev;
780
dev_hold(dev);
781
llc_sap_add_socket(llc->sap, newsk);
782
llc_sap_hold(llc->sap);
783
out:
784
return newsk;
785
}
786
787
void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
788
{
789
struct llc_addr saddr, daddr;
790
struct sock *sk;
791
792
llc_pdu_decode_sa(skb, saddr.mac);
793
llc_pdu_decode_ssap(skb, &saddr.lsap);
794
llc_pdu_decode_da(skb, daddr.mac);
795
llc_pdu_decode_dsap(skb, &daddr.lsap);
796
797
sk = __llc_lookup(sap, &saddr, &daddr);
798
if (!sk)
799
goto drop;
800
801
bh_lock_sock(sk);
802
/*
803
* This has to be done here and not at the upper layer ->accept
804
* method because of the way the PROCOM state machine works:
805
* it needs to set several state variables (see, for instance,
806
* llc_adm_actions_2 in net/llc/llc_c_st.c) and send a packet to
807
* the originator of the new connection, and this state has to be
808
* in the newly created struct sock private area. -acme
809
*/
810
if (unlikely(sk->sk_state == TCP_LISTEN)) {
811
struct sock *newsk = llc_create_incoming_sock(sk, skb->dev,
812
&saddr, &daddr);
813
if (!newsk)
814
goto drop_unlock;
815
skb_set_owner_r(skb, newsk);
816
} else {
817
/*
818
* Can't be skb_set_owner_r, this will be done at the
819
* llc_conn_state_process function, later on, when we will use
820
* skb_queue_rcv_skb to send it to upper layers, this is
821
* another trick required to cope with how the PROCOM state
822
* machine works. -acme
823
*/
824
skb->sk = sk;
825
}
826
if (!sock_owned_by_user(sk))
827
llc_conn_rcv(sk, skb);
828
else {
829
dprintk("%s: adding to backlog...\n", __func__);
830
llc_set_backlog_type(skb, LLC_PACKET);
831
if (sk_add_backlog(sk, skb))
832
goto drop_unlock;
833
}
834
out:
835
bh_unlock_sock(sk);
836
sock_put(sk);
837
return;
838
drop:
839
kfree_skb(skb);
840
return;
841
drop_unlock:
842
kfree_skb(skb);
843
goto out;
844
}
845
846
#undef LLC_REFCNT_DEBUG
847
#ifdef LLC_REFCNT_DEBUG
848
static atomic_t llc_sock_nr;
849
#endif
850
851
/**
852
* llc_backlog_rcv - Processes rx frames and expired timers.
853
* @sk: LLC sock (p8022 connection)
854
* @skb: queued rx frame or event
855
*
856
* This function processes frames that has received and timers that has
857
* expired during sending an I pdu (refer to data_req_handler). frames
858
* queue by llc_rcv function (llc_mac.c) and timers queue by timer
859
* callback functions(llc_c_ac.c).
860
*/
861
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
862
{
863
int rc = 0;
864
struct llc_sock *llc = llc_sk(sk);
865
866
if (likely(llc_backlog_type(skb) == LLC_PACKET)) {
867
if (likely(llc->state > 1)) /* not closed */
868
rc = llc_conn_rcv(sk, skb);
869
else
870
goto out_kfree_skb;
871
} else if (llc_backlog_type(skb) == LLC_EVENT) {
872
/* timer expiration event */
873
if (likely(llc->state > 1)) /* not closed */
874
rc = llc_conn_state_process(sk, skb);
875
else
876
goto out_kfree_skb;
877
} else {
878
printk(KERN_ERR "%s: invalid skb in backlog\n", __func__);
879
goto out_kfree_skb;
880
}
881
out:
882
return rc;
883
out_kfree_skb:
884
kfree_skb(skb);
885
goto out;
886
}
887
888
/**
889
* llc_sk_init - Initializes a socket with default llc values.
890
* @sk: socket to initialize.
891
*
892
* Initializes a socket with default llc values.
893
*/
894
static void llc_sk_init(struct sock* sk)
895
{
896
struct llc_sock *llc = llc_sk(sk);
897
898
llc->state = LLC_CONN_STATE_ADM;
899
llc->inc_cntr = llc->dec_cntr = 2;
900
llc->dec_step = llc->connect_step = 1;
901
902
setup_timer(&llc->ack_timer.timer, llc_conn_ack_tmr_cb,
903
(unsigned long)sk);
904
llc->ack_timer.expire = sysctl_llc2_ack_timeout;
905
906
setup_timer(&llc->pf_cycle_timer.timer, llc_conn_pf_cycle_tmr_cb,
907
(unsigned long)sk);
908
llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;
909
910
setup_timer(&llc->rej_sent_timer.timer, llc_conn_rej_tmr_cb,
911
(unsigned long)sk);
912
llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;
913
914
setup_timer(&llc->busy_state_timer.timer, llc_conn_busy_tmr_cb,
915
(unsigned long)sk);
916
llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;
917
918
llc->n2 = 2; /* max retransmit */
919
llc->k = 2; /* tx win size, will adjust dynam */
920
llc->rw = 128; /* rx win size (opt and equal to
921
* tx_win of remote LLC) */
922
skb_queue_head_init(&llc->pdu_unack_q);
923
sk->sk_backlog_rcv = llc_backlog_rcv;
924
}
925
926
/**
927
* llc_sk_alloc - Allocates LLC sock
928
* @family: upper layer protocol family
929
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
930
*
931
* Allocates a LLC sock and initializes it. Returns the new LLC sock
932
* or %NULL if there's no memory available for one
933
*/
934
struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot)
935
{
936
struct sock *sk = sk_alloc(net, family, priority, prot);
937
938
if (!sk)
939
goto out;
940
llc_sk_init(sk);
941
sock_init_data(NULL, sk);
942
#ifdef LLC_REFCNT_DEBUG
943
atomic_inc(&llc_sock_nr);
944
printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
945
__func__, atomic_read(&llc_sock_nr));
946
#endif
947
out:
948
return sk;
949
}
950
951
/**
952
* llc_sk_free - Frees a LLC socket
953
* @sk - socket to free
954
*
955
* Frees a LLC socket
956
*/
957
void llc_sk_free(struct sock *sk)
958
{
959
struct llc_sock *llc = llc_sk(sk);
960
961
llc->state = LLC_CONN_OUT_OF_SVC;
962
/* Stop all (possibly) running timers */
963
llc_conn_ac_stop_all_timers(sk, NULL);
964
#ifdef DEBUG_LLC_CONN_ALLOC
965
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __func__,
966
skb_queue_len(&llc->pdu_unack_q),
967
skb_queue_len(&sk->sk_write_queue));
968
#endif
969
skb_queue_purge(&sk->sk_receive_queue);
970
skb_queue_purge(&sk->sk_write_queue);
971
skb_queue_purge(&llc->pdu_unack_q);
972
#ifdef LLC_REFCNT_DEBUG
973
if (atomic_read(&sk->sk_refcnt) != 1) {
974
printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
975
sk, __func__, atomic_read(&sk->sk_refcnt));
976
printk(KERN_DEBUG "%d LLC sockets are still alive\n",
977
atomic_read(&llc_sock_nr));
978
} else {
979
atomic_dec(&llc_sock_nr);
980
printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
981
__func__, atomic_read(&llc_sock_nr));
982
}
983
#endif
984
sock_put(sk);
985
}
986
987
/**
988
* llc_sk_reset - resets a connection
989
* @sk: LLC socket to reset
990
*
991
* Resets a connection to the out of service state. Stops its timers
992
* and frees any frames in the queues of the connection.
993
*/
994
void llc_sk_reset(struct sock *sk)
995
{
996
struct llc_sock *llc = llc_sk(sk);
997
998
llc_conn_ac_stop_all_timers(sk, NULL);
999
skb_queue_purge(&sk->sk_write_queue);
1000
skb_queue_purge(&llc->pdu_unack_q);
1001
llc->remote_busy_flag = 0;
1002
llc->cause_flag = 0;
1003
llc->retry_count = 0;
1004
llc_conn_set_p_flag(sk, 0);
1005
llc->f_flag = 0;
1006
llc->s_flag = 0;
1007
llc->ack_pf = 0;
1008
llc->first_pdu_Ns = 0;
1009
llc->ack_must_be_send = 0;
1010
llc->dec_step = 1;
1011
llc->inc_cntr = 2;
1012
llc->dec_cntr = 2;
1013
llc->X = 0;
1014
llc->failed_data_req = 0 ;
1015
llc->last_nr = 0;
1016
}
1017
1018