Initial commit of an unmodified 2.11BSD source tree taken from a boot tape.
[211bsd.git] / libexec / identd / src / kernel / 4.3bsd.c
1 /*
2 ** kernel/bsd43.c               Low level kernel access functions for 4.3BSD
3 **
4 ** This program is in the public domain and may be used freely by anyone
5 ** who wants to. 
6 **
7 ** Last update: 17 March 1993
8 **
9 ** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
10 */
11
12 #include <stdio.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #include <nlist.h>
16 #include <pwd.h>
17 #include <signal.h>
18 #include <syslog.h>
19
20 #include "kvm.h"
21
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/param.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27
28 #include <sys/socketvar.h>
29
30 #define KERNEL
31
32 #include <sys/file.h>
33
34 #if 0
35
36 #include <sys/time.h>
37 #include <sys/vmmac.h>
38 #include <sys/proc.h>
39 #include <sys/dir.h>
40
41 #include <fcntl.h>
42
43 #ifdef DIRBLKSIZ
44 #  undef DIRBLKSIZ
45 #endif
46 #include <sys/user.h>
47
48 #include <sys/wait.h>
49
50 #else
51
52 #include <sys/dir.h>    /* tmk */
53 #include <sys/user.h>   /* tmk */
54 /*#include <sys/time.h>
55 */
56 #include <sys/vmmac.h>
57 #include <sys/proc.h>
58 /*#include <sys/dir.h>
59 */
60 #include <fcntl.h>
61   
62 #ifdef DIRBLKSIZ
63 #  undef DIRBLKSIZ
64 #endif
65 /*#include <sys/user.h>
66 */
67 #endif
68
69 #ifdef KERNEL
70 #undef KERNEL
71 #endif
72
73 #include <net/if.h>
74 #include <net/route.h>
75 #include <netinet/in.h>
76
77 #include <netinet/in_systm.h>
78 #include <netinet/ip.h>
79
80 #include <netinet/in_pcb.h>
81
82 #include <netinet/tcp.h>
83 #include <netinet/ip_var.h>
84 #include <netinet/tcp_timer.h>
85 #include <netinet/tcp_var.h>
86
87 #include <arpa/inet.h>
88
89 #include "identd.h"
90 #include "error.h"
91
92
93 extern void *calloc();
94 extern void *malloc();
95
96
97 struct nlist nl[] =
98 {
99 #define N_FILE 0  
100 #define N_NFILE 1
101 #define N_TCB 2
102
103   { "_file" },
104   { "_nfile" },
105   { "_tcb" },
106   { "" }
107 };
108
109 static kvm_t *kd;
110
111 static struct file *xfile;
112 static int nfile;
113
114 static struct inpcb tcb;
115
116
117 int k_open()
118 {
119   /*
120   ** Open the kernel memory device
121   */
122   if (!(kd = kvm_open(path_unix, path_kmem, NULL, O_RDONLY, NULL)))
123     ERROR("main: kvm_open");
124   
125   /*
126   ** Extract offsets to the needed variables in the kernel
127   */
128   if (kvm_nlist(kd, nl) != 0)
129     ERROR("main: kvm_nlist");
130
131   return 0;
132 }
133
134
135 /*
136 ** Get a piece of kernel memory with error handling.
137 ** Returns 1 if call succeeded, else 0 (zero).
138 */
139 static int getbuf(addr, buf, len, what)
140   long addr;
141   char *buf;
142   int len;
143   char *what;
144 {
145   if (kvm_read(kd, addr, buf, len) < 0)
146   {
147     if (syslog_flag)
148       syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m",
149              addr, len, what);
150
151     return 0;
152   }
153   
154   return 1;
155 }
156
157
158
159 /*
160 ** Traverse the inpcb list until a match is found.
161 ** Returns NULL if no match.
162 */
163 static struct socket *
164     getlist(pcbp, faddr, fport, laddr, lport)
165   struct inpcb *pcbp;
166   struct in_addr *faddr;
167   int fport;
168   struct in_addr *laddr;
169   int lport;
170 {
171   struct inpcb *head;
172
173   if (!pcbp)
174     return NULL;
175
176   
177   head = pcbp->inp_prev;
178   do 
179   {
180     if ( pcbp->inp_faddr.s_addr == faddr->s_addr &&
181          pcbp->inp_laddr.s_addr == laddr->s_addr &&
182          pcbp->inp_fport        == fport &&
183          pcbp->inp_lport        == lport )
184       return pcbp->inp_socket;
185   } while (pcbp->inp_next != head &&
186            getbuf((long) pcbp->inp_next,
187                   pcbp,
188                   sizeof(struct inpcb),
189                   "tcblist"));
190
191   return NULL;
192 }
193
194
195
196 /*
197 ** Return the user number for the connection owner
198 */
199 int k_getuid(faddr, fport, laddr, lport, uid)
200   struct in_addr *faddr;
201   int fport;
202   struct in_addr *laddr;
203   int lport;
204   int *uid;
205 {
206   long addr;
207   struct proc *pp;
208   struct user *up;
209   int offset;
210   struct socket *sockp;
211   int i;
212   
213   /* -------------------- FILE DESCRIPTOR TABLE -------------------- */
214   if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile"))
215     return -1;
216   
217   if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file"))
218     return -1;
219
220   xfile = (struct file *) calloc(nfile, sizeof(struct file));
221   if (!xfile)
222     ERROR2("k_getuid: calloc(%d,%d)", nfile, sizeof(struct file));
223   
224   if (!getbuf(addr, xfile, sizeof(struct file)*nfile, "file[]"))
225     return -1;
226   
227   /* -------------------- TCP PCB LIST -------------------- */
228   if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb"))
229     return -1;
230   
231   tcb.inp_prev = (struct inpcb *) nl[N_TCB].n_value;
232   sockp = getlist(&tcb, faddr, fport, laddr, lport);
233   
234   if (!sockp)
235     return -1;
236
237   /* -------------------- SCAN PROCESS TABLE ------------------- */
238   if (kvm_setproc(kd) < 0)
239     ERROR("k_getuid: kvm_setproc() failed");
240   
241   while (pp = kvm_nextproc(kd))
242   {
243     if (pp->p_stat == 0)
244       continue;
245
246     if (pp->p_stat == SZOMB)
247       continue;
248
249     /* ------------------- GET U_AREA FOR PROCESS ----------------- */
250     if ((up = kvm_getu(kd, pp)) == NULL)
251       ERROR1("k_getuid: kvm_getu() failed for process %d", pp->p_pid);
252
253     /* ------------------- SCAN FILE TABLE ------------------------ */
254     for (i = up->u_lastfile; i >= 0; i--)
255     {
256       if (up->u_ofile[i] == 0)
257         continue;
258
259       offset = up->u_ofile[i] - (struct file *) addr;
260       if (xfile[offset].f_type == DTYPE_SOCKET && 
261           (struct socket *) xfile[offset].f_data == sockp)
262       {
263 #ifdef TAHOE
264         *uid = up->u_ruid;
265 #else
266         *uid = pp->p_ruid;
267 #endif
268         return 0;
269       }                 /* if */
270     }                   /* for -- ofiles */
271   }                     /* for -- proc */
272   
273   return -1;
274 }
275