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