"Fossies" - the Fresh Open Source Software Archive

Member "pidentd-3.0.19/src/k_sunos55.c" (10 Aug 1999, 9010 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_sunos55.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2 ** k_sunos55.c - SunOS 5.5 and 5.5.1 kernel access functions.
    3 **
    4 ** Copyright (c) 1995-1997 Casper Dik <Casper.Dik@Holland.Sun.COM>
    5 ** Copyright (c) 1997-1998 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 #include "config.h"
   17 
   18 #if 0
   19 #define DEBUGHASH
   20 #endif
   21 
   22 #define _KMEMUSER
   23 #define _KERNEL
   24 
   25 /* some definition conflicts. but we must define _KERNEL */
   26 
   27 #define exit        kernel_exit
   28 #define strsignal   kernel_strsignal
   29 #define mutex_init  kernel_mutex_init
   30 #define mutex_destroy   kernel_mutex_destroy
   31 #define sema_init   kernel_sema_init
   32 #define sema_destroy    kernel_sema_destroy
   33 
   34 #include <syslog.h>
   35 
   36 #ifdef _POSIX_C_SOURCE
   37 #define DEF_POSIX_C_SOURCE _POSIX_C_SOURCE
   38 #undef _POSIX_C_SOURCE
   39 #endif
   40 #include <sys/types.h>
   41 #include <sys/socket.h>
   42 #include <sys/signal.h>
   43 #include <sys/param.h>
   44 #include <netinet/in.h>
   45 #ifdef DEF_POSIX_C_SOURCE
   46 #define  _POSIX_C_SOURCE DEF_POSIX_C_SOURCE
   47 #endif
   48 
   49 #include <stdio.h>
   50 #include <kvm.h>
   51 #include <nlist.h>
   52 #include <math.h>
   53 #include <stddef.h>
   54 #include <sys/fcntl.h>
   55 #include <sys/cred.h>
   56 #include <sys/file.h>
   57 #include <sys/stream.h>
   58 #include <inet/common.h>
   59 #include <inet/ip.h>
   60 
   61 /*
   62  * This really doesn't apply to 2.5.1, but this
   63  * way you can run 2.5.1 binaries on 2.5 and vv
   64  */
   65 #define BROKEN_HASH
   66 
   67 #define FANOUT_OFFSET(n)    (kip->nl[N_FANOUT].n_value + (n) * sizeof(ipc_t *))
   68 
   69 #undef exit
   70 #undef strsignal
   71 #undef mutex_init
   72 #undef mutex_destroy
   73 #undef sema_init
   74 #undef sema_destroy
   75 
   76 #undef SEMA_HELD
   77 #undef RW_LOCK_HELD
   78 #undef RW_READ_HELD
   79 #undef RW_WRITE_HELD
   80 #undef MUTEX_HELD
   81 
   82 
   83 #include <unistd.h>
   84 #include <string.h>
   85 #include <stddef.h>
   86 
   87 
   88 #include "pidentd.h"
   89 
   90 #define N_FANOUT 0
   91 
   92 
   93 struct kainfo
   94 {
   95     kvm_t *kd;
   96     struct nlist nl[2];
   97 };
   98 
   99 
  100 /*
  101 ** Make sure we are running on a supported OS version
  102 */
  103 int
  104 ka_init(void)
  105 {
  106     /* XXX: Should probably allow both 5.5 and 5.5.1 */
  107     
  108     char osinfo_current[256];
  109 
  110     if (osinfo_get(osinfo_current) == NULL)
  111     return -1;
  112 
  113     return strcmp(osinfo_build, osinfo_current);
  114 }
  115 
  116 
  117 /*
  118 ** Open kernel devices, lookup kernel symbols etc... 
  119 */
  120 int
  121 ka_open(void **misc)
  122 {
  123     struct kainfo *kp;
  124 
  125 
  126     kp = s_malloc(sizeof(*kp));
  127     
  128     /*
  129     ** Open the kernel memory device
  130     */
  131     if ((kp->kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
  132     {
  133     syslog(LOG_ERR, "kvm_open: %m");
  134     s_free(kp);
  135     return -1;
  136     }
  137     
  138     
  139     kp->nl[0].n_name = "ipc_tcp_fanout";
  140     kp->nl[1].n_name = NULL;
  141     
  142     /*
  143     ** Extract offsets to the needed variables in the kernel
  144     */
  145     if (kvm_nlist(kp->kd, kp->nl) != 0)
  146     {
  147     syslog(LOG_ERR, "kvm_nlist: %m");
  148     kvm_close(kp->kd);
  149     s_free(kp);
  150     return -1;
  151     }
  152 
  153     *misc = (void *) kp;
  154     return 0;
  155 }
  156 
  157 
  158 /*
  159 ** Get a piece of kernel memory with error handling.
  160 ** Returns 1 if call succeeded, else 0 (zero).
  161 */
  162 static int
  163 getbuf(kvm_t *kd,
  164        off_t addr,
  165        char *buf,
  166        size_t len,
  167        char *what)
  168 {
  169     int i;
  170     ssize_t status;
  171     
  172     
  173     i = 0;
  174     while (i < 5 && (status = kvm_read(kd, addr, buf, len)) < 0)
  175     ++i;
  176     
  177     if (status < 0)
  178     return 0;
  179     
  180     return 1;
  181 }
  182 
  183 
  184 
  185 
  186 /*
  187 ** Return the user number for the connection owner
  188 */
  189 int
  190 ka_lookup(void *vp, struct kernel *kp)
  191 {
  192     struct kainfo *kip;
  193     
  194     struct in_addr *faddr;
  195     int fport;
  196     struct in_addr *laddr;
  197     int lport;
  198 
  199     queue_t sqr;
  200     ipc_t ic, *icp;
  201     unsigned short uslp, usfp;
  202     unsigned int offset;
  203     file_t tf;
  204     unsigned long zero = 0;
  205     u16 *ports;
  206     u32 *locaddr, *raddr;
  207 #ifdef DEBUGHASH
  208     int i;
  209 #endif
  210     struct proc *procp;
  211 #ifdef BROKEN_HASH
  212     ipc_t *alticp = NULL;
  213     unsigned int altoffset;
  214 #endif
  215 
  216     kip = (struct kainfo *) vp;
  217     
  218     faddr = &kp->remote.sin_addr;
  219     laddr = &kp->local.sin_addr;
  220     fport = kp->remote.sin_port;
  221     lport = kp->local.sin_port;
  222     
  223     usfp = fport;
  224     uslp = lport;
  225 
  226 #ifdef BROKEN_HASH
  227     /* code used (ports > 8) instead of (ports >> 8)
  228        low byte of local port number not used, low byte of 
  229        local addres is used
  230     ip_bind  in the kernel (+ approx 0x4c0)
  231                 srl     %i3, 0x18, %o0
  232                 xor     %i2, %o0, %o0
  233                 srl     %i3, 0x10, %o1
  234                 xor     %o0, %o1, %o0
  235                 xor     %o0, %l0, %o0
  236                 xor     %o0, %i3, %o0
  237                 and     %o0, 0xff, %o0
  238                 sethi   %hi(0xfc1d9c00), %o2
  239                 or      %o2, 0x1c0, %o2          ! ipc_tcp_fanout
  240 
  241      */
  242 #if (defined(BIG_ENDIAN) || defined(_BIG_ENDIAN))
  243     altoffset = usfp >> 8;
  244 #else
  245     altoffset = uslp >> 8;
  246 #endif
  247     altoffset ^= usfp ^ uslp;
  248     altoffset ^= faddr->S_un.S_un_b.s_b4;
  249     if (uslp > 8 || usfp != 0)
  250     altoffset ^= 1;
  251     altoffset &= 0xff;
  252     if (!getbuf(kip->kd, (off_t) FANOUT_OFFSET(altoffset),
  253         (char *) &alticp,
  254         sizeof(ipc_t *),
  255         "ipc_tcp_fanout[altoffset]"))
  256     alticp = NULL;
  257 #endif
  258     
  259     offset = usfp ^ uslp;
  260     offset ^= (unsigned) faddr->S_un.S_un_b.s_b4 ^ (offset >> 8);
  261     offset &= 0xff;
  262 
  263     if (!getbuf(kip->kd, (off_t) FANOUT_OFFSET(offset),
  264         (char *) &icp,
  265         sizeof(ipc_t *),
  266         "ipc_tcp_fanout[offset]"))
  267     return -1;
  268     
  269 #ifdef BROKEN_HASH
  270     if (icp == NULL && alticp != NULL) {
  271     icp = alticp;
  272     alticp = NULL;
  273     }
  274 #endif
  275 #ifndef DEBUGHASH
  276     if (icp == NULL) {
  277     syslog(LOG_DEBUG, "ka_lookup: hash miss");
  278     return 0;
  279     }
  280 #endif
  281 
  282     locaddr = &ic.ipc_tcp_laddr;
  283     raddr = &ic.ipc_tcp_faddr;
  284     ports = (u16 *) &ic.ipc_tcp_ports;
  285 
  286 #ifdef DEBUGHASH
  287   for (i = 0; i < 256; i++) {
  288     if (!getbuf(kip->kd, (off_t) FANOUT_OFFSET(i),
  289         (char *) &icp,
  290         sizeof(ipc_t *),
  291         "ipc_tcp_fanout[offset]"))
  292     return -1;
  293     if (icp == NULL)
  294     continue;
  295 #endif
  296 
  297     while (icp != NULL) {
  298     if (!getbuf(kip->kd,
  299             (off_t) icp,
  300             (char *) &ic,
  301             sizeof(ic),
  302             "hash entry"))
  303         return -1;
  304 
  305     if (usfp == ports[0] && /* remote port */
  306         uslp == ports[1] && /* local port */
  307 #if 0
  308         memcmp(&laddr->s_addr, locaddr, 4) == 0 && /* local */
  309 #else
  310         (memcmp(&laddr->s_addr, locaddr, 4) == 0 ||
  311         /* In SunOS 5.3, the local part can be all zeros */
  312          memcmp(&zero, locaddr, 4) == 0) /* local */ &&
  313 #endif
  314         memcmp(&faddr->s_addr, raddr, 4) == 0)
  315         break;
  316     icp = ic.ipc_hash_next;
  317 #ifdef BROKEN_HASH
  318     if (icp == NULL && alticp != NULL) {
  319         icp = alticp;
  320         alticp = NULL;
  321     }
  322 #endif
  323     }
  324 #ifdef DEBUGHASH
  325     if (icp != NULL)
  326     break;
  327   } /* for i */
  328   
  329     if (icp != NULL)
  330     printf("found, offset = %x, i = %x, i ^ offset = %x\n", offset, i,
  331         offset ^ i);
  332 #endif
  333 
  334     if (icp == NULL) {
  335     syslog(LOG_INFO, "ka_lookup: port not found");
  336     return 0;
  337     }
  338     
  339     if (!getbuf(kip->kd,
  340         (off_t) ic.ipc_rq+offsetof(queue_t, q_stream),
  341         (char *) &sqr.q_stream,
  342         sizeof(sqr.q_stream),
  343         "queue.q_stream"))
  344     return -1;
  345 
  346     /* at this point sqr.q_stream holds the pointer to the stream we're
  347        interested in. Now we're going to find the file pointer
  348        that refers to the vnode that refers to this stream stream */
  349 
  350     /* Solaris 2.4 no longer links all file pointers together with
  351      * f_next, the only way seems to be scrounging them from
  352      * the proc/user structure, ugh.
  353      */
  354 
  355     if (kvm_setproc(kip->kd) != 0)
  356     return -1;
  357 
  358     while ((procp = kvm_nextproc(kip->kd)) != NULL) {
  359     struct uf_entry files[NFPCHUNK];
  360     int nfiles = procp->p_user.u_nofiles;
  361     off_t addr = (off_t) procp->p_user.u_flist;
  362 
  363     while (nfiles > 0) {
  364         int nread = nfiles > NFPCHUNK ? NFPCHUNK : nfiles;
  365         int size = nread * sizeof(struct uf_entry);
  366         int i;
  367         struct file *last = NULL;
  368         vnode_t vp;
  369 
  370         if (!getbuf(kip->kd, addr, (char*) &files[0],
  371             size, "ufentries")) {
  372         return -1;
  373         }
  374         for (i = 0; i < nread; i++) {
  375         if (files[i].uf_ofile == 0 || files[i].uf_ofile == last)
  376             continue;
  377         if (!getbuf(kip->kd,
  378                 (off_t) (last = files[i].uf_ofile),
  379                 (char*) &tf, sizeof(tf), "file pointer"))
  380         {
  381             return -1;
  382         }
  383 
  384         if (tf.f_vnode == NULL)
  385             continue;
  386 
  387         if (!getbuf(kip->kd,
  388                 (off_t) tf.f_vnode + offsetof(vnode_t,v_stream),
  389                 (char *) &vp.v_stream,
  390                 sizeof(vp.v_stream), "vnode.v_stream"))
  391             return -1;
  392 
  393         if (vp.v_stream == sqr.q_stream) {
  394             cred_t cr;
  395             struct pid p;
  396 
  397             if (!getbuf(kip->kd,
  398                 (off_t) tf.f_cred,
  399                 (char *) &cr,
  400                 sizeof(cr),
  401                 "cred"))
  402             return -1;
  403             kp->ruid = cr.cr_ruid;
  404             kp->euid = cr.cr_uid;
  405             
  406             if (getbuf(kip->kd,
  407                    (off_t) procp->p_pidp,
  408                    (char *) &p,
  409                    sizeof(struct pid),
  410                    "pidp"))
  411             {
  412             kp->pid = p.pid_id;
  413             /* get cmd */
  414             kp->cmd = s_strdup(procp->p_user.u_comm);
  415             /* get cmd args */
  416             kp->argv = s_strdup(procp->p_user.u_psargs);
  417             }
  418             
  419             return 1;
  420         }
  421         }
  422         nfiles -= nread;
  423         addr += size;
  424     }
  425     }
  426     
  427     return 0;
  428 }