/* 
 * Suns running SunOS 4.x
 *
 * $Id: sunos4.c,v 1.2 1995/08/21 23:03:18 jdd Exp $
 */

#include <stdio.h>

#ifdef SUNOS4 

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/domain.h> 
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <kvm.h>
#include <nlist.h>
#include <fcntl.h>
#include <pwd.h>
#include <sys/protosw.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>

#define KERNEL
#include <sys/file.h>
#include <sys/user.h>
#undef KERNEL

#include "tcplist.h"
#include "utils.h"


struct nlist nl[] = {
#define N_FILE 0
        { "_file" },
#define N_NFILE 1
        { "_nfile" },
        { "" },
};

struct hostlist *make_hostlist(localaddr, servershow)
u_long *localaddr;
int servershow;
{
	kvm_t *kd;
	int nfiles, i;
	u_long addr;
	struct hostlist *hlist = NUL(struct hostlist *);
	struct file *filetable;
	char *localhost = NULL;

	if(NULL==(kd=kvm_open(NULL, NULL, NULL, O_RDONLY, progname))){
		Error("kvm_open");
	}
	if(0!=kvm_nlist(kd, nl)){
		Error("kvm_nlist: %d", kvm_nlist(kd, nl));
	}
	getkvm(kd, nl[N_NFILE].n_value, &nfiles, sizeof(nfiles));
	getkvm(kd, nl[N_FILE].n_value, &addr, sizeof(addr));
	filetable=(struct file *)calloc(nfiles, sizeof(struct file));
	if(NULL==filetable){
		Error("Can't allocate memory for file table.");
	}
	getkvm(kd, addr, filetable, nfiles * sizeof(struct file));
	for(i=0;i<nfiles;i++){
		struct socket so, *sp;
		struct protosw ps;
		struct domain dom;
		struct inpcb pcb;
		struct ucred cred;
		struct passwd *pw;
		struct connection *cn;
		struct hostlist *hl;
		int found;

		sp=&so;
		if(filetable[i].f_type == DTYPE_SOCKET &&
		   0!=filetable[i].f_count){
			int uid;

			/* grab the socket out of the kernel. Is it
			 * a stream socket? If not, go on. */
			getkvm(kd, filetable[i].f_data, sp, 
				sizeof(struct socket));
			if(sp->so_type!=SOCK_STREAM) continue;
			/* now get the protosw. */
			getkvm(kd, sp->so_proto, &ps, sizeof(ps));
			/* ... and its domain. go on if not internet. */
			getkvm(kd, ps.pr_domain, &dom, sizeof(dom));
			if(dom.dom_family!=AF_INET) continue;
			/* If we've gotten this far, it's a tcp socket. Let's 
			 * get the protocol control block... */
			if(0==sp->so_pcb) continue;
			getkvm(kd, sp->so_pcb, &pcb, sizeof(pcb));
			/* (but if foreign addr is ANY, this is a server, so
			 *  if we don't want servers, stop here.) */
			if(!servershow){
				if(INADDR_ANY == pcb.inp_faddr.s_addr) continue;
			}
			/* ...and the user id */
			getkvm(kd, filetable[i].f_cred, &cred, sizeof(cred));
			uid=cred.cr_ruid;
			pw=getpwuid(uid);
			if(NULL==pw){
				pw=new(struct passwd);
				pw->pw_name=mem(10); 
				sprintf(pw->pw_name, "#%d", uid);
				pw->pw_uid=uid;
			}
#ifdef DEBUG
			dfprintf(3, stderr, "user id is %d and user is %s\n", 
				 uid, pw->pw_name);
#endif /* DEBUG */

			/* is this host already on the hostlist? */
			found = FALSE;
			for(hl=hlist;NULL!=hl;hl=hl->next){
				if(pcb.inp_faddr.s_addr == hl->addr){
					/* found it */
					found = TRUE; 
					break;
				}
			}
			if(!found){
				/* create new hostlist entry */
				hl=new(struct hostlist);
				hl->addr = pcb.inp_faddr.s_addr;
				*localaddr = pcb.inp_laddr.s_addr;
				hl->conn = NUL(struct connection *);
				hl->next = hlist;
				hlist = hl;
			}
			/* create new connection entry */
			cn=new(struct connection);
			cn->remote=pcb.inp_fport;
			cn->local=pcb.inp_lport;
			cn->user=s(pw->pw_name);
			cn->next=hl->conn;
			hl->conn=cn;
		}
	}
	return(hlist);
}

#endif /* SUNOS4 */


syntax highlighted by Code2HTML, v. 0.9.1