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