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