void socktrans(struct socket *sock, int i) { static const char *stypename[] = { "unused", /* 0 */ "stream", /* 1 */ "dgram", /* 2 */ "raw", /* 3 */ "rdm", /* 4 */ "seqpak" /* 5 */ }; #define STYPEMAX 5 struct socket so; struct protosw proto; struct domain dom; struct inpcb inpcb; struct unpcb unpcb; int len; char dname[32]; PREFIX(i); /* fill in socket */ if (!kread(sock, &so, sizeof(struct socket))) { dprintf(stderr, "can't read sock at %p\n", (void *)sock); goto bad; } /* fill in protosw entry */ if (!kread(so.so_proto, &proto, sizeof(struct protosw))) { dprintf(stderr, "can't read protosw at %p", (void *)so.so_proto); goto bad; } /* fill in domain */ if (!kread(proto.pr_domain, &dom, sizeof(struct domain))) { dprintf(stderr, "can't read domain at %p\n", (const void *)proto.pr_domain); goto bad; } if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, sizeof(dname) - 1)) < 0) { dprintf(stderr, "can't read domain name at %p\n", (void *)dom.dom_name); dname[0] = '\0'; } else dname[len] = '\0'; if ((u_short)so.so_type > STYPEMAX) printf("* %s ?%d", dname, so.so_type); else printf("* %s %s", dname, stypename[so.so_type]); /* * protocol specific formatting * * Try to find interesting things to print. For tcp, the interesting * thing is the address of the tcpcb, for udp and others, just the * inpcb (socket pcb). For unix domain, its the address of the socket * pcb and the address of the connected pcb (if connected). Otherwise * just print the protocol number and address of the socket itself. * The idea is not to duplicate netstat, but to make available enough * information for further analysis. */ switch(dom.dom_family) { case AF_INET: case AF_INET6: getinetproto(proto.pr_protocol); if (proto.pr_protocol == IPPROTO_TCP ) { if (so.so_pcb) { if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf(stderr, "can't read inpcb at %p\n", (void *)so.so_pcb); goto bad; } printf(" %lx", (u_long)inpcb.inp_ppcb); } } else if (so.so_pcb) printf(" %lx", (u_long)so.so_pcb); break; case AF_UNIX: /* print address of pcb and connected pcb */ if (so.so_pcb) { printf(" %lx", (u_long)so.so_pcb); if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, sizeof(struct unpcb)) != sizeof(struct unpcb)) { dprintf(stderr, "can't read unpcb at %p\n", (void *)so.so_pcb); goto bad; } if (unpcb.unp_conn) { char shoconn[4], *cp; cp = shoconn; if (!(so.so_state & SS_CANTRCVMORE)) *cp++ = '<'; *cp++ = '-'; if (!(so.so_state & SS_CANTSENDMORE)) *cp++ = '>'; *cp = '\0'; printf(" %s %lx", shoconn, (u_long)unpcb.unp_conn); } } break; default: /* print protocol number and socket address */ printf(" %d %lx", proto.pr_protocol, (u_long)sock); } printf("\n"); return; bad: printf("* error\n"); }
void socktrans(struct socket *sock, int i) { static char *stypename[] = { "unused", /* 0 */ "stream", /* 1 */ "dgram", /* 2 */ "raw", /* 3 */ "rdm", /* 4 */ "seqpak" /* 5 */ }; #define STYPEMAX 5 struct socket so; struct protosw proto; struct domain dom; struct inpcb inpcb; struct unpcb unpcb; int len; char dname[32]; #ifdef INET6 char xaddrbuf[NI_MAXHOST + 2]; #endif PREFIX(i); /* fill in socket */ if (!KVM_READ(sock, &so, sizeof(struct socket))) { dprintf("can't read sock at %p", sock); goto bad; } /* fill in protosw entry */ if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { dprintf("can't read protosw at %p", so.so_proto); goto bad; } /* fill in domain */ if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { dprintf("can't read domain at %p", proto.pr_domain); goto bad; } if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, sizeof(dname) - 1)) != sizeof(dname) -1) { dprintf("can't read domain name at %p", dom.dom_name); dname[0] = '\0'; } else dname[len] = '\0'; if ((u_short)so.so_type > STYPEMAX) printf("* %s ?%d", dname, so.so_type); else printf("* %s %s", dname, stypename[so.so_type]); /* * protocol specific formatting * * Try to find interesting things to print. For tcp, the interesting * thing is the address of the tcpcb, for udp and others, just the * inpcb (socket pcb). For unix domain, its the address of the socket * pcb and the address of the connected pcb (if connected). Otherwise * just print the protocol number and address of the socket itself. * The idea is not to duplicate netstat, but to make available enough * information for further analysis. */ switch(dom.dom_family) { case AF_INET: getinetproto(proto.pr_protocol); if (proto.pr_protocol == IPPROTO_TCP) { if (so.so_pcb == NULL) break; if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf("can't read inpcb at %p", so.so_pcb); goto bad; } printf(" %p", inpcb.inp_ppcb); printf(" %s:%d", inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" : inet_ntoa(inpcb.inp_laddr), ntohs(inpcb.inp_lport)); if (inpcb.inp_fport) { if (so.so_state & SS_CONNECTOUT) printf(" --> "); else printf(" <-- "); printf("%s:%d", inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" : inet_ntoa(inpcb.inp_faddr), ntohs(inpcb.inp_fport)); } } else if (proto.pr_protocol == IPPROTO_UDP) { if (so.so_pcb == NULL) break; if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf("can't read inpcb at %p", so.so_pcb); goto bad; } printf(" %s:%d", inpcb.inp_laddr.s_addr == INADDR_ANY ? "*" : inet_ntoa(inpcb.inp_laddr), ntohs(inpcb.inp_lport)); if (inpcb.inp_fport) printf(" <-> %s:%d", inpcb.inp_faddr.s_addr == INADDR_ANY ? "*" : inet_ntoa(inpcb.inp_faddr), ntohs(inpcb.inp_fport)); } else if (so.so_pcb) printf(" %p", so.so_pcb); break; #ifdef INET6 case AF_INET6: getinetproto(proto.pr_protocol); if (proto.pr_protocol == IPPROTO_TCP) { if (so.so_pcb == NULL) break; if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf("can't read inpcb at %p", so.so_pcb); goto bad; } printf(" %p", inpcb.inp_ppcb); snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", inet6_addrstr(&inpcb.inp_laddr6)); printf(" %s:%d", IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6) ? "*" : xaddrbuf, ntohs(inpcb.inp_lport)); if (inpcb.inp_fport) { if (so.so_state & SS_CONNECTOUT) printf(" --> "); else printf(" <-- "); snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", inet6_addrstr(&inpcb.inp_faddr6)); printf("%s:%d", IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6) ? "*" : xaddrbuf, ntohs(inpcb.inp_fport)); } } else if (proto.pr_protocol == IPPROTO_UDP) { if (so.so_pcb == NULL) break; if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb, sizeof(struct inpcb)) != sizeof(struct inpcb)) { dprintf("can't read inpcb at %p", so.so_pcb); goto bad; } snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", inet6_addrstr(&inpcb.inp_laddr6)); printf(" %s:%d", IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_laddr6) ? "*" : xaddrbuf, ntohs(inpcb.inp_lport)); if (inpcb.inp_fport) { snprintf(xaddrbuf, sizeof(xaddrbuf), "[%s]", inet6_addrstr(&inpcb.inp_faddr6)); printf(" <-> %s:%d", IN6_IS_ADDR_UNSPECIFIED(&inpcb.inp_faddr6) ? "*" : xaddrbuf, ntohs(inpcb.inp_fport)); } } else if (so.so_pcb) printf(" %p", so.so_pcb); break; #endif case AF_UNIX: /* print address of pcb and connected pcb */ if (so.so_pcb) { printf(" %p", so.so_pcb); if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, sizeof(struct unpcb)) != sizeof(struct unpcb)){ dprintf("can't read unpcb at %p", so.so_pcb); goto bad; } if (unpcb.unp_conn) { char shoconn[4], *cp; cp = shoconn; if (!(so.so_state & SS_CANTRCVMORE)) *cp++ = '<'; *cp++ = '-'; if (!(so.so_state & SS_CANTSENDMORE)) *cp++ = '>'; *cp = '\0'; printf(" %s %p", shoconn, unpcb.unp_conn); } } break; default: /* print protocol number and socket address */ printf(" %d %p", proto.pr_protocol, sock); } printf("\n"); return; bad: printf("* error\n"); }