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
ipfattach(softc)38 ipfattach(softc)
39 ipf_main_softc_t *softc;
40 {
41 return (0);
42 }
43
44
45 int
ipfdetach(softc)46 ipfdetach(softc)
47 ipf_main_softc_t *softc;
48 {
49 return (0);
50 }
51
52
53 /*
54 * Filter ioctl interface.
55 */
56 int
ipfioctl(softc,dev,cmd,data,mode)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
ipf_forgetifp(softc,ifp)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
no_output(ifp,m,s,rt)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
write_output(ifp,m,s,rt)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
ipf_setifpaddr(ifp,addr)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 *
get_unit(name,family)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 *
get_ifname(ifp)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
init_ifp()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
ipf_fastroute(m,mpp,fin,fdp)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
ipf_send_reset(fin)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
ipf_send_icmp_err(type,fin,dst)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
m_freem(m)461 m_freem(m)
462 mb_t *m;
463 {
464 return;
465 }
466
467
468 void
m_copydata(m,off,len,cp)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
ipfuiomove(buf,len,rwflag,uio)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
ipf_newisn(fin)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
ipf_nextipid(fin)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
ipf_checkv4sum(fin)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
ipf_checkv6sum(fin)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
ipf_ifpaddr(softc,v,atype,ifptr,inp,inpmask)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
ipf_random()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
ipf_verifysrc(fin)752 ipf_verifysrc(fin)
753 fr_info_t *fin;
754 {
755 return (1);
756 }
757
758
759 int
ipf_inject(fin,m)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
ipf_pcksum(fin,hlen,sum)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 *
ipf_pullup(m,fin,plen)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