Subject: kern/2352: ident daemon is slow, it should not use /dev/kmem at all
To: None <gnats-bugs@NetBSD.ORG>
From: Tor Egge <tegge@idt.unit.no>
List: netbsd-bugs
Date: 04/29/1996 20:24:12
>Number:         2352
>Category:       kern
>Synopsis:       ident daemon is slow, it should not use /dev/kmem at all
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Apr 29 14:50:01 1996
>Last-Modified:
>Originator:     tegge@idt.unit.no
>Organization:
	Norwegian Instistute of Science and Technology
>Release:        NetBSD-current
>Environment:
System: NetBSD ikke.idt.unit.no 1.1B NetBSD 1.1B (TEGGE) #13: Tue Apr 23 00:45:57 MET DST 1996 root@ikke.idt.unit.no:/usr/src/sys/arch/i386/compile/TEGGE i386


>Description:
	Significant delays in
	  - WWW client browser contacting nearby servers 
	  - Sendmail to a large mailing list
>How-To-Repeat:
>Fix:

This is just an example of how it can be done. The modified identd 
has to run as root, thus the inetd.conf file has to be edited too.
identd should be statically linked, to reduce the startup overhead.

Defining a new ioctl, possible on a new device, may be a better solution.


*** /usr/src/libexec/identd/Makefile.orig	Tue Apr 23 01:25:58 1996
--- usr/src/libexec/identd/Makefile	Tue Apr 23 01:26:01 1996
***************
*** 4,10 ****
  SRCS=	config.c identd.c netbsd.c parse.c proxy.c version.c
  MAN=	identd.8
  
! LDADD=	-lkvm
  DPADD=	${LIBKVM}
  
  .include <bsd.prog.mk>
--- 4,10 ----
  SRCS=	config.c identd.c netbsd.c parse.c proxy.c version.c
  MAN=	identd.8
  
! LDADD=	-static
  DPADD=	${LIBKVM}
  
  .include <bsd.prog.mk>
*** /usr/src/libexec/identd/identd.c.orig	Sat Oct 14 02:05:17 1995
--- usr/src/libexec/identd/identd.c	Tue Apr 23 01:02:15 1996
***************
*** 177,186 ****
--- 177,188 ----
  #else
    int status;
  #endif
+   int save_errno = errno;
  
    while (wait3(&status, WNOHANG, NULL) > 0)
      ;
    
+   errno = save_errno;
  #ifndef SIGRETURN_TYPE_IS_VOID
    return 0;
  #endif
***************
*** 457,462 ****
--- 459,474 ----
      if (setuid(set_uid) == -1)
        ERROR("main: setuid");
  
+   if (syslog_flag) {
+ #ifdef LOG_DAEMON
+     openlog("identd", LOG_PID, syslog_facility);
+ #else
+     openlog("identd", LOG_PID);
+ #endif
+   }
+   getpwnam("xyzzy");
+   gethostbyname("xyzzy");
+     
    /*
    ** Do some special handling if the "-b" or "-w" flags are used
    */
***************
*** 580,591 ****
    */
    if (syslog_flag)
    {
- #ifdef LOG_DAEMON
-     openlog("identd", LOG_PID, syslog_facility);
- #else
-     openlog("identd", LOG_PID);
- #endif
-     
      syslog(LOG_INFO, "Connection from %s", gethost(&faddr));
    }
    
--- 592,597 ----
*** /usr/src/libexec/identd/netbsd.c.orig	Sat Oct 14 02:05:18 1995
--- usr/src/libexec/identd/netbsd.c	Tue Apr 23 00:52:16 1996
***************
*** 20,26 ****
  #include <signal.h>
  #include <syslog.h>
  
- #include "kvm.h"
  
  #include <sys/types.h>
  #include <sys/stat.h>
--- 20,25 ----
***************
*** 67,169 ****
  extern void *malloc();
  
  
- struct nlist nl[] =
- {
- #define N_FILE 0
- #define N_NFILE 1
- #define N_TCBTABLE 2
-       
-   { "_filehead" },
-   { "_nfiles" },
-   { "_tcbtable" },
-   { "" }
- };
- 
- static kvm_t *kd;
- 
- static struct file *xfile;
- static int nfile;
- 
- static struct inpcbtable tcbtable;
-   
- 
  int k_open()
  {
-   char errbuf[_POSIX2_LINE_MAX];
- 
-   /*
-   ** Open the kernel memory device
-   */
-   if ((kd = kvm_openfiles(path_unix, path_kmem, NULL, O_RDONLY, errbuf)) ==
-       NULL)
-     ERROR1("main: kvm_open: %s", errbuf);
-   
-   /*
-   ** Extract offsets to the needed variables in the kernel
-   */
-   if (kvm_nlist(kd, nl) < 0)
-     ERROR("main: kvm_nlist");
- 
    return 0;
  }
  
  
