#ifndef lint
static char copyright[] =
"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
#endif
#include "LsofTest.h"
#include "lsof_fields.h"
#include <netdb.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SIGHANDLER_T void
#define LT_SOCKLEN_T int
#if defined(LT_DIAL_aix)
#undef LT_SOCKLEN_T
#define LT_SOCKLEN_T size_t
#endif
#if defined(LT_DIAL_darwin)
# if LT_VERS>=800
#undef LT_SOCKLEN_T
#define LT_SOCKLEN_T socklen_t
# endif
#endif
#if defined(LT_DIAL_hpux)
# if LT_VERS>=1123 && defined(__GNUC__)
#undef LT_SOCKLEN_T
#define LT_SOCKLEN_T size_t
# endif
#endif
#if defined(LT_DIAL_ou)
#undef LT_SOCKLEN_T
#define LT_SOCKLEN_T size_t
#endif
#if defined(LT_DIAL_uw)
#undef LT_SOCKLEN_T
#define LT_SOCKLEN_T size_t
#endif
#define ALARMTM 30
#define LT_CLNT 0
#define LT_SRVR 1
#define LT_FNF 0
#define LT_FBYIP 1
#define LT_FBYHN 2
#define LT_FBYPORT 4
#if !defined(MAXHOSTNAMELEN)
#define MAXHOSTNAMELEN 256
#endif
#if !defined(MAXPATHLEN)
#define MAXPATHLEN 1024
#endif
typedef struct fdpara {
int fd;
char *fds;
int ff;
char *host;
int hlen;
char *ipaddr;
int ilen;
pid_t pid;
char *port;
int plen;
struct sockaddr_in sa;
} fdpara_t;
pid_t CPid = (pid_t)0;
fdpara_t FdPara[2];
#define NFDPARA (sizeof(FdPara) /sizeof(fdpara_t))
struct sockaddr_in Myad;
pid_t MyPid = (pid_t)0;
char *Pn = (char *)NULL;
char *PtNm[] = { "client", "server" };
int Ssock = -1;
_PROTOTYPE(static void CleanupClnt,(void));
_PROTOTYPE(static void CleanupSrvr,(void));
_PROTOTYPE(static SIGHANDLER_T HandleClntAlarm,(int sig));
_PROTOTYPE(static SIGHANDLER_T HandleSrvrAlarm,(int sig));
_PROTOTYPE(static char *FindSock,(int fn));
_PROTOTYPE(static void StartClnt,(struct sockaddr_in *cad));
int
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in aa;
struct sockaddr_in ba;
char buf[2048];
int bufl = sizeof(buf);
struct sockaddr_in ca;
char *cem;
char *ep;
char hnm[MAXHOSTNAMELEN + 1];
char *host;
struct hostent *hp;
char *ipaddr;
char *pem = (char *)NULL;
char *port;
LT_SOCKLEN_T sal;
char *tcp;
int ti, tj, tk;
int tsfd;
int xv = 0;
if ((Pn = strrchr(argv[0], '/')))
Pn++;
else
Pn = argv[0];
MyPid = getpid();
(void) printf("%s ... ", Pn);
(void) fflush(stdout);
PrtMsg((char *)NULL, Pn);
for (ti = 0; ti < NFDPARA; ti++) {
(void) memset((void *)&FdPara[ti], 0, sizeof(fdpara_t));
FdPara[ti].fd = -1;
FdPara[ti].ff = LT_FNF;
}
if (ScanArg(argc, argv, "h", Pn))
xv = 1;
if (xv || LTopt_h) {
(void) PrtMsg("usage: [-h]", Pn);
PrtMsgX(" -h print help (this panel)", Pn, CleanupSrvr,
xv);
}
if ((cem = IsLsofExec()))
(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
if ((cem = CanRdKmem()))
(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
if (gethostname(hnm, sizeof(hnm) - 1)) {
cem = "ERROR!!! can't get this host's name";
goto print_errno;
}
hnm[sizeof(hnm) - 1] = '\0';
if (!(hp = gethostbyname(hnm))) {
(void) snprintf(buf, bufl - 1, "ERROR!!! can't get IP address for %s",
hnm);
buf[bufl - 1] = '\0';
cem = buf;
goto print_errno;
}
(void) memset((void *)&Myad, 0, sizeof(Myad));
if ((ti = hp->h_length) > sizeof(Myad.sin_addr))
ti = sizeof(Myad.sin_addr);
(void) memcpy((void *)&Myad.sin_addr, (void *)hp->h_addr, ti);
Myad.sin_family = hp->h_addrtype;
for (ti = 0; ti < NFDPARA; ti++) {
if ((tsfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
ep = "socket";
print_errno_by_ti:
(void) snprintf(buf, bufl - 1, "ERROR!!! %s %s() failure",
PtNm[ti], ep);
buf[bufl - 1] = '\0';
PrtMsg(buf, Pn);
(void) snprintf(buf, bufl - 1, " host: %s",
FdPara[ti].host ? FdPara[ti].host : hnm);
buf[bufl - 1] = '\0';
PrtMsg(buf, Pn);
(void) snprintf(buf, bufl - 1, " IP: %s",
FdPara[ti].ipaddr ? FdPara[ti].ipaddr
: inet_ntoa(Myad.sin_addr));
buf[bufl - 1] = '\0';
cem = buf;
print_errno:
PrtMsg(cem, Pn);
(void) snprintf(buf, bufl - 1, " Errno %d: %s", errno,
strerror(errno));
buf[bufl - 1] = '\0';
PrtMsgX(buf, Pn, CleanupSrvr, 1);
}
FdPara[ti].fd = tsfd;
(void) snprintf(buf, bufl - 1, "%d", tsfd);
buf[bufl - 1] = '\0';
FdPara[ti].fds = MkStrCpy(buf, &tj);
if (ti == LT_SRVR)
Ssock = tsfd;
}
(void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
ti = LT_SRVR;
FdPara[ti].pid = MyPid;
if (bind(Ssock, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
ep = "bind";
goto print_errno_by_ti;
}
sal = (LT_SOCKLEN_T)sizeof(ca);
if (getsockname(Ssock, (struct sockaddr *)&ca, &sal)) {
ep = "getsockname";
goto print_errno_by_ti;
}
(void) memcpy((void *)&FdPara[ti].sa, (void *)&ca, sizeof(FdPara[ti].sa));
if (listen(Ssock, 1) < 0) {
ep = "listen";
goto print_errno_by_ti;
}
switch ((CPid = (pid_t)fork())) {
case (pid_t)0:
StartClnt(&ca);
(void) PrtMsgX("ERROR!!! unexpected client return", Pn, CleanupSrvr,
1);
case (pid_t)-1:
cem = "ERROR!!! fork() error";
goto print_errno;
default:
FdPara[LT_CLNT].pid = CPid;
if (FdPara[LT_CLNT].fd >= 0) {
(void) close(FdPara[LT_CLNT].fd);
FdPara[LT_CLNT].fd = -1;
}
}
sal = (LT_SOCKLEN_T)sizeof(aa);
(void) alarm(0);
(void) signal(SIGALRM, HandleSrvrAlarm);
(void) alarm(ALARMTM);
tsfd = FdPara[LT_SRVR].fd = accept(Ssock, (struct sockaddr *)&aa, &sal);
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
if (tsfd < 0) {
ep = "accept";
goto print_errno_by_ti;
}
(void) snprintf(buf, bufl - 1, "%d", tsfd);
buf[bufl - 1] = '\0';
if (FdPara[LT_SRVR].fds)
(void) free((void *)FdPara[LT_SRVR].fds);
FdPara[LT_SRVR].fds = MkStrCpy(buf, &tj);
ti = LT_CLNT;
(void) memcpy((void *)&FdPara[ti].sa, (void *)&aa, sizeof(FdPara[ti].sa));
(void) close(Ssock);
Ssock = -1;
for (ti = 0; ti < NFDPARA; ti++) {
tcp = inet_ntoa(FdPara[ti].sa.sin_addr);
FdPara[ti].ipaddr = MkStrCpy(tcp, &FdPara[ti].ilen);
(void) snprintf(buf, bufl - 1, "%d",
(int)ntohs(FdPara[ti].sa.sin_port));
buf[bufl - 1] = '\0';
FdPara[ti].port = MkStrCpy(buf, &FdPara[ti].plen);
if (!(hp = gethostbyaddr((char *)&FdPara[ti].sa.sin_addr,
sizeof(FdPara[ti].sa.sin_addr),
FdPara[ti].sa.sin_family))
) {
ep = "gethostbyaddr";
goto print_errno_by_ti;
}
if (hp->h_name)
FdPara[ti].host = MkStrCpy(hp->h_name, &FdPara[ti].hlen);
else {
(void) snprintf(buf, bufl - 1,
"ERROR!!! can't map %s (client) to a host name",
FdPara[ti].ipaddr);
buf[bufl - 1] = '\0';
PrtMsgX(buf, Pn, CleanupSrvr, 1);
}
}
if ((cem = FindSock(LT_FBYHN)))
PrtMsgX(cem, Pn, CleanupSrvr, 1);
if ((cem = FindSock(LT_FBYIP)))
PrtMsgX(cem, Pn, CleanupSrvr, 1);
if ((cem = FindSock(LT_FBYPORT)))
PrtMsgX(cem, Pn, CleanupSrvr, 1);
for (pem = (char *)NULL, ti = 0; ti < NFDPARA; ti++) {
if ((tj = FdPara[ti].ff) != (LT_FBYHN | LT_FBYIP | LT_FBYPORT)) {
host = FdPara[ti].host;
ipaddr = FdPara[ti].ipaddr;
port = FdPara[ti].port;
if (!(tj & LT_FBYHN)) {
(void) snprintf(buf, bufl - 1,
"ERROR!!! no %s socket by host and port: %s@%s",
PtNm[ti], host, port);
buf[bufl - 1] = '\0';
if (pem)
(void) PrtMsg(pem, Pn);
pem = MkStrCpy(buf, &tk);
}
if (!(tj & LT_FBYIP)) {
(void) snprintf(buf, bufl - 1,
"ERROR!!! no %s socket by IP and port: %s@%s",
PtNm[ti], ipaddr, port);
buf[bufl - 1] = '\0';
if (pem)
(void) PrtMsg(pem, Pn);
pem = MkStrCpy(buf, &tk);
}
if (!(tj & LT_FBYPORT)) {
(void) snprintf(buf, bufl - 1,
"ERROR!!! no %s socket by port: %s",
PtNm[ti], port);
buf[bufl - 1] = '\0';
if (pem)
(void) PrtMsg(pem, Pn);
pem = MkStrCpy(buf, &tk);
}
}
}
if (pem)
(void) PrtMsgX(pem, Pn, CleanupSrvr, 1);
(void) PrtMsgX("OK", Pn, CleanupSrvr, 0);
return(0);
}
static void
CleanupClnt()
{
int tfd;
if ((tfd = FdPara[LT_CLNT].fd) >= 0) {
(void) shutdown(tfd, 2);
(void) close(tfd);
FdPara[LT_CLNT].fd = -1;
}
}
static void
CleanupSrvr()
{
int tfd;
int ti;
pid_t wpid;
if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
(void) shutdown(Ssock, 2);
(void) close(Ssock);
Ssock = -1;
}
for (ti = 0; ti < NFDPARA; ti++) {
if ((tfd = FdPara[ti].fd) >= 0) {
(void) shutdown(tfd, 2);
(void) close(tfd);
FdPara[ti].fd = -1;
}
}
if (CPid > 0) {
wpid = wait3(NULL, WNOHANG, NULL);
if (wpid != CPid) {
kill(CPid, SIGKILL);
(void) wait3(NULL, WNOHANG, NULL);
}
CPid = (pid_t)0;
}
}
static char *
FindSock(fn)
int fn;
{
char buf[2048];
int bufl = sizeof(buf);
char *cem;
LTfldo_t *cmdp;
LTfldo_t *fop;
int nf;
int nl;
LTfldo_t *nmp;
char *opv[5];
char *pem = (char *)NULL;
pid_t pid;
int pids = 0;
int pl;
int px;
char *tcp, *tcp1;
int ti, tj;
LTfldo_t *typ;
ti = 0;
switch (fn) {
case LT_FBYHN:
opv[ti++] = "-P";
for (tj = 0; tj < NFDPARA; tj++) {
(void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].host,
FdPara[tj].port);
buf[bufl - 1] = '\0';
opv[ti++] = MkStrCpy(buf, &pl);
}
break;
case LT_FBYIP:
opv[ti++] = "-Pn";
for (tj = 0; tj < NFDPARA; tj++) {
(void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].ipaddr,
FdPara[tj].port);
buf[bufl - 1] = '\0';
opv[ti++] = MkStrCpy(buf, &pl);
}
break;
case LT_FBYPORT:
opv[ti++] = "-P";
for (tj = 0; tj < NFDPARA; tj++) {
(void) snprintf(buf, bufl - 1, "-i:%s", FdPara[tj].port);
buf[bufl - 1] = '\0';
opv[ti++] = MkStrCpy(buf, &pl);
}
break;
default:
(void) snprintf(buf, bufl - 1,
"ERROR!!! illegal FindSock() function: %d", fn);
buf[bufl - 1] = '\0';
return(MkStrCpy(buf, &ti));
}
#if defined(USE_LSOF_C_OPT)
opv[ti++] = "-C";
#endif
opv[ti] = (char *)NULL;
if ((cem = ExecLsof(opv)))
return(cem);
while ((((FdPara[LT_CLNT].ff & fn) == 0)
|| ((FdPara[LT_SRVR].ff & fn) == 0))
&& (fop = RdFrLsof(&nf, &cem))
) {
if (cem) {
if (pem)
(void) PrtMsg(pem, Pn);
return(cem);
}
switch (fop->ft) {
case LSOF_FID_PID:
pid = (pid_t)atoi(fop->v);
pids = 1;
cmdp = (LTfldo_t *)NULL;
for (fop++, ti = 1; ti < nf; fop++, ti++) {
switch (fop->ft) {
case LSOF_FID_CMD:
cmdp = fop;
break;
}
}
if (!cmdp || ((pid != CPid) && (pid != MyPid)))
pids = 0;
break;
case LSOF_FID_FD:
if (!pids)
break;
if (pid == CPid)
px = LT_CLNT;
else if (pid == MyPid)
px = LT_SRVR;
else
break;
if (strcmp(fop->v, FdPara[px].fds))
break;
nmp = typ = (LTfldo_t *)NULL;
for (fop++, ti = 1; ti < nf; fop++, ti++) {
switch (fop->ft) {
case LSOF_FID_NAME:
nmp = fop;
break;
case LSOF_FID_TYPE:
typ = fop;
break;
}
}
if (!typ
|| (strcasecmp(typ->v, "inet") && strcasecmp(typ->v, "ipv4"))
) {
break;
}
if (!nmp)
break;
tcp = nmp->v;
switch (fn) {
case LT_FBYHN:
if (((nl = FdPara[px].hlen) <= 0)
|| !(tcp1 = FdPara[px].host)
|| strncasecmp(tcp, tcp1, nl)
) {
break;
}
tcp += nl;
if ((*tcp++ != ':')
|| !(tcp1 = FdPara[px].port)
|| ((pl = FdPara[px].plen) <= 0)
|| strncmp(tcp, tcp1, pl)
) {
break;
}
tcp += pl;
if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
FdPara[px].ff |= LT_FBYHN;
}
break;
case LT_FBYIP:
if (((nl = FdPara[px].ilen) <= 0)
|| !(tcp1 = FdPara[px].ipaddr)
|| strncasecmp(tcp, tcp1, nl)
) {
break;
}
tcp += nl;
if ((*tcp++ != ':')
|| !(tcp1 = FdPara[px].port)
|| ((pl = FdPara[px].plen) <= 0)
|| strncmp(tcp, tcp1, pl)
) {
break;
}
tcp += pl;
if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
FdPara[px].ff |= LT_FBYIP;
}
break;
case LT_FBYPORT:
if (!(tcp = strchr(tcp, ':')))
break;
tcp++;
if (!(tcp1 = FdPara[px].port)
|| ((pl = FdPara[px].plen) <= 0)
|| strncmp(tcp, tcp1, pl)
) {
break;
}
tcp += pl;
if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
FdPara[px].ff |= LT_FBYPORT;
}
break;
}
}
}
(void) StopLsof();
return(pem);
}
static SIGHANDLER_T
HandleClntAlarm(sig)
int sig;
{
(void) PrtMsgX("ERROR!!! client caught an alarm signal", Pn,
CleanupClnt, 1);
}
static SIGHANDLER_T
HandleSrvrAlarm(sig)
int sig;
{
(void) PrtMsgX("ERROR!!! server caught an alarm signal.", Pn,
CleanupSrvr, 1);
}
static void
StartClnt(cad)
struct sockaddr_in *cad;
{
struct sockaddr_in ba;
int br;
char buf[2048];
int bufl = sizeof(buf);
int cr;
char *em;
int fd = FdPara[LT_CLNT].fd;
if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
(void) close(Ssock);
Ssock = -1;
}
if (FdPara[LT_SRVR].fd >= 0) {
(void) close(FdPara[LT_SRVR].fd);
FdPara[LT_SRVR].fd = -1;
}
(void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
if (bind(fd, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
em = "bind";
client_errno:
(void) snprintf(buf, bufl - 1,
"ERROR!!! client %s error: %s", em, strerror(errno));
buf[bufl - 1] = '\0';
(void) PrtMsgX(em, Pn, CleanupClnt, 1);
}
(void) signal(SIGALRM, HandleClntAlarm);
(void) alarm(ALARMTM);
cr = connect(fd, (struct sockaddr *)cad, sizeof(struct sockaddr_in));
(void) alarm(0);
(void) signal(SIGALRM, SIG_DFL);
if (cr) {
em = "connect";
goto client_errno;
}
for (br = 0; br >= 0;) {
sleep(1);
br = read(fd, buf, bufl);
}
(void) CleanupClnt();
exit(0);
}