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