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