sock.c revision 344833
1/* $FreeBSD: stable/11/contrib/ipfilter/ipsend/sock.c 344833 2019-03-06 02:37:25Z cy $ */
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)
9static const char sccsid[] = "@(#)sock.c	1.2 1/11/96 (C)1995 Darren Reed";
10static 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 */
22typedef int     boolean_t;
23#endif
24#ifndef	ultrix
25#include <fcntl.h>
26#endif
27#if (__FreeBSD_version >= 300000)
28# include <sys/dirent.h>
29#else
30# include <sys/dir.h>
31#endif
32# ifdef __NetBSD__
33#  include <machine/lock.h>
34# endif
35# ifdef __FreeBSD__
36#  define _WANT_FILE
37# else
38#  define _KERNEL
39#  define	KERNEL
40# endif
41# ifdef	ultrix
42#  undef	LOCORE
43#  include <sys/smp_lock.h>
44# endif
45# include <sys/file.h>
46# ifdef __FreeBSD__
47#  undef _WANT_FILE
48# else
49#  undef  _KERNEL
50#  undef  KERNEL
51# endif
52#include <nlist.h>
53#include <sys/user.h>
54#include <sys/socket.h>
55#include <sys/socketvar.h>
56#include <sys/proc.h>
57#if !defined(ultrix) && !defined(hpux) && !defined(__osf__)
58# include <kvm.h>
59#endif
60#ifdef sun
61#include <sys/systm.h>
62#include <sys/session.h>
63#endif
64#if BSD >= 199103
65#include <sys/sysctl.h>
66#include <sys/filedesc.h>
67#include <paths.h>
68#endif
69#include <math.h>
70#include <netinet/in.h>
71#include <netinet/in_systm.h>
72#include <netinet/ip.h>
73#include <netinet/tcp.h>
74#include <net/if.h>
75# include <net/route.h>
76#include <netinet/ip_var.h>
77#include <netinet/in_pcb.h>
78#include <netinet/tcp_timer.h>
79#include <netinet/tcp_var.h>
80#include <stdio.h>
81#include <unistd.h>
82#include <string.h>
83#include <stdlib.h>
84#include <stddef.h>
85#include <pwd.h>
86#include "ipsend.h"
87
88
89int	nproc;
90struct	proc	*proc;
91
92#ifndef	KMEM
93# ifdef	_PATH_KMEM
94#  define	KMEM	_PATH_KMEM
95# endif
96#endif
97#ifndef	KERNEL
98# ifdef	_PATH_UNIX
99#  define	KERNEL	_PATH_UNIX
100# endif
101#endif
102#ifndef	KMEM
103# define	KMEM	"/dev/kmem"
104#endif
105#ifndef	KERNEL
106# define	KERNEL	"/vmunix"
107#endif
108
109
110#if BSD < 199103
111static	struct	proc	*getproc __P((void));
112#else
113static	struct	kinfo_proc	*getproc __P((void));
114#endif
115
116
117int	kmemcpy(buf, pos, n)
118	char	*buf;
119	void	*pos;
120	int	n;
121{
122	static	int	kfd = -1;
123	off_t	offset = (u_long)pos;
124
125	if (kfd == -1)
126		kfd = open(KMEM, O_RDONLY);
127
128	if (lseek(kfd, offset, SEEK_SET) == -1)
129	    {
130		perror("lseek");
131		return -1;
132	    }
133	if (read(kfd, buf, n) == -1)
134	    {
135		perror("read");
136		return -1;
137	    }
138	return n;
139}
140
141struct	nlist	names[4] = {
142	{ "_proc" },
143	{ "_nproc" },
144#ifdef	ultrix
145	{ "_u" },
146#else
147	{ NULL },
148#endif
149	{ NULL }
150	};
151
152#if BSD < 199103
153static struct proc *getproc()
154{
155	struct	proc	*p;
156	pid_t	pid = getpid();
157	int	siz, n;
158
159	n = nlist(KERNEL, names);
160	if (n != 0)
161	    {
162		fprintf(stderr, "nlist(%#x) == %d\n", names, n);
163		return NULL;
164	    }
165	if (KMCPY(&nproc, names[1].n_value, sizeof(nproc)) == -1)
166	    {
167		fprintf(stderr, "read nproc (%#x)\n", names[1].n_value);
168		return NULL;
169	    }
170	siz = nproc * sizeof(struct proc);
171	if (KMCPY(&p, names[0].n_value, sizeof(p)) == -1)
172	    {
173		fprintf(stderr, "read(%#x,%#x,%d) proc\n",
174			names[0].n_value, &p, sizeof(p));
175		return NULL;
176	    }
177	proc = (struct proc *)malloc(siz);
178	if (KMCPY(proc, p, siz) == -1)
179	    {
180		fprintf(stderr, "read(%#x,%#x,%d) proc\n",
181			p, proc, siz);
182		return NULL;
183	    }
184
185	p = proc;
186
187	for (n = nproc; n; n--, p++)
188		if (p->p_pid == pid)
189			break;
190	if (!n)
191		return NULL;
192
193	return p;
194}
195
196
197struct	tcpcb	*find_tcp(fd, ti)
198	int	fd;
199	struct	tcpiphdr *ti;
200{
201	struct	tcpcb	*t;
202	struct	inpcb	*i;
203	struct	socket	*s;
204	struct	user	*up;
205	struct	proc	*p;
206	struct	file	*f, **o;
207
208	if (!(p = getproc()))
209		return NULL;
210	up = (struct user *)malloc(sizeof(*up));
211#ifndef	ultrix
212	if (KMCPY(up, p->p_uarea, sizeof(*up)) == -1)
213	    {
214		fprintf(stderr, "read(%#x,%#x) failed\n", p, p->p_uarea);
215		return NULL;
216	    }
217#else
218	if (KMCPY(up, names[2].n_value, sizeof(*up)) == -1)
219	    {
220		fprintf(stderr, "read(%#x,%#x) failed\n", p, names[2].n_value);
221		return NULL;
222	    }
223#endif
224
225	o = (struct file **)calloc(up->u_lastfile + 1, sizeof(*o));
226	if (KMCPY(o, up->u_ofile, (up->u_lastfile + 1) * sizeof(*o)) == -1)
227	    {
228		fprintf(stderr, "read(%#x,%#x,%d) - u_ofile - failed\n",
229			up->u_ofile, o, sizeof(*o));
230		return NULL;
231	    }
232	f = (struct file *)calloc(1, sizeof(*f));
233	if (KMCPY(f, o[fd], sizeof(*f)) == -1)
234	    {
235		fprintf(stderr, "read(%#x,%#x,%d) - o[fd] - failed\n",
236			up->u_ofile[fd], f, sizeof(*f));
237		return NULL;
238	    }
239
240	s = (struct socket *)calloc(1, sizeof(*s));
241	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
242	    {
243		fprintf(stderr, "read(%#x,%#x,%d) - f_data - failed\n",
244			o[fd], s, sizeof(*s));
245		return NULL;
246	    }
247
248	i = (struct inpcb *)calloc(1, sizeof(*i));
249	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
250	    {
251		fprintf(stderr, "kvm_read(%#x,%#x,%d) - so_pcb - failed\n",
252			s->so_pcb, i, sizeof(*i));
253		return NULL;
254	    }
255
256	t = (struct tcpcb *)calloc(1, sizeof(*t));
257	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
258	    {
259		fprintf(stderr, "read(%#x,%#x,%d) - inp_ppcb - failed\n",
260			i->inp_ppcb, t, sizeof(*t));
261		return NULL;
262	    }
263	return (struct tcpcb *)i->inp_ppcb;
264}
265#else
266static struct kinfo_proc *getproc()
267{
268	static	struct	kinfo_proc kp;
269	pid_t	pid = getpid();
270	int	mib[4];
271	size_t	n;
272
273	mib[0] = CTL_KERN;
274	mib[1] = KERN_PROC;
275	mib[2] = KERN_PROC_PID;
276	mib[3] = pid;
277
278	n = sizeof(kp);
279	if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1)
280	    {
281		perror("sysctl");
282		return NULL;
283	    }
284	return &kp;
285}
286
287
288struct	tcpcb	*find_tcp(tfd, ti)
289	int	tfd;
290	struct	tcpiphdr *ti;
291{
292	struct	tcpcb	*t;
293	struct	inpcb	*i;
294	struct	socket	*s;
295	struct	filedesc	*fd;
296	struct	kinfo_proc	*p;
297	struct	file	*f, **o;
298
299	if (!(p = getproc()))
300		return NULL;
301
302	fd = (struct filedesc *)malloc(sizeof(*fd));
303	if (fd == NULL)
304		return NULL;
305#if defined( __FreeBSD_version) && __FreeBSD_version >= 500013
306	if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1)
307	    {
308		fprintf(stderr, "read(%#lx,%#lx) failed\n",
309			(u_long)p, (u_long)p->ki_fd);
310		free(fd);
311		return NULL;
312	    }
313#else
314	if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1)
315	    {
316		fprintf(stderr, "read(%#lx,%#lx) failed\n",
317			(u_long)p, (u_long)p->kp_proc.p_fd);
318		free(fd);
319		return NULL;
320	    }
321#endif
322
323	o = NULL;
324	f = NULL;
325	s = NULL;
326	i = NULL;
327	t = NULL;
328
329	o = (struct file **)calloc(fd->fd_lastfile + 1, sizeof(*o));
330	if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1)
331	    {
332		fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n",
333			(u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o));
334		goto finderror;
335	    }
336	f = (struct file *)calloc(1, sizeof(*f));
337	if (KMCPY(f, o[tfd], sizeof(*f)) == -1)
338	    {
339		fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n",
340			(u_long)o[tfd], (u_long)f, (u_long)sizeof(*f));
341		goto finderror;
342	    }
343
344	s = (struct socket *)calloc(1, sizeof(*s));
345	if (KMCPY(s, f->f_data, sizeof(*s)) == -1)
346	    {
347		fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n",
348			(u_long)f->f_data, (u_long)s, (u_long)sizeof(*s));
349		goto finderror;
350	    }
351
352	i = (struct inpcb *)calloc(1, sizeof(*i));
353	if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1)
354	    {
355		fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n",
356			(u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i));
357		goto finderror;
358	    }
359
360	t = (struct tcpcb *)calloc(1, sizeof(*t));
361	if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1)
362	    {
363		fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n",
364			(u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t));
365		goto finderror;
366	    }
367	return (struct tcpcb *)i->inp_ppcb;
368
369finderror:
370	if (o != NULL)
371		free(o);
372	if (f != NULL)
373		free(f);
374	if (s != NULL)
375		free(s);
376	if (i != NULL)
377		free(i);
378	if (t != NULL)
379		free(t);
380	return NULL;
381}
382#endif /* BSD < 199301 */
383
384int	do_socket(dev, mtu, ti, gwip)
385	char	*dev;
386	int	mtu;
387	struct	tcpiphdr *ti;
388	struct	in_addr	gwip;
389{
390	struct	sockaddr_in	rsin, lsin;
391	struct	tcpcb	*t, tcb;
392	int	fd, nfd;
393	socklen_t len;
394
395	printf("Dest. Port: %d\n", ti->ti_dport);
396
397	fd = socket(AF_INET, SOCK_STREAM, 0);
398	if (fd == -1)
399	    {
400		perror("socket");
401		return -1;
402	    }
403
404	if (fcntl(fd, F_SETFL, FNDELAY) == -1)
405	    {
406		perror("fcntl");
407		return -1;
408	    }
409
410	bzero((char *)&lsin, sizeof(lsin));
411	lsin.sin_family = AF_INET;
412	bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr,
413	      sizeof(struct in_addr));
414	if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1)
415	    {
416		perror("bind");
417		return -1;
418	    }
419	len = sizeof(lsin);
420	(void) getsockname(fd, (struct sockaddr *)&lsin, &len);
421	ti->ti_sport = lsin.sin_port;
422	printf("sport %d\n", ntohs(lsin.sin_port));
423
424	nfd = initdevice(dev, 1);
425	if (nfd == -1)
426		return -1;
427
428	if (!(t = find_tcp(fd, ti)))
429		return -1;
430
431	bzero((char *)&rsin, sizeof(rsin));
432	rsin.sin_family = AF_INET;
433	bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr,
434	      sizeof(struct in_addr));
435	rsin.sin_port = ti->ti_dport;
436	if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 &&
437	    errno != EINPROGRESS)
438	    {
439		perror("connect");
440		return -1;
441	    }
442	KMCPY(&tcb, t, sizeof(tcb));
443	ti->ti_win = tcb.rcv_adv;
444	ti->ti_seq = tcb.snd_nxt - 1;
445	ti->ti_ack = tcb.rcv_nxt;
446
447	if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1)
448		return -1;
449	(void)write(fd, "Hello World\n", 12);
450	sleep(2);
451	close(fd);
452	return 0;
453}
454