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