1/* 2 * dsock.c - Darwin socket processing functions for /dev/kmem-based lsof 3 */ 4 5/* 6 * Special Darwin socket info: Justin Walker, 000927 7 */ 8 9/* 10 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana 11 * 47907. All rights reserved. 12 * 13 * Written by Victor A. Abell 14 * 15 * This software is not subject to any license of the American Telephone 16 * and Telegraph Company or the Regents of the University of California. 17 * 18 * Permission is granted to anyone to use this software for any purpose on 19 * any computer system, and to alter it and redistribute it freely, subject 20 * to the following restrictions: 21 * 22 * 1. Neither the authors nor Purdue University are responsible for any 23 * consequences of the use of this software. 24 * 25 * 2. The origin of this software must not be misrepresented, either by 26 * explicit claim or by omission. Credit to the authors and Purdue 27 * University must appear in documentation and sources. 28 * 29 * 3. Altered versions must be plainly marked as such, and must not be 30 * misrepresented as being the original software. 31 * 32 * 4. This notice may not be removed or altered. 33 */ 34 35#ifndef lint 36static char copyright[] = 37"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; 38static char *rcsid = "$Id: dsock.c,v 1.11 2005/11/01 20:24:51 abe Exp $"; 39#endif 40 41 42#include "lsof.h" 43 44 45#if defined(HASIPv6) 46/* 47 * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained 48 * in an IPv6 address 49 */ 50 51#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) 52#endif /* defined(HASIPv6) */ 53 54 55/* 56 * process_socket() - process socket 57 */ 58 59void 60process_socket(sa) 61 KA_T sa; /* socket address in kernel */ 62{ 63 struct domain d; 64 unsigned char *fa = (unsigned char *)NULL; 65 int fam, lp; 66 int fp = 0; 67 struct inpcb inp; 68 unsigned char *la = (unsigned char *)NULL; 69 struct protosw p; 70 struct socket s; 71 struct tcpcb t; 72 KA_T ta = (KA_T)NULL; 73 struct unpcb uc, unp; 74 struct sockaddr_un *ua = NULL; 75 struct sockaddr_un un; 76 int unl; 77 78#if defined(HASIPv6) 79 struct in6pcb in6p; 80#endif /* defined(HASIPv6) */ 81 82#if defined(AF_SYSTEM) 83 struct kern_event_pcb kev_cb; 84#endif /* defined(AF_SYSTEM) */ 85 86#if defined(AF_NDRV) 87 char buf[IFNAMSIZ]; 88 struct ndrv_cb ndrv_cb; 89 struct ifnet ifnet; 90#endif /* defined(AF_NDRV) */ 91 92 (void) snpf(Lf->type, sizeof(Lf->type), "sock"); 93 Lf->inp_ty = 2; 94/* 95 * Read the socket, protocol, and domain structures. 96 */ 97 if (!sa) { 98 enter_nm("no socket address"); 99 return; 100 } 101 if (kread(sa, (char *)&s, sizeof(s))) { 102 (void) snpf(Namech, Namechl, "can't read socket struct from %s", 103 print_kptr(sa, (char *)NULL, 0)); 104 enter_nm(Namech); 105 return; 106 } 107 if (!s.so_type) { 108 enter_nm("no socket type"); 109 return; 110 } 111 if (!s.so_proto 112 || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { 113 (void) snpf(Namech, Namechl, "can't read protocol switch from %s", 114 print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); 115 enter_nm(Namech); 116 return; 117 } 118 if (!p.pr_domain 119 || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { 120 (void) snpf(Namech, Namechl, "can't read domain struct from %s", 121 print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); 122 enter_nm(Namech); 123 return; 124 } 125/* 126 * Save size information. 127 */ 128 if (Fsize) { 129 if (Lf->access == 'r') 130 Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; 131 else if (Lf->access == 'w') 132 Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; 133 else 134 Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); 135 Lf->sz_def = 1; 136 } else 137 Lf->off_def = 1; 138 139#if defined(HASTCPTPIQ) 140 Lf->lts.rq = s.so_rcv.sb_cc; 141 Lf->lts.sq = s.so_snd.sb_cc; 142 Lf->lts.rqs = Lf->lts.sqs = 1; 143#endif /* defined(HASTCPTPIQ) */ 144 145#if defined(HASSOOPT) 146 Lf->lts.ltm = (unsigned int)(s.so_linger & 0xffff); 147 Lf->lts.opt = (unsigned int)(s.so_options & 0xffff); 148 Lf->lts.pqlen = (unsigned int)s.so_incqlen; 149 Lf->lts.qlen = (unsigned int)s.so_qlen; 150 Lf->lts.qlim = (unsigned int)s.so_qlimit; 151 Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; 152 Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; 153 Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs 154 = Lf->lts.sbszs = (unsigned char)1; 155#endif /* defined(HASSOOPT) */ 156 157#if defined(HASSOSTATE) 158 Lf->lts.ss = (unsigned int)s.so_state; 159#endif /* defined(HASSOSTATE) */ 160 161/* 162 * Process socket by the associated domain family. 163 */ 164 switch ((fam = d.dom_family)) { 165/* 166 * Process an Internet domain socket. 167 */ 168 case AF_INET: 169 170#if defined(HASIPv6) 171 case AF_INET6: 172#endif /* defined(HASIPv6) */ 173 174 if (Fnet) { 175 if (!FnetTy 176 || ((FnetTy == 4) && (fam == AF_INET)) 177 178#if defined(HASIPv6) 179 || ((FnetTy == 6) && (fam == AF_INET6)) 180#endif /* defined(HASIPv6) */ 181 182 ) 183 Lf->sf |= SELNET; 184 } 185 printiproto(p.pr_protocol); 186 187#if defined(HASIPv6) 188 (void) snpf(Lf->type, sizeof(Lf->type), 189 (fam == AF_INET) ? "IPv4" : "IPv6"); 190#else /* !defined(HASIPv6) */ 191 (void) snpf(Lf->type, sizeof(Lf->type), "inet"); 192#endif /* defined(HASIPv6) */ 193 194#if defined(HASIPv6) 195 if (fam == AF_INET6) { 196 197 /* 198 * Read IPv6 protocol control block. 199 */ 200 if (!s.so_pcb 201 || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) 202 { 203 (void) snpf(Namech, Namechl, "can't read in6pcb at %s", 204 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); 205 enter_nm(Namech); 206 return; 207 } 208 /* 209 * Save IPv6 address information. 210 */ 211 enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb 212 : s.so_pcb), 213 (char *)NULL, 0)); 214 if (p.pr_protocol == IPPROTO_TCP) 215 ta = (KA_T)in6p.in6p_ppcb; 216 la = (unsigned char *)&in6p.in6p_laddr; 217 lp = (int)ntohs(in6p.in6p_lport); 218 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr) 219 || in6p.in6p_fport) 220 { 221 fa = (unsigned char *)&in6p.in6p_faddr; 222 fp = (int)ntohs(in6p.in6p_fport); 223 } 224 } else 225#endif /* defined(HASIPv6) */ 226 227 { 228 229 /* 230 * Read IPv4 protocol control block. 231 */ 232 if (!s.so_pcb 233 || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { 234 if (!s.so_pcb) { 235 (void) snpf(Namech, Namechl, "no PCB%s%s", 236 (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" 237 : "", 238 (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" 239 : ""); 240 } else { 241 (void) snpf(Namech, Namechl, "can't read inpcb at %s", 242 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); 243 } 244 enter_nm(Namech); 245 return; 246 } 247 /* 248 * Print Internet socket information. 249 */ 250 enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb 251 : s.so_pcb), 252 (char *)NULL, 0)); 253 /* 254 * Save IPv4 address information. 255 */ 256 if (p.pr_protocol == IPPROTO_TCP) 257 ta = (KA_T)inp.inp_ppcb; 258 la = (unsigned char *)&inp.inp_laddr; 259 lp = (int)ntohs(inp.inp_lport); 260 if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) { 261 fa = (unsigned char *)&inp.inp_faddr; 262 fp = (int)ntohs(inp.inp_fport); 263 } 264 } 265 266#if defined(HASIPv6) 267 if ((fam == AF_INET6) 268 && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) 269 || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) { 270 271 /* 272 * Adjust for IPv4 addresses mapped in IPv6 addresses. 273 */ 274 if (la) 275 la = (unsigned char *)IPv6_2_IPv4(la); 276 if (fa) 277 fa = (unsigned char *)IPv6_2_IPv4(fa); 278 fam = AF_INET; 279 } 280#endif /* defined(HASIPv6) */ 281 282 /* 283 * Enter local and remote addresses by address family. 284 */ 285 if (fa || la) 286 (void) ent_inaddr(la, lp, fa, fp, fam); 287 if (ta && !kread(ta, (char *)&t, sizeof(t))) { 288 Lf->lts.type = 0; 289 Lf->lts.state.i = (int)t.t_state; 290 291#if defined(HASSOOPT) 292 Lf->lts.kai = (unsigned int)t.t_timer[TCPT_KEEP]; 293#endif /* defined(HASSOOPT) */ 294 295#if defined(HASTCPOPT) 296 Lf->lts.mss = (unsigned long)t.t_maxseg; 297 Lf->lts.msss = (unsigned char)1; 298 Lf->lts.topt = (unsigned int)t.t_flags; 299#endif /* defined(HASTCPOPT) */ 300 301 } 302 break; 303 304#if defined(AF_NDRV) 305/* 306 * Process an NDRV domain socket. 307 */ 308 case AF_NDRV: 309 { 310 (void) snpf(Lf->type, sizeof(Lf->type), "ndrv"); 311 /* 312 * Read protocol control block. 313 */ 314 if (!s.so_pcb 315 || kread((KA_T)s.so_pcb, (char *)&ndrv_cb, sizeof(ndrv_cb))) { 316 (void) snpf(Namech, Namechl, "can't read ndrv_cb at %s", 317 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); 318 enter_nm(Namech); 319 return; 320 } 321 /* 322 * Print NDRV socket information. 323 */ 324 enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); 325 /* 326 * Print device name, if bound 327 */ 328 if (!ndrv_cb.nd_if 329 || kread((KA_T)ndrv_cb.nd_if, (char *)&ifnet, sizeof(ifnet))) { 330 (void) snpf(Namech, Namechl, "can't read ifnet at %s", 331 print_kptr((KA_T)ndrv_cb.nd_if, (char *)NULL, 0)); 332 enter_nm(Namech); 333 return; 334 } 335 if (!ifnet.if_name 336 || kread((KA_T)ifnet.if_name, buf, sizeof(buf))) { 337 (void) snpf(Namech, Namechl, "can't read ifnet.if_name at %s", 338 print_kptr((KA_T)ifnet.if_name, (char *)NULL, 0)); 339 enter_nm(Namech); 340 return; 341 } 342 (void) snpf(Namech, Namechl, "-> %s%d", buf, ifnet.if_unit); 343 } 344 break; 345#endif /* defined(AF_NDRV) */ 346 347#if defined(pseudo_AF_KEY) 348/* 349 * Process an [internal] key-management function socket 350 */ 351 case pseudo_AF_KEY: 352 (void) snpf(Lf->type, sizeof(Lf->type), "key"); 353 break; 354#endif /* defined(pseudo_AF_KEY) */ 355 356#if defined(AF_SYSTEM) 357/* 358 * Process a SYSTEM domain socket 359 */ 360 case AF_SYSTEM: 361 (void) snpf(Lf->type, sizeof(Lf->type), "systm"); 362 /* 363 * Read protocol control block. 364 */ 365 if (!s.so_pcb 366 || kread((KA_T)s.so_pcb, (char *)&kev_cb, sizeof(kev_cb))) { 367 (void) snpf(Namech, Namechl, "can't read kev_cb at %s", 368 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); 369 enter_nm(Namech); 370 return; 371 } 372 /* 373 * Print SYSTEM socket information. 374 */ 375 enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); 376 (void) snpf(Namech, Namechl, "[%lx:%lx:%lx]", 377 kev_cb.vendor_code_filter, 378 kev_cb.class_filter, kev_cb.subclass_filter); 379 break; 380#endif /* defined(AF_SYSTEM) */ 381 382#if defined(AF_PPP) 383/* 384 * Process a PPP domain socket 385 */ 386 case AF_PPP: 387 (void) snpf(Lf->type, sizeof(Lf->type), "ppp"); 388 break; 389#endif /* defined(AF_PPP) */ 390 391/* 392 * Process a ROUTE domain socket. 393 */ 394 case AF_ROUTE: 395 (void) snpf(Lf->type, sizeof(Lf->type), "rte"); 396 if (s.so_pcb) 397 enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); 398 else 399 (void) snpf(Namech, Namechl, "no protocol control block"); 400 if (!Fsize) 401 Lf->off_def = 1; 402 break; 403/* 404 * Process a Unix domain socket. 405 */ 406 case AF_UNIX: 407 if (Funix) 408 Lf->sf |= SELUNX; 409 (void) snpf(Lf->type, sizeof(Lf->type), "unix"); 410 /* 411 * Read Unix protocol control block and the Unix address structure. 412 */ 413 414 enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); 415 if (!s.so_pcb 416 || kread((KA_T)s.so_pcb, (char *)&unp, sizeof(unp))) { 417 (void) snpf(Namech, Namechl, "can't read unpcb at %s", 418 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); 419 break; 420 } 421 if ((struct socket *)sa != unp.unp_socket) { 422 (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", 423 print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); 424 break; 425 } 426 if (unp.unp_addr) { 427 if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) { 428 (void) snpf(Namech, Namechl, "can't read unp_addr at %s", 429 print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); 430 break; 431 } 432 ua = &un; 433 } 434 if (!ua) { 435 ua = &un; 436 (void) bzero((char *)ua, sizeof(un)); 437 ua->sun_family = AF_UNSPEC; 438 } 439 /* 440 * Print information on Unix socket that has no address bound 441 * to it, although it may be connected to another Unix domain 442 * socket as a pipe. 443 */ 444 if (ua->sun_family != AF_UNIX) { 445 if (ua->sun_family == AF_UNSPEC) { 446 if (unp.unp_conn) { 447 if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) 448 (void) snpf(Namech, Namechl, 449 "can't read unp_conn at %s", 450 print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); 451 else 452 (void) snpf(Namech, Namechl, "->%s", 453 print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); 454 } else 455 (void) snpf(Namech, Namechl, "->(none)"); 456 } else 457 (void) snpf(Namech, Namechl, "unknown sun_family (%d)", 458 ua->sun_family); 459 break; 460 } 461 if (ua->sun_path[0]) { 462 unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path); 463 if ((unl < 0) || (unl >= sizeof(ua->sun_path))) 464 unl = sizeof(ua->sun_path) - 1; 465 ua->sun_path[unl] = '\0'; 466 if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0)) 467 Lf->sf |= SELNM; 468 if (ua->sun_path[0] && !Namech[0]) 469 (void) snpf(Namech, Namechl, "%s", ua->sun_path); 470 } else 471 (void) snpf(Namech, Namechl, "no address"); 472 break; 473 default: 474 printunkaf(fam, 1); 475 } 476 if (Namech[0]) 477 enter_nm(Namech); 478} 479