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