"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/k_sunos510.c" (18 Oct 2005, 6776 Bytes) of package /linux/misc/old/pidentd-3.0.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "k_sunos510.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** k_sunos510.c - SunOS 5.10 kernel access functions
    3 **
    4 ** Copyright (c) 1995-2003 Casper Dik <Casper.Dik@Holland.Sun.COM>
    5 ** Copyright (c) 1997      Peter Eriksson <pen@lysator.liu.se>
    6 **
    7 ** This program is free software; you can redistribute it and/or
    8 ** modify it as you wish - as long as you don't claim that you wrote
    9 ** it.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   14 **
   15 */
   16 
   17 #include "config.h"
   18 
   19 #include <unistd.h>
   20 #include <string.h>
   21 #include <stddef.h>
   22 
   23 #include <stdio.h>
   24 #include <nlist.h>
   25 #include <math.h>
   26 
   27 #define _KMEMUSER
   28 #define _KERNEL
   29 
   30 #include <sys/cred_impl.h>
   31 #include <kvm.h>
   32 
   33 /* some definition conflicts. but we must define _KERNEL */
   34 
   35 #define ffs     kernel_ffs
   36 #define ka_init     kernel_ka_init
   37 #define getbuf      kernel_ka_init
   38 #define exit        kernel_exit
   39 #define strsignal   kernel_strsignal
   40 #define mutex_init  kernel_mutex_init
   41 #define mutex_destroy   kernel_mutex_destroy
   42 #define sema_init   kernel_sema_init
   43 #define sema_destroy    kernel_sema_destroy
   44 
   45 #include <syslog.h>
   46 
   47 #include <sys/types.h>
   48 #include <sys/socket.h>
   49 #include <sys/signal.h>
   50 #include <sys/param.h>
   51 #include <netinet/in.h>
   52 
   53 #include <sys/fcntl.h>
   54 #include <sys/cred.h>
   55 #include <sys/file.h>
   56 #include <sys/stream.h>
   57 #include <sys/dlpi.h>
   58 #include <net/if_types.h>
   59 #include <inet/common.h>
   60 #include <netinet/ip6.h>
   61 #include <inet/ip.h>
   62 #include <inet/tcp.h>
   63 #include <inet/ipclassifier.h>
   64 #include <netinet/ip6.h>
   65 #include <net/if.h>
   66 
   67 uint_t   ipcl_conn_fanout_size;
   68 
   69 #if   !defined(IN6_V4_MAPPED_TO_INADDR)
   70 
   71 #define IPv6_2_IPv4(v6, v4)                                     \
   72         ((v4)->s_addr = *((uint32_t *)                          \
   73                 (((uint8_t *)((struct in6_addr *)v6)->s6_addr)+12)))
   74 
   75 #else         /*  defined(IN6_V4_MAPPED_TO_INADDR) */
   76 
   77 #define IPv6_2_IPv4(v6, v4) IN6_V4MAPPED_TO_INADDR((struct in6_addr *)v6, v4)
   78 
   79 #endif        /* defined(IN6_V4MAPPED_TO_INADDR) */
   80 
   81 #define FANOUT_OFFSET(n)  (kip->hash_table + (n) * sizeof(connf_t) + \
   82             offsetof(connf_t, connf_head))
   83 
   84 #undef exit
   85 #undef strsignal
   86 #undef mutex_init
   87 #undef mutex_destroy
   88 #undef sema_init
   89 #undef sema_destroy
   90 #undef ffs
   91 #undef ka_init
   92 #undef getbuf
   93 
   94 #undef SEMA_HELD
   95 #undef RW_LOCK_HELD
   96 #undef RW_READ_HELD
   97 #undef RW_WRITE_HELD
   98 #undef MUTEX_HELD
   99 
  100 #include "pidentd.h"
  101 
  102 #define N_FANOUT 0
  103 #define N_HASH_SIZE 1
  104 
  105 struct kainfo
  106 {
  107     kvm_t *kd;
  108     uint_t hash_size;
  109     unsigned long hash_table;
  110     struct nlist nl[3];
  111 };
  112 
  113 
  114 /*
  115 ** Make sure we are running on a supported OS version
  116 */
  117 int
  118 ka_init(void)
  119 {
  120     char osinfo_current[256];
  121 
  122     if (osinfo_get(osinfo_current) == NULL)
  123     return -1;
  124 
  125     return strcmp(osinfo_build, osinfo_current);
  126 }
  127 
  128 /*
  129 ** Get a piece of kernel memory with error handling.
  130 ** Returns 1 if call succeeded, else 0 (zero).
  131 */
  132 static int
  133 getbuf(kvm_t *kd, off_t addr, char *buf, size_t len, char *what)
  134 {
  135     int i;
  136     ssize_t status;
  137     
  138     
  139     i = 0;
  140     while (i < 5 && (status = kvm_read(kd, addr, buf, len)) < 0)
  141     ++i;
  142     
  143     if (status < 0)
  144     return 0;
  145     
  146     return 1;
  147 }
  148 
  149 
  150 /*
  151 ** Open kernel devices, lookup kernel symbols etc... 
  152 */
  153 int
  154 ka_open(void **misc)
  155 {
  156     struct kainfo *kp;
  157 
  158 
  159     kp = s_malloc(sizeof(*kp));
  160     
  161     /*
  162     ** Open the kernel memory device
  163     */
  164     if ((kp->kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
  165     {
  166     syslog(LOG_ERR, "kvm_open: %m");
  167     s_free(kp);
  168     return -1;
  169     }
  170     
  171     
  172     kp->nl[0].n_name = "ipcl_conn_fanout";
  173     kp->nl[1].n_name = "ipcl_conn_fanout_size";
  174     kp->nl[2].n_name = NULL;
  175     
  176     /*
  177     ** Extract offsets to the needed variables in the kernel
  178     */
  179     if (kvm_nlist(kp->kd, kp->nl) != 0)
  180     {
  181     syslog(LOG_ERR, "kvm_nlist: %m");
  182     kvm_close(kp->kd);
  183     s_free(kp);
  184     return -1;
  185     }
  186 
  187     /*
  188      * Read the two kernel values we need but won't change
  189      */
  190     if (!getbuf(kp->kd, kp->nl[N_HASH_SIZE].n_value, (char *) &kp->hash_size,
  191         sizeof(kp->hash_size), kp->nl[N_HASH_SIZE].n_name) ||
  192     !getbuf(kp->kd, kp->nl[N_FANOUT].n_value, (char *) &kp->hash_table,
  193     sizeof(kp->hash_table), kp->nl[N_FANOUT].n_name)) {
  194         kvm_close(kp->kd);
  195         s_free(kp);
  196         syslog(LOG_ERR, "getbuf: can't get needed symbols");
  197         return -1;
  198     }
  199 
  200     *misc = (void *) kp;
  201     return 0;
  202 }
  203 
  204 
  205 
  206 /*
  207 ** Return the user number for the connection owner
  208 */
  209 int
  210 ka_lookup(void *vp, struct kernel *kp)
  211 {
  212     struct kainfo *kip;
  213     unsigned short uslp, usfp;
  214     unsigned int offset;
  215     file_t tf;
  216     unsigned long zero = 0;
  217     uint32_t *locaddr, *raddr;
  218     struct proc *procp;
  219     char *faddr;
  220     int fport;
  221     char *laddr;
  222     int lport;
  223     struct stdata *std;
  224     conn_t *connfp;
  225     queue_t *q;
  226     char *iphash;
  227     cred_t cr;
  228     conn_t con;
  229     uint_t ports;
  230     uint16_t *pptr = (uint16_t *)&ports;
  231     
  232     kip = (struct kainfo *) vp;
  233     
  234     faddr = (char *) SGADDRP(kp->remote);
  235     laddr = (char *) SGADDRP(kp->local);
  236     fport = SGPORT(kp->remote);
  237     lport = SGPORT(kp->local);
  238 
  239     /* XXX: the V4_PART macros don't work and port to well to this */
  240     iphash = SGFAM(kp->remote) == AF_INET ? faddr : faddr + 12;
  241     
  242     usfp = fport;
  243     uslp = lport;
  244     
  245     /*
  246      * All tcp connections are in one single hash table; IPV4 connections
  247      * over AF_INET6 sockets do not show up in the normal tcp hash tables
  248      *
  249      * First we need to find the hash entry in the tcp table;
  250      * then we need to follow the chain and get the TCP entry.
  251      */
  252 
  253     pptr[0] = fport;
  254     pptr[1] = lport;
  255     /* XXX: need to change in build 46 */
  256     offset = (unsigned)ntohl(*(uint_t *)iphash) ^
  257     (ports >> 24) ^ (ports >> 16) ^ (ports >> 8) ^ ports;
  258 
  259     offset %= kip->hash_size;
  260 
  261     if (!getbuf(kip->kd, FANOUT_OFFSET(offset), (char*) &connfp, sizeof(connfp),
  262     "ipcl_conn_fanout[hash]"))
  263         return -1;
  264 
  265     if (connfp == NULL) {
  266      syslog(LOG_DEBUG, "k_getuid: tcp hash miss");
  267      return -1;
  268     }
  269 
  270     while (connfp != NULL) {
  271 
  272     if (!getbuf(kip->kd, (unsigned long) connfp, (char *) &con, sizeof(con),
  273         "struct conn_s"))
  274         return -1;
  275 
  276     if (uslp == con.conn_lport && usfp == con.conn_fport) {
  277         if (SGFAM(kp->remote) == AF_INET) {
  278         struct in_addr fv4, lv4;
  279         IPv6_2_IPv4(&con.conn_srcv6, &lv4);
  280         IPv6_2_IPv4(&con.conn_remv6, &fv4);
  281         if (memcmp(&lv4, laddr, 4) == 0 && memcmp(&fv4, faddr, 4) == 0)
  282             break;
  283         } else if (memcmp(&con.conn_srcv6, laddr, SGSIZE(kp->local))
  284              == 0 &&
  285             memcmp(&con.conn_remv6, faddr, SGSIZE(kp->remote))
  286              == 0) {
  287                 break;
  288         }
  289     }
  290 
  291     connfp = con.conn_next;
  292     }
  293 
  294     if (connfp == NULL)
  295     return -1;
  296 
  297     if (!getbuf(kip->kd, (off_t) con.conn_cred, (char *) &cr,
  298                 sizeof(cr), "cred"))
  299     return -1;
  300     
  301     kp->ruid = cr.cr_ruid;
  302     kp->euid = cr.cr_uid;
  303 
  304     return (1);
  305 }