/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2022 Garrett D'Amore */ #ifndef _SOCKFS_SOCKTPI_H #define _SOCKFS_SOCKTPI_H #ifdef __cplusplus extern "C" { #endif /* * Internal representation used for addresses. */ struct soaddr { struct sockaddr *soa_sa; /* Actual address */ t_uscalar_t soa_len; /* Length in bytes for kmem_free */ t_uscalar_t soa_maxlen; /* Allocated length */ }; /* Maximum size address for transports that have ADDR_size == 1 */ #define SOA_DEFSIZE 128 struct sonode; /* * TPI Sockets * ====================== * * A TPI socket can be created by the TPI socket module, or as a * result of fallback. In either case, the TPI related information is * stored in a sotpi_info_t. Sockets that are TPI based from the * beginning will use a sotpi_sonode_t, but fallback case the * sotpi_info_t will be allocated when needed. However, the so_priv * field in the sonode will always point to the sotpi_info_t, and the * structure should only be accessed via so_priv. Use SOTOTPI(). * * A TPI socket always corresponds to a VCHR stream representing the * transport provider (e.g. /dev/tcp). This information is retrieved * from the kernel socket configuration table and accessible via * so_sockparams->sp_sdev_info. sockfs uses this to perform * VOP_ACCESS checks before allowing an open of the transport * provider. * * AF_UNIX Sockets * ------------------------- * * When an AF_UNIX socket is bound to a pathname the sockfs creates a * VSOCK vnode in the underlying file system. However, the vnodeops * etc in this VNODE remain those of the underlying file system. * Sockfs uses the v_stream pointer in the underlying file system * VSOCK node to find the sonode bound to the pathname. The bound * pathname vnode is accessed through sti_ux_vp. * * Out of Band Data Handling * ------------------------- * * The counts (sti_oobcnt and sti_oobsigcnt) track the number of * urgent indicates that are (logically) queued on the stream head * read queue. The urgent data is queued on the stream head * as follows. * * In the normal case the SIGURG is not generated until * the T_EXDATA_IND arrives at the stream head. However, transports * that have an early indication that urgent data is pending * (e.g. TCP receiving a "new" urgent pointer value) can send up * an M_PCPROTO/SIGURG message to generate the signal early. * * The mark is indicated by either: * - a T_EXDATA_IND (with no M_DATA b_cont) with MSGMARK set. * When this message is consumed by sorecvmsg the socket layer * sets SS_RCVATMARK until data has been consumed past the mark. * - a message with MSGMARKNEXT set (indicating that the * first byte of the next message constitutes the mark). When * the last byte of the MSGMARKNEXT message is consumed in * the stream head the stream head sets STRATMARK. This flag * is cleared when at least one byte is read. (Note that * the MSGMARKNEXT messages can be of zero length when there * is no previous data to which the marknext can be attached.) * * While the T_EXDATA_IND method is the common case which is used * with all TPI transports, the MSGMARKNEXT method is needed to * indicate the mark when e.g. the TCP urgent byte has not been * received yet but the TCP urgent pointer has made TCP generate * the M_PCSIG/SIGURG. * * The signal (the M_PCSIG carrying the SIGURG) and the mark * indication can not be delivered as a single message, since * the signal should be delivered as high priority and any mark * indication must flow with the data. This implies that immediately * when the SIGURG has been delivered if the stream head queue is * empty it is impossible to determine if this will be the position * of the mark. This race condition is resolved by using MSGNOTMARKNEXT * messages and the STRNOTATMARK flag in the stream head. The * SIOCATMARK code calls the stream head to wait for either a * non-empty queue or one of the STR*ATMARK flags being set. * This implies that any transport that is sending M_PCSIG(SIGURG) * should send the appropriate MSGNOTMARKNEXT message (which can be * zero length) after sending an M_PCSIG to prevent SIOCATMARK * from sleeping unnecessarily. */ #define SOTPI_INFO_MAGIC 0x12345678 /* * Information used by TPI/STREAMS sockets */ typedef struct sotpi_info { /* * These fields are initialized once. */ uint32_t sti_magic; /* always set to SOTPI_INFO_MAGIC */ dev_t sti_dev; /* device the sonode represents */ struct sockparams *sti_orig_sp; /* in case of fallback; the orig sp */ kmutex_t sti_plumb_lock; /* serializes plumbs, and the related */ /* so_pushcnt */ short sti_pushcnt; /* Number of modules above "sockmod" */ kcondvar_t sti_ack_cv; /* wait for TPI acks */ uint8_t sti_laddr_valid : 1, /* sti_laddr valid for user */ sti_faddr_valid : 1, /* sti_faddr valid for user */ sti_faddr_noxlate : 1, /* No xlation of faddr for AF_UNIX */ sti_direct : 1, /* transport is directly below */ sti_pad_to_bit7 : 4; mblk_t *sti_ack_mp; /* TPI ack received from below */ mblk_t *sti_unbind_mp; /* Preallocated T_UNBIND_REQ message */ time_t sti_atime; /* time of last access */ time_t sti_mtime; /* time of last modification */ time_t sti_ctime; /* time of last attributes change */ ushort_t sti_delayed_error; /* From T_uderror_ind */ mblk_t *sti_eaddr_mp; /* for so_delayed_error */ /* put here for delayed processing */ mblk_t *sti_conn_ind_head; /* b_next list of T_CONN_IND */ mblk_t *sti_conn_ind_tail; uint_t sti_oobsigcnt; /* Number of SIGURG generated */ uint_t sti_oobcnt; /* Number of T_EXDATA_IND queued */ /* From T_info_ack */ t_uscalar_t sti_tsdu_size; t_uscalar_t sti_etsdu_size; t_scalar_t sti_addr_size; t_uscalar_t sti_opt_size; t_uscalar_t sti_tidu_size; t_scalar_t sti_serv_type; /* From T_capability_ack */ t_uscalar_t sti_acceptor_id; /* Internal provider information */ struct tpi_provinfo *sti_provinfo; /* * The local and remote addresses have multiple purposes * but one of the key reasons for their existence and careful * tracking in sockfs is to support getsockname and getpeername * when the transport does not handle the TI_GET*NAME ioctls * and caching when it does (signalled by valid bits in so_state). * When all transports support the new TPI (with T_ADDR_REQ) * we can revisit this code. * * The other usage of sti_faddr is to keep the "connected to" * address for datagram sockets. * * Finally, for AF_UNIX both local and remote addresses are used * to record the sockaddr_un since we use a separate namespace * in the loopback transport. */ struct soaddr sti_laddr; /* Local address */ struct soaddr sti_faddr; /* Peer address */ #define sti_laddr_sa sti_laddr.soa_sa #define sti_faddr_sa sti_faddr.soa_sa #define sti_laddr_len sti_laddr.soa_len #define sti_faddr_len sti_faddr.soa_len #define sti_laddr_maxlen sti_laddr.soa_maxlen #define sti_faddr_maxlen sti_faddr.soa_maxlen /* * For AF_UNIX sockets: * * sti_ux_laddr/faddr records the internal addresses used with the * transport. sti_ux_vp and v_stream->sd_vnode form the * cross-linkage between the underlying fs vnode corresponding * to the bound sockaddr_un and the socket node. * * sti_ux_taddr holds the result of translations done in * so_ux_addr_xlate(), which may or may not be the same as * sti_ux_faddr (which is our connected peer address). */ struct so_ux_addr sti_ux_laddr; /* laddr bound with the transport */ struct so_ux_addr sti_ux_faddr; /* connected peer address */ struct so_ux_addr sti_ux_taddr; /* temporary address for sendmsg */ struct vnode *sti_ux_bound_vp; /* bound AF_UNIX file system vnode */ struct sonode *sti_next_so; /* next sonode on socklist */ struct sonode *sti_prev_so; /* previous sonode on socklist */ mblk_t *sti_discon_ind_mp; /* T_DISCON_IND received from below */ } sotpi_info_t; struct T_capability_ack; extern sonodeops_t sotpi_sonodeops; extern int socktpi_init(void); extern int sotpi_convert_sonode(struct sonode *, struct sockparams *, boolean_t *, queue_t **, struct cred *); extern void sotpi_revert_sonode(struct sonode *, struct cred *); extern void sotpi_update_state(struct sonode *, struct T_capability_ack *, struct sockaddr *, socklen_t, struct sockaddr *, socklen_t, short); extern sotpi_info_t *sotpi_sototpi(struct sonode *); #ifdef DEBUG #define SOTOTPI(so) (sotpi_sototpi(so)) #else #define SOTOTPI(so) ((sotpi_info_t *)(so)->so_priv) #endif /* for consumers outside sockfs */ #define _SOTOTPI(so) ((sotpi_info_t *)(so)->so_priv) #ifdef __cplusplus } #endif #endif /* _SOCKFS_SOCKTPI_H */