1/* 2 * Copyright (c) 2005-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <sys/types.h> 30#include <sys/kernel_types.h> 31#include <sys/errno.h> 32#include <sys/kernel.h> 33#include <sys/file_internal.h> 34#include <sys/stat.h> 35#include <sys/select.h> 36#include <sys/pipe.h> 37#include <sys/proc_info.h> 38#include <sys/domain.h> 39#include <sys/protosw.h> 40#include <sys/domain.h> 41#include <sys/socketvar.h> 42#include <sys/unpcb.h> 43#include <sys/sys_domain.h> 44#include <sys/kern_event.h> 45#include <mach/vm_param.h> 46#include <net/ndrv_var.h> 47#include <netinet/in_pcb.h> 48#include <netinet/tcp_var.h> 49#include <string.h> 50 51static void fill_sockbuf_info(struct sockbuf *sb, struct sockbuf_info *sbi); 52static void fill_common_sockinfo(struct socket *so, struct socket_info *si); 53 54static void 55fill_sockbuf_info(struct sockbuf *sb, struct sockbuf_info *sbi) 56{ 57 sbi->sbi_cc = sb->sb_cc; 58 sbi->sbi_hiwat = sb->sb_hiwat; 59 sbi->sbi_mbcnt = sb->sb_mbcnt; 60 sbi->sbi_mbmax = sb->sb_mbmax; 61 sbi->sbi_lowat = sb->sb_lowat; 62 sbi->sbi_flags = sb->sb_flags; 63 sbi->sbi_timeo = (u_int32_t)(sb->sb_timeo.tv_sec * hz) + 64 sb->sb_timeo.tv_usec / tick; 65 if (sbi->sbi_timeo == 0 && sb->sb_timeo.tv_usec != 0) 66 sbi->sbi_timeo = 1; 67} 68 69static void 70fill_common_sockinfo(struct socket *so, struct socket_info *si) 71{ 72 si->soi_so = (u_int64_t)VM_KERNEL_ADDRPERM(so); 73 si->soi_type = so->so_type; 74 si->soi_options = (short)(so->so_options & 0xffff); 75 si->soi_linger = so->so_linger; 76 si->soi_state = so->so_state; 77 si->soi_pcb = (u_int64_t)VM_KERNEL_ADDRPERM(so->so_pcb); 78 if (so->so_proto) { 79 si->soi_protocol = SOCK_PROTO(so); 80 if (so->so_proto->pr_domain) 81 si->soi_family = SOCK_DOM(so); 82 else 83 si->soi_family = 0; 84 } else { 85 si->soi_protocol = si->soi_family = 0; 86 } 87 si->soi_qlen = so->so_qlen; 88 si->soi_incqlen = so->so_incqlen; 89 si->soi_qlimit = so->so_qlimit; 90 si->soi_timeo = so->so_timeo; 91 si->soi_error = so->so_error; 92 si->soi_oobmark = so->so_oobmark; 93 fill_sockbuf_info(&so->so_snd, &si->soi_snd); 94 fill_sockbuf_info(&so->so_rcv, &si->soi_rcv); 95} 96 97errno_t 98fill_socketinfo(struct socket *so, struct socket_info *si) 99{ 100 errno_t error = 0; 101 int domain; 102 short type; 103 short protocol; 104 105 socket_lock(so, 0); 106 107 si->soi_kind = SOCKINFO_GENERIC; 108 109 fill_common_sockinfo(so, si); 110 111 if (so->so_pcb == NULL || so->so_proto == 0 || 112 so->so_proto->pr_domain == NULL) 113 goto out; 114 115 /* 116 * The kind of socket is determined by the triplet 117 * {domain, type, protocol} 118 */ 119 domain = SOCK_DOM(so); 120 type = SOCK_TYPE(so); 121 protocol = SOCK_PROTO(so); 122 switch (domain) { 123 case PF_INET: 124 case PF_INET6: { 125 struct in_sockinfo *insi = &si->soi_proto.pri_in; 126 struct inpcb *inp = (struct inpcb *)so->so_pcb; 127 128 si->soi_kind = SOCKINFO_IN; 129 130 insi->insi_fport = inp->inp_fport; 131 insi->insi_lport = inp->inp_lport; 132 insi->insi_gencnt = inp->inp_gencnt; 133 insi->insi_flags = inp->inp_flags; 134 insi->insi_vflag = inp->inp_vflag; 135 insi->insi_ip_ttl = inp->inp_ip_ttl; 136 insi->insi_faddr.ina_6 = inp->inp_dependfaddr.inp6_foreign; 137 insi->insi_laddr.ina_6 = inp->inp_dependladdr.inp6_local; 138 insi->insi_v4.in4_tos = inp->inp_depend4.inp4_ip_tos; 139 insi->insi_v6.in6_hlim = 0; 140 insi->insi_v6.in6_cksum = inp->inp_depend6.inp6_cksum; 141 insi->insi_v6.in6_ifindex = 0; 142 insi->insi_v6.in6_hops = inp->inp_depend6.inp6_hops; 143 144 if (type == SOCK_STREAM && (protocol == 0 || 145 protocol == IPPROTO_TCP) && inp->inp_ppcb != NULL) { 146 struct tcp_sockinfo *tcpsi = &si->soi_proto.pri_tcp; 147 struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb; 148 149 si->soi_kind = SOCKINFO_TCP; 150 151 tcpsi->tcpsi_state = tp->t_state; 152 tcpsi->tcpsi_timer[TSI_T_REXMT] = 153 tp->t_timer[TCPT_REXMT]; 154 tcpsi->tcpsi_timer[TSI_T_PERSIST] = 155 tp->t_timer[TCPT_PERSIST]; 156 tcpsi->tcpsi_timer[TSI_T_KEEP] = 157 tp->t_timer[TCPT_KEEP]; 158 tcpsi->tcpsi_timer[TSI_T_2MSL] = 159 tp->t_timer[TCPT_2MSL]; 160 tcpsi->tcpsi_mss = tp->t_maxseg; 161 tcpsi->tcpsi_flags = tp->t_flags; 162 tcpsi->tcpsi_tp = 163 (u_int64_t)VM_KERNEL_ADDRPERM(tp); 164 } 165 break; 166 } 167 case PF_UNIX: { 168 struct unpcb *unp = (struct unpcb *)so->so_pcb; 169 struct un_sockinfo *unsi = &si->soi_proto.pri_un; 170 171 si->soi_kind = SOCKINFO_UN; 172 173 unsi->unsi_conn_pcb = 174 (uint64_t)VM_KERNEL_ADDRPERM(unp->unp_conn); 175 if (unp->unp_conn) 176 unsi->unsi_conn_so = (uint64_t) 177 VM_KERNEL_ADDRPERM(unp->unp_conn->unp_socket); 178 179 if (unp->unp_addr) { 180 size_t addrlen = unp->unp_addr->sun_len; 181 182 if (addrlen > SOCK_MAXADDRLEN) 183 addrlen = SOCK_MAXADDRLEN; 184 bcopy(unp->unp_addr, &unsi->unsi_addr, addrlen); 185 } 186 if (unp->unp_conn && unp->unp_conn->unp_addr) { 187 size_t addrlen = unp->unp_conn->unp_addr->sun_len; 188 189 if (addrlen > SOCK_MAXADDRLEN) 190 addrlen = SOCK_MAXADDRLEN; 191 bcopy(unp->unp_conn->unp_addr, &unsi->unsi_caddr, 192 addrlen); 193 } 194 break; 195 } 196 case PF_NDRV: { 197 struct ndrv_cb *ndrv_cb = (struct ndrv_cb *)so->so_pcb; 198 struct ndrv_info *ndrvsi = &si->soi_proto.pri_ndrv; 199 200 si->soi_kind = SOCKINFO_NDRV; 201 202 /* TDB lock ifnet ???? */ 203 if (ndrv_cb->nd_if != 0) { 204 struct ifnet *ifp = ndrv_cb->nd_if; 205 206 ndrvsi->ndrvsi_if_family = ifp->if_family; 207 ndrvsi->ndrvsi_if_unit = ifp->if_unit; 208 strlcpy(ndrvsi->ndrvsi_if_name, ifp->if_name, IFNAMSIZ); 209 } 210 break; 211 } 212 case PF_SYSTEM: 213 if (SOCK_PROTO(so) == SYSPROTO_EVENT) { 214 struct kern_event_pcb *ev_pcb = 215 (struct kern_event_pcb *)so->so_pcb; 216 struct kern_event_info *kesi = 217 &si->soi_proto.pri_kern_event; 218 219 si->soi_kind = SOCKINFO_KERN_EVENT; 220 221 kesi->kesi_vendor_code_filter = 222 ev_pcb->evp_vendor_code_filter; 223 kesi->kesi_class_filter = ev_pcb->evp_class_filter; 224 kesi->kesi_subclass_filter = ev_pcb->evp_subclass_filter; 225 226 } else if (SOCK_PROTO(so) == SYSPROTO_CONTROL) { 227 struct ctl_cb *kcb = (struct ctl_cb *)so->so_pcb; 228 struct kern_ctl_info *kcsi = 229 &si->soi_proto.pri_kern_ctl; 230 struct kctl *kctl = kcb->kctl; 231 232 si->soi_kind = SOCKINFO_KERN_CTL; 233 234 if (kctl == 0) 235 break; 236 kcsi->kcsi_id = kctl->id; 237 kcsi->kcsi_reg_unit = kctl->id; 238 kcsi->kcsi_flags = kctl->flags; 239 kcsi->kcsi_recvbufsize = kctl->recvbufsize; 240 kcsi->kcsi_sendbufsize = kctl->sendbufsize; 241 kcsi->kcsi_unit = kcb->unit; 242 strlcpy(kcsi->kcsi_name, kctl->name, MAX_KCTL_NAME); 243 } 244 break; 245 246 case PF_ROUTE: 247 case PF_PPP: 248 default: 249 break; 250 } 251out: 252 socket_unlock(so, 0); 253 254 return (error); 255} 256