summaryrefslogtreecommitdiff
path: root/dialects/n+obsd/dsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'dialects/n+obsd/dsock.c')
-rw-r--r--dialects/n+obsd/dsock.c425
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);
+}