Date: Tue, 18 May 1999 01:36:11 -0500 (EST) From: Alfred Perlstein <bright@rush.net> To: Marc Slemko <marcs@znep.com> Cc: hackers@FreeBSD.ORG Subject: forgot some stuff about sysctl: Re: libkvm sucks Message-ID: <Pine.BSF.3.96.990518013321.26546F-100000@cygnus.rush.net> In-Reply-To: <Pine.BSF.4.05.9905172057160.24565-100000@alive.znep.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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 majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.990518013321.26546F-100000>