- /*
- ** Get a piece of kernel memory with error handling.
- ** Returns 1 if call succeeded, else 0 (zero).
- */
- static int getbuf(addr, buf, len, what)
-   long addr;
-   char *buf;
-   int len;
-   char *what;
- {
-   if (kvm_read(kd, addr, buf, len) < 0)
-   {
-     if (syslog_flag)
-       syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
- 	     addr, len, what);
- 
-     return 0;
-   }
-   
-   return 1;
- }
- 
- 
- 
- /*
- ** Traverse the inpcb list until a match is found.
- ** Returns NULL if no match.
- */
- static struct socket *
- getlist(tcbtablep, ktcbtablep, faddr, fport, laddr, lport)
- 	struct inpcbtable *tcbtablep, *ktcbtablep;
- 	struct in_addr *faddr;
- 	int fport;
- 	struct in_addr *laddr;
- 	int lport;
- {
- 	struct inpcb *kpcbp, pcb;
- 
- 	if (!tcbtablep)
- 		return NULL;
-  
- 	for (kpcbp = tcbtablep->inpt_queue.cqh_first;
- 	     kpcbp != (struct inpcb *)ktcbtablep;
- 	     kpcbp = pcb.inp_queue.cqe_next) {
- 		if (!getbuf((long) kpcbp, &pcb, sizeof(struct inpcb), "tcb"))
- 			break;
- 		if (pcb.inp_faddr.s_addr == faddr->s_addr &&
- 		    pcb.inp_laddr.s_addr == laddr->s_addr &&
- 		    pcb.inp_fport        == fport &&
- 		    pcb.inp_lport        == lport )
- 			return pcb.inp_socket;
- 	}
-   return NULL;
- }
- 
- 
  
  /*
  ** Return the user number for the connection owner
--- 66,77 ----
***************
*** 177,244 ****
  {
    long addr;
    struct socket *sockp;
!   int i, mib[2];
    struct ucred ucb;
!   
!   /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
!   if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
!     return -1;
!   
!   if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
!     return -1;
  
!   {
!     size_t siz;
!     int rv;
! 
!     mib[0] = CTL_KERN;
!     mib[1] = KERN_FILE;
!     if ((rv = sysctl(mib, 2, NULL, &siz, NULL, 0)) == -1)
      {
        ERROR1("k_getuid: sysctl 1 (%d)", rv);
        return -1;
      }
!     xfile = malloc(siz);
!     if (!xfile)
!       ERROR1("k_getuid: malloc(%d)", siz);
!     if ((rv = sysctl(mib, 2, xfile, &siz, NULL, 0)) == -1)
!     {
!       ERROR1("k_getuid: sysctl 2 (%d)", rv);
!       return -1;
!     }
!     xfile = (struct file *)((char *)xfile + sizeof(filehead));
!   }
!   
!   /* -------------------- TCP PCB LIST -------------------- */
!   if (!getbuf(nl[N_TCBTABLE].n_value, &tcbtable, sizeof(tcbtable), "tcbtable"))
!     return -1;
!   
!   sockp = getlist(&tcbtable, nl[N_TCBTABLE].n_value, faddr, fport, laddr,
!       lport);
!   
!   if (!sockp)
!     return -1;
! 
!   /*
!   ** Locate the file descriptor that has the socket in question
!   ** open so that we can get the 'ucred' information
!   */
!   for (i = 0; i < nfile; i++)
!   {
!     if (xfile[i].f_count == 0)
!       continue;
!     
!     if (xfile[i].f_type == DTYPE_SOCKET &&
! 	(struct socket *) xfile[i].f_data == sockp)
!     {
!       if (!getbuf(xfile[i].f_cred, &ucb, sizeof(ucb), "ucb"))
! 	return -1;
! 
!       *uid = ucb.cr_uid;
!       return 0;
!     }
!   }
! 
!   return -1;
  }
  
--- 85,116 ----
  {
    long addr;
    struct socket *sockp;
!   int i, mib[4];
    struct ucred ucb;
!   uid_t myuid = -1;
!   size_t uidlen;
!   struct sysctl_tcp_ident_args args;
!   int rv;
!   
!   mib[0] = CTL_NET;
!   mib[1] = PF_INET;
!   mib[2] = IPPROTO_TCP;
!   mib[3] = TCPCTL_IDENT;
! 
!   args.raddr = *faddr;
!   args.rport = fport;
!   args.laddr = *laddr;
!   args.lport = lport;
  
!   uidlen = sizeof(myuid);
!   
!     if ((rv = sysctl(mib, 4, &myuid, &uidlen, &args,sizeof(args)))== -1)
      {
        ERROR1("k_getuid: sysctl 1 (%d)", rv);
        return -1;
      }
!    
!   *uid = myuid;
!   return 0;
  }
  
