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