^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);