On Mon, 17 May 1999, Marc Slemko wrote:

> The premise: libkvm is fatally flawed by design, and fixing it is not an
> easy proposition.
> 
> The reasoning: reading from kernel data structures without any locking has
> obvious race conditions.  
> 
> This is why any identd that uses libkvm sucks and gets into loops all the 
> time, etc.
> 
> This is why netstat will often bail out in the middle with kvm errors on a
> busy machine with lots of TCP connections, especially if you slow it down
> by doing hostname lookups.
> 
> In fact, on BSDI systems I have even seen identd hang the entire machine
> hard by reading from the wrong address that the IO APIC is mapped at (BSDI
> maps it starting at 0xffff0000, which much worse than a random address
> for accidental reads).
> 
> In general, I'm no fan of the Linux style proc (by "Linux style" I mean
> going crazy with the types of info there and the huge amount of formatting
> done in the kernel), but in this case it can work a whole lot better, even
> if it is somewhat less efficient.
> 
> I'm sure this isn't a new problem, but I don't recall hearing of any
> suggested solutions and I'm not aware of any alternative interface to get
> the same info on FreeBSD.  Anyone?

doh: you also need a buncha headers:

#include <stdio.h>
#include <unistd.h>

#include <pthread.h>
#include <string.h>

#include <stdarg.h> 
#include <sys/types.h>
#include <pwd.h> 

#include <sys/time.h>

#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>

#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_seq.h>   
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_debug.h>     

#define NO_ERR                          0
#define ERR_SYSCTL                      1
#define ERR_MALLOC                      2
#define ERR_NOUSER                      3
#define ERR_READ                        4
#define ERR_TIMEOUT_READ        5
#define ERR_WRITE                       6
#define ERR_TIMEOUT_WRITE       7

you may be able to trim this list, and here's that function again:

uid_t get_sok_uid(u_short lport, u_short fport, int *err){

/* mostly stolen from netstat */
        char    *mibvar =       "net.inet.tcp.pcblist";
        char    *buf;
        int             proto = IPPROTO_TCP;
        
        uid_t   retval = 0;

        struct tcpcb *tp;
        struct inpcb *inp;
        struct xinpgen *xig, *oxig;
        struct xsocket *so;
        size_t len = 0;
        
        *err = NO_ERR;  

    if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
        *err = ERR_SYSCTL;
                return(0);
    }
        if ((buf = (char *) malloc(len)) == 0) {
        *err = ERR_MALLOC;
        return(0);
    }
    if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
        *err = ERR_SYSCTL;
                free(buf);
        return(0);
    } 
   


        oxig = xig = (struct xinpgen *)buf;
        for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
             xig->xig_len > sizeof(struct xinpgen);
             xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {

                tp = &((struct xtcpcb *)xig)->xt_tp;
                inp = &((struct xtcpcb *)xig)->xt_inp;
                so = &((struct xtcpcb *)xig)->xt_socket;

                /* Ignore sockets for protocols other than the desired one. */
                if (so->xso_protocol != proto)
                        continue;

                /* Ignore PCBs which were freed during copyout. */
                if (inp->inp_gencnt > oxig->xig_gen)
                        continue;


                /* check port */
                if (    htons(inp->inp_fport) == fport && 
                                htons(inp->inp_lport) == lport){
                        printf("pgid = %d\n", so->so_pgid);
                        retval = so->so_uid;
                        free(buf);
                        return( retval );
                }
        }
        *err = ERR_NOUSER;
        free(buf);
}


-Alfred



To Unsubscribe: send mail to [email protected]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to