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