xref: /freebsd/sbin/ipf/ipftest/ip_fil.c (revision 9768746b)
1 /*	$FreeBSD$	*/
2 
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * $Id$
9  */
10 #if !defined(lint)
11 static const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
12 static const char rcsid[] = "@(#)$Id$";
13 #endif
14 
15 #include "ipf.h"
16 #include "md5.h"
17 #include "ipt.h"
18 
19 ipf_main_softc_t	ipfmain;
20 
21 static	struct	ifnet **ifneta = NULL;
22 static	int	nifs = 0;
23 
24 struct	rtentry;
25 
26 static	void	ipf_setifpaddr(struct ifnet *, char *);
27 void	init_ifp(void);
28 static int 	no_output(struct ifnet *, struct mbuf *,
29 			       struct sockaddr *, struct rtentry *);
30 static int	write_output(struct ifnet *, struct mbuf *,
31 				  struct sockaddr *, struct rtentry *);
32 
33 struct ifaddr {
34 	struct sockaddr_storage ifa_addr;
35 };
36 
37 int
38 ipfattach(softc)
39 	ipf_main_softc_t *softc;
40 {
41 	return (0);
42 }
43 
44 
45 int
46 ipfdetach(softc)
47 	ipf_main_softc_t *softc;
48 {
49 	return (0);
50 }
51 
52 
53 /*
54  * Filter ioctl interface.
55  */
56 int
57 ipfioctl(softc, dev, cmd, data, mode)
58 	ipf_main_softc_t *softc;
59 	int dev;
60 	ioctlcmd_t cmd;
61 	caddr_t data;
62 	int mode;
63 {
64 	int error = 0, unit = 0, uid;
65 
66 	uid = getuid();
67 	unit = dev;
68 
69 	SPL_NET(s);
70 
71 	error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
72 	if (error != -1) {
73 		SPL_X(s);
74 		return (error);
75 	}
76 	SPL_X(s);
77 	return (error);
78 }
79 
80 
81 void
82 ipf_forgetifp(softc, ifp)
83 	ipf_main_softc_t *softc;
84 	void *ifp;
85 {
86 	register frentry_t *f;
87 
88 	WRITE_ENTER(&softc->ipf_mutex);
89 	for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
90 	     f = f->fr_next)
91 		if (f->fr_ifa == ifp)
92 			f->fr_ifa = (void *)-1;
93 	for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
94 	     f = f->fr_next)
95 		if (f->fr_ifa == ifp)
96 			f->fr_ifa = (void *)-1;
97 	for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
98 	     f = f->fr_next)
99 		if (f->fr_ifa == ifp)
100 			f->fr_ifa = (void *)-1;
101 	for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
102 	     f = f->fr_next)
103 		if (f->fr_ifa == ifp)
104 			f->fr_ifa = (void *)-1;
105 	RWLOCK_EXIT(&softc->ipf_mutex);
106 	ipf_nat_sync(softc, ifp);
107 	ipf_lookup_sync(softc, ifp);
108 }
109 
110 
111 static int
112 no_output(ifp, m, s, rt)
113 	struct rtentry *rt;
114 	struct ifnet *ifp;
115 	struct mbuf *m;
116 	struct sockaddr *s;
117 {
118 	return (0);
119 }
120 
121 
122 static int
123 write_output(ifp, m, s, rt)
124 	struct rtentry *rt;
125 	struct ifnet *ifp;
126 	struct mbuf *m;
127 	struct sockaddr *s;
128 {
129 	char fname[32];
130 	mb_t *mb;
131 	ip_t *ip;
132 	int fd;
133 
134 	mb = (mb_t *)m;
135 	ip = MTOD(mb, ip_t *);
136 
137 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
138     defined(__FreeBSD__)
139 	sprintf(fname, "/tmp/%s", ifp->if_xname);
140 #else
141 	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
142 #endif
143 	fd = open(fname, O_WRONLY|O_APPEND);
144 	if (fd == -1) {
145 		perror("open");
146 		return (-1);
147 	}
148 	write(fd, (char *)ip, ntohs(ip->ip_len));
149 	close(fd);
150 	return (0);
151 }
152 
153 
154 static void
155 ipf_setifpaddr(ifp, addr)
156 	struct ifnet *ifp;
157 	char *addr;
158 {
159 	struct ifaddr *ifa;
160 
161 #if defined(__NetBSD__) || defined(__FreeBSD__)
162 	if (ifp->if_addrlist.tqh_first != NULL)
163 #else
164 	if (ifp->if_addrlist != NULL)
165 #endif
166 		return;
167 
168 	ifa = (struct ifaddr *)malloc(sizeof(*ifa));
169 #if defined(__NetBSD__) || defined(__FreeBSD__)
170 	ifp->if_addrlist.tqh_first = ifa;
171 #else
172 	ifp->if_addrlist = ifa;
173 #endif
174 
175 	if (ifa != NULL) {
176 		struct sockaddr_in *sin;
177 
178 		sin = (struct sockaddr_in *)&ifa->ifa_addr;
179 #ifdef USE_INET6
180 		if (index(addr, ':') != NULL) {
181 			struct sockaddr_in6 *sin6;
182 
183 			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
184 			sin6->sin6_family = AF_INET6;
185 			/* Abort if bad address. */
186 			switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr))
187 			{
188 			case 1:
189 				break;
190 			case -1:
191 				perror("inet_pton");
192 				abort();
193 				break;
194 			default:
195 				abort();
196 				break;
197 			}
198 		} else
199 #endif
200 		{
201 			sin->sin_family = AF_INET;
202 			sin->sin_addr.s_addr = inet_addr(addr);
203 			if (sin->sin_addr.s_addr == 0)
204 				abort();
205 		}
206 	}
207 }
208 
209 struct ifnet *
210 get_unit(name, family)
211 	char *name;
212 	int family;
213 {
214 	struct ifnet *ifp, **ifpp, **old_ifneta;
215 	char *addr;
216 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
217     defined(__FreeBSD__)
218 
219 	if (!*name)
220 		return (NULL);
221 
222 	if (name == NULL)
223 		name = "anon0";
224 
225 	addr = strchr(name, '=');
226 	if (addr != NULL)
227 		*addr++ = '\0';
228 
229 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
230 		if (!strcmp(name, ifp->if_xname)) {
231 			if (addr != NULL)
232 				ipf_setifpaddr(ifp, addr);
233 			return (ifp);
234 		}
235 	}
236 #else
237 	char *s, ifname[LIFNAMSIZ+1];
238 
239 	if (name == NULL)
240 		name = "anon0";
241 
242 	addr = strchr(name, '=');
243 	if (addr != NULL)
244 		*addr++ = '\0';
245 
246 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
247 		COPYIFNAME(family, ifp, ifname);
248 		if (!strcmp(name, ifname)) {
249 			if (addr != NULL)
250 				ipf_setifpaddr(ifp, addr);
251 			return (ifp);
252 		}
253 	}
254 #endif
255 
256 	if (!ifneta) {
257 		ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
258 		if (!ifneta)
259 			return (NULL);
260 		ifneta[1] = NULL;
261 		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
262 		if (!ifneta[0]) {
263 			free(ifneta);
264 			return (NULL);
265 		}
266 		nifs = 1;
267 	} else {
268 		old_ifneta = ifneta;
269 		nifs++;
270 		ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1,
271 						  sizeof(ifp));
272 		if (!ifneta) {
273 			free(old_ifneta);
274 			nifs = 0;
275 			return (NULL);
276 		}
277 		ifneta[nifs] = NULL;
278 		ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
279 		if (!ifneta[nifs - 1]) {
280 			nifs--;
281 			return (NULL);
282 		}
283 	}
284 	ifp = ifneta[nifs - 1];
285 
286 #if defined(__NetBSD__) || defined(__FreeBSD__)
287 	TAILQ_INIT(&ifp->if_addrlist);
288 #endif
289 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
290     defined(__FreeBSD__)
291 	(void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
292 #else
293 	s = name + strlen(name) - 1;
294 	for (; s > name; s--) {
295 		if (!ISDIGIT(*s)) {
296 			s++;
297 			break;
298 		}
299 	}
300 
301 	if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
302 		ifp->if_unit = atoi(s);
303 		ifp->if_name = (char *)malloc(s - name + 1);
304 		(void) strncpy(ifp->if_name, name, s - name);
305 		ifp->if_name[s - name] = '\0';
306 	} else {
307 		ifp->if_name = strdup(name);
308 		ifp->if_unit = -1;
309 	}
310 #endif
311 	ifp->if_output = (void *)no_output;
312 
313 	if (addr != NULL) {
314 		ipf_setifpaddr(ifp, addr);
315 	}
316 
317 	return (ifp);
318 }
319 
320 
321 char *
322 get_ifname(ifp)
323 	struct ifnet *ifp;
324 {
325 	static char ifname[LIFNAMSIZ];
326 
327 #if defined(__NetBSD__) || defined(__FreeBSD__)
328 	sprintf(ifname, "%s", ifp->if_xname);
329 #else
330 	if (ifp->if_unit != -1)
331 		sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
332 	else
333 		strcpy(ifname, ifp->if_name);
334 #endif
335 	return (ifname);
336 }
337 
338 
339 
340 void
341 init_ifp()
342 {
343 	struct ifnet *ifp, **ifpp;
344 	char fname[32];
345 	int fd;
346 
347 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
348     defined(__FreeBSD__)
349 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
350 		ifp->if_output = (void *)write_output;
351 		sprintf(fname, "/tmp/%s", ifp->if_xname);
352 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
353 		if (fd == -1)
354 			perror("open");
355 		else
356 			close(fd);
357 	}
358 #else
359 
360 	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
361 		ifp->if_output = (void *)write_output;
362 		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
363 		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
364 		if (fd == -1)
365 			perror("open");
366 		else
367 			close(fd);
368 	}
369 #endif
370 }
371 
372 
373 int
374 ipf_fastroute(m, mpp, fin, fdp)
375 	mb_t *m, **mpp;
376 	fr_info_t *fin;
377 	frdest_t *fdp;
378 {
379 	struct ifnet *ifp;
380 	ip_t *ip = fin->fin_ip;
381 	frdest_t node;
382 	int error = 0;
383 	frentry_t *fr;
384 	void *sifp;
385 	int sout;
386 
387 	sifp = fin->fin_ifp;
388 	sout = fin->fin_out;
389 	fr = fin->fin_fr;
390 	ip->ip_sum = 0;
391 
392 	if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
393 	    (fdp->fd_type == FRD_DSTLIST)) {
394 		bzero(&node, sizeof(node));
395 		ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
396 		fdp = &node;
397 	}
398 	ifp = fdp->fd_ptr;
399 
400 	if (ifp == NULL)
401 		return (0;	/* no routing table out here */);
402 
403 	if (fin->fin_out == 0) {
404 		fin->fin_ifp = ifp;
405 		fin->fin_out = 1;
406 		(void) ipf_acctpkt(fin, NULL);
407 		fin->fin_fr = NULL;
408 		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
409 			u_32_t pass;
410 
411 			(void) ipf_state_check(fin, &pass);
412 		}
413 
414 		switch (ipf_nat_checkout(fin, NULL))
415 		{
416 		case 0 :
417 			break;
418 		case 1 :
419 			ip->ip_sum = 0;
420 			break;
421 		case -1 :
422 			error = -1;
423 			goto done;
424 			break;
425 		}
426 
427 	}
428 
429 	m->mb_ifp = ifp;
430 	printpacket(fin->fin_out, m);
431 
432 	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
433 done:
434 	fin->fin_ifp = sifp;
435 	fin->fin_out = sout;
436 	return (error);
437 }
438 
439 
440 int
441 ipf_send_reset(fin)
442 	fr_info_t *fin;
443 {
444 	ipfkverbose("- TCP RST sent\n");
445 	return (0);
446 }
447 
448 
449 int
450 ipf_send_icmp_err(type, fin, dst)
451 	int type;
452 	fr_info_t *fin;
453 	int dst;
454 {
455 	ipfkverbose("- ICMP unreachable sent\n");
456 	return (0);
457 }
458 
459 
460 void
461 m_freem(m)
462 	mb_t *m;
463 {
464 	return;
465 }
466 
467 
468 void
469 m_copydata(m, off, len, cp)
470 	mb_t *m;
471 	int off, len;
472 	caddr_t cp;
473 {
474 	bcopy((char *)m + off, cp, len);
475 }
476 
477 
478 int
479 ipfuiomove(buf, len, rwflag, uio)
480 	caddr_t buf;
481 	int len, rwflag;
482 	struct uio *uio;
483 {
484 	int left, ioc, num, offset;
485 	struct iovec *io;
486 	char *start;
487 
488 	if (rwflag == UIO_READ) {
489 		left = len;
490 		ioc = 0;
491 
492 		offset = uio->uio_offset;
493 
494 		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
495 			io = uio->uio_iov + ioc;
496 			num = io->iov_len;
497 			if (num > left)
498 				num = left;
499 			start = (char *)io->iov_base + offset;
500 			if (start > (char *)io->iov_base + io->iov_len) {
501 				offset -= io->iov_len;
502 				ioc++;
503 				continue;
504 			}
505 			bcopy(buf, start, num);
506 			uio->uio_resid -= num;
507 			uio->uio_offset += num;
508 			left -= num;
509 			if (left > 0)
510 				ioc++;
511 		}
512 		if (left > 0)
513 			return (EFAULT);
514 	}
515 	return (0);
516 }
517 
518 
519 u_32_t
520 ipf_newisn(fin)
521 	fr_info_t *fin;
522 {
523 	static int iss_seq_off = 0;
524 	u_char hash[16];
525 	u_32_t newiss;
526 	MD5_CTX ctx;
527 
528 	/*
529 	 * Compute the base value of the ISS.  It is a hash
530 	 * of (saddr, sport, daddr, dport, secret).
531 	 */
532 	MD5Init(&ctx);
533 
534 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
535 		  sizeof(fin->fin_fi.fi_src));
536 	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
537 		  sizeof(fin->fin_fi.fi_dst));
538 	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
539 
540 	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
541 
542 	MD5Final(hash, &ctx);
543 
544 	memcpy(&newiss, hash, sizeof(newiss));
545 
546 	/*
547 	 * Now increment our "timer", and add it in to
548 	 * the computed value.
549 	 *
550 	 * XXX Use `addin'?
551 	 * XXX TCP_ISSINCR too large to use?
552 	 */
553 	iss_seq_off += 0x00010000;
554 	newiss += iss_seq_off;
555 	return (newiss);
556 }
557 
558 
559 /* ------------------------------------------------------------------------ */
560 /* Function:    ipf_nextipid                                                */
561 /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
562 /* Parameters:  fin(I) - pointer to packet information                      */
563 /*                                                                          */
564 /* Returns the next IPv4 ID to use for this packet.                         */
565 /* ------------------------------------------------------------------------ */
566 inline u_short
567 ipf_nextipid(fin)
568 	fr_info_t *fin;
569 {
570 	static u_short ipid = 0;
571 	ipf_main_softc_t *softc = fin->fin_main_soft;
572 	u_short id;
573 
574 	MUTEX_ENTER(&softc->ipf_rw);
575 	if (fin->fin_pktnum != 0) {
576 		/*
577 		 * The -1 is for aligned test results.
578 		 */
579 		id = (fin->fin_pktnum - 1) & 0xffff;
580 	} else {
581 	}
582 		id = ipid++;
583 	MUTEX_EXIT(&softc->ipf_rw);
584 
585 	return (id);
586 }
587 
588 
589 inline int
590 ipf_checkv4sum(fin)
591 	fr_info_t *fin;
592 {
593 
594 	if (fin->fin_flx & FI_SHORT)
595 		return (1);
596 
597 	if (ipf_checkl4sum(fin) == -1) {
598 		fin->fin_flx |= FI_BAD;
599 		return (-1);
600 	}
601 	return (0);
602 }
603 
604 
605 #ifdef	USE_INET6
606 inline int
607 ipf_checkv6sum(fin)
608 	fr_info_t *fin;
609 {
610 	if (fin->fin_flx & FI_SHORT)
611 		return (1);
612 
613 	if (ipf_checkl4sum(fin) == -1) {
614 		fin->fin_flx |= FI_BAD;
615 		return (-1);
616 	}
617 	return (0);
618 }
619 #endif
620 
621 
622 #if 0
623 /*
624  * See above for description, except that all addressing is in user space.
625  */
626 int
627 copyoutptr(softc, src, dst, size)
628 	void *src, *dst;
629 	size_t size;
630 {
631 	caddr_t ca;
632 
633 	bcopy(dst, (char *)&ca, sizeof(ca));
634 	bcopy(src, ca, size);
635 	return (0);
636 }
637 
638 
639 /*
640  * See above for description, except that all addressing is in user space.
641  */
642 int
643 copyinptr(src, dst, size)
644 	void *src, *dst;
645 	size_t size;
646 {
647 	caddr_t ca;
648 
649 	bcopy(src, (char *)&ca, sizeof(ca));
650 	bcopy(ca, dst, size);
651 	return (0);
652 }
653 #endif
654 
655 
656 /*
657 * return the first IP Address associated with an interface
658  */
659 int
660 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
661 	ipf_main_softc_t *softc;
662 	int v, atype;
663 	void *ifptr;
664 	i6addr_t *inp, *inpmask;
665 {
666 	struct ifnet *ifp = ifptr;
667 	struct ifaddr *ifa;
668 
669 #if defined(__NetBSD__) || defined(__FreeBSD__)
670 	ifa = ifp->if_addrlist.tqh_first;
671 #else
672 	ifa = ifp->if_addrlist;
673 #endif
674 	if (ifa != NULL) {
675 		if (v == 4) {
676 			struct sockaddr_in *sin, mask;
677 
678 			mask.sin_addr.s_addr = 0xffffffff;
679 
680 			sin = (struct sockaddr_in *)&ifa->ifa_addr;
681 
682 			return (ipf_ifpfillv4addr(atype, sin, &mask,
683 						 &inp->in4, &inpmask->in4));
684 		}
685 #ifdef USE_INET6
686 		if (v == 6) {
687 			struct sockaddr_in6 *sin6, mask;
688 
689 			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
690 			((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
691 			((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
692 			((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
693 			((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
694 			return (ipf_ifpfillv6addr(atype, sin6, &mask,
695 						 inp, inpmask));
696 		}
697 #endif
698 	}
699 	return (0);
700 }
701 
702 
703 /*
704  * This function is not meant to be random, rather just produce a
705  * sequence of numbers that isn't linear to show "randomness".
706  */
707 u_32_t
708 ipf_random()
709 {
710 	static unsigned int last = 0xa5a5a5a5;
711 	static int calls = 0;
712 	int number;
713 
714 	calls++;
715 
716 	/*
717 	 * These are deliberately chosen to ensure that there is some
718 	 * attempt to test whether the output covers the range in test n18.
719 	 */
720 	switch (calls)
721 	{
722 	case 1 :
723 		number = 0;
724 		break;
725 	case 2 :
726 		number = 4;
727 		break;
728 	case 3 :
729 		number = 3999;
730 		break;
731 	case 4 :
732 		number = 4000;
733 		break;
734 	case 5 :
735 		number = 48999;
736 		break;
737 	case 6 :
738 		number = 49000;
739 		break;
740 	default :
741 		number = last;
742 		last *= calls;
743 		last++;
744 		number ^= last;
745 		break;
746 	}
747 	return (number);
748 }
749 
750 
751 int
752 ipf_verifysrc(fin)
753 	fr_info_t *fin;
754 {
755 	return (1);
756 }
757 
758 
759 int
760 ipf_inject(fin, m)
761 	fr_info_t *fin;
762 	mb_t *m;
763 {
764 	FREE_MB_T(m);
765 
766 	return (0);
767 }
768 
769 
770 u_int
771 ipf_pcksum(fin, hlen, sum)
772 	fr_info_t *fin;
773 	int hlen;
774 	u_int sum;
775 {
776 	u_short *sp;
777 	u_int sum2;
778 	int slen;
779 
780 	slen = fin->fin_plen - hlen;
781 	sp = (u_short *)((u_char *)fin->fin_ip + hlen);
782 
783 	for (; slen > 1; slen -= 2)
784 		sum += *sp++;
785 	if (slen)
786 		sum += ntohs(*(u_char *)sp << 8);
787 	while (sum > 0xffff)
788 		sum = (sum & 0xffff) + (sum >> 16);
789 	sum2 = (u_short)(~sum & 0xffff);
790 
791 	return (sum2);
792 }
793 
794 
795 void *
796 ipf_pullup(m, fin, plen)
797 	mb_t *m;
798 	fr_info_t *fin;
799 	int plen;
800 {
801 	if (M_LEN(m) >= plen)
802 		return (fin->fin_ip);
803 
804 	/*
805 	 * Fake ipf_pullup failing
806 	 */
807 	fin->fin_reason = FRB_PULLUP;
808 	*fin->fin_mp = NULL;
809 	fin->fin_m = NULL;
810 	fin->fin_ip = NULL;
811 	return (NULL);
812 }
813