Changeset 193
- Timestamp:
- Nov 14, 2008, 8:12:32 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/sh_port2proc.c
r180 r193 46 46 #if defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)) 47 47 48 #if defined(__linux__) 48 /**************************************************************************** 49 * 50 * >>> COMMON CODE <<< 51 * 52 ****************************************************************************/ 53 #if defined(__linux__) || defined(__FreeBSD__) 49 54 50 55 #include "samhain.h" … … 55 60 #define FIL__ _("sh_port2proc.c") 56 61 62 #endif 63 64 /**************************************************************************** 65 * 66 * >>> LINUX CODE <<< 67 * 68 ****************************************************************************/ 69 70 #if defined(__linux__) 71 57 72 static size_t sh_minpid = 0x0001; 58 73 static size_t sh_maxpid = 0x8000; … … 63 78 64 79 #if defined(S_IFLNK) && !defined(S_ISLNK) 65 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)80 # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 66 81 #else 67 # if !defined(S_ISLNK)68 # define S_ISLNK(mode) (0)69 # endif82 # if !defined(S_ISLNK) 83 # define S_ISLNK(mode) (0) 84 # endif 70 85 #endif 71 86 … … 294 309 #include <arpa/inet.h> 295 310 311 /* returns the command and fills the 'user' array 312 */ 296 313 char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport, 297 314 char * user, size_t userlen) … … 350 367 } 351 368 352 #else /* !defined(__linux__) */ 369 370 /**************************************************************************** 371 * 372 * >>> FREEBSD CODE <<< 373 * 374 ****************************************************************************/ 375 376 #elif defined(__FreeBSD__) 377 378 /* Uses code from sockstat.c. Error and memory handling modified. 379 * Only required functions from sockstat.c are included. 380 */ 381 382 /*- 383 * Copyright (c) 2002 Dag-Erling Co<EF>dan Sm<F8>rgrav 384 * All rights reserved. 385 * 386 * Redistribution and use in source and binary forms, with or without 387 * modification, are permitted provided that the following conditions 388 * are met: 389 * 1. Redistributions of source code must retain the above copyright 390 * notice, this list of conditions and the following disclaimer 391 * in this position and unchanged. 392 * 2. Redistributions in binary form must reproduce the above copyright 393 * notice, this list of conditions and the following disclaimer in the 394 * documentation and/or other materials provided with the distribution. 395 * 3. The name of the author may not be used to endorse or promote products 396 * derived from this software without specific prior written permission. 397 * 398 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 399 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 400 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 401 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 402 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 403 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 404 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 405 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 406 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 407 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 408 */ 409 #include <sys/cdefs.h> 410 __FBSDID("$FreeBSD: src/usr.bin/sockstat/sockstat.c,v 1.13.2.1.4.1 2008/10/02 02:57:24 kensmith Exp $"); 411 412 #include <sys/param.h> 413 #include <sys/socket.h> 414 #include <sys/socketvar.h> 415 #include <sys/sysctl.h> 416 #include <sys/file.h> 417 #include <sys/user.h> 418 419 #include <sys/un.h> 420 #include <sys/unpcb.h> 421 422 #include <net/route.h> 423 424 #include <netinet/in.h> 425 #include <netinet/in_pcb.h> 426 #include <netinet/tcp.h> 427 #include <netinet/tcp_seq.h> 428 #include <netinet/tcp_var.h> 429 #include <arpa/inet.h> 430 431 #include <ctype.h> 432 #include <errno.h> 433 #include <netdb.h> 434 #include <stdio.h> 435 #include <stdlib.h> 436 437 #include <unistd.h> 438 439 static int opt_4 = 1; /* Show IPv4 sockets */ 440 static int opt_6 = 0; /* Show IPv6 sockets */ 441 static int opt_c = 0; /* Show connected sockets */ 442 static int opt_l = 1; /* Show listening sockets */ 443 static int opt_u = 0; /* Show Unix domain sockets */ 444 static int opt_v = 0; /* Verbose mode */ 445 446 struct sock { 447 void *socket; 448 void *pcb; 449 int vflag; 450 int family; 451 int proto; 452 453 struct sockaddr_storage laddr; 454 struct sockaddr_storage faddr; 455 struct sock *next; 456 }; 457 458 #define HASHSIZE 1009 459 static struct sock *sockhash[HASHSIZE]; 460 461 static struct xfile *xfiles; 462 static int nxfiles; 463 464 465 static void * xrealloc(void * buf, size_t len0, size_t len) 466 { 467 if (len > 0) 468 { 469 void xbuf = SH_ALLOC(len); 470 memcpy(xbuf, buf, len0); 471 SH_FREE(buf); 472 return xbuf; 473 } 474 SH_FREE(buf); 475 return NULL; 476 } 477 478 /* Sets address and port in struct sockaddr_storage *sa 479 */ 480 static void 481 sockaddr(struct sockaddr_storage *sa, int af, void *addr, int port) 482 { 483 struct sockaddr_in *sin4; 484 struct sockaddr_in6 *sin6; 485 486 bzero(sa, sizeof *sa); 487 switch (af) { 488 case AF_INET: 489 sin4 = (struct sockaddr_in *)sa; 490 sin4->sin_len = sizeof *sin4; 491 sin4->sin_family = af; 492 sin4->sin_port = port; 493 sin4->sin_addr = *(struct in_addr *)addr; 494 break; 495 case AF_INET6: 496 sin6 = (struct sockaddr_in6 *)sa; 497 sin6->sin6_len = sizeof *sin6; 498 sin6->sin6_family = af; 499 sin6->sin6_port = port; 500 sin6->sin6_addr = *(struct in6_addr *)addr; 501 break; 502 default: 503 return; 504 } 505 } 506 507 /* Get socket information from the kernel. 508 */ 509 static void 510 gather_inet(int proto) 511 { 512 struct xinpgen *xig, *exig; 513 struct xinpcb *xip; 514 struct xtcpcb *xtp; 515 struct inpcb *inp; 516 struct xsocket *so; 517 struct sock *sock; 518 char varname[32]; 519 size_t len, bufsize, bufsize0; 520 void *buf; 521 int hash, retry, vflag; 522 523 vflag = 0; 524 if (opt_4) 525 vflag |= INP_IPV4; 526 if (opt_6) 527 vflag |= INP_IPV6; 528 529 switch (proto) { 530 case IPPROTO_TCP: 531 sl_strlcpy(varname, _("net.inet.tcp.pcblist"), sizeof(varname)); 532 break; 533 case IPPROTO_UDP: 534 sl_strlcpy(varname, _("net.inet.udp.pcblist"), sizeof(varname)); 535 break; 536 case IPPROTO_DIVERT: 537 sl_strlcpy(varname, _("net.inet.divert.pcblist"), sizeof(varname)); 538 break; 539 default: 540 return; 541 } 542 543 buf = NULL; 544 bufsize = 8192; 545 bufsize0 = bufsize; 546 retry = 5; 547 do { 548 for (;;) { 549 buf = xrealloc(buf, bufsize0, bufsize); 550 bufsize0 = bufsize; 551 len = bufsize; 552 if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) 553 break; 554 if (errno == ENOENT) 555 goto out; 556 if (errno != ENOMEM) 557 { 558 SH_MUTEX_LOCK(mutex_thread_nolog); 559 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 560 _("sysctlbyname()"), 561 _("gather_inet")); 562 SH_MUTEX_UNLOCK(mutex_thread_nolog); 563 return; 564 } 565 bufsize *= 2; 566 } 567 xig = (struct xinpgen *)buf; 568 exig = (struct xinpgen *)(void *) 569 ((char *)buf + len - sizeof *exig); 570 if (xig->xig_len != sizeof *xig || 571 exig->xig_len != sizeof *exig) 572 { 573 SH_MUTEX_LOCK(mutex_thread_nolog); 574 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 575 _("struct xinpgen size mismatch"), 576 _("gather_inet")); 577 SH_MUTEX_UNLOCK(mutex_thread_nolog); 578 goto out; 579 } 580 581 } while (xig->xig_gen != exig->xig_gen && retry--); 582 583 if (xig->xig_gen != exig->xig_gen && opt_v) 584 { 585 SH_MUTEX_LOCK(mutex_thread_nolog); 586 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 587 _("data may be inconsistent"), 588 _("gather_inet")); 589 SH_MUTEX_UNLOCK(mutex_thread_nolog); 590 } 591 592 for (;;) { 593 xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); 594 if (xig >= exig) 595 break; 596 switch (proto) { 597 case IPPROTO_TCP: 598 xtp = (struct xtcpcb *)xig; 599 if (xtp->xt_len != sizeof *xtp) { 600 SH_MUTEX_LOCK(mutex_thread_nolog); 601 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 602 _("struct xtcpcb size mismatch"), 603 _("gather_inet")); 604 SH_MUTEX_UNLOCK(mutex_thread_nolog); 605 goto out; 606 } 607 inp = &xtp->xt_inp; 608 so = &xtp->xt_socket; 609 break; 610 case IPPROTO_UDP: 611 case IPPROTO_DIVERT: 612 xip = (struct xinpcb *)xig; 613 if (xip->xi_len != sizeof *xip) { 614 SH_MUTEX_LOCK(mutex_thread_nolog); 615 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 616 _("struct xinpcb size mismatch"), 617 _("gather_inet")); 618 SH_MUTEX_UNLOCK(mutex_thread_nolog); 619 goto out; 620 } 621 inp = &xip->xi_inp; 622 so = &xip->xi_socket; 623 break; 624 default: 625 return; 626 } 627 if ((inp->inp_vflag & vflag) == 0) 628 continue; 629 if (inp->inp_vflag & INP_IPV4) { 630 if ((inp->inp_fport == 0 && !opt_l) || 631 (inp->inp_fport != 0 && !opt_c)) 632 continue; 633 } else if (inp->inp_vflag & INP_IPV6) { 634 if ((inp->in6p_fport == 0 && !opt_l) || 635 (inp->in6p_fport != 0 && !opt_c)) 636 continue; 637 } else { 638 if (opt_v) { 639 char errmsg[64]; 640 sl_snprintf(errmsg, sizeof(errmsg), 641 _("invalid vflag 0x%x"), inp->inp_vflag); 642 SH_MUTEX_LOCK(mutex_thread_nolog); 643 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN, 644 errmsg, 645 _("gather_inet")); 646 SH_MUTEX_UNLOCK(mutex_thread_nolog); 647 continue; 648 } 649 } 650 651 sock = SH_ALLOC(sizeof *sock); 652 memset(sock, '\0', sizeof (*sock)); 653 654 sock->socket = so->xso_so; 655 sock->proto = proto; 656 if (inp->inp_vflag & INP_IPV4) { 657 sock->family = AF_INET; 658 sockaddr(&sock->laddr, sock->family, 659 &inp->inp_laddr, inp->inp_lport); 660 sockaddr(&sock->faddr, sock->family, 661 &inp->inp_faddr, inp->inp_fport); 662 } else if (inp->inp_vflag & INP_IPV6) { 663 sock->family = AF_INET6; 664 sockaddr(&sock->laddr, sock->family, 665 &inp->in6p_laddr, inp->in6p_lport); 666 sockaddr(&sock->faddr, sock->family, 667 &inp->in6p_faddr, inp->in6p_fport); 668 } 669 sock->vflag = inp->inp_vflag; 670 671 hash = (int)((uintptr_t)sock->socket % HASHSIZE); 672 sock->next = sockhash[hash]; 673 sockhash[hash] = sock; 674 } 675 out: 676 free(buf); 677 } 678 679 static void 680 getfiles(void) 681 { 682 size_t len; 683 size_t len0; 684 685 xfiles = SH_ALLOC(len = sizeof *xfiles); 686 len0 = len; 687 688 while (sysctlbyname(_("kern.file"), xfiles, &len, 0, 0) == -1) { 689 if (errno != ENOMEM) 690 { 691 SH_MUTEX_LOCK(mutex_thread_nolog); 692 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 693 _("sysctlbyname()"), 694 _("getfiles")); 695 SH_MUTEX_UNLOCK(mutex_thread_nolog); 696 } 697 len *= 2; 698 xfiles = xrealloc(xfiles, len0, len); 699 len0 = len; 700 } 701 if (len > 0 && xfiles->xf_size != sizeof *xfiles) 702 if (errno != ENOMEM) 703 { 704 SH_MUTEX_LOCK(mutex_thread_nolog); 705 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 706 _("struct xfile size mismatch"), 707 _("getfiles")); 708 SH_MUTEX_UNLOCK(mutex_thread_nolog); 709 } 710 nxfiles = len / sizeof *xfiles; 711 } 712 713 static const char * 714 getprocname(pid_t pid) 715 { 716 static struct kinfo_proc proc; 717 size_t len; 718 int mib[4]; 719 720 mib[0] = CTL_KERN; 721 mib[1] = KERN_PROC; 722 mib[2] = KERN_PROC_PID; 723 mib[3] = (int)pid; 724 len = sizeof proc; 725 if (sysctl(mib, 4, &proc, &len, NULL, 0) == -1) { 726 /* Do not warn if the process exits before we get its name. */ 727 if (errno != ESRCH) 728 { 729 SH_MUTEX_LOCK(mutex_thread_nolog); 730 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_SUBGEN, 731 _("sysctl()"), 732 _("getfiles")); 733 SH_MUTEX_UNLOCK(mutex_thread_nolog); 734 } 735 return ("-"); 736 } 737 return (proc.ki_ocomm); 738 } 739 740 char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport, 741 char * user, size_t userlen) 742 { 743 struct xfile *xf; 744 struct in_addr * haddr; 745 746 for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) { 747 748 if (xf->xf_data == NULL) 749 continue; 750 751 /* Find the socket in sockhash[] that corresponds to it 752 */ 753 hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); 754 for (s = sockhash[hash]; s != NULL; s = s->next) 755 if ((void *)s->socket == xf->xf_data) 756 break; 757 758 if (s->proto != proto) 759 continue; 760 761 if (s->family != AF_INET /* && s->family != AF_INET6 */) 762 continue; 763 764 if (sport != ntohs(((struct sockaddr_in *)s)->sin_port)) 765 continue; 766 767 haddr = &((struct sockaddr_in *)s)->sin_addr; 768 if (haddr.s_addr == saddr->s_addr) 769 { 770 char * tmp = sh_unix_getUIDname (SH_ERR_ALL, xf->xf_uid, user, userlen); 771 if (!tmp) 772 sl_snprintf (user, userlen, "%ld", (unsigned long) xf->xf_uid); 773 return sh_util_strdup(getprocname(xf->xf_pid)); 774 } 775 } 776 } 777 778 static void sockdel(struct sock * sock) 779 { 780 if (sock) 781 { 782 if (sock->next) 783 sockdel(sock->next); 784 SH_FREE(sock); 785 } 786 return; 787 } 788 789 int sh_port2proc_prepare() 790 { 791 int i; 792 793 if (xfiles) 794 { 795 SH_FREE(xfiles); 796 xfiles = NULL; 797 } 798 799 for (i = 0; i < HASHSIZE; ++i) 800 sockdel(sockhash[i]); 801 802 /* Inet connections 803 */ 804 gather_inet(IPPROTO_TCP); 805 gather_inet(IPPROTO_UDP); 806 gather_inet(IPPROTO_DIVERT); 807 808 getfiles(); 809 810 return 0; 811 } 812 813 #else /* !defined(__linux__) && !defined(__FreeBSD__) */ 353 814 354 815 char * sh_port2proc_query(int proto, struct in_addr * saddr, int sport,
Note:
See TracChangeset
for help on using the changeset viewer.