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
ipfattach(softc)33 ipfattach(softc)
34 ipf_main_softc_t *softc;
35 {
36 return (0);
37 }
38
39
40 int
ipfdetach(softc)41 ipfdetach(softc)
42 ipf_main_softc_t *softc;
43 {
44 return (0);
45 }
46
47
48 /*
49 * Filter ioctl interface.
50 */
51 int
ipfioctl(softc,dev,cmd,data,mode)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
ipf_forgetifp(softc,ifp)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
no_output(ifp,m,s,rt)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
write_output(ifp,m,s,rt)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
ipf_setifpaddr(ifp,addr)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 *
get_unit(name,family)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 *
get_ifname(ifp)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
init_ifp()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
ipf_fastroute(m,mpp,fin,fdp)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
ipf_send_reset(fin)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
ipf_send_icmp_err(type,fin,dst)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
m_freem(m)456 m_freem(m)
457 mb_t *m;
458 {
459 return;
460 }
461
462
463 void
m_copydata(m,off,len,cp)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
ipfuiomove(buf,len,rwflag,uio)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
ipf_newisn(fin)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
ipf_nextipid(fin)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
ipf_checkv4sum(fin)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
ipf_checkv6sum(fin)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
ipf_ifpaddr(softc,v,atype,ifptr,inp,inpmask)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
ipf_random()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
ipf_verifysrc(fin)747 ipf_verifysrc(fin)
748 fr_info_t *fin;
749 {
750 return (1);
751 }
752
753
754 int
ipf_inject(fin,m)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
ipf_pcksum(fin,hlen,sum)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 *
ipf_pullup(m,fin,plen)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