/*
* Query lsof for open TCP connections. Assumes lsof, awk, sort, and uniq
# are accessible via the current path.
*
* $Id: lsof.c,v 1.6 1996/11/21 02:02:00 jdd Exp $
*/
#include <stdio.h>
#ifdef LSOF
#include <stdlib.h>
#include <pwd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "tcplist.h"
#include "utils.h"
#ifndef LSOFCMD
#ifdef OLDLSOF
/* Older versions of lsof use -H instead of -n */
#define LSOFCMD "lsof -HPsli TCP | awk '{print $3,$NF}' | sort | uniq"
#else /* !OLDLSOF */
/* These use the current (as of 3.62W, at least) parameters for lsof */
#define LSOFCMD "lsof -nPsli TCP | awk '{print $3,$(NF - 1)}' | sort | uniq"
#endif /* !OLDLSOF */
#endif /* LSOFCMD */
#ifndef WHITESPACE
#define WHITESPACE " \t\n"
#endif /* WHITESPACE */
struct hostlist *make_hostlist(localaddr, servershow)
u_long *localaddr;
int servershow;
{
FILE *fp;
char buff[BUFSIZ], *cp;
int i, lport, fport, uid;
u_long laddr, faddr;
struct passwd *pw;
struct hostlist *hlist = NUL(struct hostlist *);
buff[sizeof(buff)-1]='\0'; /* make sure we have null termination */
#ifndef INSECURE
(void)setuid(getuid()); /* just in case installed setuid/setgrpid */
#endif /* ndef INSECURE */
signal(SIGPIPE, SIG_IGN);
if(NULL==(fp=popen(LSOFCMD, "r"))){
Error("Can't run lsof. Check your $PATH.");
}
/* grab and throw away initial header */
if(NULL==fgets(buff, sizeof(buff)-1,fp)){
Error("Can't get lsof output header");
}
while(NULL!=fgets(buff,sizeof(buff)-1,fp)){
struct connection *cn;
struct hostlist *hl;
int found;
buff[strlen(buff)-1]='\0'; /* strip trailing newline */
#ifdef DEBUG
dfprintf(3, stderr, ">> %s\n", buff);
#endif /* DEBUG */
/* get uid */
if(NULL==(cp=strtok(buff, WHITESPACE))) continue;
uid=atoi(cp);
if(0==uid && '0'!=*cp) continue;
/* we split the next field as follows: */
/* Syntax: sourceaddr:lport->destaddr:destport */
/* or: *:lport */
/* or: sourceaddr->destaddr:destport */
if(NULL==(cp=strtok(NULL, WHITESPACE))) continue;
if('*'==*cp){
/* *:lport case */
if(!servershow) continue;
laddr=*localaddr;
/* source port */
lport=atoi(cp+2);
if(0==lport) continue;
faddr=INADDR_ANY;
fport=PORT_ANY;
} else {
char *p1, *p2;
/* split field into local and remote halves */
if(NULL==(p1=strtok(cp, "->"))) continue;
if(NULL==(p2=strtok(NULL, "->"))) continue;
/* split halves */
if(NULL==(cp=strtok(p1, ":"))) continue;
laddr=inet_addr(cp);
#ifdef DEBUG
dfprintf(5, stderr, "Local address is %s\n", cp);
#endif /* DEBUG */
cp=strtok(NULL, ":");
if(NULL==cp) {
lport=PORT_ANY;
} else {
lport=atoi(cp);
}
#ifdef DEBUG
dfprintf(5, stderr, "Local port is %u\n", lport);
#endif /* DEBUG */
/* split halves */
if(NULL==(cp=strtok(p2, ":"))) continue;
faddr=inet_addr(cp);
#ifdef DEBUG
dfprintf(5, stderr, "Foreign address is %s\n", cp);
#endif /* DEBUG */
cp=strtok(NULL, ":");
if(NULL==cp) {
fport=PORT_ANY;
} else {
fport=atoi(cp);
}
#ifdef DEBUG
dfprintf(5, stderr, "Foreign port is %u\n", lport);
#endif /* DEBUG */
}
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(faddr == hl->addr){
/* found it */
found = TRUE;
break;
}
}
if(!found){
/* create new hostlist entry */
hl=new(struct hostlist);
hl->addr = faddr;
*localaddr = laddr;
hl->conn = NUL(struct connection *);
hl->next = hlist;
hlist = hl;
}
/* create new connection entry */
cn=new(struct connection);
cn->remote=fport;
cn->local=lport;
cn->user=s(pw->pw_name);
cn->next=hl->conn;
hl->conn=cn;
}
(void)fclose(fp);
return(hlist);
}
#endif /* LSOF */
syntax highlighted by Code2HTML, v. 0.9.1