diff options
Diffstat (limited to 'dialects/n+obsd/dsock.c')
-rw-r--r-- | dialects/n+obsd/dsock.c | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/dialects/n+obsd/dsock.c b/dialects/n+obsd/dsock.c new file mode 100644 index 0000000..0e10971 --- /dev/null +++ b/dialects/n+obsd/dsock.c @@ -0,0 +1,425 @@ +/* + * dsock.c - NetBSD and OpenBSD socket processing functions for lsof + */ + + +/* + * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana + * 47907. All rights reserved. + * + * Written by Victor A. Abell + * + * This software is not subject to any license of the American Telephone + * and Telegraph Company or the Regents of the University of California. + * + * Permission is granted to anyone to use this software for any purpose on + * any computer system, and to alter it and redistribute it freely, subject + * to the following restrictions: + * + * 1. Neither the authors nor Purdue University are responsible for any + * consequences of the use of this software. + * + * 2. The origin of this software must not be misrepresented, either by + * explicit claim or by omission. Credit to the authors and Purdue + * University must appear in documentation and sources. + * + * 3. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 4. This notice may not be removed or altered. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; +static char *rcsid = "$Id: dsock.c,v 1.25 2005/08/08 19:53:24 abe Exp $"; +#endif + + +#include "lsof.h" + + +#if defined(HASIPv6) + +/* + * IPv6_2_IPv4() -- macro to define the address of an IPv4 address contained + * in an IPv6 address + */ + +#define IPv6_2_IPv4(v6) (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12) +#endif /* defined(HASIPv6) */ + + +/* + * process_socket() - process socket + */ + +void +process_socket(sa) + KA_T sa; /* socket address in kernel */ +{ + struct domain d; + unsigned char *fa = (unsigned char *)NULL; + int fam; + int fp, lp; + struct inpcb inp; + unsigned char *la = (unsigned char *)NULL; + struct protosw p; + struct socket s; + struct tcpcb t; + KA_T ta = (KA_T)NULL; + struct unpcb uc, unp; + struct sockaddr_un *ua = NULL; + struct sockaddr_un un; + +#if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) + struct in6pcb in6p; +#endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */ + +#define UNPADDR_IN_MBUF + +#if defined(NETBSDV) +# if NETBSDV>=1004000 +#undef UNPADDR_IN_MBUF +# endif /* NETBSDV>=1004000 */ +#endif /* defined(NETBSDV) */ + +#if defined(UNPADDR_IN_MBUF) + struct mbuf mb; +#endif /* defined(UNPADDR_IN_MBUF) */ + + (void) snpf(Lf->type, sizeof(Lf->type), "sock"); + Lf->inp_ty = 2; +/* + * Read the socket, protocol, and domain structures. + */ + if (!sa) { + enter_nm("no socket address"); + return; + } + if (kread(sa, (char *) &s, sizeof(s))) { + (void) snpf(Namech, Namechl, "can't read socket struct from %s", + print_kptr(sa, (char *)NULL, 0)); + enter_nm(Namech); + return; + } + if (!s.so_type) { + enter_nm("no socket type"); + return; + } + if (!s.so_proto + || kread((KA_T)s.so_proto, (char *)&p, sizeof(p))) { + (void) snpf(Namech, Namechl, "can't read protocol switch from %s", + print_kptr((KA_T)s.so_proto, (char *)NULL, 0)); + enter_nm(Namech); + return; + } + if (!p.pr_domain + || kread((KA_T)p.pr_domain, (char *)&d, sizeof(d))) { + (void) snpf(Namech, Namechl, "can't read domain struct from %s", + print_kptr((KA_T)p.pr_domain, (char *)NULL, 0)); + enter_nm(Namech); + return; + } +/* + * Save size information. + */ + if (Fsize) { + if (Lf->access == 'r') + Lf->sz = (SZOFFTYPE)s.so_rcv.sb_cc; + else if (Lf->access == 'w') + Lf->sz = (SZOFFTYPE)s.so_snd.sb_cc; + else + Lf->sz = (SZOFFTYPE)(s.so_rcv.sb_cc + s.so_snd.sb_cc); + Lf->sz_def = 1; + } else + Lf->off_def = 1; + +#if defined(HASTCPTPIQ) + Lf->lts.rq = s.so_rcv.sb_cc; + Lf->lts.sq = s.so_snd.sb_cc; + Lf->lts.rqs = Lf->lts.sqs = 1; +#endif /* defined(HASTCPTPIQ) */ + +#if defined(HASSOOPT) + Lf->lts.ltm = (unsigned int)s.so_linger; + Lf->lts.opt = (unsigned int)s.so_options; + Lf->lts.pqlen = (unsigned int)s.so_q0len; + Lf->lts.qlen = (unsigned int)s.so_qlen; + Lf->lts.qlim = (unsigned int)s.so_qlimit; + Lf->lts.rbsz = (unsigned long)s.so_rcv.sb_mbmax; + Lf->lts.sbsz = (unsigned long)s.so_snd.sb_mbmax; + Lf->lts.pqlens = Lf->lts.qlens = Lf->lts.qlims = Lf->lts.rbszs + = Lf->lts.sbszs = (unsigned char)1; +#endif /* defined(HASSOOPT) */ + +#if defined(HASSOSTATE) + Lf->lts.ss = (unsigned int)s.so_state; +#endif /* defined(HASSOSTATE) */ + +/* + * Process socket by the associated domain family. + */ + switch ((fam = d.dom_family)) { +/* + * Process an Internet domain socket. + */ + case AF_INET: + +#if defined(HASIPv6) + case AF_INET6: +#endif /* defined(HASIPv6) */ + + if (Fnet) { + if (!FnetTy + || ((FnetTy == 4) && (fam == AF_INET)) + +#if defined(HASIPv6) + || ((FnetTy == 6) && (fam == AF_INET6)) +#endif /* defined(HASIPv6) */ + ) + + Lf->sf |= SELNET; + } + printiproto(p.pr_protocol); + +#if defined(HASIPv6) + (void) snpf(Lf->type, sizeof(Lf->type), + (fam == AF_INET) ? "IPv4" : "IPv6"); +#else /* !defined(HASIPv6) */ + (void) snpf(Lf->type, sizeof(Lf->type), "inet"); +#endif /* defined(HASIPv6) */ + +#if defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) + if (fam == AF_INET6) { + + /* + * Read IPv6 protocol control block. + */ + if (!s.so_pcb + || kread((KA_T)s.so_pcb, (char *)&in6p, sizeof(in6p))) { + (void) snpf(Namech, Namechl, "can't read in6pcb at %s", + print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); + enter_nm(Namech); + return; + } + /* + * Save IPv6 address information. + */ + enter_dev_ch(print_kptr((KA_T)(in6p.in6p_ppcb ? in6p.in6p_ppcb + : s.so_pcb), + (char *)NULL, 0)); + if (p.pr_protocol == IPPROTO_TCP) + ta = (KA_T)in6p.in6p_ppcb; + la = (unsigned char *)&in6p.in6p_laddr; + lp = (int)ntohs(in6p.in6p_lport); + if (!IN6_IS_ADDR_UNSPECIFIED(&in6p.in6p_faddr) + || in6p.in6p_fport) + { + fa = (unsigned char *)&in6p.in6p_faddr; + fp = (int)ntohs(in6p.in6p_fport); + } + } else +#endif /* defined(HASIPv6) && defined(NETBSDV) && !defined(HASINRIAIPv6) */ + + { + + /* + * Read IPv4 or IPv6 (OpenBSD) protocol control block. + */ + if (!s.so_pcb + || kread((KA_T)s.so_pcb, (char *)&inp, sizeof(inp))) { + if (!s.so_pcb) { + (void) snpf(Namech, Namechl, "no PCB%s%s", + (s.so_state & SS_CANTSENDMORE) ? ", CANTSENDMORE" + : "", + (s.so_state & SS_CANTRCVMORE) ? ", CANTRCVMORE" + : ""); + } else { + (void) snpf(Namech, Namechl, "can't read inpcb at %s", + print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); + } + enter_nm(Namech); + return; + } + enter_dev_ch(print_kptr((KA_T)(inp.inp_ppcb ? inp.inp_ppcb + : s.so_pcb), + (char *)NULL, 0)); + if (p.pr_protocol == IPPROTO_TCP) + ta = (KA_T)inp.inp_ppcb; + lp = (int)ntohs(inp.inp_lport); + if (fam == AF_INET) { + + /* + * Save IPv4 address information. + */ + la = (unsigned char *)&inp.inp_laddr; + if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport) { + fa = (unsigned char *)&inp.inp_faddr; + fp = (int)ntohs(inp.inp_fport); + } + } + +#if defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6)) + else { + la = (unsigned char *)&inp.inp_laddr6; + if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6) + || inp.inp_fport) + { + fa = (unsigned char *)&inp.inp_faddr6; + fp = (int)ntohs(inp.inp_fport); + } + } +#endif /* defined(HASIPv6) && (defined(OPENBSDV) || defined(HASINRIAIPv6)) */ + + } + +#if defined(HASIPv6) + if ((fam == AF_INET6) + && ((la && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)la)) + || ((fa && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)fa))))) { + + /* + * Adjust for IPv4 addresses mapped in IPv6 addresses. + */ + if (la) + la = (unsigned char *)IPv6_2_IPv4(la); + if (fa) + fa = (unsigned char *)IPv6_2_IPv4(fa); + fam = AF_INET; + } +#endif /* defined(HASIPv6) */ + + /* + * Enter local and remote addresses by address family. + */ + if (fa || la) + (void) ent_inaddr(la, lp, fa, fp, fam); + /* + * If the protocol is TCP, and its address is available, read the + * TCP protocol control block and save its state. + */ + if (ta && !kread(ta, (char *)&t, sizeof(t))) { + Lf->lts.type = 0; + Lf->lts.state.i = (int)t.t_state; + +#if defined(HASTCPOPT) +# if defined(OPENBSDV) + Lf->lts.mss = (unsigned long)t.t_maxseg; +# else /* !defined(OPENSDV) */ + Lf->lts.mss = (unsigned long)t.t_ourmss; +# endif /* defined(OPENSDV) */ + + Lf->lts.msss = (unsigned char)1; + Lf->lts.topt = (unsigned int)t.t_flags; +#endif /* defined(HASTCPOPT) */ + + } + break; +/* + * Process a ROUTE domain socket. + */ + case AF_ROUTE: + (void) snpf(Lf->type, sizeof(Lf->type), "rte"); + if (s.so_pcb) + enter_dev_ch(print_kptr((KA_T)(s.so_pcb), (char *)NULL, 0)); + else + (void) snpf(Namech, Namechl, "no protocol control block"); + if (!Fsize) + Lf->off_def = 1; + break; +/* + * Process a Unix domain socket. + */ + case AF_UNIX: + if (Funix) + Lf->sf |= SELUNX; + (void) snpf(Lf->type, sizeof(Lf->type), "unix"); + /* + * Read Unix protocol control block and the Unix address structure. + */ + + enter_dev_ch(print_kptr(sa, (char *)NULL, 0)); + if (kread((KA_T) s.so_pcb, (char *) &unp, sizeof(unp))) { + (void) snpf(Namech, Namechl, "can't read unpcb at %s", + print_kptr((KA_T)s.so_pcb, (char *)NULL, 0)); + break; + } + if ((struct socket *)sa != unp.unp_socket) { + (void) snpf(Namech, Namechl, "unp_socket (%s) mismatch", + print_kptr((KA_T)unp.unp_socket, (char *)NULL, 0)); + break; + } + if (unp.unp_addr) { + +#if defined(UNPADDR_IN_MBUF) + if (kread((KA_T)unp.unp_addr, (char *)&mb, sizeof(mb))) +#else /* !defined(UNPADDR_IN_MBUF) */ + if (kread((KA_T)unp.unp_addr, (char *)&un, sizeof(un))) +#endif /* defined(UNPADDR_IN_MBUF) */ + + { + (void) snpf(Namech, Namechl, "can't read unp_addr at %s", + print_kptr((KA_T)unp.unp_addr, (char *)NULL, 0)); + break; + } + +#if defined(UNPADDR_IN_MBUF) + if (mb.m_hdr.mh_len == sizeof(struct sockaddr_un)) + ua = (struct sockaddr_un *) ((char *) &mb + + (mb.m_hdr.mh_data - (caddr_t) unp.unp_addr)); +#else /* !defined(UNPADDR_IN_MBUF) */ + ua = &un; +#endif /* defined(UNPADDR_IN_MBUF) */ + + } + if (!ua) { + ua = &un; + (void) bzero((char *)ua, sizeof(un)); + ua->sun_family = AF_UNSPEC; + } + /* + * Print information on Unix socket that has no address bound + * to it, although it may be connected to another Unix domain + * socket as a pipe. + */ + if (ua->sun_family != AF_UNIX) { + if (ua->sun_family == AF_UNSPEC) { + if (unp.unp_conn) { + if (kread((KA_T)unp.unp_conn, (char *)&uc, sizeof(uc))) + (void) snpf(Namech, Namechl, + "can't read unp_conn at %s", + print_kptr((KA_T)unp.unp_conn,(char *)NULL,0)); + else + (void) snpf(Namech, Namechl, "->%s", + print_kptr((KA_T)uc.unp_socket,(char *)NULL,0)); + } else + (void) snpf(Namech, Namechl, "->(none)"); + } else + (void) snpf(Namech, Namechl, "unknown sun_family (%d)", + ua->sun_family); + break; + } + if (ua->sun_path[0]) { + +#if defined(UNPADDR_IN_MBUF) + if (mb.m_len >= sizeof(struct sockaddr_un)) + mb.m_len = sizeof(struct sockaddr_un) - 1; + *((char *)ua + mb.m_len) = '\0'; +#else /* !defined(UNPADDR_IN_MBUF) */ + ua->sun_path[sizeof(ua->sun_path) - 1] = '\0'; +#endif /* defined(UNPADDR_IN_MBUF) */ + + if (Sfile && is_file_named(ua->sun_path, 0)) + Lf->sf |= SELNM; + if (!Namech[0]) + (void) snpf(Namech, Namechl, "%s", ua->sun_path); + } else + (void) snpf(Namech, Namechl, "no address"); + break; + default: + printunkaf(fam, 1); + } + if (Namech[0]) + enter_nm(Namech); +} |