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