/************************************************************************* * * Copyright (c) 1999 Cornell University * Computer Systems Laboratory * Cornell University, Ithaca, NY 14853 * All Rights Reserved * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies. Cornell University makes no representations * about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. Export of this * software outside of the United States of America may require an * export license. * * $Id$ * ************************************************************************** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define KERNEL #include #include #include #undef KERNEL #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct kinfo_proc *p, *plast; static kvm_t *kd; static int cnt; /* *------------------------------------------------------------------------ * * Initialize kvm structures, if necessary * * Returns: * Side effects: * *------------------------------------------------------------------------ */ void initialize_kernel (void) { char buf[_POSIX2_LINE_MAX]; if ((kd = kvm_open (NULL, NULL, NULL, O_RDONLY, buf)) == NULL) { errx (1, "%s", buf); } } static struct file **ofiles = NULL;/* buffer of pointers to file structures */ static int maxfiles = 0; #define ALLOC_OFILES(d) \ if ((d) > maxfiles) { \ if (ofiles) free(ofiles); \ ofiles = malloc((d) * sizeof(struct file *)); \ if (ofiles == NULL) { \ err(1, NULL); \ } \ maxfiles = (d); \ } /* *------------------------------------------------------------------------ * * Determine user id of the person who owns the particular port * * Returns: uid owning port "query_port" * Side effects: none * *------------------------------------------------------------------------ */ long gather_proc_info (int query_port) { struct filedesc0 filed0; struct proc *gp; struct eproc *ep; struct kinfo_proc *kp; long pid; int uid; int i; struct file file; if ((p = kvm_getprocs(kd, KERN_PROC_ALL, 0, &cnt)) == NULL) errx(1, "%s", kvm_geterr(kd)); #define KVM_READ(kaddr, paddr, len) \ (kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (len)) #define FPSIZE (sizeof (struct file *)) #define filed filed0.fd_fd kp = p; for (plast = &p[cnt]; kp < plast; kp++) { gp = &kp->kp_proc; ep = &kp->kp_eproc; pid = gp->p_pid; uid = ep->e_ucred.cr_uid; if (gp->p_stat == SZOMB) continue; if (gp->p_fd == NULL) continue; if (!KVM_READ(gp->p_fd, &filed0, sizeof(filed0))) { fprintf (stderr, "can't read filedesc at %p (pid=%d)\n", (void*)gp->p_fd, pid); continue; } ALLOC_OFILES(filed.fd_lastfile+1); if (filed.fd_nfiles > NDFILE) { if (!KVM_READ (filed.fd_ofiles, ofiles, (filed.fd_lastfile+1) * FPSIZE)) { fprintf (stderr, "can't read file structures at %p (pid=%d)\n", (void*)filed.fd_ofiles, pid); return; } } else { bcopy (filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE); } for (i=0; i <= filed.fd_lastfile; i++) { if (ofiles[i] == NULL) continue; if (!KVM_READ (ofiles[i], &file, sizeof (struct file))) { fprintf (stderr, "can't read file %d at %p (pid=%d)\n", i, (void*)ofiles[i], pid); continue; } if (file.f_type == DTYPE_SOCKET) { struct socket *sock = (struct socket *)file.f_data; struct socket so; struct domain dom; struct protosw proto; struct inpcb inpcb; if (!KVM_READ (sock, &so, sizeof(struct socket))) { fprintf (stderr, "can't read sock at %p\n", (void*)sock); continue; } if (!KVM_READ (so.so_proto, &proto, sizeof (struct protosw))) { fprintf (stderr, "can't read protosw at %p\n", (void*)so.so_proto); continue; } if (!KVM_READ (proto.pr_domain, &dom, sizeof (struct domain))) { fprintf (stderr, "can't read domain at %p\n", (void*)proto.pr_domain); continue; } if (dom.dom_family != AF_INET) /* not ip */ continue; if (proto.pr_protocol != IPPROTO_TCP) /* not tcp */ continue; if (!KVM_READ (so.so_pcb, &inpcb, sizeof (struct inpcb))) { fprintf (stderr, "can't read inpcb at %p\n", so.so_pcb); continue; } if (query_port == htons(inpcb.inp_lport)) { return uid; } } } } return -1; }