mb@rex.cs.tulane.edu (Mark Benard) (02/28/91)
Has anyone modified ofiles to run on a Pyramid? Mark
romain@pyramid.pyramid.com (Romain Kang) (02/28/91)
/etc/fuser should be sufficient for most applications where you'd want to use ofiles, but... This should run under OSx 5.0 or later. 4.4 needs a getuser() variant more like stock BSD. /* ofiles.c * * ofiles [-d ] [-k nlist core] [-n] [-p] args * * Show owner of open file or network connection. * * Reports owner, process ID, access type, command and inode number. * * -d select verbose debugging output * * -k nlist core specifies alternative name list and core files * (DYNIX only) * * -n interpret names as network connection, hexadecimal * Protocol Control Block (PCB) addresses * * -p gives brief (pids only) report * * names file names, file system names or network connection * PCB addresses * * Stat each file or file system argument and scan the process table, * looking for a match in the associated user structure's file lists. * * Follow each PCB arg to the Internet Protocol Control Block (INPCB), * thence to the socket; then scan the file table to find the file * structure address associated with the socket; finally, scan the * process table, looking for a nacth in the associated user structure's * file lists. * * Doesn't handlle remote NFS files. */ /* * Authors: * * The orignal author is: * * C. Spencer * * Contributors include: * * Michael Ditto * Tom Dunigan * Alexander Dupuy * Greg Nebbett * Richard Tobin * * From the Purdue University Computing Center: * * Mike Spitzer converted to 4.3BSD, DYNIX 3.0.1[24] * Ray Moody SunOS 4.0 and ULTRIX 2.2 * Vik Lall * * Vic Abell added socket option and removed lint * */ #ifndef lint static char rcsid[]="$Header: ofiles.c,v 1.8.1.2 91/02/28 03:01:30 romain Exp $"; #endif /* lint */ #include <sys/param.h> #include <sys/dir.h> #include <sys/user.h> #ifdef DYNIX #define KERNEL #include <sys/file.h> #include <sys/vnode.h> #include <sys/inode.h> #undef KERNEL #else #define KERNEL #include <sys/file.h> #if !defined(sun) && !defined(pyr) #include <sys/inode.h> #endif #undef KERNEL #endif #ifdef pyr #else #include <machine/pte.h> #if !defined(ultrix) && !defined(sun) #include <machine/machparam.h> #endif #endif #include <sys/proc.h> #include <nlist.h> #include <sys/stat.h> #include <pwd.h> #include <fstab.h> #include <sys/vmmac.h> #include <stdio.h> #ifdef sun #include <kvm.h> kvm_t *kd; #endif #if defined(sun) || defined(pyr) #include <sys/vnode.h> #include <ufs/inode.h> struct snode { struct snode *s_next; struct vnode s_vnode; struct vnode *s_realvp; struct vnode *s_bdevvp; u_short s_flag; dev_t s_dev; }; #endif #ifdef ultrix #include <sys/gnode.h> #include <sys/gnode_common.h> #include <machine/param.h> #endif #include <sys/socket.h> #include <sys/socketvar.h> #include <net/route.h> #include <netinet/in.h> #include <netinet/in_pcb.h> #include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #define CDIR 01 #define OFILE 02 #define RDIR 04 #define SHFILE 010 #define EXFILE 020 #define SOCKET 040 char *namelist; char *corefile; int k_opt = 0; int n_opt = 0; #ifdef ultrix #define ls_t long #else #define ls_t off_t #endif #ifdef sun char *sprintf(); #endif ls_t lseek(), vtophys(); void eread(), eseek(); #ifdef ultrix void exit(), nlist(), perror(); #endif int nproc; /* number of entries in proc table */ int mem; /* fd for /dev/mem */ int kmem; int swap; /* fd for /dev/swap */ long procbase; int ppid = -1; /* previously display PID */ int dirinode; /* directory (CDIR or RDIR) inode */ int opninode; /* save inode of open file */ int pids_only = 0; /* if non-zero, only output process ids */ char *progname; struct nlist nl[] = { #define X_PROC 0 { "_proc" }, #define X_NPROC 1 {"_nproc"}, #define X_USRPTMA 2 {"_Usrptmap"}, #define X_USRPT 3 {"_usrpt"}, #define X_SYSMAP 4 {"_Sysmap"}, #define SFIL 5 { "_file" }, #define SNFILE 6 { "_nfile" }, { "" }, }; #ifndef DYNIX struct pte *usrpt, *Usrptma; #endif int debug; main(argc, argv) int argc; char *argv[]; { #ifdef ultrix struct gnode *i, *getinode(); #else struct inode *i, *getinode(); #endif #ifdef pyr int fdspace; struct file **fd_array; #endif struct stat s; struct user *u, *getuser(); struct proc p; register int filen, flags, procn; register char *filename, *fsname; struct fstab *fs, *getfsfile(), *getfsspec(); char *getsockfp(), *rindex(); struct file *fp; int ax, err, findf, nmct; char *ap; int exitval = 0; #ifdef lint /* * The following code satisfies lint for KERNEL symbols. * This program is lint-free under 4.3BSD, DYNIX 3.0.1[24], SunOS 4.0 * and ULTRIX 2.2, using the lint libraries of the systems at the * Purdue University Computing Center. */ #if !defined(ultrix) && !defined(DYNIX) && !defined(sun) long lintlong; #endif #ifdef ultrix struct nch *lintnch; float lintfloat; #endif #if !defined(DYNIX) file = fileNFILE = NULL; fp = file; fp = fileNFILE; nfile = 0; filen = nfile; #endif #if !defined(ultrix) && !defined(DYNIX) && !defined(sun) inode = inodeNINODE = rootdir = NULL; i = inode; i = inodeNINODE; i = rootdir; ninode = 0; nextinodeid = 0l; lintlong = nextinodeid; nextinodeid = lintlong; filen = ninode; #endif #ifdef sun tcp_ttl = 0; filen = tcp_ttl; #endif #ifdef ultrix nch = NULL; lintnch = nch; nch = lintnch; nchsize = 0; filen = nchsize; tcp_alpha = tcp_beta = 0.0; lintfloat = tcp_alpha; lintfloat = tcp_beta; tcp_alpha = lintfloat; #endif #endif /* lint */ if ((progname = rindex(argv[0], '/'))) progname++; else progname = argv[0]; if (argc == 1) { usage: #ifdef DYNIX (void) fprintf(stderr, "usage: %s [-d ] [-k nlist core] [-n] [-p] names\n", progname); #else (void) fprintf(stderr, "usage: %s [-d ] [-n] [-p] names\n", progname); #endif (void) fprintf(stderr, "\t-d = select verbose debugging output\n"); #ifdef DYNIX (void) fprintf(stderr, "\t-k = use specified nlist and core files\n"); #endif (void) fprintf(stderr, "\t-n = interpret names as network connection, hexadecimal,\n"); (void) fprintf(stderr, "\t Protocol Control Block (PCB) addresses, as supplied\n"); (void) fprintf(stderr, "\t by netstat's -A option\n"); (void) fprintf(stderr, "\t-p = print only process IDs\n"); (void) fprintf(stderr, "\tnames = file names or PCB addresses\n"); exit(exitval); } /* check for switches */ for (err = 0, ax = 1; ax < argc; ax++) { ap = argv[ax]; if (*ap++ != '-') break; while (*ap) { switch (*ap++) { case 'd': debug = 1; break; #ifdef DYNIX case 'k': if ((ax + 2) >= argc) { (void) fprintf(stderr, "%s: no nlist/core after -k\n", progname); err++; } else { namelist = argv[++ax]; corefile = argv[++ax]; k_opt = 1; continue; } break; #endif case 'n': n_opt++; break; case 'p': pids_only = 1; break; default: (void) fprintf(stderr, "%s: unknown switch - %c\n", progname, *(ap - 1)); err++; } } } if (ax >= argc) { (void) fprintf(stderr, "%s: no names specified\n", progname); err++; } if (err) { exitval = 1; goto usage; } #ifdef sun if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY)) == 0) { (void) fprintf(stderr, "%s: can't access memory: ", progname); perror (""); exit(1); } #endif if ((mem = open("/dev/mem", 0)) < 0) { (void) fprintf(stderr, "%s: /dev/mem: ", progname); perror(""); exit(1); } if (k_opt) { if ((kmem = open(corefile, 0)) < 0) { (void) fprintf(stderr, "%s: %s: ", progname, corefile); perror(""); exit(1); } } else { if ((kmem = open("/dev/kmem", 0)) < 0) { (void) fprintf(stderr, "%s: /dev/kmem: ", progname); perror(""); exit(1); } } if (!k_opt) #ifndef pyr if ((swap = open("/dev/drum", 0)) < 0) { (void) fprintf(stderr, "%s: /dev/drum: ", progname); perror(""); exit(1); } #endif getsyms(); for (err = 0, nmct = argc - ax; ax < argc; ax++) { /* if -n, then arg is a PCB */ if (n_opt) { if ((filename = getsockfp(argv[ax], &fp)) == NULL) { err++; continue; } fsname = ""; } else { /* assume arg is a filesystem */ if ((fs = getfsfile(argv[ax])) != NULL) { fsname = argv[ax]; if (strcmp(".", argv[ax]) == 0) filename = argv[ax]; else filename = fs->fs_spec; /* maybe it's the device name for a filesystem */ } else if ((fs = getfsspec(argv[ax])) != NULL) { filename = argv[ax]; fsname = fs->fs_file; /* probably a regular file */ } else { filename = argv[ax]; fsname = ""; } if (stat(filename, &s)) { (void) fprintf(stderr, "%s: can't stat %s: ", progname, filename); perror(""); err++; continue; } if (debug) (void) printf( "stat dev %x ino %d mode %x rdev %x\n", s.st_dev, s.st_ino, s.st_mode, s.st_rdev); } if (! pids_only) { (void) printf("%s\t%s", filename, fsname); if (!n_opt) { if ((s.st_mode & S_IFMT) == S_IFDIR) (void) printf("(directory)"); } (void) printf("\n%-8.8s %5s %-6.6s FD %-14.14s", "USER", "PID", "TYPE", "CMD"); if (!n_opt) (void) printf(" INODE"); (void) printf("\n"); } for (findf = procn = 0; procn < nproc; procn++) { procslot(procn, &p); flags = 0; if (p.p_stat == 0 || p.p_stat == SZOMB) continue; #ifdef sun u = kvm_getu(kd, &p); #else u = getuser(&p); #endif if ( u == (struct user *)NULL) continue; if (debug) (void) printf("pid %d uid %d cmd %s\n", p.p_pid, p.p_uid, u->u_comm); if (!n_opt) { i = getinode(u->u_rdir, "rdir"); if (check(&s, i)) { dirinode = s.st_ino; gotone(u, &p, -1, RDIR); findf++; } i = getinode(u->u_cdir, "cdir"); if (check(&s, i)) { dirinode = s.st_ino; gotone(u, &p, -1, CDIR); findf++; } } #ifdef pyr if (u->u_fdheap) { fdspace = sizeof(caddr_t) * u->u_rlimit[RLIMIT_FDMAX].rlim_cur; fd_array = (struct file **)malloc(fdspace); eseek(kmem, (ls_t)u->u_ofile, 0, "u_ofile"); eread(kmem, (char *)fd_array, fdspace, "u_ofile"); } else fd_array = u->u_ofile_arr; for (filen = 0; filen < u->u_maxofile; filen++) #else #ifdef DYNIX for (filen = 0; filen < u->u_nofile; filen++) #else for (filen = 0; filen < NOFILE; filen++) #endif #endif { struct file f; flags = 0; if (n_opt) { #ifdef DYNIX if (u->u_lofile[filen].of_file != fp) #else #ifdef pyr if (fd_array[filen] != fp) #else if (u->u_ofile[filen] != fp) #endif pyr #endif continue; } else { #ifdef DYNIX if (u->u_lofile[filen].of_file == NULL) continue; #else #ifdef pyr if (fd_array[filen] == NULL) continue; #else if (u->u_ofile[filen] == NULL) continue; #endif /* pyr */ #endif } if (k_opt) #ifdef DYNIX eseek(kmem, vtophys((ls_t)u->u_lofile[filen].of_file), 0, "file"); #else eseek(kmem, vtophys((ls_t)u->u_ofile[filen]), 0, "file"); #endif else #ifdef DYNIX eseek(kmem, (ls_t)u->u_lofile[filen].of_file, 0, "file"); #else #ifdef pyr eseek(kmem, (ls_t)fd_array[filen], 0, "file"); #else eseek(kmem, (ls_t)u->u_ofile[filen], 0, "file"); #endif /* pyr */ #endif eread(kmem, (char *)&f, sizeof(f), "file"); if (f.f_count > 0) { if (n_opt && f.f_type == DTYPE_SOCKET) { gotone(u, &p, filen, SOCKET); findf++; continue; } #if defined(DTYPE_VNODE) if (f.f_type != DTYPE_VNODE) #else if (f.f_type != DTYPE_INODE) #endif continue; #if defined(DTYPE_VNODE) i = getinode((struct vnode *)f.f_data, "ofile"); #else #ifdef ultrix i = getinode((struct gnode *)f.f_data, "ofile"); #else i = getinode((struct inode *)f.f_data, "ofile"); #endif #endif if (check(&s, i)) { #if !defined(ultrix) opninode = i->i_number; #else opninode = (int)i->g_req.gr_number; #endif flags |= OFILE; if (f.f_flag & FEXLOCK) { flags |= EXFILE; } if (f.f_flag & FSHLOCK) { flags |= SHFILE; } gotone(u, &p, filen, flags); findf++; } } } #ifdef pyr if (u->u_fdheap) free(fd_array); #endif } if (findf) nmct--; if (! pids_only) { (void) printf("\n"); (void) fflush(stdout); } } if (pids_only && ppid != -1) { (void) printf("\n"); (void) fflush(stdout); } exitval = (err || nmct) ? 1 : 0; exit(exitval); } /* * print the name of the user owning process "p" and the pid of that process */ gotone(u, p, fd, f) struct user *u; struct proc *p; int fd; int f; { char *ty, tybuf[8], *strcat(), *strcpy(); struct passwd *getpwuid(); register struct passwd *pw; /* only print pids and return */ if (pids_only) { if (ppid != p->p_pid) { if (ppid != -1) (void) printf(" "); (void) printf("%d", p->p_pid); (void) fflush(stdout); ppid = p->p_pid; } return; } pw = getpwuid((int)p->p_uid); if (pw) (void) printf("%-8.8s ", pw->pw_name ); else (void) printf("%-8d ", p->p_uid); (void) printf("%5d ", p->p_pid); if (f & OFILE) { (void) strcpy(tybuf, "file"); ty = tybuf; if (f & SHFILE) (void) strcat(ty, "/s"); else if (f & EXFILE) (void) strcat(ty, "/x"); } else if (f & CDIR) ty = "cwd"; else if (f & RDIR) ty = "rdir"; else if (f & SOCKET) ty = "sock"; else ty = ""; (void) printf("%-6.6s ", ty); if (fd >= 0) (void) printf("%2d ", fd); else (void) printf(" "); (void) printf("%-14.14s", u->u_comm); if (f & OFILE) (void) printf(" %5d", opninode); else if (f & (CDIR|RDIR)) (void) printf(" %5d", dirinode); (void) printf("\n"); return; } /* * is inode "i" on device "s"? returns TRUE or FALSE */ check(s, i) struct stat *s; #ifdef ultrix struct gnode *i; #else struct inode *i; #endif { if (s == (struct stat *)NULL) return 0; #ifdef ultrix if (i == (struct gnode *)NULL) return 0; if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->g_dev) return 1; else if ((s->st_dev == i->g_dev) && (s->st_ino == i->g_req.gr_number)) return 1; #else if (i == (struct inode *)NULL) return 0; if ((s->st_mode & S_IFMT) == S_IFBLK && s->st_rdev == i->i_dev) return 1; else if ((s->st_dev == i->i_dev) && (s->st_ino == i->i_number)) return 1; #endif #ifdef sun else if (s->st_rdev == i->i_dev && i->i_number == 0) return 1; #endif else return 0; } /* * getinode - read an inode from from mem at address "addr" * return pointer to inode struct. */ #if defined(DTYPE_VNODE) struct inode * getinode(ip, s) struct vnode *ip; char *s; { static struct inode i; static struct vnode v; #if defined(sun) || defined(pyr) struct snode sn; #endif if (ip == NULL) return(NULL); if (k_opt) eseek(kmem, vtophys((ls_t)ip), 0, "vnode"); else eseek(kmem, (ls_t)ip, 0, "vnode"); eread(kmem, (char *)&v, sizeof(v), "vnode"); if (debug) (void) printf("vnode %s at %x %x dev=%x vtype=%d inode@%x\n", s, ip, v.v_flag, v.v_rdev, v.v_type, v.v_data); if (k_opt) eseek(kmem, vtophys((ls_t)v.v_data), 0, "inode"); else eseek(kmem, (ls_t)v.v_data, 0, "inode"); #if defined(sun) || defined(pyr) #ifdef pyr if (v.v_type == VBLK || v.v_type == VCHR) #else if (v.v_type == VBLK || v.v_type == VCHR || v.v_type == VFIFO) #endif { eread(kmem, (char *)&sn, sizeof(sn), "snode"); if (debug) (void) printf( "snode %s at %x %x dev=%x realvp=%x bdevvp=%x\n", s, ip, sn.s_vnode.v_type, sn.s_dev, sn.s_realvp, sn.s_bdevvp); if (sn.s_realvp || sn.s_bdevvp) { eseek(kmem, (sn.s_realvp) ? (ls_t)sn.s_realvp : (ls_t)sn.s_bdevvp, 0, "rvnode"); eread(kmem, (char *)&v, sizeof(v), "rvnode"); eseek(kmem, (ls_t)v.v_data, 0, "rinode"); } } #endif eread(kmem, (char *)&i, sizeof(i), "inode"); if (debug) (void) printf("inode %s at %x %x dev=%x inode=%d vtype=%x\n", s, v.v_data, i.i_flag, i.i_dev, i.i_number, i.i_vnode.v_type); return &i; } #else /* ARGSUSED */ #ifdef ultrix struct gnode * getinode(ip, s) struct gnode *ip; #else struct inode * getinode(ip, s) struct inode *ip; #endif char *s; { #if defined(ultrix) static struct gnode i; #else static struct inode i; #endif eseek(kmem, (ls_t)ip, 0, "inode"); eread(kmem, (char *)&i, sizeof(i), "inode"); return &i; } #endif #if !defined(sun) /* * get user page for proc "p" from core or swap * return pointer to user struct */ #ifdef DYNIX struct user * getuser(p) struct proc *p; { int btr; ls_t sp; static struct user *u = NULL; char *valloc(); if (u == NULL) { if ((u = (struct user *) valloc(ctob(UPAGES))) == NULL) { (void) fprintf(stderr, "%s: can't allocate space for user structure\n", progname); exit(1); } } btr = ctob(UPAGES); if ((p->p_flag & SLOAD) == 0) { if (k_opt) return (struct user *)NULL; sp = (ls_t) dtob(p->p_swaddr); if (lseek(swap, sp, 0) != sp) { if (debug) { (void) fprintf(stderr, "%s: error seeking to swap for %d: ", progname, p->p_pid); perror(""); } return (struct user *)NULL; } if (read(swap, (char*)u, btr) != btr) { if (debug) { (void) fprintf(stderr, "%s: error reading swap for %d: ", progname, p->p_pid); perror(""); } return (struct user *)NULL; } if (debug) (void) printf("read swap\n"); } else { if (k_opt) (void) lseek(kmem, vtophys((ls_t)p->p_uarea), L_SET); else (void) lseek(kmem, (ls_t)p->p_uarea, L_SET); if (read(kmem, (char *)u, btr) != btr) return (struct user *)NULL; } return u; } #else #ifdef pyr struct user * getuser(p) struct proc *p; { static struct user *u = NULL; char *valloc(); if (u == NULL) { if ((u = (struct user *) valloc(ptob(UPAGES))) == NULL) { (void) fprintf(stderr, "%s: can't allocate space for user structure\n", progname); exit(1); } } if (readublk(p->p_pid, u) == -1) return (struct user *)NULL; else return u; } #else struct user * getuser(p) struct proc *p; { struct pte *ptep, apte; struct pte mypgtbl[NBPG/sizeof(struct pte)]; int upage; char *up; static struct user user; /* easy way */ if ((p->p_flag & SLOAD) == 0) { if (k_opt) return (struct user *)NULL; (void) lseek(swap, (ls_t)dtob(p->p_swaddr), 0); if (read(swap, (char *)&user, sizeof(struct user))==0) { (void) fprintf(stderr, "%s: can't get swapped user page\n", progname); return (struct user *)NULL; } if (debug) (void) printf("read swap\n"); } else { /* boo */ ptep = &Usrptma[btokmx(p->p_p0br) + p->p_szpt - 1]; /* get the page table for the user page */ (void) lseek(kmem, (ls_t)ptep, 0); if (read(kmem, (char *)&apte, sizeof(apte)) == 0) { (void) fprintf(stderr, "%s: can't get user page table\n", progname); return (struct user *)NULL; } /* now get this user's page table */ eseek(mem, (ls_t)ctob(apte.pg_pfnum) ,0, "page tbl"); if (read(mem, (char *)mypgtbl, sizeof(mypgtbl)) == 0) { (void) fprintf(stderr, "%s: can't get mypgtbl.\n", progname); return (struct user *)NULL; } /* now collect various pages of u area */ for (upage = 0, up = (char *)&user; upage < sizeof(struct user)/NBPG; upage++) { eseek(mem, (ls_t)ctob(mypgtbl[NPTEPG-UPAGES+upage].pg_pfnum), 0, "u page"); if (read(mem, up, NBPG) == 0) { (void) fprintf(stderr, "%s: can't get page %d of user area.\n", progname, upage); return(NULL); } up += NBPG; } } return &user; } #endif /* pyr */ #endif #endif /* * read with error checking */ void eread(fd, p, size, s) int fd; char *p; int size; char *s; { char buf[100]; if (read(fd, p, size) != size) { if (!k_opt) { (void) fprintf(stderr, "%s: eread ", progname); perror(""); } (void) sprintf(buf, "read error for %s\n", s); error(buf); } } /* * seek with error checking */ void eseek(fd, off, whence, s) int fd; ls_t off; int whence; char *s; { ls_t ret; char buf[100]; #ifdef pyr if (( ret = lseek(fd, off, whence)) == -1) #else if (( ret = lseek(fd, off, whence)) != off) #endif { (void) sprintf(buf, "seek for %s failed, wanted %o, got %o.\n", s, off, ret); error(buf); } } /* * print mesg "s", don't exit if we are processing a core, * so that corrupt entries don't prevent further uncorrupted * entries from showing up. */ error(s) char *s; { if (s && !k_opt) (void) fprintf(stderr, "%s: %s", progname, s); if (!k_opt) exit(1); } /* * get some symbols form the kernel */ getsyms() { register i; if (k_opt) { #ifdef ultrix (void) nlist(namelist, nl); #else /* not ultrix */ if (nlist(namelist, nl) == -1) { (void) fprintf(stderr, "%s: can't get name list from %s\n", progname, namelist); exit(1); } #endif /* ultrix */ } else { #ifdef ultrix (void) nlist("/vmunix", nl); #else /* not ultrix */ #ifdef DYNIX if (nlist("/dynix", nl) == -1) #else /* not DYNIX */ if (nlist("/vmunix", nl) == -1) #endif /* DYNIX */ { (void) fprintf(stderr, "%s: can't get name list from %s\n", #ifdef DYNIX progname, "/dynix"); #else /* not DYNIX */ progname, "/vmunix"); #endif /* DYNIX */ exit(1); } #endif /* ultrix */ } for (i = 0; i < (sizeof(nl)/sizeof(nl[0]))-1; i++) if (nl[i].n_value == 0) { (void) fprintf(stderr, "%s: can't nlist symbol %s\n", progname, nl[i].n_name); exit(1); } eseek(kmem, (ls_t)(nl[X_PROC].n_value), 0, "procbase 1"); eread(kmem, (char *)&procbase, sizeof(procbase), "procbase 1"); eseek(kmem, (ls_t)(nl[X_NPROC].n_value), 0, "nproc"); eread(kmem, (char *)&nproc, sizeof(nproc), "nproc"); #ifndef DYNIX Usrptma = (struct pte *)nl[X_USRPTMA].n_value; usrpt = (struct pte *)nl[X_USRPT].n_value; /* used by <vmmac.h>*/ #endif return; } /* * read proc table entry "n" into buffer "p" */ procslot(n, p) int n; struct proc *p; { if (k_opt) eseek(kmem, vtophys((ls_t)(procbase + (long)(n * sizeof(struct proc)))), 0, "proc"); else eseek(kmem, (ls_t)(procbase + (long)(n * sizeof(struct proc))), 0, "proc"); eread(kmem, (char *)p, sizeof(struct proc), "proc"); return; } /* * When looking at kernel data space through /dev/mem or * with a core file, do virtual memory mapping. */ ls_t vtophys(vaddr) ls_t vaddr; { u_int paddr; #ifdef i386 if (vaddr < 8192) return vaddr; #endif paddr = nl[X_SYSMAP].n_value; (void) lseek(kmem, (ls_t)paddr, 0); (void) read(kmem, (char *)&paddr, sizeof paddr); paddr = (int)((int *)paddr + (vaddr / NBPG)); (void) lseek(kmem, (ls_t)paddr, 0); (void) read(kmem, (char *)&paddr, sizeof paddr); #ifndef i386 # define PTBITS 0x1ff /* 512 byte pages */ #else # define PTBITS 0xfff /* 4096 byte pages */ #endif return ((ls_t)(paddr & ~PTBITS) | (vaddr & PTBITS)); } /* * get file pointer for socket */ char * getsockfp(cba, pfp) char *cba; struct file **pfp; { register char *cp; struct file *socktofile(); struct inpcb inpcb; static char nmbuf[128]; struct socket sock; struct tcpcb tcpcb; long x; /* * Convert PCB address from ASCII to hex. */ for (cp = cba, x = 0l; *cp; cp++) { x <<= 4; if (*cp >= '0' && *cp <= '9') x += *cp - '0'; else if (*cp >= 'a' && *cp <= 'f') x += *cp - 'a' + 10; else if (*cp >= 'A' && *cp <= 'F') x += *cp - 'A' + 10; else { (void) fprintf(stderr, "%s: non-hex address, %s\n", progname, cba); return(NULL); } } /* * Read PCB and make sure it is in LISTEN or ESTABLISHED state. */ eseek(kmem, (ls_t)x, 0, "tcpcb"); eread(kmem, (char *)&tcpcb, sizeof(tcpcb), "tcpcb"); if (tcpcb.t_state < TCPS_LISTEN || tcpcb.t_state > TCPS_ESTABLISHED) { (void) fprintf(stderr, "%s: PCB %x not in LISTEN to ESTABLISHED state\n", progname, x); return(NULL); } if (tcpcb.t_inpcb == (struct inpcb *)0) { (void) fprintf(stderr, "%s: PCB %x has no INPCB\n", progname, x); return(NULL); } /* * Read INPCB for PCB and make sure it points back to the PCB. */ eseek(kmem, (ls_t)tcpcb.t_inpcb, 0, "inpcb"); eread(kmem, (char *)&inpcb, sizeof(inpcb), "inpcb"); if ((caddr_t)x != inpcb.inp_ppcb) { (void) fprintf(stderr, "%s: INPCB for PCB %x not linked to it\n", progname, x); return(NULL); } /* * Read the socket and make sure it points back to the INPCB. */ eseek(kmem, (ls_t)inpcb.inp_socket, 0, "socket"); eread(kmem, (char *)&sock, sizeof(sock), "socket"); if (sock.so_pcb != (caddr_t)tcpcb.t_inpcb) { (void) fprintf(stderr, "%s: socket not linked to INPCB for PCB %x\n", progname, x); return(NULL); } /* * Find the file structure that is linked to the socket. */ if ((*pfp = socktofile((caddr_t)inpcb.inp_socket)) == NULL) { (void) fprintf(stderr, "%s: no file structure for socket of PCB %x\n", progname, x); return(NULL); } /* * Construct a pseudo file name and return it. */ (void) sprintf(nmbuf, "file %lx of socket %lx of INPCB %lx of PCB %lx", (long)*pfp, (long)inpcb.inp_socket, (long)tcpcb.t_inpcb, x); return(nmbuf); } /* * Convert a socket address to a file address. */ struct file * socktofile(s) caddr_t s; { register struct file *afile; char *calloc(); register struct file *fp; static struct file *ftp; static int nfile = -1; static struct file *xfile = NULL; /* * Read the size of file table, allocate space * for it, and read the file table pointer (once). */ if (nfile < 0) { eseek(kmem, (ls_t)(nl[SNFILE].n_value), 0, "_nfile"); eread(kmem, (char *)&nfile, sizeof(nfile), "_nfile"); xfile = (struct file *) calloc((unsigned)nfile, sizeof (struct file)); eseek(kmem, (ls_t)(nl[SFIL].n_value), 0, "_file"); eread(kmem, (char *)&ftp, sizeof(ftp), "_file"); } /* * Read the file table and search for an in-use * socket file with a matching data address. */ eseek(kmem, (ls_t)ftp, 0, "_file"); eread(kmem, (char *)xfile, nfile * sizeof(struct file), "_file"); for (fp = xfile, afile = ftp; fp < &xfile[nfile]; fp++, afile++) { if (fp->f_count && fp->f_type == DTYPE_SOCKET && s == fp->f_data) return(afile); } return(NULL); }