^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * llc_sap.c - driver routines for SAP 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 <net/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <net/llc_if.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/llc_conn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/llc_pdu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/llc_sap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/llc_s_ac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/llc_s_ev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/llc_s_st.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <net/tcp_states.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int llc_mac_header_len(unsigned short devtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) switch (devtype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) case ARPHRD_ETHER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) case ARPHRD_LOOPBACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return sizeof(struct ethhdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * llc_alloc_frame - allocates sk_buff for frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @sk: socket to allocate frame to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @dev: network device this skb will be sent over
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * @type: pdu type to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * @data_size: data size to allocate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Allocates an sk_buff for frame and initializes sk_buff fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Returns allocated skb or %NULL when out of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u8 type, u32 data_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int hlen = type == LLC_PDU_TYPE_U ? 3 : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) hlen += llc_mac_header_len(dev->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) skb = alloc_skb(hlen + data_size, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) skb_reserve(skb, hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) skb_reset_network_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) skb_reset_transport_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) skb->protocol = htons(ETH_P_802_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) skb->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if (sk != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) skb_set_owner_w(skb, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) void llc_save_primitive(struct sock *sk, struct sk_buff *skb, u8 prim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct sockaddr_llc *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* save primitive for use by the user. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) addr = llc_ui_skb_cb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) memset(addr, 0, sizeof(*addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) addr->sllc_family = sk->sk_family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) addr->sllc_arphrd = skb->dev->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) addr->sllc_test = prim == LLC_TEST_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) addr->sllc_xid = prim == LLC_XID_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) llc_pdu_decode_sa(skb, addr->sllc_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) llc_pdu_decode_ssap(skb, &addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @sap: pointer to SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @skb: received pdu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct llc_sap_state_ev *ev = llc_sap_ev(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) switch (LLC_U_PDU_RSP(pdu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) case LLC_1_PDU_CMD_TEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ev->prim = LLC_TEST_PRIM; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) case LLC_1_PDU_CMD_XID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ev->prim = LLC_XID_PRIM; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case LLC_1_PDU_CMD_UI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ev->prim = LLC_DATAUNIT_PRIM; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ev->ind_cfm_flag = LLC_IND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * llc_find_sap_trans - finds transition for event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @sap: pointer to SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * @skb: happened event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * This function finds transition that matches with happened event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * Returns the pointer to found transition on success or %NULL for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct llc_sap_state_trans *rc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct llc_sap_state_trans **next_trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * Search thru events for this state until list exhausted or until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * its obvious the event is not valid for the current state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!next_trans[i]->ev(sap, skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) rc = next_trans[i]; /* got event match; return it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * llc_exec_sap_trans_actions - execute actions related to event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @sap: pointer to SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * @trans: pointer to transition that it's actions must be performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * @skb: happened event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * This function executes actions that is related to happened event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Returns 0 for success and 1 for failure of at least one action.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int llc_exec_sap_trans_actions(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct llc_sap_state_trans *trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) const llc_sap_action_t *next_action = trans->ev_actions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) for (; next_action && *next_action; next_action++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if ((*next_action)(sap, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * llc_sap_next_state - finds transition, execs actions & change SAP state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * @sap: pointer to SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @skb: happened event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * This function finds transition that matches with happened event, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * executes related actions and finally changes state of SAP. It returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * 0 on success and 1 for failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct llc_sap_state_trans *trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (sap->state > LLC_NR_SAP_STATES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) trans = llc_find_sap_trans(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * Got the state to which we next transition; perform the actions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * associated with this transition before actually transitioning to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * next state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) rc = llc_exec_sap_trans_actions(sap, trans, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Transition SAP to next state if all actions execute successfully
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) sap->state = trans->next_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * llc_sap_state_process - sends event to SAP state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @sap: sap to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @skb: pointer to occurred event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * After executing actions of the event, upper layer will be indicated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * if needed(on receiving an UI frame). sk can be null for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * datalink_proto case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * This function always consumes a reference to the skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct llc_sap_state_ev *ev = llc_sap_ev(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) ev->ind_cfm_flag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) llc_sap_next_state(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (ev->ind_cfm_flag == LLC_IND && skb->sk->sk_state != TCP_LISTEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) llc_save_primitive(skb->sk, skb, ev->prim);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* queue skb to the user. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) if (sock_queue_rcv_skb(skb->sk, skb) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * llc_build_and_send_test_pkt - TEST interface for upper layers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @sap: sap to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @skb: packet to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @dmac: destination mac address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * @dsap: destination sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * This function is called when upper layer wants to send a TEST pdu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * Returns 0 for success, 1 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) void llc_build_and_send_test_pkt(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct sk_buff *skb, u8 *dmac, u8 dsap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct llc_sap_state_ev *ev = llc_sap_ev(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ev->saddr.lsap = sap->laddr.lsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ev->daddr.lsap = dsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ev->type = LLC_SAP_EV_TYPE_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ev->prim = LLC_TEST_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ev->prim_type = LLC_PRIM_TYPE_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) llc_sap_state_process(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * llc_build_and_send_xid_pkt - XID interface for upper layers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * @sap: sap to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * @skb: packet to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @dmac: destination mac address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @dsap: destination sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * This function is called when upper layer wants to send a XID pdu.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Returns 0 for success, 1 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) u8 *dmac, u8 dsap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct llc_sap_state_ev *ev = llc_sap_ev(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ev->saddr.lsap = sap->laddr.lsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) ev->daddr.lsap = dsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ev->type = LLC_SAP_EV_TYPE_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) ev->prim = LLC_XID_PRIM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ev->prim_type = LLC_PRIM_TYPE_REQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) llc_sap_state_process(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * llc_sap_rcv - sends received pdus to the sap state machine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @sap: current sap component structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * @skb: received frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * @sk: socket to associate to frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * Sends received pdus to the sap state machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct llc_sap_state_ev *ev = llc_sap_ev(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ev->type = LLC_SAP_EV_TYPE_PDU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ev->reason = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) skb_orphan(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) skb->sk = sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) skb->destructor = sock_efree;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) llc_sap_state_process(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static inline bool llc_dgram_match(const struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) const struct llc_addr *laddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) const struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return sk->sk_type == SOCK_DGRAM &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) llc->laddr.lsap == laddr->lsap &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ether_addr_equal(llc->laddr.mac, laddr->mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * llc_lookup_dgram - Finds dgram socket for the local sap/mac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @sap: SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @laddr: address of local LLC (MAC + SAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * Search socket list of the SAP and finds connection using the local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * mac, and local sap. Returns pointer for socket found, %NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static struct sock *llc_lookup_dgram(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) const struct llc_addr *laddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct sock *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) struct hlist_nulls_node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int slot = llc_sk_laddr_hashfn(sap, laddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) rcu_read_lock_bh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) again:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sk_nulls_for_each_rcu(rc, node, laddr_hb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (llc_dgram_match(sap, laddr, rc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (unlikely(llc_sk(rc)->sap != sap ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) !llc_dgram_match(sap, laddr, rc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) sock_put(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) rc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * if the nulls value we got at the end of this lookup is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * not the expected one, we must restart lookup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * We probably met an item that was moved to another chain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (unlikely(get_nulls_value(node) != slot))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) goto again;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) rcu_read_unlock_bh();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static inline bool llc_mcast_match(const struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) const struct llc_addr *laddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) const struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) const struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return sk->sk_type == SOCK_DGRAM &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) llc->laddr.lsap == laddr->lsap &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) llc->dev == skb->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) static void llc_do_mcast(struct llc_sap *sap, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct sock **stack, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) struct sk_buff *skb1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) skb1 = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) if (!skb1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) sock_put(stack[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) llc_sap_rcv(sap, skb1, stack[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) sock_put(stack[i]);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * @sap: SAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * @laddr: address of local LLC (MAC + SAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * @skb: PDU to deliver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Search socket list of the SAP and finds connections with same sap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * Deliver clone to each.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void llc_sap_mcast(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) const struct llc_addr *laddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct sock *stack[256 / sizeof(struct sock *)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct llc_sock *llc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct hlist_head *dev_hb = llc_sk_dev_hash(sap, skb->dev->ifindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) spin_lock_bh(&sap->sk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) hlist_for_each_entry(llc, dev_hb, dev_hash_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) sk = &llc->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (!llc_mcast_match(sap, laddr, skb, sk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (i < ARRAY_SIZE(stack))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) stack[i++] = sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) llc_do_mcast(sap, skb, stack, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) spin_unlock_bh(&sap->sk_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) llc_do_mcast(sap, skb, stack, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^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) void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct llc_addr laddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) llc_pdu_decode_da(skb, laddr.mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) llc_pdu_decode_dsap(skb, &laddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (is_multicast_ether_addr(laddr.mac)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) llc_sap_mcast(sap, &laddr, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct sock *sk = llc_lookup_dgram(sap, &laddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) llc_sap_rcv(sap, skb, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }