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
98static	struct	kinfo_proc	*getproc(void);
99
100
101int	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
125struct	nlist	names[4] = {
126	{ "_proc" },
127	{ "_nproc" },
128	{ NULL },
129	{ NULL }
130	};
131
132static struct kinfo_proc *getproc()
133{
134	static	struct	kinfo_proc kp;
135	pid_t	pid = getpid();
136	int	mib[4];
137	size_t	n;
138
139	mib[0] = CTL_KERN;
140	mib[1] = KERN_PROC;
141	mib[2] = KERN_PROC_PID;
142	mib[3] = pid;
143
144	n = sizeof(kp);
145	if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
146	    {
147		perror("sysctl");
148		return NULL;
149	    }
150	return &kp;
151}
152
153
154struct	tcpcb	*find_tcp(tfd, ti)
155	int	tfd;
156	struct	tcpiphdr *ti;
157{
158	struct	tcpcb	*t;
159	struct	inpcb	*i;
160	struct	socket	*s;
161	struct	filedesc	*fd;
162	struct	kinfo_proc	*p;
163	struct	file	*f, **o;
164
165	if (!(p = getproc()))
166		return NULL;
167
168	fd = (struct filedesc *)malloc(sizeof(*fd));
169	if (fd == NULL)
170		return NULL;
171#if defined( __FreeBSD__)
172	if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
173	    {
174		fprintf(stderr, "read(%#lx,%#lx) failed\n",
175			(u_long)p, (u_long)p->ki_fd);
176		free(fd);
177		return NULL;
178	    }
179#else
180	if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
181	    {
182		fprintf(stderr, "read(%#lx,%#lx) failed\n",
183			(u_long)p, (u_long)p->kp_proc.p_fd);
184		free(fd);
185		return NULL;
186	    }
187#endif
188
189	o = NULL;
190	f = NULL;
191	s = NULL;
192	i = NULL;
193	t = NULL;
194
195	o = (struct file **)calloc(fd->fd_lastfile + 1, sizeof(*o));
196	if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
197	    {
198		fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
199			(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
200		goto finderror;
201	    }
202	f = (struct file *)calloc(1, sizeof(*f));
203	if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
204	    {
205		fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
206			(u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
207		goto finderror;
208	    }
209
210	s = (struct socket *)calloc(1, sizeof(*s));
211	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
212	    {
213		fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
214			(u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
215		goto finderror;
216	    }
217
218	i = (struct inpcb *)calloc(1, sizeof(*i));
219	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
220	    {
221		fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
222			(u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
223		goto finderror;
224	    }
225
226	t = (struct tcpcb *)calloc(1, sizeof(*t));
227	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
228	    {
229		fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
230			(u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
231		goto finderror;
232	    }
233	return (struct tcpcb *)i->inp_ppcb;
234
235finderror:
236	if (o != NULL)
237		free(o);
238	if (f != NULL)
239		free(f);
240	if (s != NULL)
241		free(s);
242	if (i != NULL)
243		free(i);
244	if (t != NULL)
245		free(t);
246	return NULL;
247}
248
249int	do_socket(dev, mtu, ti, gwip)
250	char	*dev;
251	int	mtu;
252	struct	tcpiphdr *ti;
253	struct	in_addr	gwip;
254{
255	struct	sockaddr_in	rsin, lsin;
256	struct	tcpcb	*t, tcb;
257	int	fd, nfd;
258	socklen_t len;
259
260	printf("Dest. Port: %d\n", ti->ti_dport);
261
262	fd = socket(AF_INET, SOCK_STREAM, 0);
263	if (fd == -1)
264	    {
265		perror("socket");
266		return -1;
267	    }
268
269	if (fcntl(fd, F_SETFL, FNDELAY) == -1)
270	    {
271		perror("fcntl");
272		return -1;
273	    }
274
275	bzero((char *)&lsin, sizeof(lsin));
276	lsin.sin_family = AF_INET;
277	bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
278	      sizeof(struct in_addr));
279	if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
280	    {
281		perror("bind");
282		return -1;
283	    }
284	len = sizeof(lsin);
285	(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
286	ti->ti_sport = lsin.sin_port;
287	printf("sport %d\n", ntohs(lsin.sin_port));
288
289	nfd = initdevice(dev, 1);
290	if (nfd == -1)
291		return -1;
292
293	if (!(t = find_tcp(fd, ti)))
294		return -1;
295
296	bzero((char *)&rsin, sizeof(rsin));
297	rsin.sin_family = AF_INET;
298	bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
299	      sizeof(struct in_addr));
300	rsin.sin_port = ti->ti_dport;
301	if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
302	    errno != EINPROGRESS)
303	    {
304		perror("connect");
305		return -1;
306	    }
307	KMCPY(&tcb, t, sizeof(tcb));
308	ti->ti_win = tcb.rcv_adv;
309	ti->ti_seq = tcb.snd_nxt - 1;
310	ti->ti_ack = tcb.rcv_nxt;
311
312	if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
313		return -1;
314	(void)write(fd, "Hello World\n", 12);
315	sleep(2);
316	close(fd);
317	return 0;
318}
319