1/*
2 * LTsock.c -- Lsof Test IPv4 sockets
3 *
4 * V. Abell
5 * Purdue University
6 */
7
8
9/*
10 * Copyright 2002 Purdue Research Foundation, West Lafayette, Indiana
11 * 47907.  All rights reserved.
12 *
13 * Written by V. Abell.
14 *
15 * This software is not subject to any license of the American Telephone
16 * and Telegraph Company or the Regents of the University of California.
17 *
18 * Permission is granted to anyone to use this software for any purpose on
19 * any computer system, and to alter it and redistribute it freely, subject
20 * to the following restrictions:
21 *
22 * 1. Neither the authors nor Purdue University are responsible for any
23 *    consequences of the use of this software.
24 *
25 * 2. The origin of this software must not be misrepresented, either by
26 *    explicit claim or by omission.  Credit to the authors and Purdue
27 *    University must appear in documentation and sources.
28 *
29 * 3. Altered versions must be plainly marked as such, and must not be
30 *    misrepresented as being the original software.
31 *
32 * 4. This notice may not be removed or altered.
33 */
34
35#ifndef lint
36static char copyright[] =
37"@(#) Copyright 2002 Purdue Research Foundation.\nAll rights reserved.\n";
38#endif
39
40#include "LsofTest.h"
41#include "lsof_fields.h"
42
43#include <netdb.h>
44#include <signal.h>
45#include <sys/socket.h>
46#include <netinet/in.h>
47#include <arpa/inet.h>
48
49
50/*
51 * Pre-definitions that make be changed or revoked by dialects
52 */
53
54#define SIGHANDLER_T	void		/* signal handler function type */
55#define	LT_SOCKLEN_T	int		/* socket length type */
56
57
58#if	defined(LT_DIAL_aix)
59/*
60 * AIX-specific items
61 */
62
63#undef	LT_SOCKLEN_T
64#define	LT_SOCKLEN_T	size_t
65#endif	/* defined(LT_DIAL_aix) */
66
67
68#if	defined(LT_DIAL_darwin)
69/*
70 * Darwin-specific items
71 */
72
73# if	LT_VERS>=800
74#undef	LT_SOCKLEN_T
75#define	LT_SOCKLEN_T	socklen_t
76# endif	/* LT_VERS>=800 */
77#endif	/* defined(LT_DIAL_darwin) */
78
79
80#if	defined(LT_DIAL_freebsd)
81/*
82 * FreeBSD-specific items
83 */
84#undef	LT_SOCKLEN_T
85#define	LT_SOCKLEN_T	socklen_t
86#endif	/* defined(LT_DIAL_freebsd) */
87
88
89#if	defined(LT_DIAL_hpux)
90/*
91 * HP-UX-specific items
92 */
93
94# if	LT_VERS>=1123 && defined(__GNUC__)
95#undef	LT_SOCKLEN_T
96#define	LT_SOCKLEN_T	size_t
97# endif	/* LT_VERS>=1123 && defined(__GNUC__) */
98#endif	/* defined(LT_DIAL_hpux) */
99
100
101#if	defined(LT_DIAL_ou)
102/*
103 * OpenUNIX-specific items
104 */
105
106#undef	LT_SOCKLEN_T
107#define	LT_SOCKLEN_T	size_t
108#endif	/* defined(LT_DIAL_ou) */
109
110
111#if	defined(LT_DIAL_uw)
112/*
113 * UnixWare-specific items
114 */
115
116#undef	LT_SOCKLEN_T
117#define	LT_SOCKLEN_T	size_t
118#endif	/* defined(LT_DIAL_uw) */
119
120
121/*
122 * Local definitions
123 */
124
125#define	ALARMTM		30		/* alarm timer */
126
127#define	LT_CLNT		0		/* child process index */
128#define	LT_SRVR		1		/* parent process index */
129
130#define	LT_FNF		0		/* file not found */
131#define LT_FBYIP	1		/* file found by IP address */
132#define	LT_FBYHN	2		/* file found by host name */
133#define	LT_FBYPORT	4		/* file found by port */
134
135#if	!defined(MAXHOSTNAMELEN)
136#define	MAXHOSTNAMELEN	256		/* maximum host name length */
137#endif	/* !defined(MAXHOSTNAMELEN) */
138
139#if	!defined(MAXPATHLEN)
140#define	MAXPATHLEN	1024		/* maximum path length */
141#endif	/* !defined(MAXPATHLEN) */
142
143
144/*
145 * Local structure definitions.
146 */
147
148
149typedef struct fdpara {		/* file descriptor parameters */
150    int fd;			/* FD */
151    char *fds;			/* FD in ASCII */
152    int ff;			/* file found flags (see LT_F*) */
153    char *host;			/* host name */
154    int hlen;			/* strlen(host) */
155    char *ipaddr;		/* dotted IP address */
156    int ilen;			/* strlen(ipaddr) */
157    pid_t pid;			/* PID of process */
158    char *port;			/* port in ASCII */
159    int plen;			/* strlen(port) */
160    struct sockaddr_in sa;	/* socket's address */
161} fdpara_t;
162
163
164/*
165 * Globals
166 */
167
168pid_t CPid = (pid_t)0;		/* client PID */
169fdpara_t FdPara[2];		/* file descriptor parameters */
170#define	NFDPARA	(sizeof(FdPara) /sizeof(fdpara_t))
171struct sockaddr_in Myad;	/* my (server) socket address */
172pid_t MyPid = (pid_t)0;		/* PID of this process */
173char *Pn = (char *)NULL;	/* program name */
174char *PtNm[] = { "client", "server" };
175				/* program type name */
176int Ssock = -1;			/* server socket */
177
178
179/*
180 * Local function prototypes
181 */
182
183_PROTOTYPE(static void CleanupClnt,(void));
184_PROTOTYPE(static void CleanupSrvr,(void));
185_PROTOTYPE(static SIGHANDLER_T HandleClntAlarm,(int sig));
186_PROTOTYPE(static SIGHANDLER_T HandleSrvrAlarm,(int sig));
187_PROTOTYPE(static char *FindSock,(int fn));
188_PROTOTYPE(static void StartClnt,(struct sockaddr_in *cad));
189
190
191/*
192 * Main program
193 */
194
195int
196main(argc, argv)
197    int argc;				/* argument count */
198    char *argv[];			/* arguments */
199{
200    struct sockaddr_in aa;		/* accept address */
201    struct sockaddr_in ba;		/* bind address */
202    char buf[2048];			/* temporary buffer */
203    int bufl = sizeof(buf);		/* size of buf[] */
204    struct sockaddr_in ca;		/* connect address */
205    char *cem;				/* current error message pointer */
206    char *ep;				/* error message parameter */
207    char hnm[MAXHOSTNAMELEN + 1];	/* this host's name */
208    char *host;				/* host name */
209    struct hostent *hp;			/* this host's hostent structure */
210    char *ipaddr;			/* IP address */
211    char *pem = (char *)NULL;		/* previous error message */
212    char *port;				/* port */
213    LT_SOCKLEN_T sal;			/* socket address length */
214    char *tcp;				/* temporary character size */
215    int ti, tj, tk;			/* temporary indexes */
216    int tsfd;				/* temporary socket FD */
217    int xv = 0;				/* exit value */
218/*
219 * Get program name and PID, issue start message, and build space prefix.
220 */
221    if ((Pn = strrchr(argv[0], '/')))
222	Pn++;
223    else
224	Pn = argv[0];
225    MyPid = getpid();
226    (void) printf("%s ... ", Pn);
227    (void) fflush(stdout);
228    PrtMsg((char *)NULL, Pn);
229/*
230 * Initalize the FdPara[] array before any CleanupClnt() call.
231 */
232    for (ti = 0; ti < NFDPARA; ti++) {
233	(void) memset((void *)&FdPara[ti], 0, sizeof(fdpara_t));
234	FdPara[ti].fd = -1;
235	FdPara[ti].ff = LT_FNF;
236    }
237/*
238 * Process arguments.
239 */
240    if (ScanArg(argc, argv, "h", Pn))
241	xv = 1;
242    if (xv || LTopt_h) {
243	(void) PrtMsg("usage: [-h]", Pn);
244	PrtMsgX("       -h       print help (this panel)", Pn, CleanupSrvr,
245		xv);
246    }
247/*
248 * See if lsof can be executed and can access kernel memory.
249 */
250    if ((cem = IsLsofExec()))
251	(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
252    if ((cem = CanRdKmem()))
253	(void) PrtMsgX(cem, Pn, CleanupSrvr, 1);
254/*
255 * Get the host name and its IP address.  Convert the IP address to dotted
256 * ASCII form.
257 */
258    if (gethostname(hnm, sizeof(hnm) - 1)) {
259	cem = "ERROR!!!  can't get this host's name";
260	goto print_errno;
261    }
262    hnm[sizeof(hnm) - 1] = '\0';
263    if (!(hp = gethostbyname(hnm))) {
264	(void) snprintf(buf, bufl - 1, "ERROR!!!  can't get IP address for %s",
265	    hnm);
266	buf[bufl - 1] = '\0';
267	cem = buf;
268	goto print_errno;
269    }
270    (void) memset((void *)&Myad, 0, sizeof(Myad));
271    if ((ti = hp->h_length) > sizeof(Myad.sin_addr))
272	ti = sizeof(Myad.sin_addr);
273    (void) memcpy((void *)&Myad.sin_addr, (void *)hp->h_addr, ti);
274    Myad.sin_family = hp->h_addrtype;
275/*
276 * Get INET domain socket FDs.
277 */
278    for (ti = 0; ti < NFDPARA; ti++) {
279	if ((tsfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
280	    ep = "socket";
281
282print_errno_by_ti:
283
284	/*
285	 * Report socket function error.
286	 *
287	 * Entry: ep   = function name
288	 *	  hnm  = this host's name
289	 *	  Myad = this host's IP address
290	 *	  ti   =  FdPara[] index
291	 */
292	    (void) snprintf(buf, bufl - 1, "ERROR!!!  %s %s() failure",
293		PtNm[ti], ep);
294	    buf[bufl - 1] = '\0';
295	    PrtMsg(buf, Pn);
296	    (void) snprintf(buf, bufl - 1, "    host: %s",
297		FdPara[ti].host ? FdPara[ti].host : hnm);
298	    buf[bufl - 1] = '\0';
299	    PrtMsg(buf, Pn);
300	    (void) snprintf(buf, bufl - 1, "    IP: %s",
301		FdPara[ti].ipaddr ? FdPara[ti].ipaddr
302				  : inet_ntoa(Myad.sin_addr));
303	    buf[bufl - 1] = '\0';
304	    cem = buf;
305
306print_errno:
307
308	/*
309	 * Report errno.
310	 *
311	 * Entry: errno = error number
312	 */
313	    PrtMsg(cem, Pn);
314	    (void) snprintf(buf, bufl - 1, "    Errno %d: %s", errno,
315		strerror(errno));
316	    buf[bufl - 1] = '\0';
317	    PrtMsgX(buf, Pn, CleanupSrvr, 1);
318	}
319    /*
320     * Put the FD just acquired in FdPara[ti].fd.
321     *
322     * Set the file-not-found to LT_FNF.
323     *
324     * Save the server socket if this FdPara[] is for it.
325     */
326	FdPara[ti].fd = tsfd;
327	(void) snprintf(buf, bufl - 1, "%d", tsfd);
328	buf[bufl - 1] = '\0';
329	FdPara[ti].fds = MkStrCpy(buf, &tj);
330	if (ti == LT_SRVR)
331	    Ssock = tsfd;
332    }
333/*
334 * Bind the host name to the server socket.
335 *
336 * Get and save the server's socket address.
337 *
338 * Initiate a listen with an address list of one.
339 */
340    (void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
341    ti = LT_SRVR;
342    FdPara[ti].pid = MyPid;
343    if (bind(Ssock, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
344	ep = "bind";
345	goto print_errno_by_ti;
346    }
347    sal = (LT_SOCKLEN_T)sizeof(ca);
348    if (getsockname(Ssock, (struct sockaddr *)&ca, &sal)) {
349	ep = "getsockname";
350	goto print_errno_by_ti;
351    }
352    (void) memcpy((void *)&FdPara[ti].sa, (void *)&ca, sizeof(FdPara[ti].sa));
353    if (listen(Ssock, 1) < 0) {
354	ep = "listen";
355	goto print_errno_by_ti;
356    }
357/*
358 * Fork a child process to run as the client.
359 */
360    switch ((CPid = (pid_t)fork())) {
361    case (pid_t)0:
362
363    /*
364     * This is the child.  Start the client.
365     */
366	StartClnt(&ca);
367	(void) PrtMsgX("ERROR!!!  unexpected client return", Pn, CleanupSrvr,
368		       1);
369    case (pid_t)-1:
370
371    /*
372     * This is a fork error.
373     */
374	cem = "ERROR!!! fork() error";
375	goto print_errno;
376    default:
377
378    /*
379     * This is the parent.
380     *
381     * Save the client's PID.
382     *
383     * Close the client's socket.
384     */
385	FdPara[LT_CLNT].pid = CPid;
386	if (FdPara[LT_CLNT].fd >= 0) {
387	    (void) close(FdPara[LT_CLNT].fd);
388	    FdPara[LT_CLNT].fd = -1;
389	}
390    }
391/*
392 * Set a SIGALRM, then accept() the connection from the client.
393 *
394 * Save the client's socket address.
395 *
396 * Replace the server's FD with the accepted one and close the original.
397 */
398    sal = (LT_SOCKLEN_T)sizeof(aa);
399    (void) alarm(0);
400    (void) signal(SIGALRM, HandleSrvrAlarm);
401    (void) alarm(ALARMTM);
402    tsfd = FdPara[LT_SRVR].fd = accept(Ssock, (struct sockaddr *)&aa, &sal);
403    (void) alarm(0);
404    (void) signal(SIGALRM, SIG_DFL);
405    if (tsfd < 0) {
406	ep = "accept";
407	goto print_errno_by_ti;
408    }
409    (void) snprintf(buf, bufl - 1, "%d", tsfd);
410    buf[bufl - 1] = '\0';
411    if (FdPara[LT_SRVR].fds)
412	(void) free((void *)FdPara[LT_SRVR].fds);
413    FdPara[LT_SRVR].fds = MkStrCpy(buf, &tj);
414    ti = LT_CLNT;
415    (void) memcpy((void *)&FdPara[ti].sa, (void *)&aa, sizeof(FdPara[ti].sa));
416    (void) close(Ssock);
417    Ssock = -1;
418/*
419 * Convert the client and server IP address to ASCII form.
420 *
421 * Look up the client and server host names for their IP addresses.
422 *
423 * Convert the port from the socket address to host form.
424 */
425    for (ti = 0; ti < NFDPARA; ti++) {
426	tcp = inet_ntoa(FdPara[ti].sa.sin_addr);
427	FdPara[ti].ipaddr = MkStrCpy(tcp, &FdPara[ti].ilen);
428	(void) snprintf(buf, bufl - 1, "%d",
429	    (int)ntohs(FdPara[ti].sa.sin_port));
430	buf[bufl - 1] = '\0';
431	FdPara[ti].port = MkStrCpy(buf, &FdPara[ti].plen);
432	if (!(hp = gethostbyaddr((char *)&FdPara[ti].sa.sin_addr,
433				 sizeof(FdPara[ti].sa.sin_addr),
434				 FdPara[ti].sa.sin_family))
435	) {
436	    ep = "gethostbyaddr";
437	    goto print_errno_by_ti;
438	}
439	if (hp->h_name)
440	    FdPara[ti].host = MkStrCpy(hp->h_name, &FdPara[ti].hlen);
441	else {
442
443	/*
444	 * The connected client's socket address can't be mapped to a host
445	 * name.
446	 */
447
448	    (void) snprintf(buf, bufl - 1,
449		"ERROR!!!  can't map %s (client) to a host name",
450		FdPara[ti].ipaddr);
451	    buf[bufl - 1] = '\0';
452	    PrtMsgX(buf, Pn, CleanupSrvr, 1);
453	}
454    }
455/*
456 * Call lsof three times to find the two sockets: 1) by host name and port;
457 * 2) by IP address and port; and 3) by port.
458 */
459    if ((cem = FindSock(LT_FBYHN)))
460	PrtMsgX(cem, Pn, CleanupSrvr, 1);
461    if ((cem = FindSock(LT_FBYIP)))
462	PrtMsgX(cem, Pn, CleanupSrvr, 1);
463    if ((cem = FindSock(LT_FBYPORT)))
464	PrtMsgX(cem, Pn, CleanupSrvr, 1);
465/*
466 * Check the FindSock() results.
467 */
468    for (pem = (char *)NULL, ti = 0; ti < NFDPARA; ti++) {
469	if ((tj = FdPara[ti].ff) != (LT_FBYHN | LT_FBYIP | LT_FBYPORT)) {
470	    host = FdPara[ti].host;
471	    ipaddr = FdPara[ti].ipaddr;
472	    port = FdPara[ti].port;
473
474	/*
475	 * This FD wasn't found by some search method.
476	 */
477	    if (!(tj & LT_FBYHN)) {
478
479	    /*
480	     * The search by host name and port failed.
481	     */
482		(void) snprintf(buf, bufl - 1,
483		    "ERROR!!!  no %s socket by host and port: %s@%s",
484		    PtNm[ti], host, port);
485		buf[bufl - 1] = '\0';
486		if (pem)
487		    (void) PrtMsg(pem, Pn);
488		pem = MkStrCpy(buf, &tk);
489	    }
490	    if (!(tj & LT_FBYIP)) {
491
492	    /*
493	     * The search by IP address and port failed.
494	     */
495		(void) snprintf(buf, bufl - 1,
496		    "ERROR!!!  no %s socket by IP and port: %s@%s",
497		    PtNm[ti], ipaddr, port);
498		buf[bufl - 1] = '\0';
499		if (pem)
500		    (void) PrtMsg(pem, Pn);
501		pem = MkStrCpy(buf, &tk);
502	    }
503	    if (!(tj & LT_FBYPORT)) {
504
505	    /*
506	     * The search by port number failed.
507	     */
508		(void) snprintf(buf, bufl - 1,
509		    "ERROR!!!  no %s socket by port: %s",
510		    PtNm[ti], port);
511		buf[bufl - 1] = '\0';
512		if (pem)
513		    (void) PrtMsg(pem, Pn);
514		pem = MkStrCpy(buf, &tk);
515	    }
516	}
517    }
518    if (pem)
519	(void) PrtMsgX(pem, Pn, CleanupSrvr, 1);
520/*
521 * Exit successfully.
522 */
523    (void) PrtMsgX("OK", Pn, CleanupSrvr, 0);
524    return(0);
525}
526
527
528/*
529 * ClntCleanup() -- release client resources
530 */
531
532static void
533CleanupClnt()
534{
535    int tfd;				/* temporary file descriptor */
536
537    if ((tfd = FdPara[LT_CLNT].fd) >= 0) {
538	(void) shutdown(tfd, 2);
539	(void) close(tfd);
540	FdPara[LT_CLNT].fd = -1;
541    }
542}
543
544
545/*
546 * CleanupSrvr() -- release server resources
547 */
548
549static void
550CleanupSrvr()
551{
552    int tfd;				/* temporary file descriptor */
553    int ti;				/* temporary index */
554    pid_t wpid;				/* wait() PID */
555
556    if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
557	(void) shutdown(Ssock, 2);
558	(void) close(Ssock);
559	Ssock = -1;
560    }
561    for (ti = 0; ti < NFDPARA; ti++) {
562	if ((tfd = FdPara[ti].fd) >= 0) {
563	    (void) shutdown(tfd, 2);
564	    (void) close(tfd);
565	    FdPara[ti].fd = -1;
566	}
567    }
568    if (CPid > 0) {
569	wpid = wait3(NULL, WNOHANG, NULL);
570	if (wpid != CPid) {
571	    kill(CPid, SIGKILL);
572	    (void) wait3(NULL, WNOHANG, NULL);
573	}
574	CPid = (pid_t)0;
575    }
576}
577
578
579/*
580 * FindSock() -- find sockets with lsof
581 */
582
583static char *
584FindSock(fn)
585    int fn;				/* function -- an LT_FBY* value */
586{
587    char buf[2048];			/* temporary buffer */
588    int bufl = sizeof(buf);		/* size of buf[] */
589    char *cem;				/* current error message pointer */
590    LTfldo_t *cmdp;			/* command pointer */
591    LTfldo_t *fop;			/* field output pointer */
592    int nf;				/* number of fields */
593    int nl;				/* name length */
594    LTfldo_t *nmp;			/* name pointer */
595    char *opv[5];			/* option vector for ExecLsof() */
596    char *pem = (char *)NULL;		/* previous error message pointer */
597    pid_t pid;				/* PID */
598    int pids = 0;			/* PID found status */
599    int pl;				/* port length */
600    int px;				/* process index -- LT_CLNT or
601					 * LT_SRVR */
602    char *tcp, *tcp1;			/* temporary character pointers */
603    int ti, tj;				/* temporary integers */
604    LTfldo_t *typ;			/* file type pointer */
605/*
606 * Check the function and determine the first lsof option from it.
607 */
608    ti = 0;
609    switch (fn) {
610    case LT_FBYHN:
611	opv[ti++] = "-P";
612	for (tj = 0; tj < NFDPARA; tj++) {
613	    (void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].host,
614		FdPara[tj].port);
615	    buf[bufl - 1] = '\0';
616	    opv[ti++] = MkStrCpy(buf, &pl);
617	}
618	break;
619    case LT_FBYIP:
620	opv[ti++] = "-Pn";
621	for (tj = 0; tj < NFDPARA; tj++) {
622	    (void) snprintf(buf, bufl - 1, "-i@%s:%s", FdPara[tj].ipaddr,
623		FdPara[tj].port);
624	    buf[bufl - 1] = '\0';
625	    opv[ti++] = MkStrCpy(buf, &pl);
626	}
627	break;
628    case LT_FBYPORT:
629	opv[ti++] = "-P";
630	for (tj = 0; tj < NFDPARA; tj++) {
631	    (void) snprintf(buf, bufl - 1, "-i:%s", FdPara[tj].port);
632	    buf[bufl - 1] = '\0';
633	    opv[ti++] = MkStrCpy(buf, &pl);
634	}
635	break;
636    default:
637	(void) snprintf(buf, bufl - 1,
638	    "ERROR!!!  illegal FindSock() function: %d", fn);
639	buf[bufl - 1] = '\0';
640	return(MkStrCpy(buf, &ti));
641    }
642/*
643 * Complete the option vector and start lsof execution.
644 */
645
646#if	defined(USE_LSOF_C_OPT)
647    opv[ti++] = "-C";
648#endif	/* defined(USE_LSOF_C_OPT) */
649
650    opv[ti] = (char *)NULL;
651    if ((cem = ExecLsof(opv)))
652	return(cem);
653/*
654 * Read lsof output.
655 */
656    while ((((FdPara[LT_CLNT].ff & fn) == 0)
657    ||	    ((FdPara[LT_SRVR].ff & fn) == 0))
658    &&	   (fop = RdFrLsof(&nf, &cem))
659    ) {
660	if (cem) {
661	    if (pem)
662		(void) PrtMsg(pem, Pn);
663	    return(cem);
664	}
665	switch (fop->ft) {
666	case LSOF_FID_PID:
667
668	/*
669	 * This is a process information line.
670	 */
671	    pid = (pid_t)atoi(fop->v);
672	    pids = 1;
673	    cmdp = (LTfldo_t *)NULL;
674	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
675		switch (fop->ft) {
676		case LSOF_FID_CMD:
677		    cmdp = fop;
678		    break;
679		}
680	    }
681	    if (!cmdp || ((pid != CPid) && (pid != MyPid)))
682		pids = 0;
683	    break;
684	case LSOF_FID_FD:
685
686	/*
687	 * This is a file descriptor line.
688	 *
689	 * Identify the process -- client or server.
690	 */
691	    if (!pids)
692		break;
693	    if (pid == CPid)
694		px = LT_CLNT;
695	    else if (pid == MyPid)
696		px = LT_SRVR;
697	    else
698		break;
699	/*
700	 * Make sure the FD matches the identified process.
701	 */
702	    if (strcmp(fop->v, FdPara[px].fds))
703		break;
704	/*
705	 * Scan for name and type.
706	 */
707	    nmp = typ  = (LTfldo_t *)NULL;
708	    for (fop++, ti = 1; ti < nf; fop++, ti++) {
709		switch (fop->ft) {
710		case LSOF_FID_NAME:
711		    nmp = fop;
712		    break;
713		case LSOF_FID_TYPE:
714		    typ = fop;
715		    break;
716		}
717	    }
718	/*
719	 * Check the type of the file.
720	 */
721	    if (!typ
722	    ||  (strcasecmp(typ->v, "inet") && strcasecmp(typ->v, "ipv4"))
723	    ) {
724		break;
725	    }
726	/*
727	 * Check the addess in the name, based on the calling function.
728	 */
729	    if (!nmp)
730		break;
731	    tcp = nmp->v;
732	    switch (fn) {
733	    case LT_FBYHN:
734		if (((nl = FdPara[px].hlen) <= 0)
735		||  !(tcp1 = FdPara[px].host)
736		||  strncasecmp(tcp, tcp1, nl)
737		) {
738		    break;
739		}
740		tcp += nl;
741		if ((*tcp++ != ':')
742		||  !(tcp1 = FdPara[px].port)
743		||  ((pl = FdPara[px].plen) <= 0)
744		||  strncmp(tcp, tcp1, pl)
745		) {
746		    break;
747		}
748		tcp += pl;
749		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
750		    FdPara[px].ff |= LT_FBYHN;
751		}
752		break;
753	    case LT_FBYIP:
754		if (((nl = FdPara[px].ilen) <= 0)
755		||  !(tcp1 = FdPara[px].ipaddr)
756		||  strncasecmp(tcp, tcp1, nl)
757		) {
758		    break;
759		}
760		tcp += nl;
761		if ((*tcp++ != ':')
762		||  !(tcp1 = FdPara[px].port)
763		||  ((pl = FdPara[px].plen) <= 0)
764		||  strncmp(tcp, tcp1, pl)
765		) {
766		    break;
767		}
768		tcp += pl;
769		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
770		    FdPara[px].ff |= LT_FBYIP;
771		}
772		break;
773	    case LT_FBYPORT:
774		if (!(tcp = strchr(tcp, ':')))
775		    break;
776		tcp++;
777		if (!(tcp1 = FdPara[px].port)
778		||  ((pl = FdPara[px].plen) <= 0)
779		||  strncmp(tcp, tcp1, pl)
780		) {
781		    break;
782		}
783		tcp += pl;
784		if ((*tcp == '-') || (*tcp == ' ') || !*tcp) {
785		    FdPara[px].ff |= LT_FBYPORT;
786		}
787		break;
788	    }
789	}
790    }
791/*
792 * Clean up and return.
793 */
794    (void) StopLsof();
795    return(pem);
796}
797
798
799/*
800 * HandleClntAlarm() -- handle client alarm
801 */
802
803static SIGHANDLER_T
804HandleClntAlarm(sig)
805    int sig;				/* the signal (SIGALRM) */
806{
807    (void) PrtMsgX("ERROR!!!  client caught an alarm signal", Pn,
808	CleanupClnt, 1);
809}
810
811
812/*
813 * Handle SrvrAlarm() -- handle server alarm
814 */
815
816static SIGHANDLER_T
817HandleSrvrAlarm(sig)
818    int sig;				/* the signal (SIGALRM) */
819{
820    (void) PrtMsgX("ERROR!!!  server caught an alarm signal.", Pn,
821	CleanupSrvr, 1);
822}
823
824
825/*
826 * StartClnt() -- start network client
827 */
828
829static void
830StartClnt(cad)
831    struct sockaddr_in *cad;		/* connection address */
832{
833    struct sockaddr_in ba;		/* bind address */
834    int br;				/* bytes read */
835    char buf[2048];			/* temporary buffer */
836    int bufl = sizeof(buf);		/* size of buf[] */
837    int cr;				/* connect() reply */
838    char *em;				/* error message pointer */
839    int fd = FdPara[LT_CLNT].fd;	/* client's socket FD */
840/*
841 * Close the server's sockets.
842 */
843    if ((Ssock >= 0) && (Ssock != FdPara[LT_SRVR].fd)) {
844	(void) close(Ssock);
845	Ssock = -1;
846    }
847    if (FdPara[LT_SRVR].fd >= 0) {
848	(void) close(FdPara[LT_SRVR].fd);
849	FdPara[LT_SRVR].fd = -1;
850    }
851/*
852 * Bind to the local address.
853 */
854    (void) memcpy((void *)&ba, (void *)&Myad, sizeof(ba));
855    if (bind(fd, (struct sockaddr *)&ba, sizeof(ba)) < 0) {
856	em = "bind";
857
858client_errno:
859
860	(void) snprintf(buf, bufl - 1,
861	    "ERROR!!!  client %s error: %s", em, strerror(errno));
862	buf[bufl - 1] = '\0';
863	(void) PrtMsgX(em, Pn, CleanupClnt, 1);
864    }
865/*
866 * Set an alarm timeout and connect to the server.
867 */
868    (void) signal(SIGALRM, HandleClntAlarm);
869    (void) alarm(ALARMTM);
870    cr = connect(fd, (struct sockaddr *)cad, sizeof(struct sockaddr_in));
871    (void) alarm(0);
872    (void) signal(SIGALRM, SIG_DFL);
873    if (cr) {
874	em = "connect";
875	goto client_errno;
876    }
877/*
878 * Sleep until the socket closes or the parent kills the process.
879 */
880    for (br = 0; br >= 0;) {
881	sleep(1);
882	br = read(fd, buf, bufl);
883    }
884    (void) CleanupClnt();
885    exit(0);
886}
887