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