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#include <fcntl.h>
25# include <sys/dirent.h>
26# ifdef __NetBSD__
27#  include <machine/lock.h>
28# endif
29# ifdef __FreeBSD__
30#  define _WANT_FILE
31# else
32#  define _KERNEL
33#  define	KERNEL
34# endif
35# include <sys/file.h>
36# ifdef __FreeBSD__
37#  undef _WANT_FILE
38# else
39#  undef  _KERNEL
40#  undef  KERNEL
41# endif
42#include <nlist.h>
43#include <sys/user.h>
44#include <sys/socket.h>
45#include <sys/socketvar.h>
46#include <sys/proc.h>
47# include <kvm.h>
48#ifdef sun
49#include <sys/systm.h>
50#include <sys/session.h>
51#endif
52#include <sys/sysctl.h>
53#include <sys/filedesc.h>
54#include <paths.h>
55#include <math.h>
56#include <netinet/in.h>
57#include <netinet/in_systm.h>
58#include <netinet/ip.h>
59#include <netinet/tcp.h>
60#include <net/if.h>
61# include <net/route.h>
62#include <netinet/ip_var.h>
63#define	_WANT_INPCB
64#include <netinet/in_pcb.h>
65#include <netinet/tcp_timer.h>
66#define	_WANT_TCPCB
67#include <netinet/tcp_var.h>
68#include <stdio.h>
69#include <unistd.h>
70#include <string.h>
71#include <stdlib.h>
72#include <stddef.h>
73#include <pwd.h>
74#include "ipsend.h"
75
76
77int	nproc;
78struct	proc	*proc;
79
80#ifndef	KMEM
81# ifdef	_PATH_KMEM
82#  define	KMEM	_PATH_KMEM
83# endif
84#endif
85#ifndef	KERNEL
86# ifdef	_PATH_UNIX
87#  define	KERNEL	_PATH_UNIX
88# endif
89#endif
90#ifndef	KMEM
91# define	KMEM	"/dev/kmem"
92#endif
93#ifndef	KERNEL
94# define	KERNEL	"/vmunix"
95#endif
96
97
98#if BSD < 199103
99static	struct	proc	*getproc __P((void));
100#else
101static	struct	kinfo_proc	*getproc __P((void));
102#endif
103
104
105int	kmemcpy(buf, pos, n)
106	char	*buf;
107	void	*pos;
108	int	n;
109{
110	static	int	kfd = -1;
111	off_t	offset = (u_long)pos;
112
113	if (kfd == -1)
114		kfd = open(KMEM, O_RDONLY);
115
116	if (lseek(kfd, offset, SEEK_SET) == -1)
117	    {
118		perror("lseek");
119		return -1;
120	    }
121	if (read(kfd, buf, n) == -1)
122	    {
123		perror("read");
124		return -1;
125	    }
126	return n;
127}
128
129struct	nlist	names[4] = {
130	{ "_proc" },
131	{ "_nproc" },
132	{ NULL },
133	{ NULL }
134	};
135
136static struct kinfo_proc *getproc()
137{
138	static	struct	kinfo_proc kp;
139	pid_t	pid = getpid();
140	int	mib[4];
141	size_t	n;
142
143	mib[0] = CTL_KERN;
144	mib[1] = KERN_PROC;
145	mib[2] = KERN_PROC_PID;
146	mib[3] = pid;
147
148	n = sizeof(kp);
149	if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
150	    {
151		perror("sysctl");
152		return NULL;
153	    }
154	return &kp;
155}
156
157
158struct	tcpcb	*find_tcp(tfd, ti)
159	int	tfd;
160	struct	tcpiphdr *ti;
161{
162	struct	tcpcb	*t;
163	struct	inpcb	*i;
164	struct	socket	*s;
165	struct	filedesc	*fd;
166	struct	kinfo_proc	*p;
167	struct	file	*f, **o;
168
169	if (!(p = getproc()))
170		return NULL;
171
172	fd = (struct filedesc *)malloc(sizeof(*fd));
173	if (fd == NULL)
174		return NULL;
175#if defined( __FreeBSD_version)
176	if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
177	    {
178		fprintf(stderr, "read(%#lx,%#lx) failed\n",
179			(u_long)p, (u_long)p->ki_fd);
180		free(fd);
181		return NULL;
182	    }
183#else
184	if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
185	    {
186		fprintf(stderr, "read(%#lx,%#lx) failed\n",
187			(u_long)p, (u_long)p->kp_proc.p_fd);
188		free(fd);
189		return NULL;
190	    }
191#endif
192
193	o = NULL;
194	f = NULL;
195	s = NULL;
196	i = NULL;
197	t = NULL;
198
199	o = (struct file **)calloc(fd->fd_lastfile + 1, sizeof(*o));
200	if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
201	    {
202		fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
203			(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
204		goto finderror;
205	    }
206	f = (struct file *)calloc(1, sizeof(*f));
207	if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
208	    {
209		fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
210			(u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
211		goto finderror;
212	    }
213
214	s = (struct socket *)calloc(1, sizeof(*s));
215	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
216	    {
217		fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
218			(u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
219		goto finderror;
220	    }
221
222	i = (struct inpcb *)calloc(1, sizeof(*i));
223	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
224	    {
225		fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
226			(u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
227		goto finderror;
228	    }
229
230	t = (struct tcpcb *)calloc(1, sizeof(*t));
231	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
232	    {
233		fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
234			(u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
235		goto finderror;
236	    }
237	return (struct tcpcb *)i->inp_ppcb;
238
239finderror:
240	if (o != NULL)
241		free(o);
242	if (f != NULL)
243		free(f);
244	if (s != NULL)
245		free(s);
246	if (i != NULL)
247		free(i);
248	if (t != NULL)
249		free(t);
250	return NULL;
251}
252
253int	do_socket(dev, mtu, ti, gwip)
254	char	*dev;
255	int	mtu;
256	struct	tcpiphdr *ti;
257	struct	in_addr	gwip;
258{
259	struct	sockaddr_in	rsin, lsin;
260	struct	tcpcb	*t, tcb;
261	int	fd, nfd;
262	socklen_t len;
263
264	printf("Dest. Port: %d\n", ti->ti_dport);
265
266	fd = socket(AF_INET, SOCK_STREAM, 0);
267	if (fd == -1)
268	    {
269		perror("socket");
270		return -1;
271	    }
272
273	if (fcntl(fd, F_SETFL, FNDELAY) == -1)
274	    {
275		perror("fcntl");
276		return -1;
277	    }
278
279	bzero((char *)&lsin, sizeof(lsin));
280	lsin.sin_family = AF_INET;
281	bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
282	      sizeof(struct in_addr));
283	if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
284	    {
285		perror("bind");
286		return -1;
287	    }
288	len = sizeof(lsin);
289	(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
290	ti->ti_sport = lsin.sin_port;
291	printf("sport %d\n", ntohs(lsin.sin_port));
292
293	nfd = initdevice(dev, 1);
294	if (nfd == -1)
295		return -1;
296
297	if (!(t = find_tcp(fd, ti)))
298		return -1;
299
300	bzero((char *)&rsin, sizeof(rsin));
301	rsin.sin_family = AF_INET;
302	bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
303	      sizeof(struct in_addr));
304	rsin.sin_port = ti->ti_dport;
305	if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
306	    errno != EINPROGRESS)
307	    {
308		perror("connect");
309		return -1;
310	    }
311	KMCPY(&tcb, t, sizeof(tcb));
312	ti->ti_win = tcb.rcv_adv;
313	ti->ti_seq = tcb.snd_nxt - 1;
314	ti->ti_ack = tcb.rcv_nxt;
315
316	if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
317		return -1;
318	(void)write(fd, "Hello World\n", 12);
319	sleep(2);
320	close(fd);
321	return 0;
322}
323