__private_extern__ void sotoxsocket_n(struct socket *so, struct xsocket_n *xso) { xso->xso_len = sizeof (struct xsocket_n); xso->xso_kind = XSO_SOCKET; if (so != NULL) { xso->xso_so = (uint64_t)VM_KERNEL_ADDRPERM(so); xso->so_type = so->so_type; xso->so_options = so->so_options; xso->so_linger = so->so_linger; xso->so_state = so->so_state; xso->so_pcb = (uint64_t)VM_KERNEL_ADDRPERM(so->so_pcb); if (so->so_proto) { xso->xso_protocol = SOCK_PROTO(so); xso->xso_family = SOCK_DOM(so); } else { xso->xso_protocol = xso->xso_family = 0; } xso->so_qlen = so->so_qlen; xso->so_incqlen = so->so_incqlen; xso->so_qlimit = so->so_qlimit; xso->so_timeo = so->so_timeo; xso->so_error = so->so_error; xso->so_pgid = so->so_pgid; xso->so_oobmark = so->so_oobmark; xso->so_uid = kauth_cred_getuid(so->so_cred); xso->so_last_pid = so->last_pid; xso->so_e_pid = so->e_pid; } }
static void fill_common_sockinfo(struct socket *so, struct socket_info *si) { si->soi_so = (u_int64_t)VM_KERNEL_ADDRPERM(so); si->soi_type = so->so_type; si->soi_options = (short)(so->so_options & 0xffff); si->soi_linger = so->so_linger; si->soi_state = so->so_state; si->soi_pcb = (u_int64_t)VM_KERNEL_ADDRPERM(so->so_pcb); if (so->so_proto) { si->soi_protocol = SOCK_PROTO(so); if (so->so_proto->pr_domain) si->soi_family = SOCK_DOM(so); else si->soi_family = 0; } else { si->soi_protocol = si->soi_family = 0; } si->soi_qlen = so->so_qlen; si->soi_incqlen = so->so_incqlen; si->soi_qlimit = so->so_qlimit; si->soi_timeo = so->so_timeo; si->soi_error = so->so_error; si->soi_oobmark = so->so_oobmark; fill_sockbuf_info(&so->so_snd, &si->soi_snd); fill_sockbuf_info(&so->so_rcv, &si->soi_rcv); }
__private_extern__ void inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags, bitstr_t *bitfield, struct inpcbinfo *pcbinfo) { struct inpcb *inp; struct socket *so; inp_gen_t gencnt; bool iswildcard, wildcardok, nowakeok; bool recvanyifonly, extbgidleok; bool activeonly; wildcardok = ((flags & INPCB_GET_PORTS_USED_WILDCARDOK) != 0); nowakeok = ((flags & INPCB_GET_PORTS_USED_NOWAKEUPOK) != 0); recvanyifonly = ((flags & INPCB_GET_PORTS_USED_RECVANYIFONLY) != 0); extbgidleok = ((flags & INPCB_GET_PORTS_USED_EXTBGIDLEONLY) != 0); activeonly = ((flags & INPCB_GET_PORTS_USED_ACTIVEONLY) != 0); lck_rw_lock_shared(pcbinfo->ipi_lock); gencnt = pcbinfo->ipi_gencnt; for (inp = LIST_FIRST(pcbinfo->ipi_listhead); inp; inp = LIST_NEXT(inp, inp_list)) { uint16_t port; if (inp->inp_gencnt > gencnt || inp->inp_state == INPCB_STATE_DEAD || inp->inp_wantcnt == WNT_STOPUSING) continue; if ((so = inp->inp_socket) == NULL || (so->so_state & SS_DEFUNCT) || (so->so_state & SS_ISDISCONNECTED)) continue; if (!(protocol == PF_UNSPEC || (protocol == PF_INET && (inp->inp_vflag & INP_IPV4)) || (protocol == PF_INET6 && (inp->inp_vflag & INP_IPV6)))) continue; iswildcard = (((inp->inp_vflag & INP_IPV4) && inp->inp_laddr.s_addr == INADDR_ANY) || ((inp->inp_vflag & INP_IPV6) && IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))); if (!wildcardok && iswildcard) continue; if ((so->so_options & SO_NOWAKEFROMSLEEP) && !nowakeok) continue; if (!(inp->inp_flags & INP_RECV_ANYIF) && recvanyifonly) continue; if (!(so->so_flags1 & SOF1_EXTEND_BK_IDLE_WANTED) && extbgidleok) continue; if (!iswildcard && !(ifindex == 0 || inp->inp_last_outifp == NULL || ifindex == inp->inp_last_outifp->if_index)) continue; if (SOCK_PROTO(inp->inp_socket) == IPPROTO_UDP && so->so_state & SS_CANTRCVMORE) continue; if (SOCK_PROTO(inp->inp_socket) == IPPROTO_TCP) { struct tcpcb *tp = sototcpcb(inp->inp_socket); /* * Workaround race where inp_ppcb is NULL during * socket initialization */ if (tp == NULL) continue; switch (tp->t_state) { case TCPS_CLOSED: continue; /* NOT REACHED */ case TCPS_LISTEN: case TCPS_SYN_SENT: case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: /* * Note: FIN_WAIT_1 is an active state * because we need our FIN to be * acknowledged */ break; case TCPS_CLOSE_WAIT: case TCPS_CLOSING: case TCPS_LAST_ACK: case TCPS_FIN_WAIT_2: /* * In the closing states, the connection * is not idle when there is outgoing * data having to be acknowledged */ if (activeonly && so->so_snd.sb_cc == 0) continue; break; case TCPS_TIME_WAIT: continue; /* NOT REACHED */ } } /* * Final safeguard to exclude unspecified local port */ port = ntohs(inp->inp_lport); if (port == 0) continue; bit_set(bitfield, port); } lck_rw_done(pcbinfo->ipi_lock); }
errno_t fill_socketinfo(struct socket *so, struct socket_info *si) { errno_t error = 0; int domain; short type; short protocol; socket_lock(so, 0); si->soi_kind = SOCKINFO_GENERIC; fill_common_sockinfo(so, si); if (so->so_pcb == NULL || so->so_proto == 0 || so->so_proto->pr_domain == NULL) goto out; /* * The kind of socket is determined by the triplet * {domain, type, protocol} */ domain = SOCK_DOM(so); type = SOCK_TYPE(so); protocol = SOCK_PROTO(so); switch (domain) { case PF_INET: case PF_INET6: { struct in_sockinfo *insi = &si->soi_proto.pri_in; struct inpcb *inp = (struct inpcb *)so->so_pcb; si->soi_kind = SOCKINFO_IN; insi->insi_fport = inp->inp_fport; insi->insi_lport = inp->inp_lport; insi->insi_gencnt = inp->inp_gencnt; insi->insi_flags = inp->inp_flags; insi->insi_vflag = inp->inp_vflag; insi->insi_ip_ttl = inp->inp_ip_ttl; insi->insi_faddr.ina_6 = inp->inp_dependfaddr.inp6_foreign; insi->insi_laddr.ina_6 = inp->inp_dependladdr.inp6_local; insi->insi_v4.in4_tos = inp->inp_depend4.inp4_ip_tos; insi->insi_v6.in6_hlim = 0; insi->insi_v6.in6_cksum = inp->inp_depend6.inp6_cksum; insi->insi_v6.in6_ifindex = 0; insi->insi_v6.in6_hops = inp->inp_depend6.inp6_hops; if (type == SOCK_STREAM && (protocol == 0 || protocol == IPPROTO_TCP) && inp->inp_ppcb != NULL) { struct tcp_sockinfo *tcpsi = &si->soi_proto.pri_tcp; struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; si->soi_kind = SOCKINFO_TCP; tcpsi->tcpsi_state = tp->t_state; tcpsi->tcpsi_timer[TCPT_REXMT] = tp->t_timer[TCPT_REXMT]; tcpsi->tcpsi_timer[TCPT_PERSIST] = tp->t_timer[TCPT_PERSIST]; tcpsi->tcpsi_timer[TCPT_KEEP] = tp->t_timer[TCPT_KEEP]; tcpsi->tcpsi_timer[TCPT_2MSL] = tp->t_timer[TCPT_2MSL]; tcpsi->tcpsi_mss = tp->t_maxseg; tcpsi->tcpsi_flags = tp->t_flags; tcpsi->tcpsi_tp = (u_int64_t)VM_KERNEL_ADDRPERM(tp); } break; } case PF_UNIX: { struct unpcb *unp = (struct unpcb *)so->so_pcb; struct un_sockinfo *unsi = &si->soi_proto.pri_un; si->soi_kind = SOCKINFO_UN; unsi->unsi_conn_pcb = (uint64_t)VM_KERNEL_ADDRPERM(unp->unp_conn); if (unp->unp_conn) unsi->unsi_conn_so = (uint64_t) VM_KERNEL_ADDRPERM(unp->unp_conn->unp_socket); if (unp->unp_addr) { size_t addrlen = unp->unp_addr->sun_len; if (addrlen > SOCK_MAXADDRLEN) addrlen = SOCK_MAXADDRLEN; bcopy(unp->unp_addr, &unsi->unsi_addr, addrlen); } if (unp->unp_conn && unp->unp_conn->unp_addr) { size_t addrlen = unp->unp_conn->unp_addr->sun_len; if (addrlen > SOCK_MAXADDRLEN) addrlen = SOCK_MAXADDRLEN; bcopy(unp->unp_conn->unp_addr, &unsi->unsi_caddr, addrlen); } break; } case PF_NDRV: { struct ndrv_cb *ndrv_cb = (struct ndrv_cb *)so->so_pcb; struct ndrv_info *ndrvsi = &si->soi_proto.pri_ndrv; si->soi_kind = SOCKINFO_NDRV; /* TDB lock ifnet ???? */ if (ndrv_cb->nd_if != 0) { struct ifnet *ifp = ndrv_cb->nd_if; ndrvsi->ndrvsi_if_family = ifp->if_family; ndrvsi->ndrvsi_if_unit = ifp->if_unit; strlcpy(ndrvsi->ndrvsi_if_name, ifp->if_name, IFNAMSIZ); } break; } case PF_SYSTEM: if (SOCK_PROTO(so) == SYSPROTO_EVENT) { struct kern_event_pcb *ev_pcb = (struct kern_event_pcb *)so->so_pcb; struct kern_event_info *kesi = &si->soi_proto.pri_kern_event; si->soi_kind = SOCKINFO_KERN_EVENT; kesi->kesi_vendor_code_filter = ev_pcb->evp_vendor_code_filter; kesi->kesi_class_filter = ev_pcb->evp_class_filter; kesi->kesi_subclass_filter = ev_pcb->evp_subclass_filter; } else if (SOCK_PROTO(so) == SYSPROTO_CONTROL) { struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb; struct kern_ctl_info *kcsi = &si->soi_proto.pri_kern_ctl; struct kctl *kctl = kcb->kctl; si->soi_kind = SOCKINFO_KERN_CTL; if (kctl == 0) break; kcsi->kcsi_id = kctl->id; kcsi->kcsi_reg_unit = kctl->id; kcsi->kcsi_flags = kctl->flags; kcsi->kcsi_recvbufsize = kctl->recvbufsize; kcsi->kcsi_sendbufsize = kctl->sendbufsize; kcsi->kcsi_unit = kcb->unit; strlcpy(kcsi->kcsi_name, kctl->name, MAX_KCTL_NAME); } break; case PF_ROUTE: case PF_PPP: default: break; } out: socket_unlock(so, 0); return (error); }