*** /usr/src/sys/sys/socketvar.h.orig	Sat Feb 10 13:34:35 1996
--- usr/src/sys/sys/socketvar.h	Tue Apr 23 00:13:27 1996
***************
*** 96,101 ****
--- 96,102 ----
  	void	*so_internal;		/* Space for svr4 stream data */
  	void	(*so_upcall) __P((struct socket *so, caddr_t arg, int waitf));
  	caddr_t	so_upcallarg;		/* Arg for above */
+ 	uid_t   so_rfc931_uid;		/* Answer for RFC931 ident queries */
  };
  
  /*
*** /usr/src/sys/netinet/tcp_usrreq.c.orig	Wed Feb 14 13:37:03 1996
--- usr/src/sys/netinet/tcp_usrreq.c	Tue Apr 23 00:45:50 1996
***************
*** 561,569 ****
  	case TCPCTL_RFC1323:
  		return (sysctl_int(oldp, oldlenp, newp, newlen,
  		    &tcp_do_rfc1323));
! 
  	default:
  		return (ENOPROTOOPT);
  	}
  	/* NOTREACHED */
  }
--- 561,611 ----
  	case TCPCTL_RFC1323:
  		return (sysctl_int(oldp, oldlenp, newp, newlen,
  		    &tcp_do_rfc1323));
! 	case TCPCTL_IDENT:
! 	  	return (tcp_sysctl_ident(oldp,oldlenp,newp,newlen));
  	default:
  		return (ENOPROTOOPT);
  	}
  	/* NOTREACHED */
+ }
+ 
+ int 
+ tcp_sysctl_ident(oldp,oldlenp,newp,newlen)
+      void *oldp;
+      size_t *oldlenp;
+      void *newp;
+      size_t newlen;
+ {
+   struct sysctl_tcp_ident_args args;
+   struct socket *sockp;
+   struct inpcb *inb;
+   uid_t uid = -1;
+   int error = 0;
+ 
+   if (newlen != sizeof(struct sysctl_tcp_ident_args))
+     return EINVAL;
+   if (!newp)
+     return EFAULT;
+   if (*oldlenp != sizeof(uid_t))
+     return ENOMEM;
+   if (!oldp || *oldlenp != sizeof(uid_t))
+     return ENOMEM;
+   if ((error = copyin(newp, &args,newlen)))
+     return error;
+   
+   inb = in_pcbhashlookup(&tcbtable,
+ 			 args.raddr,
+ 			 args.rport,
+ 			 args.laddr,
+ 			 args.lport);
+   if (inb) {
+     sockp = inb->inp_socket;
+     if (sockp)
+       uid = sockp->so_rfc931_uid;
+   }
+ 
+   if ((error = copyout(&uid,oldp,sizeof(uid))))
+     return error;
+ 
+   return 0;
  }
*** /usr/src/sys/netinet/tcp_var.h.orig	Wed Feb 14 13:37:03 1996
--- usr/src/sys/netinet/tcp_var.h	Tue Apr 23 00:26:44 1996
***************
*** 230,241 ****
   */
  			/* enable/disable RFC1323 timestamps/scaling */
  #define	TCPCTL_RFC1323		1
! #define	TCPCTL_MAXID		2
  
  #define	TCPCTL_NAMES { \
  	{ 0, 0 }, \
  	{ "rfc1323",	CTLTYPE_INT }, \
  }
  
  #ifdef _KERNEL
  struct	inpcbtable tcbtable;	/* head of queue of active tcpcb's */
--- 230,250 ----
   */
  			/* enable/disable RFC1323 timestamps/scaling */
  #define	TCPCTL_RFC1323		1
! #define TCPCTL_IDENT		2
! #define	TCPCTL_MAXID		3
  
  #define	TCPCTL_NAMES { \
  	{ 0, 0 }, \
  	{ "rfc1323",	CTLTYPE_INT }, \
+ 	{ "ident",	CTLTYPE_STRUCT }, \
  }
+ 
+ struct sysctl_tcp_ident_args {
+   struct in_addr raddr;
+   u_int rport;
+   struct in_addr laddr;
+   u_int lport;
+ };
  
  #ifdef _KERNEL
  struct	inpcbtable tcbtable;	/* head of queue of active tcpcb's */
*** /usr/src/sys/kern/uipc_socket.c.orig	Sun Feb  4 14:09:47 1996
--- usr/src/sys/kern/uipc_socket.c	Tue Apr 23 00:44:52 1996
***************
*** 82,87 ****
--- 82,88 ----
  	so->so_type = type;
  	if (p->p_ucred->cr_uid == 0)
  		so->so_state = SS_PRIV;
+ 	so->so_rfc931_uid = p->p_cred->p_ruid;
  	so->so_proto = prp;
  	error =
  	    (*prp->pr_usrreq)(so, PRU_ATTACH, NULL, (struct mbuf *)(long)proto,

>Audit-Trail:
>Unformatted: