Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2)  * af_llc.c - LLC User Interface SAPs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *   Functions in this module are implementation of socket based llc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *   communications for the Linux operating system. Support of llc class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *   one and class two is provided via SOCK_DGRAM and SOCK_STREAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *   respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *   An llc2 connection is (mac + sap), only one llc2 sap connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *   is allowed per mac. Though one sap may have multiple mac + sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *   connections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *		 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  * This program can be redistributed or modified under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  * GNU General Public License as published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)  * This program is distributed without any warranty or implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)  * of merchantability or fitness for a particular purpose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)  * See the GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <net/llc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <net/llc_sap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <net/llc_pdu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <net/llc_conn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <net/tcp_states.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) /* remember: uninitialized global data is zeroed because its in .bss */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) static u16 llc_ui_sap_link_no_max[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) static struct sockaddr_llc llc_ui_addrnull;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) static const struct proto_ops llc_ui_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) static bool llc_ui_wait_for_conn(struct sock *sk, long timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define dprintk(args...) printk(KERN_DEBUG args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #define dprintk(args...) do {} while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) /* Maybe we'll add some more in the future. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #define LLC_CMSG_PKTINFO	1
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  *	llc_ui_next_link_no - return the next unused link number for a sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59)  *	@sap: Address of sap to get link number from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61)  *	Return the next unused link number for a given sap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) static inline u16 llc_ui_next_link_no(int sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 	return llc_ui_sap_link_no_max[sap]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) }
^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)  *	llc_proto_type - return eth protocol for ARP header type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70)  *	@arphrd: ARP header type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72)  *	Given an ARP header type return the corresponding ethernet protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) static inline __be16 llc_proto_type(u16 arphrd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 	return htons(ETH_P_802_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80)  *	llc_ui_addr_null - determines if a address structure is null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81)  *	@addr: Address to test if null.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 	return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr));
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  *	llc_ui_header_len - return length of llc header based on operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  *	@sk: Socket which contains a valid llc socket type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  *	@addr: Complete sockaddr_llc structure received from the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  *	Provide the length of the llc header depending on what kind of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  *	operation the user would like to perform and the type of socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  *	Returns the correct llc header length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	u8 rc = LLC_PDU_LEN_U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	if (addr->sllc_test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		rc = LLC_PDU_LEN_U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	else if (addr->sllc_xid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 		/* We need to expand header to sizeof(struct llc_xid_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 		 * since llc_pdu_init_as_xid_cmd() sets 4,5,6 bytes of LLC header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		 * as XID PDU. In llc_ui_sendmsg() we reserved header size and then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 		 * filled all other space with user data. If we won't reserve this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 		 * bytes, llc_pdu_init_as_xid_cmd() will overwrite user data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 		rc = LLC_PDU_LEN_U_XID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	else if (sk->sk_type == SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 		rc = LLC_PDU_LEN_I;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117)  *	llc_ui_send_data - send data via reliable llc2 connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  *	@sk: Connection the socket is using.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  *	@skb: Data the user wishes to send.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  *	@noblock: can we block waiting for data?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122)  *	Send data via reliable llc2 connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  *	Returns 0 upon success, non-zero if action did not succeed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125)  *	This function always consumes a reference to the skb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	struct llc_sock* llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	if (unlikely(llc_data_accept_state(llc->state) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 		     llc->remote_busy_flag ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 		     llc->p_flag)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 		long timeout = sock_sndtimeo(sk, noblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 		int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 		rc = llc_ui_wait_for_busy_core(sk, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 		if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 			kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 			return rc;
^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) 	return llc_build_and_send_pkt(sk, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 	sock_graft(sk, sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	sk->sk_type	= sock->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 	sock->ops	= &llc_ui_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) static struct proto llc_proto = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	.name	  = "LLC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	.owner	  = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	.obj_size = sizeof(struct llc_sock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	.slab_flags = SLAB_TYPESAFE_BY_RCU,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  *	llc_ui_create - alloc and init a new llc_ui socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  *	@net: network namespace (must be default network)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  *	@sock: Socket to initialize and attach allocated sk to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)  *	@protocol: Unused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  *	@kern: on behalf of kernel or userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  *	Allocate and initialize a new llc_ui socket, validate the user wants a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  *	socket type we have available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  *	Returns 0 upon success, negative upon failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) static int llc_ui_create(struct net *net, struct socket *sock, int protocol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 			 int kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	struct sock *sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	int rc = -ESOCKTNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	if (!ns_capable(net->user_ns, CAP_NET_RAW))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 		return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	if (!net_eq(net, &init_net))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 		return -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 		rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 		sk = llc_sk_alloc(net, PF_LLC, GFP_KERNEL, &llc_proto, kern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 		if (sk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 			rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 			llc_ui_sk_init(sock, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	return rc;
^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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195)  *	llc_ui_release - shutdown socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196)  *	@sock: Socket to release.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)  *	Shutdown and deallocate an existing socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) static int llc_ui_release(struct socket *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	struct llc_sock *llc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	if (unlikely(sk == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	sock_hold(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	dprintk("%s: closing local(%02X) remote(%02X)\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 		llc->laddr.lsap, llc->daddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	if (!llc_send_disc(sk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 	if (!sock_flag(sk, SOCK_ZAPPED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 		struct llc_sap *sap = llc->sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 		/* Hold this for release_sock(), so that llc_backlog_rcv()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 		 * could still use it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		llc_sap_hold(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 		llc_sap_remove_socket(llc->sap, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 		release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 		llc_sap_put(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 		release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	if (llc->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		dev_put(llc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	sock_put(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	llc_sk_free(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236)  *	llc_ui_autoport - provide dynamically allocate SAP number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238)  *	Provide the caller with a dynamically allocated SAP number according
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239)  *	to the rules that are set in this function. Returns: 0, upon failure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240)  *	SAP number otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) static int llc_ui_autoport(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	struct llc_sap *sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	int i, tries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	while (tries < LLC_SAP_DYN_TRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 		for (i = llc_ui_sap_last_autoport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 		     i < LLC_SAP_DYN_STOP; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 			sap = llc_sap_find(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 			if (!sap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 				llc_ui_sap_last_autoport = i + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 			llc_sap_put(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 		tries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 	return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266)  *	llc_ui_autobind - automatically bind a socket to a sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267)  *	@sock: socket to bind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268)  *	@addr: address to connect to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270)  * 	Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)  * 	specifically used llc_ui_bind to bind to an specific address/sap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  *	Returns: 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	struct llc_sap *sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	if (!sock_flag(sk, SOCK_ZAPPED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	if (!addr->sllc_arphrd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 		addr->sllc_arphrd = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	if (addr->sllc_arphrd != ARPHRD_ETHER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	if (sk->sk_bound_dev_if) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		if (dev && addr->sllc_arphrd != dev->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 			dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 			dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 		dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	rc = -EUSERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	llc->laddr.lsap = llc_ui_autoport();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	if (!llc->laddr.lsap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	rc = -EBUSY; /* some other network layer is using the sap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	sap = llc_sap_open(llc->laddr.lsap, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	if (!sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	/* Note: We do not expect errors from this point. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	llc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	memcpy(&llc->addr, addr, sizeof(llc->addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 	/* assign new connection to its SAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	llc_sap_add_socket(sap, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	sock_reset_flag(sk, SOCK_ZAPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 	dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325)  *	llc_ui_bind - bind a socket to a specific address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326)  *	@sock: Socket to bind an address to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327)  *	@uaddr: Address the user wants the socket bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328)  *	@addrlen: Length of the uaddr structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)  *	Bind a socket to a specific address. For llc a user is able to bind to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)  *	a specific sap only or mac + sap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332)  *	If the user desires to bind to a specific mac + sap, it is possible to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333)  *	have multiple sap connections via multiple macs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334)  *	Bind and autobind for that matter must enforce the correct sap usage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335)  *	otherwise all hell will break loose.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336)  *	Returns: 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	struct net_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	struct llc_sap *sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	rc = -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	if (!addr->sllc_arphrd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 		addr->sllc_arphrd = ARPHRD_ETHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	if (unlikely(addr->sllc_family != AF_LLC || addr->sllc_arphrd != ARPHRD_ETHER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	if (sk->sk_bound_dev_if) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 			if (is_zero_ether_addr(addr->sllc_mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 				memcpy(addr->sllc_mac, dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 				       IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 			if (addr->sllc_arphrd != dev->type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 			    !ether_addr_equal(addr->sllc_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 					      dev->dev_addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 				rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 				dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 		dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 					   addr->sllc_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	if (dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		dev_hold(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	if (!addr->sllc_sap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 		rc = -EUSERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 		addr->sllc_sap = llc_ui_autoport();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 		if (!addr->sllc_sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) 	sap = llc_sap_find(addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	if (!sap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 		sap = llc_sap_open(addr->sllc_sap, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 		rc = -EBUSY; /* some other network layer is using the sap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 		if (!sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		struct llc_addr laddr, daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 		struct sock *ask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		memset(&laddr, 0, sizeof(laddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		memset(&daddr, 0, sizeof(daddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		 * FIXME: check if the address is multicast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		 * 	  only SOCK_DGRAM can do this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		laddr.lsap = addr->sllc_sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		rc = -EADDRINUSE; /* mac + sap clash. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		ask = llc_lookup_established(sap, &daddr, &laddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		if (ask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 			sock_put(ask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 			goto out_put;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	/* Note: We do not expect errors from this point. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	llc->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 	llc->laddr.lsap = addr->sllc_sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 	memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	memcpy(&llc->addr, addr, sizeof(llc->addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	/* assign new connection to its SAP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	llc_sap_add_socket(sap, sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	sock_reset_flag(sk, SOCK_ZAPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) out_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	llc_sap_put(sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	dev_put(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432)  *	llc_ui_shutdown - shutdown a connect llc2 socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433)  *	@sock: Socket to shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434)  *	@how: What part of the socket to shutdown.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436)  *	Shutdown a connected llc2 socket. Currently this function only supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437)  *	shutting down both sends and receives (2), we could probably make this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438)  *	function such that a user can shutdown only half the connection but not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439)  *	right now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440)  *	Returns: 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) static int llc_ui_shutdown(struct socket *sock, int how)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	int rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	if (unlikely(sk->sk_state != TCP_ESTABLISHED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	if (how != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 	rc = llc_send_disc(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		rc = llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	/* Wake up anyone sleeping in poll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	sk->sk_state_change(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464)  *	llc_ui_connect - Connect to a remote llc2 mac + sap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465)  *	@sock: Socket which will be connected to the remote destination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466)  *	@uaddr: Remote and possibly the local address of the new connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467)  *	@addrlen: Size of uaddr structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468)  *	@flags: Operational flags specified by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470)  *	Connect to a remote llc2 mac + sap. The caller must specify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471)  *	destination mac and address to connect to. If the user hasn't previously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472)  *	called bind(2) with a smac the address of the first interface of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473)  *	specified arp type will be used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474)  *	This function will autobind if user did not previously call bind.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475)  *	Returns: 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 			  int addrlen, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	if (unlikely(addrlen != sizeof(*addr)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	rc = -EAFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	if (unlikely(addr->sllc_family != AF_LLC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	if (unlikely(sk->sk_type != SOCK_STREAM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	rc = -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	if (unlikely(sock->state == SS_CONNECTING))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	/* bind connection to sap if user hasn't done it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	if (sock_flag(sk, SOCK_ZAPPED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		/* bind to sap with null dev, exclusive */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		rc = llc_ui_autobind(sock, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	llc->daddr.lsap = addr->sllc_sap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	sock->state = SS_CONNECTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 	sk->sk_state   = TCP_SYN_SENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 	llc->link   = llc_ui_next_link_no(llc->sap->laddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	rc = llc_establish_connection(sk, llc->dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 				      addr->sllc_mac, addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		dprintk("%s: llc_ui_send_conn failed :-(\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 		sock->state  = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 		sk->sk_state = TCP_CLOSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	if (sk->sk_state == TCP_SYN_SENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		rc = sock_intr_errno(timeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	if (sk->sk_state == TCP_CLOSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		goto sock_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	sock->state = SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) sock_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	rc = sock_error(sk) ? : -ECONNABORTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	sock->state = SS_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543)  *	llc_ui_listen - allow a normal socket to accept incoming connections
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544)  *	@sock: Socket to allow incoming connections on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545)  *	@backlog: Number of connections to queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547)  *	Allow a normal socket to accept incoming connections.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548)  *	Returns 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) static int llc_ui_listen(struct socket *sock, int backlog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	if (unlikely(sock->state != SS_UNCONNECTED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	if (unlikely(sk->sk_type != SOCK_STREAM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (sock_flag(sk, SOCK_ZAPPED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	if (!(unsigned int)backlog)	/* BSDism */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		backlog = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	sk->sk_max_ack_backlog = backlog;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	if (sk->sk_state != TCP_LISTEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		sk->sk_ack_backlog = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		sk->sk_state	   = TCP_LISTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 	sk->sk_socket->flags |= __SO_ACCEPTCON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	add_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		rc = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 		rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 		if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	remove_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	add_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		if (signal_pending(current) || !timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	remove_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	return timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	add_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		if (sk_wait_event(sk, &timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 				  (sk->sk_shutdown & RCV_SHUTDOWN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 				  (!llc_data_accept_state(llc->state) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 				   !llc->remote_busy_flag &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 				   !llc->p_flag), &wait))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 		rc = -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		if (!timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 	remove_wait_queue(sk_sleep(sk), &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) static int llc_wait_data(struct sock *sk, long timeo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 	while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		 * POSIX 1003.1g mandates this order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 		rc = sock_error(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		if (sk->sk_shutdown & RCV_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		rc = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		if (!timeo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 		rc = sock_intr_errno(timeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 		if (sk_wait_data(sk, &timeo, NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	struct llc_sock *llc = llc_sk(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	if (llc->cmsg_flags & LLC_CMSG_PKTINFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		struct llc_pktinfo info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		memset(&info, 0, sizeof(info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		llc_pdu_decode_dsap(skb, &info.lpi_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		llc_pdu_decode_da(skb, info.lpi_mac);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		put_cmsg(msg, SOL_LLC, LLC_OPT_PKTINFO, sizeof(info), &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683)  *	llc_ui_accept - accept a new incoming connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)  *	@sock: Socket which connections arrive on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685)  *	@newsock: Socket to move incoming connection to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)  *	@flags: User specified operational flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687)  *	@kern: If the socket is kernel internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)  *	Accept a new incoming connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  *	Returns 0 upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 			 bool kern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	struct sock *sk = sock->sk, *newsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	struct llc_sock *llc, *newllc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	int rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	dprintk("%s: accepting on %02X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 		llc_sk(sk)->laddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 	if (unlikely(sk->sk_type != SOCK_STREAM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	if (unlikely(sock->state != SS_UNCONNECTED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		     sk->sk_state != TCP_LISTEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	/* wait for a connection to arrive. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	if (skb_queue_empty(&sk->sk_receive_queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 		rc = llc_wait_data(sk, sk->sk_rcvtimeo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	dprintk("%s: got a new connection on %02X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		llc_sk(sk)->laddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	skb = skb_dequeue(&sk->sk_receive_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	if (!skb->sk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 		goto frees;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	newsk = skb->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	/* attach connection to a new socket. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	llc_ui_sk_init(newsock, newsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	sock_reset_flag(newsk, SOCK_ZAPPED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	newsk->sk_state		= TCP_ESTABLISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	newsock->state		= SS_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	llc			= llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	newllc			= llc_sk(newsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	newllc->link = llc_ui_next_link_no(newllc->laddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	/* put original socket back into a clean listen state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	sk->sk_state = TCP_LISTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 	sk_acceptq_removed(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 	dprintk("%s: ok success on %02X, client on %02X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) frees:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746)  *	llc_ui_recvmsg - copy received data to the socket user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747)  *	@sock: Socket to copy data from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748)  *	@msg: Various user space related information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749)  *	@len: Size of user buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750)  *	@flags: User specified flags.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752)  *	Copy received data to the socket user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753)  *	Returns non-negative upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 			  int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	DECLARE_SOCKADDR(struct sockaddr_llc *, uaddr, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	const int nonblock = flags & MSG_DONTWAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	size_t copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	u32 peek_seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	u32 *seq, skb_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	unsigned long used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	int target;	/* Read at least this many bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	long timeo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	copied = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	timeo = sock_rcvtimeo(sk, nonblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	seq = &llc->copied_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	if (flags & MSG_PEEK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 		peek_seq = llc->copied_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 		seq = &peek_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	copied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		u32 offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		 * We need to check signals first, to get correct SIGURG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		 * handling. FIXME: Need to check this doesn't impact 1003.1g
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		 * and move it down to the bottom of the loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 			if (copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 			copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 		/* Next get a buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 		skb = skb_peek(&sk->sk_receive_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			offset = *seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 			goto found_ok_skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 		/* Well, if we have backlog, try to process it now yet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		if (copied >= target && !READ_ONCE(sk->sk_backlog.tail))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		if (copied) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			if (sk->sk_err ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			    sk->sk_state == TCP_CLOSE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 			    (sk->sk_shutdown & RCV_SHUTDOWN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 			    !timeo ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 			    (flags & MSG_PEEK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 			if (sock_flag(sk, SOCK_DONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 			if (sk->sk_err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 				copied = sock_error(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 			if (sk->sk_shutdown & RCV_SHUTDOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 			if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 				if (!sock_flag(sk, SOCK_DONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 					/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 					 * This occurs when user tries to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 					 * from never connected socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 					 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 					copied = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 			if (!timeo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 				copied = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 		if (copied >= target) { /* Do not sleep, just process backlog. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 			release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 			lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 			sk_wait_data(sk, &timeo, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 			net_dbg_ratelimited("LLC(%s:%d): Application bug, race in MSG_PEEK\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 					    current->comm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 					    task_pid_nr(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			peek_seq = llc->copied_seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	found_ok_skb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		skb_len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 		/* Ok so how much can we use? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		used = skb->len - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		if (len < used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 			used = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 		if (!(flags & MSG_TRUNC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 			int rc = skb_copy_datagram_msg(skb, offset, msg, used);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 				/* Exception. Bailout! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 				if (!copied)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 					copied = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 		*seq += used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		copied += used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		len -= used;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		/* For non stream protcols we get one packet per recvmsg call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 		if (sk->sk_type != SOCK_STREAM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			goto copy_uaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 		if (!(flags & MSG_PEEK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 			skb_unlink(skb, &sk->sk_receive_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 			kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			*seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 		/* Partial read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		if (used + offset < skb_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	} while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	return copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) copy_uaddr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	if (uaddr != NULL && skb != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		msg->msg_namelen = sizeof(*uaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	if (llc_sk(sk)->cmsg_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		llc_cmsg_rcv(msg, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	if (!(flags & MSG_PEEK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 		skb_unlink(skb, &sk->sk_receive_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		*seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918)  *	llc_ui_sendmsg - Transmit data provided by the socket user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919)  *	@sock: Socket to transmit data from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920)  *	@msg: Various user related information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921)  *	@len: Length of data to transmit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923)  *	Transmit data provided by the socket user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)  *	Returns non-negative upon success, negative otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	int flags = msg->msg_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	int noblock = flags & MSG_DONTWAIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	struct sk_buff *skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	size_t size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	int rc = -EINVAL, copied = 0, hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	dprintk("%s: sending from %02X to %02X\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		llc->laddr.lsap, llc->daddr.lsap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	if (addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		if (msg->msg_namelen < sizeof(*addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		if (llc_ui_addr_null(&llc->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		addr = &llc->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	/* must bind connection to sap if user hasn't done it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	if (sock_flag(sk, SOCK_ZAPPED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		/* bind to sap with null dev, exclusive. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		rc = llc_ui_autobind(sock, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 		if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	size = hdrlen + len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	if (size > llc->dev->mtu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		size = llc->dev->mtu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	copied = size - hdrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	if (copied < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	skb = sock_alloc_send_skb(sk, size, noblock, &rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	skb->dev      = llc->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	skb->protocol = llc_proto_type(addr->sllc_arphrd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	skb_reserve(skb, hdrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 	if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 		llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 					  addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	if (addr->sllc_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 					    addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	if (addr->sllc_xid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 		llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 					   addr->sllc_sap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 		skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	rc = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	rc = llc_ui_send_data(sk, skb, noblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	skb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 		dprintk("%s: failed sending from %02X to %02X: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 			__func__, llc->laddr.lsap, llc->daddr.lsap, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	return rc ? : copied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)  *	llc_ui_getname - return the address info of a socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)  *	@sock: Socket to get address of.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)  *	@uaddr: Address structure to return information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)  *	@peer: Does user want local or remote address information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)  *	Return the address information of a socket.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 			  int peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	struct sockaddr_llc sllc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	int rc = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	memset(&sllc, 0, sizeof(sllc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	if (sock_flag(sk, SOCK_ZAPPED))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	if (peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 		rc = -ENOTCONN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 		if (sk->sk_state != TCP_ESTABLISHED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		if(llc->dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 			sllc.sllc_arphrd = llc->dev->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		sllc.sllc_sap = llc->daddr.lsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		memcpy(&sllc.sllc_mac, &llc->daddr.mac, IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 		rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		if (!llc->sap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		sllc.sllc_sap = llc->sap->laddr.lsap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		if (llc->dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 			sllc.sllc_arphrd = llc->dev->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 			memcpy(&sllc.sllc_mac, llc->dev->dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 			       IFHWADDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 	sllc.sllc_family = AF_LLC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	memcpy(uaddr, &sllc, sizeof(sllc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) 	rc = sizeof(sllc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)  *	llc_ui_ioctl - io controls for PF_LLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)  *	@sock: Socket to get/set info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)  *	@cmd: command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)  *	@arg: optional argument for cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)  *	get/set info on llc sockets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static int llc_ui_ioctl(struct socket *sock, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 			unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) 	return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)  *	llc_ui_setsockopt - set various connection specific parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)  *	@sock: Socket to set options on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)  *	@level: Socket level user is requesting operations on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)  *	@optname: Operation name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)  *	@optval: User provided operation data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)  *	@optlen: Length of optval.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)  *	Set various connection specific parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 			     sockptr_t optval, unsigned int optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	unsigned int opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	int rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 	if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) 	rc = copy_from_sockptr(&opt, optval, sizeof(opt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) 	case LLC_OPT_RETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 		if (opt > LLC_OPT_MAX_RETRY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) 		llc->n2 = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) 	case LLC_OPT_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 		if (opt > LLC_OPT_MAX_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) 		llc->n1 = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	case LLC_OPT_ACK_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 		if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 		llc->ack_timer.expire = opt * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	case LLC_OPT_P_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 		if (opt > LLC_OPT_MAX_P_TMR_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 		llc->pf_cycle_timer.expire = opt * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) 	case LLC_OPT_REJ_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 		if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 		llc->rej_sent_timer.expire = opt * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	case LLC_OPT_BUSY_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 		llc->busy_state_timer.expire = opt * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) 	case LLC_OPT_TX_WIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 		if (opt > LLC_OPT_MAX_WIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 		llc->k = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	case LLC_OPT_RX_WIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 		if (opt > LLC_OPT_MAX_WIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 		llc->rw = opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	case LLC_OPT_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		if (opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 			llc->cmsg_flags |= LLC_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			llc->cmsg_flags &= ~LLC_CMSG_PKTINFO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 		rc = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)  *	llc_ui_getsockopt - get connection specific socket info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152)  *	@sock: Socket to get information from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  *	@level: Socket level user is requesting operations on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)  *	@optname: Operation name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)  *	@optval: Variable to return operation data in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)  *	@optlen: Length of optval.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)  *	Get connection specific socket information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 			     char __user *optval, int __user *optlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	struct sock *sk = sock->sk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	struct llc_sock *llc = llc_sk(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	int val = 0, len = 0, rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	lock_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	if (unlikely(level != SOL_LLC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	rc = get_user(len, optlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 	if (len != sizeof(int))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	switch (optname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	case LLC_OPT_RETRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		val = llc->n2;					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 	case LLC_OPT_SIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		val = llc->n1;					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	case LLC_OPT_ACK_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 		val = llc->ack_timer.expire / HZ;		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	case LLC_OPT_P_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 		val = llc->pf_cycle_timer.expire / HZ;		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 	case LLC_OPT_REJ_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 		val = llc->rej_sent_timer.expire / HZ;		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 	case LLC_OPT_BUSY_TMR_EXP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		val = llc->busy_state_timer.expire / HZ;	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	case LLC_OPT_TX_WIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		val = llc->k;				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 	case LLC_OPT_RX_WIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 		val = llc->rw;				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	case LLC_OPT_PKTINFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		val = (llc->cmsg_flags & LLC_CMSG_PKTINFO) != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 		rc = -ENOPROTOOPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	if (put_user(len, optlen) || copy_to_user(optval, &val, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 		rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) 	release_sock(sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) static const struct net_proto_family llc_ui_family_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	.family = PF_LLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 	.create = llc_ui_create,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	.owner	= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) static const struct proto_ops llc_ui_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	.family	     = PF_LLC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 	.owner       = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 	.release     = llc_ui_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	.bind	     = llc_ui_bind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	.connect     = llc_ui_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	.socketpair  = sock_no_socketpair,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	.accept      = llc_ui_accept,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	.getname     = llc_ui_getname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 	.poll	     = datagram_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	.ioctl       = llc_ui_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	.listen      = llc_ui_listen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	.shutdown    = llc_ui_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	.setsockopt  = llc_ui_setsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	.getsockopt  = llc_ui_getsockopt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 	.sendmsg     = llc_ui_sendmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	.recvmsg     = llc_ui_recvmsg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 	.mmap	     = sock_no_mmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 	.sendpage    = sock_no_sendpage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) static const char llc_proc_err_msg[] __initconst =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) static const char llc_sysctl_err_msg[] __initconst =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 	KERN_CRIT "LLC: Unable to register the sysctl entries\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static const char llc_sock_err_msg[] __initconst =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	KERN_CRIT "LLC: Unable to register the network family\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) static int __init llc2_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 	int rc = proto_register(&llc_proto, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) 	if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 	llc_build_offset_table();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	llc_station_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	rc = llc_proc_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 		printk(llc_proc_err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 		goto out_station;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	rc = llc_sysctl_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 		printk(llc_sysctl_err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 		goto out_proc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 	rc = sock_register(&llc_ui_family_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 		printk(llc_sock_err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 		goto out_sysctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) out_sysctl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) 	llc_sysctl_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) out_proc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	llc_proc_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) out_station:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	llc_station_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	proto_unregister(&llc_proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) static void __exit llc2_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	llc_station_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	llc_remove_pack(LLC_DEST_SAP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	llc_remove_pack(LLC_DEST_CONN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	sock_unregister(PF_LLC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 	llc_proc_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	llc_sysctl_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 	proto_unregister(&llc_proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) module_init(llc2_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) module_exit(llc2_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) MODULE_DESCRIPTION("IEEE 802.2 PF_LLC support");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) MODULE_ALIAS_NETPROTO(PF_LLC);