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