2 * dsock.c - FreeBSD socket processing functions for lsof
7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907. All rights reserved.
10 * Written by Victor A. Abell
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
19 * 1. Neither the authors nor Purdue University are responsible for any
20 * consequences of the use of this software.
22 * 2. The origin of this software must not be misrepresented, either by
23 * explicit claim or by omission. Credit to the authors and Purdue
24 * University must appear in documentation and sources.
26 * 3. Altered versions must be plainly marked as such, and must not be
27 * misrepresented as being the original software.
29 * 4. This notice may not be removed or altered.
33 static char copyright[] =
34 "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
35 static char *rcsid = "$Id: dsock.c,v 1.29 2013/01/02 17:01:43 abe Exp $";
45 * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained
49 #define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)
51 # if defined(HAS_NO_6PORT)
53 * If the in_pcb structure no longer has the KAME accommodations of
54 * in6p_[fl]port, redefine them to inp_[fl]port.
57 #define in6p_fport inp_fport
58 #define in6p_lport inp_lport
59 # endif /* defined(HAS_NO_6PORT) */
61 # if defined(HAS_NO_6PPCB)
63 * If the in_pcb structure no longer has the KAME accommodation of in6p_pcb,
64 * redefine it to inp_ppcb.
67 #define in6p_ppcb inp_ppcb
68 # endif /* defined(HAS_NO_6PPCB) */
69 #endif /* defined(HASIPv6) */
73 * Local function prototypes
76 _PROTOTYPE(static int ckstate,(KA_T ta, struct tcpcb *t, int fam));
80 * ckstate() -- read TCP control block and check TCP state for inclusion
82 * return: -1 == no TCP CB available
83 * 0 == TCP DB available; continue processing file
84 * 1 == stop processing file
89 KA_T ta; /* TCP control block address */
90 struct tcpcb *t; /* TCP control block receptor */
91 int fam; /* protocol family */
95 * Read TCP control block.
97 if (kread(ta, (char *)t, sizeof(struct tcpcb)))
99 if (TcpStXn || TcpStIn) {
102 * If there are TCP state inclusions or exclusions, check them.
104 tsnx = (int)t->t_state + TcpStOff;
123 if (!(Lf->sf & SELNET) && !TcpStIn) {
126 * See if this TCP file should be selected.
130 || ((FnetTy == 4) && (fam == AF_INET))
133 || ((FnetTy == 6) && (fam == AF_INET6))
134 #endif /* defined(HASIPv6) */
146 * process_socket() - process socket
151 KA_T sa; /* socket address in kernel */
154 unsigned char *fa = (unsigned char *)NULL;
158 unsigned char *la = (unsigned char *)NULL;
163 struct unpcb uc, unp;
164 struct sockaddr_un *ua = NULL;
165 struct sockaddr_un un;
169 #else /* FREEBSDV>=4050 */
171 #endif /* FREEBSDV<4050 */
173 #if defined(HASIPv6) && !defined(HASINRIAIPv6)
175 #endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
177 (void) snpf(Lf->type, sizeof(Lf->type), "sock");
180 * Read the socket, protocol, and domain structures.
183 enter_nm("no socket address");
186 if (kread(sa, (char *) &s, sizeof(s))) {
187 (void) snpf(Namech, Namechl, "can't read socket struct from %s",
188 print_kptr(sa, (char *)NULL, 0));
193 enter_nm("no socket type");
197 || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) {
198 (void) snpf(Namech, Namechl, "can't read protocol switch from %s",
199 print_kptr((KA_T)s.so_proto, (char *)NULL, 0));
204 || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) {
205 (void) snpf(Namech, Namechl, "can't read domain struct from %s",
206 print_kptr((KA_T)p.pr_domain, (char *)NULL, 0));
211 * Save size information.
214 if (Lf->access == 'r')
215 Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc;
216 else if (Lf->access == 'w')
217 Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc;
219 Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc);
224 #if defined(HASTCPTPIQ)
225 Lf->lts.rq = s.so_rcv.sb_cc;
226 Lf->lts.sq = s.so_snd.sb_cc;
227 Lf->lts.rqs = Lf->lts.sqs = 1;
228 #endif /* defined(HASTCPTPIQ) */
230 #if defined(HASSOOPT)
231 Lf->lts.ltm = (unsigned int)s.so_linger;
232 Lf->lts.opt = (unsigned int)s.so_options;
233 Lf->lts.pqlen = (unsigned int)s.so_incqlen;
234 Lf->lts.qlen = (unsigned int)s.so_qlen;
235 Lf->lts.qlim = (unsigned int)s.so_qlimit;
236 Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax;
237 Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax;
238 Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs
239 = Lf->lts.sbszs = (unsigned char)1;
240 #endif /* defined(HASSOOPT) */
242 #if defined(HASSOSTATE)
243 Lf->lts.ss = (unsigned int)s.so_state;
244 # if defined(HASSBSTATE)
245 Lf->lts.sbs_rcv = s.so_rcv.sb_state;
246 Lf->lts.sbs_snd = s.so_snd.sb_state;
247 # endif /* defined(HASSBSTATE) */
248 #endif /* defined(HASSOSTATE) */
251 * Process socket by the associated domain family.
253 switch ((fam = d.dom_family)) {
255 * Process an Internet domain socket.
261 #endif /* defined(HASIPv6) */
265 || ((FnetTy == 4) && (fam == AF_INET))
268 || ((FnetTy == 6) && (fam == AF_INET6))
269 #endif /* defined(HASIPv6) */
272 if (!TcpStIn && !UdpStIn)
276 printiproto(p.pr_protocol);
279 (void) snpf(Lf->type, sizeof(Lf->type),
280 (fam == AF_INET) ? "IPv4" : "IPv6");
281 #else /* !defined(HASIPv6) */
282 (void) snpf(Lf->type, sizeof(Lf->type), "inet");
283 #endif /* defined(HASIPv6) */
285 #if defined(HASIPv6) && !defined(HASINRIAIPv6)
286 if (fam == AF_INET6) {
289 * Read IPv6 protocol control block.
292 || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) {
293 (void) snpf(Namech, Namechl, "can't read in6pcb at %s",
294 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
299 * Save IPv6 address information.
301 if (p.pr_protocol == IPPROTO_TCP) {
302 if (in6p.in6p_ppcb) {
303 if ((ts = ckstate((KA_T)in6p.in6p_ppcb, &t, fam)) == 1)
307 enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb
310 la = (unsigned char *)&in6p.in6p_laddr;
311 lp = (int)ntohs(in6p.in6p_lport);
312 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr)
315 fa = (unsigned char *)&in6p.in6p_faddr;
316 fp = (int)ntohs(in6p.in6p_fport);
319 #endif /* defined(HASIPv6) && !defined(HASINRIAIPv6) */
324 * Read Ipv4 or IPv6 (INRIA) protocol control block.
327 || kread((KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) {
329 (void) snpf(Namech, Namechl, "no PCB%s%s",
331 #if defined(HASSBSTATE)
332 (s.so_snd.sb_state & SBS_CANTSENDMORE) ?
333 #else /* !defined(HASSBSTATE) */
334 (s.so_state & SS_CANTSENDMORE) ?
335 #endif /* defined(HASSBSTATE) */
337 ", CANTSENDMORE" : "",
338 #if defined(HASSBSTATE)
339 (s.so_rcv.sb_state & SBS_CANTRCVMORE) ?
340 #else /* !defined(HASSBSTATE) */
341 (s.so_state & SS_CANTRCVMORE) ?
342 #endif /* defined(HASSBSTATE) */
344 ", CANTRCVMORE" : "");
346 (void) snpf(Namech, Namechl, "can't read inpcb at %s",
347 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
352 if (p.pr_protocol == IPPROTO_TCP) {
354 if ((ts = ckstate((KA_T)inp.inp_ppcb, &t, fam)) == 1)
358 enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb
361 lp = (int)ntohs(inp.inp_lport);
362 if (fam == AF_INET) {
365 * Save IPv4 address information.
367 la = (unsigned char *)&inp.inp_laddr;
368 if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) {
369 fa = (unsigned char *)&inp.inp_faddr;
370 fp = (int)ntohs(inp.inp_fport);
374 #if defined(HASIPv6) && defined(HASINRIAIPv6)
376 la = (unsigned char *)&inp.inp_laddr6;
377 if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)
380 fa = (unsigned char *)&inp.inp_faddr6;
381 fp = (int)ntohs(inp.inp_fport);
384 #endif /* defined(HASIPv6) && defined(HASINRIAIPv6) */
390 if ((fam == AF_INET6)
391 && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la))
392 || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) {
395 * Adjust for IPv4 addresses mapped in IPv6 addresses.
398 la = (unsigned char *)IPv6_2_IPv4(la);
400 fa = (unsigned char *)IPv6_2_IPv4(fa);
403 #endif /* defined(HASIPv6) */
406 * Enter local and remote addresses by address family.
409 (void) ent_inaddr(la, lp, fa, fp, fam);
412 Lf->lts.state.i = (int)t.t_state;
414 #if defined(HASTCPOPT)
415 Lf->lts.mss = (unsigned long)t.t_maxseg;
416 Lf->lts.msss = (unsigned char)1;
417 Lf->lts.topt = (unsigned int)t.t_flags;
418 #endif /* defined(HASTCPOPT) */
423 * Process a ROUTE domain socket.
426 (void) snpf(Lf->type, sizeof(Lf->type), "rte");
428 enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0));
430 (void) snpf(Namech, Namechl, "no protocol control block");
435 * Process a Unix domain socket.
440 (void) snpf(Lf->type, sizeof(Lf->type), "unix");
442 * Read Unix protocol control block and the Unix address structure.
445 enter_dev_ch(print_kptr(sa, (char *)NULL, 0));
446 if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) {
447 (void) snpf(Namech, Namechl, "can't read unpcb at %s",
448 print_kptr((KA_T)s.so_pcb, (char *)NULL, 0));
451 if ((struct socket *)sa != unp.unp_socket) {
452 (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch",
453 print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0));
459 if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb)))
460 #else /* FREEBSDV>=4050 */
461 if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un)))
462 #endif /* FREEBSDV<4050 */
465 (void) snpf(Namech, Namechl, "can't read unp_addr at %s",
466 print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0));
471 if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un))
472 ua = (struct sockaddr_un *) ((char *) &mb
473 + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr));
474 #else /* FREEBSDV>=4050 */
476 #endif /* FREEBSDV<4050 */
481 (void) bzero((char *)ua, sizeof(un));
482 ua->sun_family = AF_UNSPEC;
485 * Print information on Unix socket that has no address bound
486 * to it, although it may be connected to another Unix domain
489 if (ua->sun_family != AF_UNIX) {
490 if (ua->sun_family == AF_UNSPEC) {
492 if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc)))
493 (void) snpf(Namech, Namechl,
494 "can't read unp_conn at %s",
495 print_kptr((KA_T)unp.unp_conn,(char *)NULL,0));
497 (void) snpf(Namech, Namechl, "->%s",
498 print_kptr((KA_T)uc.unp_socket,(char *)NULL,0));
500 (void) snpf(Namech, Namechl, "->(none)");
502 (void) snpf(Namech, Namechl, "unknown sun_family (%d)",
506 if (ua->sun_path[0]) {
509 if (mb.m_len >= sizeof(struct sockaddr_un))
510 mb.m_len = sizeof(struct sockaddr_un) - 1;
511 *((char *)ua + mb.m_len) = '\0';
512 #else /* FREEBSDV>=4050 */
514 unl = ua->sun_len - offsetof(struct sockaddr_un, sun_path);
515 # else /* FREEBSDV<4060 */
516 unl = sizeof(ua->sun_path) - 1;
517 # endif /* FREEBSDV>4060 */
518 if ((unl < 0) || (unl >= sizeof(ua->sun_path)))
519 unl = sizeof(ua->sun_path) - 1;
520 ua->sun_path[unl] = '\0';
521 #endif /* FREEBSDV<4050 */
523 if (ua->sun_path[0] && Sfile && is_file_named(ua->sun_path, 0))
525 if (ua->sun_path[0] && !Namech[0])
526 (void) snpf(Namech, Namechl, "%s", ua->sun_path);
528 (void) snpf(Namech, Namechl, "no address");