sock.c revision 172776
157109Speter/* $FreeBSD: head/contrib/ipfilter/ipsend/sock.c 172776 2007-10-18 21:52:14Z darrenr $ */
222514Sdarrenr/*
357109Speter * sock.c (C) 1995-1998 Darren Reed
422514Sdarrenr *
580490Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
6145519Sdarrenr *
722514Sdarrenr */
8145519Sdarrenr#if !defined(lint)
9145519Sdarrenrstatic const char sccsid[] = "@(#)sock.c	1.2 1/11/96 (C)1995 Darren Reed";
10172776Sdarrenrstatic const char rcsid[] = "@(#)$Id: sock.c,v 2.8.4.7 2007/09/13 07:19:34 darrenr Exp $";
1192691Sdarrenr#endif
12145519Sdarrenr#include <sys/param.h>
1322514Sdarrenr#include <sys/types.h>
1422514Sdarrenr#include <sys/time.h>
1522514Sdarrenr#include <sys/stat.h>
16161357Sguido#if defined(__NetBSD__) && defined(__vax__)
17161357Sguido/*
18161357Sguido * XXX need to declare boolean_t for _KERNEL <sys/files.h>
19161357Sguido * which ends up including <sys/device.h> for vax.  See PR#32907
20161357Sguido * for further details.
21161357Sguido */
22161357Sguidotypedef int     boolean_t;
23161357Sguido#endif
2431183Speter#ifndef	ultrix
2522514Sdarrenr#include <fcntl.h>
2631183Speter#endif
2757109Speter#if (__FreeBSD_version >= 300000)
2857109Speter# include <sys/dirent.h>
2957109Speter#else
3057109Speter# include <sys/dir.h>
3134752Speter#endif
32145519Sdarrenr#if !defined(__osf__)
33172776Sdarrenr# ifdef __NetBSD__
34172776Sdarrenr#  include <machine/lock.h>
35172776Sdarrenr# endif
36145519Sdarrenr# define _KERNEL
37145519Sdarrenr# define	KERNEL
38145519Sdarrenr# ifdef	ultrix
39145519Sdarrenr#  undef	LOCORE
40145519Sdarrenr#  include <sys/smp_lock.h>
41145519Sdarrenr# endif
42145519Sdarrenr# include <sys/file.h>
43145519Sdarrenr# undef  _KERNEL
44145519Sdarrenr# undef  KERNEL
4531183Speter#endif
4622514Sdarrenr#include <nlist.h>
4722514Sdarrenr#include <sys/user.h>
4822514Sdarrenr#include <sys/socket.h>
4922514Sdarrenr#include <sys/socketvar.h>
5022514Sdarrenr#include <sys/proc.h>
51145519Sdarrenr#if !defined(ultrix) && !defined(hpux) && !defined(__osf__)
5231183Speter# include <kvm.h>
5331183Speter#endif
5422514Sdarrenr#ifdef sun
5522514Sdarrenr#include <sys/systm.h>
5622514Sdarrenr#include <sys/session.h>
5722514Sdarrenr#endif
5822514Sdarrenr#if BSD >= 199103
5922514Sdarrenr#include <sys/sysctl.h>
6022514Sdarrenr#include <sys/filedesc.h>
6122514Sdarrenr#include <paths.h>
6222514Sdarrenr#endif
6322514Sdarrenr#include <math.h>
6422514Sdarrenr#include <netinet/in.h>
6522514Sdarrenr#include <netinet/in_systm.h>
6622514Sdarrenr#include <netinet/ip.h>
6722514Sdarrenr#include <netinet/tcp.h>
6822514Sdarrenr#include <net/if.h>
69145519Sdarrenr#if defined(__FreeBSD__)
70145519Sdarrenr# include "radix_ipf.h"
71145519Sdarrenr#endif
72170268Sdarrenr#ifndef __osf__
73170268Sdarrenr# include <net/route.h>
74170268Sdarrenr#endif
7522514Sdarrenr#include <netinet/ip_var.h>
7622514Sdarrenr#include <netinet/in_pcb.h>
7722514Sdarrenr#include <netinet/tcp_timer.h>
7822514Sdarrenr#include <netinet/tcp_var.h>
79145519Sdarrenr#include <stdio.h>
80145519Sdarrenr#include <unistd.h>
81145519Sdarrenr#include <string.h>
82145519Sdarrenr#include <stdlib.h>
83145519Sdarrenr#include <stddef.h>
84145519Sdarrenr#include <pwd.h>
8524583Sdarrenr#include "ipsend.h"
8622514Sdarrenr
8780490Sdarrenr
8822514Sdarrenrint	nproc;
8922514Sdarrenrstruct	proc	*proc;
9022514Sdarrenr
9122514Sdarrenr#ifndef	KMEM
9222514Sdarrenr# ifdef	_PATH_KMEM
9322514Sdarrenr#  define	KMEM	_PATH_KMEM
9422514Sdarrenr# endif
9522514Sdarrenr#endif
9622514Sdarrenr#ifndef	KERNEL
9722514Sdarrenr# ifdef	_PATH_UNIX
9822514Sdarrenr#  define	KERNEL	_PATH_UNIX
9922514Sdarrenr# endif
10022514Sdarrenr#endif
10122514Sdarrenr#ifndef	KMEM
10222514Sdarrenr# define	KMEM	"/dev/kmem"
10322514Sdarrenr#endif
10422514Sdarrenr#ifndef	KERNEL
10522514Sdarrenr# define	KERNEL	"/vmunix"
10622514Sdarrenr#endif
10722514Sdarrenr
10824583Sdarrenr
10924583Sdarrenr#if BSD < 199103
11024583Sdarrenrstatic	struct	proc	*getproc __P((void));
11124583Sdarrenr#else
11224583Sdarrenrstatic	struct	kinfo_proc	*getproc __P((void));
11324583Sdarrenr#endif
11424583Sdarrenr
11524583Sdarrenr
11622514Sdarrenrint	kmemcpy(buf, pos, n)
11722514Sdarrenrchar	*buf;
11824583Sdarrenrvoid	*pos;
11922514Sdarrenrint	n;
12022514Sdarrenr{
12122514Sdarrenr	static	int	kfd = -1;
12231183Speter	off_t	offset = (u_long)pos;
12322514Sdarrenr
12422514Sdarrenr	if (kfd == -1)
12522514Sdarrenr		kfd = open(KMEM, O_RDONLY);
12622514Sdarrenr
12731183Speter	if (lseek(kfd, offset, SEEK_SET) == -1)
12822514Sdarrenr	    {
12922514Sdarrenr		perror("lseek");
13022514Sdarrenr		return -1;
13122514Sdarrenr	    }
13222514Sdarrenr	if (read(kfd, buf, n) == -1)
13322514Sdarrenr	    {
13422514Sdarrenr		perror("read");
13522514Sdarrenr		return -1;
13622514Sdarrenr	    }
13722514Sdarrenr	return n;
13822514Sdarrenr}
13922514Sdarrenr
14031183Speterstruct	nlist	names[4] = {
14122514Sdarrenr	{ "_proc" },
14222514Sdarrenr	{ "_nproc" },
14331183Speter#ifdef	ultrix
14431183Speter	{ "_u" },
14531183Speter#else
14631183Speter	{ NULL },
14731183Speter#endif
14822514Sdarrenr	{ NULL }
14922514Sdarrenr	};
15022514Sdarrenr
15122514Sdarrenr#if BSD < 199103
15224583Sdarrenrstatic struct proc *getproc()
15322514Sdarrenr{
15422514Sdarrenr	struct	proc	*p;
15522514Sdarrenr	pid_t	pid = getpid();
15622514Sdarrenr	int	siz, n;
15722514Sdarrenr
15822514Sdarrenr	n = nlist(KERNEL, names);
15922514Sdarrenr	if (n != 0)
16022514Sdarrenr	    {
16122514Sdarrenr		fprintf(stderr, "nlist(%#x) == %d\n", names, n);
16222514Sdarrenr		return NULL;
16322514Sdarrenr	    }
16424583Sdarrenr	if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1)
16522514Sdarrenr	    {
16622514Sdarrenr		fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
16722514Sdarrenr		return NULL;
16822514Sdarrenr	    }
16922514Sdarrenr	siz = nproc * sizeof(struct proc);
17024583Sdarrenr	if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1)
17122514Sdarrenr	    {
17222514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) proc\n",
17322514Sdarrenr			names[0].n_value, &p, sizeof(p));
17422514Sdarrenr		return NULL;
17522514Sdarrenr	    }
17622514Sdarrenr	proc = (struct proc *)malloc(siz);
17724583Sdarrenr	if (KMCPY(proc, p, siz) == -1)
17822514Sdarrenr	    {
17922514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) proc\n",
18022514Sdarrenr			p, proc, siz);
18122514Sdarrenr		return NULL;
18222514Sdarrenr	    }
18322514Sdarrenr
18422514Sdarrenr	p = proc;
18522514Sdarrenr
18622514Sdarrenr	for (n = nproc; n; n--, p++)
18722514Sdarrenr		if (p->p_pid == pid)
18822514Sdarrenr			break;
18922514Sdarrenr	if (!n)
19022514Sdarrenr		return NULL;
19122514Sdarrenr
19222514Sdarrenr	return p;
19322514Sdarrenr}
19422514Sdarrenr
19522514Sdarrenr
19622514Sdarrenrstruct	tcpcb	*find_tcp(fd, ti)
19722514Sdarrenrint	fd;
19822514Sdarrenrstruct	tcpiphdr *ti;
19922514Sdarrenr{
20022514Sdarrenr	struct	tcpcb	*t;
20122514Sdarrenr	struct	inpcb	*i;
20222514Sdarrenr	struct	socket	*s;
20322514Sdarrenr	struct	user	*up;
20422514Sdarrenr	struct	proc	*p;
20522514Sdarrenr	struct	file	*f, **o;
20622514Sdarrenr
20722514Sdarrenr	if (!(p = getproc()))
20822514Sdarrenr		return NULL;
20922514Sdarrenr	up = (struct user *)malloc(sizeof(*up));
21031183Speter#ifndef	ultrix
21124583Sdarrenr	if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1)
21222514Sdarrenr	    {
21322514Sdarrenr		fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea);
21422514Sdarrenr		return NULL;
21522514Sdarrenr	    }
21631183Speter#else
21731183Speter	if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1)
21831183Speter	    {
21931183Speter		fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value);
22031183Speter		return NULL;
22131183Speter	    }
22231183Speter#endif
22322514Sdarrenr
22422514Sdarrenr	o = (struct file **)calloc(1, sizeof(*o) * (up->u_lastfile + 1));
22524583Sdarrenr	if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1)
22622514Sdarrenr	    {
22722514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
22831183Speter			up->u_ofile, o, sizeof(*o));
22922514Sdarrenr		return NULL;
23022514Sdarrenr	    }
23122514Sdarrenr	f = (struct file *)calloc(1, sizeof(*f));
23224583Sdarrenr	if (KMCPY(f, o[fd], sizeof(*f)) == -1)
23322514Sdarrenr	    {
23422514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
23531183Speter			up->u_ofile[fd], f, sizeof(*f));
23622514Sdarrenr		return NULL;
23722514Sdarrenr	    }
23822514Sdarrenr
23922514Sdarrenr	s = (struct socket *)calloc(1, sizeof(*s));
240109153Sdillon	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
24122514Sdarrenr	    {
24222514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
24322514Sdarrenr			o[fd], s, sizeof(*s));
24422514Sdarrenr		return NULL;
24522514Sdarrenr	    }
24622514Sdarrenr
24722514Sdarrenr	i = (struct inpcb *)calloc(1, sizeof(*i));
24824583Sdarrenr	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
24922514Sdarrenr	    {
25022514Sdarrenr		fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
25122514Sdarrenr			s->so_pcb, i, sizeof(*i));
25222514Sdarrenr		return NULL;
25322514Sdarrenr	    }
25422514Sdarrenr
25522514Sdarrenr	t = (struct tcpcb *)calloc(1, sizeof(*t));
25624583Sdarrenr	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
25722514Sdarrenr	    {
25822514Sdarrenr		fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
25922514Sdarrenr			i->inp_ppcb, t, sizeof(*t));
26022514Sdarrenr		return NULL;
26122514Sdarrenr	    }
26222514Sdarrenr	return (struct tcpcb *)i->inp_ppcb;
26322514Sdarrenr}
26422514Sdarrenr#else
26524583Sdarrenrstatic struct kinfo_proc *getproc()
26622514Sdarrenr{
26722514Sdarrenr	static	struct	kinfo_proc kp;
26822514Sdarrenr	pid_t	pid = getpid();
26931183Speter	int	mib[4];
27031183Speter	size_t	n;
27122514Sdarrenr
27222514Sdarrenr	mib[0] = CTL_KERN;
27322514Sdarrenr	mib[1] = KERN_PROC;
27422514Sdarrenr	mib[2] = KERN_PROC_PID;
27522514Sdarrenr	mib[3] = pid;
27622514Sdarrenr
27734739Speter	n = sizeof(kp);
27822514Sdarrenr	if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
27922514Sdarrenr	    {
28022514Sdarrenr		perror("sysctl");
28122514Sdarrenr		return NULL;
28222514Sdarrenr	    }
28322514Sdarrenr	return &kp;
28422514Sdarrenr}
28522514Sdarrenr
28622514Sdarrenr
28722514Sdarrenrstruct	tcpcb	*find_tcp(tfd, ti)
28822514Sdarrenrint	tfd;
28922514Sdarrenrstruct	tcpiphdr *ti;
29022514Sdarrenr{
29122514Sdarrenr	struct	tcpcb	*t;
29222514Sdarrenr	struct	inpcb	*i;
29322514Sdarrenr	struct	socket	*s;
29422514Sdarrenr	struct	filedesc	*fd;
29522514Sdarrenr	struct	kinfo_proc	*p;
29622514Sdarrenr	struct	file	*f, **o;
29722514Sdarrenr
29822514Sdarrenr	if (!(p = getproc()))
29922514Sdarrenr		return NULL;
30022514Sdarrenr
30122514Sdarrenr	fd = (struct filedesc *)malloc(sizeof(*fd));
302170268Sdarrenr	if (fd == NULL)
303170268Sdarrenr		return NULL;
30470033Salfred#if defined( __FreeBSD_version) && __FreeBSD_version >= 500013
30570033Salfred	if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
30670033Salfred	    {
30770033Salfred		fprintf(stderr, "read(%#lx,%#lx) failed\n",
30870033Salfred			(u_long)p, (u_long)p->ki_fd);
309170268Sdarrenr		free(fd);
31070033Salfred		return NULL;
31170033Salfred	    }
31270033Salfred#else
31324583Sdarrenr	if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
31422514Sdarrenr	    {
31522514Sdarrenr		fprintf(stderr, "read(%#lx,%#lx) failed\n",
31622514Sdarrenr			(u_long)p, (u_long)p->kp_proc.p_fd);
317170268Sdarrenr		free(fd);
31822514Sdarrenr		return NULL;
31922514Sdarrenr	    }
32070033Salfred#endif
32122514Sdarrenr
322161357Sguido	o = NULL;
323161357Sguido	f = NULL;
324161357Sguido	s = NULL;
325161357Sguido	i = NULL;
326161357Sguido	t = NULL;
327161357Sguido
32822514Sdarrenr	o = (struct file **)calloc(1, sizeof(*o) * (fd->fd_lastfile + 1));
32924583Sdarrenr	if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
33022514Sdarrenr	    {
33131183Speter		fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
33231183Speter			(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
333161357Sguido		goto finderror;
33422514Sdarrenr	    }
33522514Sdarrenr	f = (struct file *)calloc(1, sizeof(*f));
33624583Sdarrenr	if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
33722514Sdarrenr	    {
33831183Speter		fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
33931183Speter			(u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
340161357Sguido		goto finderror;
34122514Sdarrenr	    }
34222514Sdarrenr
34322514Sdarrenr	s = (struct socket *)calloc(1, sizeof(*s));
344109153Sdillon	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
34522514Sdarrenr	    {
34631183Speter		fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
347161357Sguido			(u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
348161357Sguido		goto finderror;
34922514Sdarrenr	    }
35022514Sdarrenr
35122514Sdarrenr	i = (struct inpcb *)calloc(1, sizeof(*i));
35224583Sdarrenr	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
35322514Sdarrenr	    {
35431183Speter		fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
35531183Speter			(u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
356161357Sguido		goto finderror;
35722514Sdarrenr	    }
35822514Sdarrenr
35922514Sdarrenr	t = (struct tcpcb *)calloc(1, sizeof(*t));
36024583Sdarrenr	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
36122514Sdarrenr	    {
36231183Speter		fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
36331183Speter			(u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
364161357Sguido		goto finderror;
36522514Sdarrenr	    }
36622514Sdarrenr	return (struct tcpcb *)i->inp_ppcb;
367161357Sguido
368161357Sguidofinderror:
369161357Sguido	if (o != NULL)
370161357Sguido		free(o);
371161357Sguido	if (f != NULL)
372161357Sguido		free(f);
373161357Sguido	if (s != NULL)
374161357Sguido		free(s);
375161357Sguido	if (i != NULL)
376161357Sguido		free(i);
377161357Sguido	if (t != NULL)
378161357Sguido		free(t);
379161357Sguido	return NULL;
38022514Sdarrenr}
38122514Sdarrenr#endif /* BSD < 199301 */
38222514Sdarrenr
38324583Sdarrenrint	do_socket(dev, mtu, ti, gwip)
38422514Sdarrenrchar	*dev;
38522514Sdarrenrint	mtu;
38622514Sdarrenrstruct	tcpiphdr *ti;
38722514Sdarrenrstruct	in_addr	gwip;
38822514Sdarrenr{
38922514Sdarrenr	struct	sockaddr_in	rsin, lsin;
39022514Sdarrenr	struct	tcpcb	*t, tcb;
391172776Sdarrenr	int	fd, nfd;
392172776Sdarrenr	socklen_t len;
39322514Sdarrenr
39422514Sdarrenr	printf("Dest. Port: %d\n", ti->ti_dport);
39522514Sdarrenr
39622514Sdarrenr	fd = socket(AF_INET, SOCK_STREAM, 0);
39722514Sdarrenr	if (fd == -1)
39822514Sdarrenr	    {
39922514Sdarrenr		perror("socket");
40022514Sdarrenr		return -1;
40122514Sdarrenr	    }
40222514Sdarrenr
40322514Sdarrenr	if (fcntl(fd, F_SETFL, FNDELAY) == -1)
40422514Sdarrenr	    {
40522514Sdarrenr		perror("fcntl");
40622514Sdarrenr		return -1;
40722514Sdarrenr	    }
40822514Sdarrenr
40922514Sdarrenr	bzero((char *)&lsin, sizeof(lsin));
41022514Sdarrenr	lsin.sin_family = AF_INET;
41122514Sdarrenr	bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
41222514Sdarrenr	      sizeof(struct in_addr));
41322514Sdarrenr	if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
41422514Sdarrenr	    {
41522514Sdarrenr		perror("bind");
41622514Sdarrenr		return -1;
41722514Sdarrenr	    }
41822514Sdarrenr	len = sizeof(lsin);
41922514Sdarrenr	(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
42022514Sdarrenr	ti->ti_sport = lsin.sin_port;
42122514Sdarrenr	printf("sport %d\n", ntohs(lsin.sin_port));
422161357Sguido
423145519Sdarrenr	nfd = initdevice(dev, 1);
424161357Sguido	if (nfd == -1)
425161357Sguido		return -1;
42622514Sdarrenr
42722514Sdarrenr	if (!(t = find_tcp(fd, ti)))
42822514Sdarrenr		return -1;
42922514Sdarrenr
43022514Sdarrenr	bzero((char *)&rsin, sizeof(rsin));
43122514Sdarrenr	rsin.sin_family = AF_INET;
43222514Sdarrenr	bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
43322514Sdarrenr	      sizeof(struct in_addr));
43422514Sdarrenr	rsin.sin_port = ti->ti_dport;
43522514Sdarrenr	if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
43622514Sdarrenr	    errno != EINPROGRESS)
43722514Sdarrenr	    {
43822514Sdarrenr		perror("connect");
43922514Sdarrenr		return -1;
44022514Sdarrenr	    }
44124583Sdarrenr	KMCPY(&tcb, t, sizeof(tcb));
44222514Sdarrenr	ti->ti_win = tcb.rcv_adv;
44322514Sdarrenr	ti->ti_seq = tcb.snd_nxt - 1;
44422514Sdarrenr	ti->ti_ack = tcb.rcv_nxt;
44522514Sdarrenr
44624583Sdarrenr	if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
44722514Sdarrenr		return -1;
44822514Sdarrenr	(void)write(fd, "Hello World\n", 12);
44922514Sdarrenr	sleep(2);
45022514Sdarrenr	close(fd);
45122514Sdarrenr	return 0;
45222514Sdarrenr}
453