| /* |
| * LTsock.c -- Lsof Test IPv4 sockets |
| * |
| * V. Abell |
| * Purdue University |
| */ |
| |
| |
| /* |
| * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana |
| * 47907. All rights reserved. |
| * |
| * Written by V. Abell. |
| * |
| * This software is not subject to any license of the American Telephone |
| * and Telegraph Company or the Regents of the University of California. |
| * |
| * Permission is granted to anyone to use this software for any purpose on |
| * any computer system, and to alter it and redistribute it freely, subject |
| * to the following restrictions: |
| * |
| * 1. Neither the authors nor Purdue University are responsible for any |
| * consequences of the use of this software. |
| * |
| * 2. The origin of this software must not be misrepresented, either by |
| * explicit claim or by omission. Credit to the authors and Purdue |
| * University must appear in documentation and sources. |
| * |
| * 3. Altered versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software. |
| * |
| * 4. This notice may not be removed or altered. |
| */ |
| |
| #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> |
| |
| |
| /* |
| * Pre-definitions that make be changed or revoked by dialects |
| */ |
| |
| #define SIGHANDLER_T void /* signal handler function type */ |
| #define LT_SOCKLEN_T int /* socket length type */ |
| |
| |
| #if defined(LT_DIAL_aix) |
| /* |
| * AIX-specific items |
| */ |
| |
| #undef LT_SOCKLEN_T |
| #define LT_SOCKLEN_T size_t |
| #endif /* defined(LT_DIAL_aix) */ |
| |
| |
| #if defined(LT_DIAL_darwin) |
| /* |
| * Darwin-specific items |
| */ |
| |
| # if LT_VERS>=800 |
| #undef LT_SOCKLEN_T |
| #define LT_SOCKLEN_T socklen_t |
| # endif /* LT_VERS>=800 */ |
| #endif /* defined(LT_DIAL_darwin) */ |
| |
| |
| #if defined(LT_DIAL_hpux) |
| /* |
| * HP-UX-specific items |
| */ |
| |
| # if LT_VERS>=1123 && defined(__GNUC__) |
| #undef LT_SOCKLEN_T |
| #define LT_SOCKLEN_T size_t |
| # endif /* LT_VERS>=1123 && defined(__GNUC__) */ |
| #endif /* defined(LT_DIAL_hpux) */ |
| |
| |
| #if defined(LT_DIAL_ou) |
| /* |
| * OpenUNIX-specific items |
| */ |
| |
| #undef LT_SOCKLEN_T |
| #define LT_SOCKLEN_T size_t |
| #endif /* defined(LT_DIAL_ou) */ |
| |
| |
| #if defined(LT_DIAL_uw) |
| /* |
| * UnixWare-specific items |
| */ |
| |
| #undef LT_SOCKLEN_T |
| #define LT_SOCKLEN_T size_t |
| #endif /* defined(LT_DIAL_uw) */ |
| |
| |
| /* |
| * Local definitions |
| */ |
| |
| #define ALARMTM 30 /* alarm timer */ |
| |
| #define LT_CLNT 0 /* child process index */ |
| #define LT_SRVR 1 /* parent process index */ |
| |
| #define LT_FNF 0 /* file not found */ |
| #define LT_FBYIP 1 /* file found by IP address */ |
| #define LT_FBYHN 2 /* file found by host name */ |
| #define LT_FBYPORT 4 /* file found by port */ |
| |
| #if !defined(MAXHOSTNAMELEN) |
| #define MAXHOSTNAMELEN 256 /* maximum host name length */ |
| #endif /* !defined(MAXHOSTNAMELEN) */ |
| |
| #if !defined(MAXPATHLEN) |
| #define MAXPATHLEN 1024 /* maximum path length */ |
| #endif /* !defined(MAXPATHLEN) */ |
| |
| |
| /* |
| * Local structure definitions. |
| */ |
| |
| |
| typedef struct fdpara { /* file descriptor parameters */ |
| int fd; /* FD */ |
| char *fds; /* FD in ASCII */ |
| int ff; /* file found flags (see LT_F*) */ |
| char *host; /* host name */ |
| int hlen; /* strlen(host) */ |
| char *ipaddr; /* dotted IP address */ |
| int ilen; /* strlen(ipaddr) */ |
| pid_t pid; /* PID of process */ |
| char *port; /* port in ASCII */ |
| int plen; /* strlen(port) */ |
| struct sockaddr_in sa; /* socket's address */ |
| } fdpara_t; |
| |
| |
| /* |
| * Globals |
| */ |
| |
| pid_t CPid = (pid_t)0; /* client PID */ |
| fdpara_t FdPara[2]; /* file descriptor parameters */ |
| #define NFDPARA (sizeof(FdPara) /sizeof(fdpara_t)) |
| struct sockaddr_in Myad; /* my (server) socket address */ |
| pid_t MyPid = (pid_t)0; /* PID of this process */ |
| char *Pn = (char *)NULL; /* program name */ |
| char *PtNm[] = { "client", "server" }; |
| /* program type name */ |
| int Ssock = -1; /* server socket */ |
| |
| |
| /* |
| * Local function prototypes |
| */ |
| |
| _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)); |
| |
| |
| /* |
| * Main program |
| */ |
| |
| int |
| main(argc, argv) |
| int argc; /* argument count */ |
| char *argv[]; /* arguments */ |
| { |
| struct sockaddr_in aa; /* accept address */ |
| struct sockaddr_in ba; /* bind address */ |
| char buf[2048]; /* temporary buffer */ |
| int bufl = sizeof(buf); /* size of buf[] */ |
| struct sockaddr_in ca; /* connect address */ |
| char *cem; /* current error message pointer */ |
| char *ep; /* error message parameter */ |
| char hnm[MAXHOSTNAMELEN + 1]; /* this host's name */ |
| char *host; /* host name */ |
| struct hostent *hp; /* this host's hostent structure */ |
| char *ipaddr; /* IP address */ |
| char *pem = (char *)NULL; /* previous error message */ |
| char *port; /* port */ |
| LT_SOCKLEN_T sal; /* socket address length */ |
| char *tcp; /* temporary character size */ |
| int ti, tj, tk; /* temporary indexes */ |
| int tsfd; /* temporary socket FD */ |
| int xv = 0; /* exit value */ |
| /* |
| * Get program name and PID, issue start message, and build space prefix. |
| */ |
| if ((Pn = strrchr(argv[0], '/'))) |
| Pn++; |
| else |
| Pn = argv[0]; |
| MyPid = getpid(); |
| (void) printf("%s ... ", Pn); |
| (void) fflush(stdout); |
| PrtMsg((char *)NULL, Pn); |
| /* |
| * Initalize the FdPara[] array before any CleanupClnt() call. |
| */ |
| for (ti = 0; ti < NFDPARA; ti++) { |
| (void) memset((void *)&FdPara[ti], 0, sizeof(fdpara_t)); |
| FdPara[ti].fd = -1; |
| FdPara[ti].ff = LT_FNF; |
| } |
| /* |
| * Process arguments. |
| */ |
| 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); |
| } |
| /* |
| * See if lsof can be executed and can access kernel memory. |
| */ |
| if ((cem = IsLsofExec())) |
| (void) PrtMsgX(cem, Pn, CleanupSrvr, 1); |
| if ((cem = CanRdKmem())) |
| (void) PrtMsgX(cem, Pn, CleanupSrvr, 1); |
| /* |
| * Get the host name and its IP address. Convert the IP address to dotted |
| * ASCII form. |
| */ |
| 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; |
| /* |
| * Get INET domain socket FDs. |
| */ |
| for (ti = 0; ti < NFDPARA; ti++) { |
| if ((tsfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { |
| ep = "socket"; |
| |
| print_errno_by_ti: |
| |
| /* |
| * Report socket function error. |
| * |
| * Entry: ep = function name |
| * hnm = this host's name |
| * Myad = this host's IP address |
| * ti = FdPara[] index |
| */ |
| (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: |
| |
| /* |
| * Report errno. |
| * |
| * Entry: errno = error number |
| */ |
| PrtMsg(cem, Pn); |
| (void) snprintf(buf, bufl - 1, " Errno %d: %s", errno, |
| strerror(errno)); |
| buf[bufl - 1] = '\0'; |
| PrtMsgX(buf, Pn, CleanupSrvr, 1); |
| } |
| /* |
| * Put the FD just acquired in FdPara[ti].fd. |
| * |
| * Set the file-not-found to LT_FNF. |
| * |
| * Save the server socket if this FdPara[] is for it. |
| */ |
| 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; |
| } |
| /* |
| * Bind the host name to the server socket. |
| * |
| * Get and save the server's socket address. |
| * |
| * Initiate a listen with an address list of one. |
| */ |
| (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; |
| } |
| /* |
| * Fork a child process to run as the client. |
| */ |
| switch ((CPid = (pid_t)fork())) { |
| case (pid_t)0: |
| |
| /* |
| * This is the child. Start the client. |
| */ |
| StartClnt(&ca); |
| (void) PrtMsgX("ERROR!!! unexpected client return", Pn, CleanupSrvr, |
| 1); |
| case (pid_t)-1: |
| |
| /* |
| * This is a fork error. |
| */ |
| cem = "ERROR!!! fork() error"; |
| goto print_errno; |
| default: |
| |
| /* |
| * This is the parent. |
| * |
| * Save the client's PID. |
| * |
| * Close the client's socket. |
| */ |
| FdPara[LT_CLNT].pid = CPid; |
| if (FdPara[LT_CLNT].fd >= 0) { |
| (void) close(FdPara[LT_CLNT].fd); |
| FdPara[LT_CLNT].fd = -1; |
| } |
| } |
| /* |
| * Set a SIGALRM, then accept() the connection from the client. |
| * |
| * Save the client's socket address. |
| * |
| * Replace the server's FD with the accepted one and close the original. |
| */ |
| 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; |
| /* |
| * Convert the client and server IP address to ASCII form. |
| * |
| * Look up the client and server host names for their IP addresses. |
| * |
| * Convert the port from the socket address to host form. |
| */ |
| 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 { |
| |
| /* |
| * The connected client's socket address can't be mapped to a host |
| * name. |
| */ |
| |
| (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); |
| } |
| } |
| /* |
| * Call lsof three times to find the two sockets: 1) by host name and port; |
| * 2) by IP address and port; and 3) by port. |
| */ |
| 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); |
| /* |
| * Check the FindSock() results. |
| */ |
| 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; |
| |
| /* |
| * This FD wasn't found by some search method. |
| */ |
| if (!(tj & LT_FBYHN)) { |
| |
| /* |
| * The search by host name and port failed. |
| */ |
| (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)) { |
| |
| /* |
| * The search by IP address and port failed. |
| */ |
| (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)) { |
| |
| /* |
| * The search by port number failed. |
| */ |
| (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); |
| /* |
| * Exit successfully. |
| */ |
| (void) PrtMsgX("OK", Pn, CleanupSrvr, 0); |
| return(0); |
| } |
| |
| |
| /* |
| * ClntCleanup() -- release client resources |
| */ |
| |
| static void |
| CleanupClnt() |
| { |
| int tfd; /* temporary file descriptor */ |
| |
| if ((tfd = FdPara[LT_CLNT].fd) >= 0) { |
| (void) shutdown(tfd, 2); |
| (void) close(tfd); |
| FdPara[LT_CLNT].fd = -1; |
| } |
| } |
| |
| |
| /* |
| * CleanupSrvr() -- release server resources |
| */ |
| |
| static void |
| CleanupSrvr() |
| { |
| int tfd; /* temporary file descriptor */ |
| int ti; /* temporary index */ |
| pid_t wpid; /* wait() PID */ |
| |
| 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; |
| } |
| } |
| |
| |
| /* |
| * FindSock() -- find sockets with lsof |
| */ |
| |
| static char * |
| FindSock(fn) |
| int fn; /* function -- an LT_FBY* value */ |
| { |
| char buf[2048]; /* temporary buffer */ |
| int bufl = sizeof(buf); /* size of buf[] */ |
| char *cem; /* current error message pointer */ |
| LTfldo_t *cmdp; /* command pointer */ |
| LTfldo_t *fop; /* field output pointer */ |
| int nf; /* number of fields */ |
| int nl; /* name length */ |
| LTfldo_t *nmp; /* name pointer */ |
| char *opv[5]; /* option vector for ExecLsof() */ |
| char *pem = (char *)NULL; /* previous error message pointer */ |
| pid_t pid; /* PID */ |
| int pids = 0; /* PID found status */ |
| int pl; /* port length */ |
| int px; /* process index -- LT_CLNT or |
| * LT_SRVR */ |
| char *tcp, *tcp1; /* temporary character pointers */ |
| int ti, tj; /* temporary integers */ |
| LTfldo_t *typ; /* file type pointer */ |
| /* |
| * Check the function and determine the first lsof option from it. |
| */ |
| 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)); |
| } |
| /* |
| * Complete the option vector and start lsof execution. |
| */ |
| |
| #if defined(USE_LSOF_C_OPT) |
| opv[ti++] = "-C"; |
| #endif /* defined(USE_LSOF_C_OPT) */ |
| |
| opv[ti] = (char *)NULL; |
| if ((cem = ExecLsof(opv))) |
| return(cem); |
| /* |
| * Read lsof output. |
| */ |
| 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: |
| |
| /* |
| * This is a process information line. |
| */ |
| 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: |
| |
| /* |
| * This is a file descriptor line. |
| * |
| * Identify the process -- client or server. |
| */ |
| if (!pids) |
| break; |
| if (pid == CPid) |
| px = LT_CLNT; |
| else if (pid == MyPid) |
| px = LT_SRVR; |
| else |
| break; |
| /* |
| * Make sure the FD matches the identified process. |
| */ |
| if (strcmp(fop->v, FdPara[px].fds)) |
| break; |
| /* |
| * Scan for name and type. |
| */ |
| 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; |
| } |
| } |
| /* |
| * Check the type of the file. |
| */ |
| if (!typ |
| || (strcasecmp(typ->v, "inet") && strcasecmp(typ->v, "ipv4")) |
| ) { |
| break; |
| } |
| /* |
| * Check the addess in the name, based on the calling function. |
| */ |
| 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; |
| } |
| } |
| } |
| /* |
| * Clean up and return. |
| */ |
| (void) StopLsof(); |
| return(pem); |
| } |
| |
| |
| /* |
| * HandleClntAlarm() -- handle client alarm |
| */ |
| |
| static SIGHANDLER_T |
| HandleClntAlarm(sig) |
| int sig; /* the signal (SIGALRM) */ |
| { |
| (void) PrtMsgX("ERROR!!! client caught an alarm signal", Pn, |
| CleanupClnt, 1); |
| } |
| |
| |
| /* |
| * Handle SrvrAlarm() -- handle server alarm |
| */ |
| |
| static SIGHANDLER_T |
| HandleSrvrAlarm(sig) |
| int sig; /* the signal (SIGALRM) */ |
| { |
| (void) PrtMsgX("ERROR!!! server caught an alarm signal.", Pn, |
| CleanupSrvr, 1); |
| } |
| |
| |
| /* |
| * StartClnt() -- start network client |
| */ |
| |
| static void |
| StartClnt(cad) |
| struct sockaddr_in *cad; /* connection address */ |
| { |
| struct sockaddr_in ba; /* bind address */ |
| int br; /* bytes read */ |
| char buf[2048]; /* temporary buffer */ |
| int bufl = sizeof(buf); /* size of buf[] */ |
| int cr; /* connect() reply */ |
| char *em; /* error message pointer */ |
| int fd = FdPara[LT_CLNT].fd; /* client's socket FD */ |
| /* |
| * Close the server's sockets. |
| */ |
| 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; |
| } |
| /* |
| * Bind to the local address. |
| */ |
| (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); |
| } |
| /* |
| * Set an alarm timeout and connect to the server. |
| */ |
| (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; |
| } |
| /* |
| * Sleep until the socket closes or the parent kills the process. |
| */ |
| for (br = 0; br >= 0;) { |
| sleep(1); |
| br = read(fd, buf, bufl); |
| } |
| (void) CleanupClnt(); |
| exit(0); |
| } |