Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ipfilter / ipsend / sock.c
1 /* $FreeBSD: src/contrib/ipfilter/ipsend/sock.c,v 1.3.2.4 2003/03/01 03:55:53 darrenr Exp $ */
2 /*
3  * sock.c (C) 1995-1998 Darren Reed
4  *
5  * See the IPFILTER.LICENCE file for details on licencing.
6  */
7 #if defined(__sgi) && (IRIX > 602)
8 # include <sys/ptimers.h>
9 #endif
10 #include <stdio.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stddef.h>
15 #include <pwd.h>
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/param.h>
19 #include <sys/stat.h>
20 #ifndef ultrix
21 #include <fcntl.h>
22 #endif
23 #if (__FreeBSD_version >= 300000)
24 # include <sys/dirent.h>
25 #else
26 # include <sys/dir.h>
27 #endif
28 #define _KERNEL
29 #define KERNEL
30 #ifdef  ultrix
31 # undef LOCORE
32 # include <sys/smp_lock.h>
33 #endif
34 #include <sys/file.h>
35 #undef  _KERNEL
36 #undef  KERNEL
37 #include <nlist.h>
38 #include <sys/user.h>
39 #include <sys/socket.h>
40 #include <sys/socketvar.h>
41 #include <sys/proc.h>
42 #if !defined(ultrix) && !defined(hpux)
43 # include <kvm.h>
44 #endif
45 #ifdef sun
46 #include <sys/systm.h>
47 #include <sys/session.h>
48 #endif
49 #if BSD >= 199103
50 #include <sys/sysctl.h>
51 #include <sys/filedesc.h>
52 #include <paths.h>
53 #endif
54 #include <math.h>
55 #include <netinet/in.h>
56 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #include <netinet/tcp.h>
59 #include <net/if.h>
60 #include <net/route.h>
61 #include <netinet/ip_var.h>
62 #include <netinet/in_pcb.h>
63 #include <netinet/tcp_timer.h>
64 #include <netinet/tcp_var.h>
65 #include "ipsend.h"
66
67 #if !defined(lint)
68 static const char sccsid[] = "@(#)sock.c        1.2 1/11/96 (C)1995 Darren Reed";
69 static const char rcsid[] = "@(#)$Id: sock.c,v 2.1.4.6 2002/12/06 11:40:36 darrenr Exp $";
70 #endif
71
72
73 int     nproc;
74 struct  proc    *proc;
75
76 #ifndef KMEM
77 # ifdef _PATH_KMEM
78 #  define       KMEM    _PATH_KMEM
79 # endif
80 #endif
81 #ifndef KERNEL
82 # ifdef _PATH_UNIX
83 #  define       KERNEL  _PATH_UNIX
84 # endif
85 #endif
86 #ifndef KMEM
87 # define        KMEM    "/dev/kmem"
88 #endif
89 #ifndef KERNEL
90 # define        KERNEL  "/vmunix"
91 #endif
92
93
94 #if BSD < 199103
95 static  struct  proc    *getproc __P((void));
96 #else
97 static  struct  kinfo_proc      *getproc __P((void));
98 #endif
99
100
101 int     kmemcpy(buf, pos, n)
102 char    *buf;
103 void    *pos;
104 int     n;
105 {
106         static  int     kfd = -1;
107         off_t   offset = (u_long)pos;
108
109         if (kfd == -1)
110                 kfd = open(KMEM, O_RDONLY);
111
112         if (lseek(kfd, offset, SEEK_SET) == -1)
113             {
114                 perror("lseek");
115                 return -1;
116             }
117         if (read(kfd, buf, n) == -1)
118             {
119                 perror("read");
120                 return -1;
121             }
122         return n;
123 }
124
125 struct  nlist   names[4] = {
126         { "_proc" },
127         { "_nproc" },
128 #ifdef  ultrix
129         { "_u" },
130 #else
131         { NULL },
132 #endif
133         { NULL }
134         };
135
136 #if BSD < 199103
137 static struct proc *getproc()
138 {
139         struct  proc    *p;
140         pid_t   pid = getpid();
141         int     siz, n;
142
143         n = nlist(KERNEL, names);
144         if (n != 0)
145             {
146                 fprintf(stderr, "nlist(%#x) == %d\n", names, n);
147                 return NULL;
148             }
149         if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1)
150             {
151                 fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
152                 return NULL;
153             }
154         siz = nproc * sizeof(struct proc);
155         if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1)
156             {
157                 fprintf(stderr, "read(%#x,%#x,%d) proc\n",
158                         names[0].n_value, &p, sizeof(p));
159                 return NULL;
160             }
161         proc = (struct proc *)malloc(siz);
162         if (KMCPY(proc, p, siz) == -1)
163             {
164                 fprintf(stderr, "read(%#x,%#x,%d) proc\n",
165                         p, proc, siz);
166                 return NULL;
167             }
168
169         p = proc;
170
171         for (n = nproc; n; n--, p++)
172                 if (p->p_pid == pid)
173                         break;
174         if (!n)
175                 return NULL;
176
177         return p;
178 }
179
180
181 struct  tcpcb   *find_tcp(fd, ti)
182 int     fd;
183 struct  tcpiphdr *ti;
184 {
185         struct  tcpcb   *t;
186         struct  inpcb   *i;
187         struct  socket  *s;
188         struct  user    *up;
189         struct  proc    *p;
190         struct  file    *f, **o;
191
192         if (!(p = getproc()))
193                 return NULL;
194         up = (struct user *)malloc(sizeof(*up));
195 #ifndef ultrix
196         if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1)
197             {
198                 fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea);
199                 return NULL;
200             }
201 #else
202         if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1)
203             {
204                 fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value);
205                 return NULL;
206             }
207 #endif
208
209         o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1));
210         if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1)
211             {
212                 fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
213                         up->u_ofile, o, sizeof(*o));
214                 return NULL;
215             }
216         f = (struct file *)calloc(1, sizeof(*f));
217         if (KMCPY(f, o[fd], sizeof(*f)) == -1)
218             {
219                 fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
220                         up->u_ofile[fd], f, sizeof(*f));
221                 return NULL;
222             }
223
224         s = (struct socket *)calloc(1, sizeof(*s));
225         if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
226             {
227                 fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
228                         o[fd], s, sizeof(*s));
229                 return NULL;
230             }
231
232         i = (struct inpcb *)calloc(1, sizeof(*i));
233         if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
234             {
235                 fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
236                         s->so_pcb, i, sizeof(*i));
237                 return NULL;
238             }
239
240         t = (struct tcpcb *)calloc(1, sizeof(*t));
241         if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
242             {
243                 fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
244                         i->inp_ppcb, t, sizeof(*t));
245                 return NULL;
246             }
247         return (struct tcpcb *)i->inp_ppcb;
248 }
249 #else
250 static struct kinfo_proc *getproc()
251 {
252         static  struct  kinfo_proc kp;
253         pid_t   pid = getpid();
254         int     mib[4];
255         size_t  n;
256
257         mib[0] = CTL_KERN;
258         mib[1] = KERN_PROC;
259         mib[2] = KERN_PROC_PID;
260         mib[3] = pid;
261
262         n = sizeof(kp);
263         if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
264             {
265                 perror("sysctl");
266                 return NULL;
267             }
268         return &kp;
269 }
270
271
272 struct  tcpcb   *find_tcp(tfd, ti)
273 int     tfd;
274 struct  tcpiphdr *ti;
275 {
276         struct  tcpcb   *t;
277         struct  inpcb   *i;
278         struct  socket  *s;
279         struct  filedesc        *fd;
280         struct  kinfo_proc      *p;
281         struct  file    *f, **o;
282
283         if (!(p = getproc()))
284                 return NULL;
285
286         fd = (struct filedesc *)malloc(sizeof(*fd));
287 #if defined( __FreeBSD_version) && __FreeBSD_version >= 500013
288         if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
289             {
290                 fprintf(stderr, "read(%#lx,%#lx) failed\n",
291                         (u_long)p, (u_long)p->ki_fd);
292                 return NULL;
293             }
294 #else
295         if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
296             {
297                 fprintf(stderr, "read(%#lx,%#lx) failed\n",
298                         (u_long)p, (u_long)p->kp_proc.p_fd);
299                 return NULL;
300             }
301 #endif
302
303         o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1));
304         if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
305             {
306                 fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
307                         (u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
308                 return NULL;
309             }
310         f = (struct file *)calloc(1, sizeof(*f));
311         if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
312             {
313                 fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
314                         (u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
315                 return NULL;
316             }
317
318         s = (struct socket *)calloc(1, sizeof(*s));
319         if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
320             {
321                 fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
322                         (u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
323                 return NULL;
324             }
325
326         i = (struct inpcb *)calloc(1, sizeof(*i));
327         if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
328             {
329                 fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
330                         (u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
331                 return NULL;
332             }
333
334         t = (struct tcpcb *)calloc(1, sizeof(*t));
335         if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
336             {
337                 fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
338                         (u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
339                 return NULL;
340             }
341         return (struct tcpcb *)i->inp_ppcb;
342 }
343 #endif /* BSD < 199301 */
344
345 int     do_socket(dev, mtu, ti, gwip)
346 char    *dev;
347 int     mtu;
348 struct  tcpiphdr *ti;
349 struct  in_addr gwip;
350 {
351         struct  sockaddr_in     rsin, lsin;
352         struct  tcpcb   *t, tcb;
353         int     fd, nfd, len;
354
355         printf("Dest. Port: %d\n", ti->ti_dport);
356
357         fd = socket(AF_INET, SOCK_STREAM, 0);
358         if (fd == -1)
359             {
360                 perror("socket");
361                 return -1;
362             }
363
364         if (fcntl(fd, F_SETFL, FNDELAY) == -1)
365             {
366                 perror("fcntl");
367                 return -1;
368             }
369
370         bzero((char *)&lsin, sizeof(lsin));
371         lsin.sin_family = AF_INET;
372         bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
373               sizeof(struct in_addr));
374         if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
375             {
376                 perror("bind");
377                 return -1;
378             }
379         len = sizeof(lsin);
380         (void) getsockname(fd, (struct sockaddr *)&lsin, &len);
381         ti->ti_sport = lsin.sin_port;
382         printf("sport %d\n", ntohs(lsin.sin_port));
383         nfd = initdevice(dev, ntohs(lsin.sin_port), 1);
384
385         if (!(t = find_tcp(fd, ti)))
386                 return -1;
387
388         bzero((char *)&rsin, sizeof(rsin));
389         rsin.sin_family = AF_INET;
390         bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
391               sizeof(struct in_addr));
392         rsin.sin_port = ti->ti_dport;
393         if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
394             errno != EINPROGRESS)
395             {
396                 perror("connect");
397                 return -1;
398             }
399         KMCPY(&tcb, t, sizeof(tcb));
400         ti->ti_win = tcb.rcv_adv;
401         ti->ti_seq = tcb.snd_nxt - 1;
402         ti->ti_ack = tcb.rcv_nxt;
403
404         if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
405                 return -1;
406         (void)write(fd, "Hello World\n", 12);
407         sleep(2);
408         close(fd);
409         return 0;
410 }