xref: /freebsd/sbin/ipf/ipsend/sock.c (revision ca57a343e86ed3015596db68bda17518ad45436a)
1 /*
2  * sock.c (C) 1995-1998 Darren Reed
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  */
7 #if !defined(lint)
8 static const char sccsid[] = "@(#)sock.c	1.2 1/11/96 (C)1995 Darren Reed";
9 static const char rcsid[] = "@(#)$Id$";
10 #endif
11 #include <sys/param.h>
12 #include <sys/types.h>
13 #include <sys/time.h>
14 #include <sys/stat.h>
15 #if defined(__NetBSD__) && defined(__vax__)
16 /*
17  * XXX need to declare boolean_t for _KERNEL <sys/files.h>
18  * which ends up including <sys/device.h> for vax.  See PR#32907
19  * for further details.
20  */
21 typedef int     boolean_t;
22 #endif
23 #include <fcntl.h>
24 # include <sys/dirent.h>
25 # ifdef __NetBSD__
26 #  include <machine/lock.h>
27 # endif
28 # ifdef __FreeBSD__
29 #  define _WANT_FILE
30 # else
31 #  define _KERNEL
32 #  define	KERNEL
33 # endif
34 # include <sys/file.h>
35 # ifdef __FreeBSD__
36 #  undef _WANT_FILE
37 # else
38 #  undef  _KERNEL
39 #  undef  KERNEL
40 # endif
41 #include <nlist.h>
42 #include <sys/user.h>
43 #include <sys/socket.h>
44 #define	_WANT_SOCKET
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 
77 int	nproc;
78 struct	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 static	struct	kinfo_proc	*getproc(void);
99 
100 
101 int
102 kmemcpy(char *buf, void *pos, int n)
103 {
104 	static	int	kfd = -1;
105 	off_t	offset = (u_long)pos;
106 
107 	if (kfd == -1)
108 		kfd = open(KMEM, O_RDONLY);
109 
110 	if (lseek(kfd, offset, SEEK_SET) == -1)
111 	    {
112 		perror("lseek");
113 		return (-1);
114 	    }
115 	if (read(kfd, buf, n) == -1)
116 	    {
117 		perror("read");
118 		return (-1);
119 	    }
120 	return (n);
121 }
122 
123 struct	nlist	names[4] = {
124 	{ "_proc" },
125 	{ "_nproc" },
126 	{ NULL },
127 	{ NULL }
128 	};
129 
130 static struct
131 kinfo_proc *getproc(void)
132 {
133 	static	struct	kinfo_proc kp;
134 	pid_t	pid = getpid();
135 	int	mib[4];
136 	size_t	n;
137 
138 	mib[0] = CTL_KERN;
139 	mib[1] = KERN_PROC;
140 	mib[2] = KERN_PROC_PID;
141 	mib[3] = pid;
142 
143 	n = sizeof(kp);
144 	if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
145 	    {
146 		perror("sysctl");
147 		return (NULL);
148 	    }
149 	return (&kp);
150 }
151 
152 
153 struct tcpcb *
154 find_tcp(int tfd, struct  tcpiphdr *ti)
155 {
156 	struct	tcpcb	*t;
157 	struct	inpcb	*i;
158 	struct	socket	*s;
159 	struct	filedesc	*fd;
160 	struct	kinfo_proc	*p;
161 	struct	file	*f, **o;
162 
163 	if (!(p = getproc()))
164 		return (NULL);
165 
166 	fd = (struct filedesc *)malloc(sizeof(*fd));
167 	if (fd == NULL)
168 		return (NULL);
169 #if defined( __FreeBSD__)
170 	if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
171 	    {
172 		fprintf(stderr, "read(%#lx,%#lx) failed\n",
173 			(u_long)p, (u_long)p->ki_fd);
174 		free(fd);
175 		return (NULL);
176 	    }
177 #else
178 	if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
179 	    {
180 		fprintf(stderr, "read(%#lx,%#lx) failed\n",
181 			(u_long)p, (u_long)p->kp_proc.p_fd);
182 		free(fd);
183 		return (NULL);
184 	    }
185 #endif
186 
187 	o = NULL;
188 	f = NULL;
189 	s = NULL;
190 	i = NULL;
191 	t = NULL;
192 
193 	o = (struct file **)calloc(fd->fd_lastfile + 1, sizeof(*o));
194 	if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
195 	    {
196 		fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
197 			(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
198 		goto finderror;
199 	    }
200 	f = (struct file *)calloc(1, sizeof(*f));
201 	if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
202 	    {
203 		fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
204 			(u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
205 		goto finderror;
206 	    }
207 
208 	s = (struct socket *)calloc(1, sizeof(*s));
209 	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
210 	    {
211 		fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
212 			(u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
213 		goto finderror;
214 	    }
215 
216 	i = (struct inpcb *)calloc(1, sizeof(*i));
217 	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
218 	    {
219 		fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
220 			(u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
221 		goto finderror;
222 	    }
223 
224 	t = (struct tcpcb *)calloc(1, sizeof(*t));
225 	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
226 	    {
227 		fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
228 			(u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
229 		goto finderror;
230 	    }
231 	return (struct tcpcb *)i->inp_ppcb;
232 
233 finderror:
234 	if (o != NULL)
235 		free(o);
236 	if (f != NULL)
237 		free(f);
238 	if (s != NULL)
239 		free(s);
240 	if (i != NULL)
241 		free(i);
242 	if (t != NULL)
243 		free(t);
244 	return (NULL);
245 }
246 
247 int
248 do_socket(char *dev, int mtu, struct  tcpiphdr *ti, struct  in_addr gwip)
249 {
250 	struct	sockaddr_in	rsin, lsin;
251 	struct	tcpcb	*t, tcb;
252 	int	fd, nfd;
253 	socklen_t len;
254 
255 	printf("Dest. Port: %d\n", ti->ti_dport);
256 
257 	fd = socket(AF_INET, SOCK_STREAM, 0);
258 	if (fd == -1)
259 	    {
260 		perror("socket");
261 		return (-1);
262 	    }
263 
264 	if (fcntl(fd, F_SETFL, FNDELAY) == -1)
265 	    {
266 		perror("fcntl");
267 		return (-1);
268 	    }
269 
270 	bzero((char *)&lsin, sizeof(lsin));
271 	lsin.sin_family = AF_INET;
272 	bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
273 	      sizeof(struct in_addr));
274 	if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
275 	    {
276 		perror("bind");
277 		return (-1);
278 	    }
279 	len = sizeof(lsin);
280 	(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
281 	ti->ti_sport = lsin.sin_port;
282 	printf("sport %d\n", ntohs(lsin.sin_port));
283 
284 	nfd = initdevice(dev, 1);
285 	if (nfd == -1)
286 		return (-1);
287 
288 	if (!(t = find_tcp(fd, ti)))
289 		return (-1);
290 
291 	bzero((char *)&rsin, sizeof(rsin));
292 	rsin.sin_family = AF_INET;
293 	bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
294 	      sizeof(struct in_addr));
295 	rsin.sin_port = ti->ti_dport;
296 	if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
297 	    errno != EINPROGRESS)
298 	    {
299 		perror("connect");
300 		return (-1);
301 	    }
302 	KMCPY(&tcb, t, sizeof(tcb));
303 	ti->ti_win = tcb.rcv_adv;
304 	ti->ti_seq = tcb.snd_nxt - 1;
305 	ti->ti_ack = tcb.rcv_nxt;
306 
307 	if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
308 		return (-1);
309 	(void)write(fd, "Hello World\n", 12);
310 	sleep(2);
311 	close(fd);
312 	return (0);
313 }
314