^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * llc_input.c - Minimal input path for LLC
^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) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/llc_pdu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/llc_sap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define dprintk(args...) printk(KERN_DEBUG args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define dprintk(args...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Packet handler for the station, registerable because in the minimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * LLC core that is taking shape only the very minimal subset of LLC that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * is needed for things like IPX, Appletalk, etc will stay, with all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * rest in the llc1 and llc2 modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void (*llc_station_handler)(struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Packet handlers for LLC_DEST_SAP and LLC_DEST_CONN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void (*llc_type_handlers[2])(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct sk_buff *skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) smp_wmb(); /* ensure initialisation is complete before it's called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) llc_type_handlers[type - 1] = handler;
^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) void llc_remove_pack(int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) llc_type_handlers[type - 1] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) synchronize_net();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Ensure initialisation is complete before it's called */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) smp_wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) llc_station_handler = handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) synchronize_net();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^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) * llc_pdu_type - returns which LLC component must handle for PDU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * @skb: input skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * This function returns which LLC component must handle this PDU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static __inline__ int llc_pdu_type(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) switch (LLC_U_PDU_CMD(pdu)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) case LLC_1_PDU_CMD_XID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case LLC_1_PDU_CMD_UI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) case LLC_1_PDU_CMD_TEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) type = LLC_DEST_SAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) case LLC_2_PDU_CMD_SABME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) case LLC_2_PDU_CMD_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) case LLC_2_PDU_RSP_UA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) case LLC_2_PDU_RSP_DM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) case LLC_2_PDU_RSP_FRMR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) type = LLC_DEST_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * llc_fixup_skb - initializes skb pointers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @skb: This argument points to incoming skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * Initializes internal skb pointer to start of network layer by deriving
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * length of LLC header; finds length of LLC control field in LLC header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * by looking at the two lowest-order bits of the first control field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * byte; field is either 3 or 4 bytes long.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline int llc_fixup_skb(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) u8 llc_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct llc_pdu_un *pdu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (unlikely(!pskb_may_pull(skb, sizeof(*pdu))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pdu = (struct llc_pdu_un *)skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) llc_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) llc_len += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (unlikely(!pskb_may_pull(skb, llc_len)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) skb->transport_header += llc_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) skb_pull(skb, llc_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (skb->protocol == htons(ETH_P_802_2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) __be16 pdulen = eth_hdr(skb)->h_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) s32 data_size = ntohs(pdulen) - llc_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (data_size < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) !pskb_may_pull(skb, data_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (unlikely(pskb_trim_rcsum(skb, data_size)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * llc_rcv - 802.2 entry point from net lower layers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @skb: received pdu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @dev: device that receive pdu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @pt: packet type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * @orig_dev: the original receive net device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * When the system receives a 802.2 frame this function is called. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * checks SAP and connection of received pdu and passes frame to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * llc_{station,sap,conn}_rcv for sending to proper state machine. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * the frame is related to a busy connection (a connection is sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * data now), it queues this frame in the connection's backlog.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int llc_rcv(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct packet_type *pt, struct net_device *orig_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct llc_sap *sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct llc_pdu_sn *pdu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int (*rcv)(struct sk_buff *, struct net_device *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct packet_type *, struct net_device *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) void (*sta_handler)(struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (!net_eq(dev_net(dev), &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * When the interface is in promisc. mode, drop all the crap that it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * receives, do not try to analyse it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dprintk("%s: PACKET_OTHERHOST\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) skb = skb_share_check(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (unlikely(!skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (unlikely(!llc_fixup_skb(skb)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) pdu = llc_pdu_sn_hdr(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) goto handle_station;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) sap = llc_sap_find(pdu->dsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (unlikely(!sap)) {/* unknown SAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dprintk("%s: llc_sap_find(%02X) failed!\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pdu->dsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * First the upper layer protocols that don't need the full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * LLC functionality
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) rcv = rcu_dereference(sap->rcv_func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) dest = llc_pdu_type(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) sap_handler = dest ? READ_ONCE(llc_type_handlers[dest - 1]) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (unlikely(!sap_handler)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (rcv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) rcv(skb, dev, pt, orig_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (rcv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (cskb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rcv(cskb, dev, pt, orig_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) sap_handler(sap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) llc_sap_put(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) drop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) handle_station:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sta_handler = READ_ONCE(llc_station_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (!sta_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) goto drop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) sta_handler(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) EXPORT_SYMBOL(llc_add_pack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) EXPORT_SYMBOL(llc_remove_pack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) EXPORT_SYMBOL(llc_set_station_handler);