home *** CD-ROM | disk | FTP | other *** search
- /*
- ** kernel/sco324.c Kernel access functions to retrieve user number
- **
- ** This program is in the public domain and may be used freely by anyone
- ** who wants to.
- **
- ** Last update: 17 March 1993
- **
- ** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
- **
- ** fast COFF nlist() code written by Peter Wemm <peter@DIALix.oz.au>
- ** This is up to 100 times faster than 3.2v1.0 to 3.2v4.1's nlist().
- ** This is slightly faster than the 3.2v4.2 nlist().
- **
- ** Preliminary SCO support by Peter Wemm <peter@DIALix.oz.au>
- ** Known Limitations:
- ** 1: Can only get *effective* UID of a socket. This is a real
- ** serious problem, as it looks like all rlogins, and rcp'c
- ** come from root. Any volunteers to emulate the fuser command
- ** and grope around the kernel user structs for file pointers
- ** to get the *real* uid?
- ** 2: THIS WILL NOT (YET!) WORK WITH SCO TCP 1.2.1 and hence ODT 3.0
- */
-
- #include <stdio.h>
-
- #include <filehdr.h>
- #include <syms.h>
-
- /* Name space collision */
- #undef n_name
-
- #include <nlist.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <malloc.h>
- #include <string.h>
-
- /* how much buffer space to allocate to the symbol scanning */
- /* Make this at least 4096, but much more than 8192 is a waste */
- #define CHUNKSIZE 8192
-
- int nlist(const char *filename, struct nlist *nl)
- {
- FILHDR fh; /* COFF file header */
- SYMENT *se; /* pointer to a SYMENT */
-
- int i, n; /* iterative variables */
-
- long strsect; /* seek pos of extended string table */
- long strsize; /* byte size of extended string table*/
-
- int mchunk; /* max number of syments per chunk */
- int p; /* Symbol entry cache */
- int slotnum; /* Symbol entry cache */
- int chunknum; /* Symbol entry cache */
- int oldchunknum; /* Symbol entry cache */
-
- char *strtab = NULL; /* malloc'ed extended string table buffer */
- char *symchunk = NULL; /* malloc'ed SYMENT symbol entry cache */
-
- int fd = -1; /* File descriptor we are dealing with */
-
- int nument = 0; /* How many symbols in the array */
- int numremaining; /* Counter for symbols not found yet */
- struct nlist *nptr; /* Pointer to current struct nlist entry */
-
- /* a check from sanity claus */
- if (filename == NULL || nl == NULL)
- goto cleanup;
-
- /* count the entries in the request table */
- nptr = nl;
- while (nptr->n_name && strlen(nptr->n_name) > 0) {
- /* clear out the values as per the man-page */
- nptr->n_value = 0;
- nptr->n_scnum = 0;
- nptr->n_type = 0;
- nptr->n_sclass = 0;
- nptr->n_numaux = 0;
- nptr++;
- nument++;
- }
-
- /* early exit if nothing wanted.. return success */
- if (nument == 0)
- return 0;
-
- /* no point scanning whole list if we've found'em all */
- numremaining = nument;
-
- /* open the COFF file */
- fd = open(filename, O_RDONLY, 0);
-
- if (fd < 0)
- goto cleanup;
-
- /* read the COFF file header */
- if (read(fd, &fh, FILHSZ) < FILHSZ)
- goto cleanup;
-
- /* calcualte the starting offset of the string table */
- strsect = fh.f_symptr + (fh.f_nsyms * SYMESZ);
-
- /* read the length of the string table */
- if (lseek(fd, strsect, SEEK_SET) < 0)
- goto cleanup;
- if (read(fd, &strsize, sizeof(strsize)) < sizeof(strsize))
- goto cleanup;
-
- /* allocate a buffer for the string table */
- strtab = malloc(strsize);
- if (strtab == NULL)
- goto cleanup;
-
- /* allocate a buffer for the string table */
- mchunk = CHUNKSIZE / SYMESZ;
- symchunk = malloc(mchunk * SYMESZ);
- if (symchunk == NULL)
- goto cleanup;
-
- /* read the string table */
- if (lseek(fd, strsect, SEEK_SET) < 0)
- goto cleanup;
- if (read(fd, strtab, strsize) < strsize)
- goto cleanup;
-
- /* step through the symbol table */
- if (lseek(fd, fh.f_symptr, SEEK_SET) < 0)
- goto cleanup;
-
- oldchunknum = -1;
- p = 0; /* symbol slot number */
- for (i = 0; i < fh.f_nsyms; i++) {
-
- /* which "chunk" of the symbol table we want */
- chunknum = p / mchunk;
-
- /* Where in the chunk is the SYMENT we are up to? */
- slotnum = p % mchunk;
-
- /* load the chunk buffer if needed */
- if (chunknum != oldchunknum) {
- if (read(fd, symchunk, mchunk * SYMESZ) <= 0)
- goto cleanup;
- oldchunknum = chunknum;
- }
-
- /* and of course.. Get a pointer.. */
- se = (SYMENT *) (symchunk + slotnum * SYMESZ);
-
- /* next entry */
- p++;
-
- /* is it a long string? */
- if (se->n_zeroes == 0) {
-
- /* check table */
- for (n = 0; n < nument; n++) {
- if (strcmp(strtab + se->n_offset, nl[n].n_name) == 0) {
- /* load the requested table */
- nl[n].n_value = se->n_value;
- nl[n].n_scnum = se->n_scnum;
- nl[n].n_type = se->n_type;
- nl[n].n_sclass = se->n_sclass;
- nl[n].n_numaux = se->n_numaux;
- numremaining--;
- break;
- }
- }
- if (numremaining == 0)
- break; /* drop the for loop */
-
- } else {
-
- /* check table */
- for (n = 0; n < nument; n++) {
-
- if (strncmp(se->_n._n_name, nl[n].n_name, sizeof(se->_n._n_name)) == 0) {
- /* since we stopped at the 8th char, make sure that's all we want */
- if ((int)strlen(nl[n].n_name) <= 8) {
- /* load the requested table */
- nl[n].n_value = se->n_value;
- nl[n].n_scnum = se->n_scnum;
- nl[n].n_type = se->n_type;
- nl[n].n_sclass = se->n_sclass;
- nl[n].n_numaux = se->n_numaux;
- numremaining--;
- break;
- }
- }
- }
- if (numremaining == 0)
- break; /* drop the for loop */
-
- }
-
- /* does it have auxillary entries? */
- p += se->n_numaux;
-
- }
-
- free(strtab);
- free(symchunk);
- close(fd);
-
- return numremaining;
-
- cleanup:
- if (fd >= 0)
- close(fd);
- if (strtab)
- free(strtab);
- if (symchunk)
- free(symchunk);
- return -1;
-
- }
-
- #include <stdio.h>
- #include <errno.h>
- #include <ctype.h>
- #include <nlist.h>
- #include <pwd.h>
- #include <signal.h>
- #include <syslog.h>
-
- #include "kvm.h"
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include <sys/sysmacros.h>
- #include <sys/ioctl.h>
-
- #define _KERNEL
-
- #include <sys/file.h>
- #include <sys/dir.h>
-
- #include <sys/inode.h>
-
- #include <fcntl.h>
-
- #include <sys/user.h>
- #include <sys/wait.h>
-
- #include <sys/var.h>
-
- #undef _KERNEL
-
- #include <sys/socket.h>
- #include <sys/stream.h>
-
- #include <net/if.h>
- #include <net/route.h>
- #include <netinet/in.h>
-
- #include <netinet/in_systm.h>
- #include <netinet/in_pcb.h>
-
- #include <netinet/ip_var.h>
-
- #include <netinet/tcp.h>
- #include <netinet/tcpip.h>
- #include <netinet/ip_var.h>
- #include <netinet/tcp_timer.h>
- #include <netinet/tcp_var.h>
- #include <netinet/tcp_debug.h>
-
- #include <arpa/inet.h>
-
- #include <sys/net/protosw.h>
- #include <sys/net/socketvar.h>
-
- #include "identd.h"
- #include "error.h"
-
-
- extern void *calloc();
- extern void *malloc();
-
- struct nlist nl[] =
- {
- #define N_V 0
- #define N_TCB 1
-
- { "v" },
- { "tcb" },
- { "" }
- };
-
- static kvm_t *kd;
-
- static struct var v;
-
- static struct inpcb tcb;
-
-
- int k_open()
- {
- /*
- ** Open the kernel memory device
- */
- if (!(kd = kvm_open(path_unix, path_kmem, NULL, O_RDONLY, NULL)))
- ERROR("main: kvm_open");
-
- /*
- ** Extract offsets to the needed variables in the kernel
- */
- if (kvm_nlist(kd, nl) != 0)
- ERROR("main: kvm_nlist");
-
- return 0;
- }
-
-
- /*
- ** Get a piece of kernel memory with error handling.
- ** Returns 1 if call succeeded, else 0 (zero).
- */
- static int getbuf(addr, buf, len, what)
- long addr;
- char *buf;
- int len;
- char *what;
- {
- if (kvm_read(kd, addr, buf, len) < 0)
- {
- if (syslog_flag)
- syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
- addr, len, what);
-
- return 0;
- }
-
- return 1;
- }
-
-
-
- /*
- ** Traverse the inpcb list until a match is found.
- ** Returns NULL if no match.
- */
- static struct inpcb *
- getlist(pcbp, faddr, fport, laddr, lport)
- struct inpcb *pcbp;
- struct in_addr *faddr;
- int fport;
- struct in_addr *laddr;
- int lport;
- {
- struct inpcb *head;
-
- if (!pcbp)
- return NULL;
-
- head = pcbp->inp_prev;
- do
- {
- if ( pcbp->inp_faddr.s_addr == faddr->s_addr &&
- pcbp->inp_laddr.s_addr == laddr->s_addr &&
- pcbp->inp_fport == fport &&
- pcbp->inp_lport == lport )
- {
- return pcbp;
- }
-
- } while (pcbp->inp_next != head &&
- getbuf((long) pcbp->inp_next,
- pcbp,
- sizeof(struct inpcb),
- "tcblist"));
-
- return NULL;
- }
-
- static caddr_t
- followqueue(pcbp)
- struct inpcb *pcbp;
- {
- queue_t *q;
- queue_t qbuf;
- int n = 1;
-
- if (!pcbp)
- return NULL;
-
- q = pcbp->inp_q;
-
- while (getbuf((long) q, &qbuf, sizeof(qbuf), "queue_t inp_q"))
- {
- q = qbuf.q_next;
- n++;
- if (qbuf.q_next == NULL)
- return qbuf.q_ptr;
- }
-
- return NULL;
- }
-
-
- /*
- ** Return the user number for the connection owner
- */
- int k_getuid(faddr, fport, laddr, lport, uid)
- struct in_addr *faddr;
- int fport;
- struct in_addr *laddr;
- int lport;
- int *uid;
- {
- int i;
- struct inode inode;
- struct stat s;
- struct inpcb *sockp;
- caddr_t cad;
- struct socket socket;
- struct file file;
- short sockmajor;
- short sockminor;
-
-
- /* -------------------- TCP PCB LIST -------------------- */
- if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb"))
- return -1;
-
- tcb.inp_prev = (struct inpcb *) nl[N_TCB].n_value;
-
- sockp = getlist(&tcb, faddr, fport, laddr, lport);
-
- if (!sockp)
- return -1;
-
- if (sockp->inp_protoopt & SO_IMASOCKET)
- {
-
- cad = followqueue(sockp); /* socket pointer */
-
- if (!getbuf((long)cad, &socket, sizeof(struct socket), "socket"))
- return -1;
-
- if (!getbuf((long)socket.so_fp, &file, sizeof(struct file), "file"))
- return -1;
-
- if (!getbuf((long)file.f_inode, &inode, sizeof(struct inode), "inode"))
- return -1;
-
- *uid = inode.i_uid;
- return 0;
- } else {
-
- /* we just need to determine the major number of the tcp module, which
- is the minor number of the tcp clone device /dev/tcp */
- if (stat("/dev/inet/tcp", &s))
- ERROR("stat(\"/dev/inet/tcp\")");
-
- sockmajor = major(s.st_rdev);
- sockminor = sockp->inp_minor;
-
- if (!getbuf(nl[N_V].n_value, &v, sizeof(struct var), "var"))
- return -1;
-
- for (i = 0; i < v.v_inode; i++) {
-
- if (!getbuf(((long) v.ve_inode) + i * sizeof(struct inode),
- &inode, sizeof(struct inode), "inode"))
- return -1;
-
- if (((inode.i_ftype & IFMT) == IFCHR) &&
- (major(inode.i_rdev) == sockmajor) &&
- (minor(inode.i_rdev) == sockminor))
- {
- *uid = inode.i_uid;
- return 0;
- }
- }
- return -1;
- }
- }
-
-
-