4 * Copyright (C) 1993-2001 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 static const char sccsid
[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid
[] = "@(#)Id: ip_fil.c,v 2.133.2.20 2008/07/27 08:27:04 darrenr Exp";
14 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
17 #include <sys/param.h>
18 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
19 # if defined(IPFILTER_LKM)
20 # ifndef __FreeBSD_cc_version
21 # include <osreldate.h>
23 # if __FreeBSD_cc_version < 430000
24 # include <osreldate.h>
29 #include <sys/errno.h>
30 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
31 # include <sys/kern_svcs.h>
33 #include <sys/types.h>
43 #include <sys/ioctl.h>
45 # include <sys/ptimers.h>
49 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
50 # include <sys/dirent.h>
55 # include <sys/filio.h>
58 # include <sys/protosw.h>
60 #include <sys/socket.h>
69 # define _NET_ROUTE_INCLUDED
75 #if __FreeBSD_version >= 300000
76 # include <net/if_var.h>
79 #include <sys/debug.h>
80 # ifdef IFF_DRVRLOCK /* IRIX6 */
81 #include <sys/hashing.h>
84 #if defined(__FreeBSD__) || defined(SOLARIS2)
85 # include "radix_ipf.h"
88 # include <net/route.h>
90 #include <netinet/in.h>
91 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
92 !defined(__hpux) && !defined(linux)
93 # include <netinet/in_var.h>
95 #include <netinet/in_systm.h>
96 #include <netinet/ip.h>
98 # include <netinet/ip_var.h>
100 #include <netinet/tcp.h>
102 # include <netinet/tcp_timer.h>
104 #if defined(__osf__) || defined(__hpux) || defined(__sgi)
105 # include "radix_ipf_local.h"
108 #include <netinet/udp.h>
109 #include <netinet/tcpip.h>
110 #include <netinet/ip_icmp.h>
113 #include <arpa/inet.h>
115 # undef _NET_ROUTE_INCLUDED
117 #include "netinet/ip_compat.h"
118 #include "netinet/ip_fil.h"
119 #include "netinet/ip_nat.h"
120 #include "netinet/ip_frag.h"
121 #include "netinet/ip_state.h"
122 #include "netinet/ip_proxy.h"
123 #include "netinet/ip_auth.h"
125 #include "netinet/ip_sync.h"
128 #include "netinet/ip_scan.h"
130 #include "netinet/ip_pool.h"
131 #ifdef IPFILTER_COMPILED
132 # include "netinet/ip_rules.h"
134 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
135 # include <sys/malloc.h>
143 #if !defined(__osf__) && !defined(__linux__)
144 extern struct protosw inetsw
[];
148 static struct ifnet
**ifneta
= NULL
;
151 static void fr_setifpaddr
__P((struct ifnet
*, char *));
152 void init_ifp
__P((void));
153 #if defined(__sgi) && (IRIX < 60500)
154 static int no_output
__P((struct ifnet
*, struct mbuf
*,
156 static int write_output
__P((struct ifnet
*, struct mbuf
*,
160 static int no_output
__P((struct ifnet
*, struct mbuf
*,
161 struct sockaddr
*, struct rtentry
*, char *));
162 static int write_output
__P((struct ifnet
*, struct mbuf
*,
163 struct sockaddr
*, struct rtentry
*, char *));
165 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
166 static int no_output(struct ifnet
*, struct mbuf
*,
167 const struct sockaddr
*, struct rtentry
*);
168 static int write_output(struct ifnet
*, struct mbuf
*,
169 const struct sockaddr
*, struct rtentry
*);
171 static int no_output
__P((struct ifnet
*, struct mbuf
*,
172 struct sockaddr
*, struct rtentry
*));
173 static int write_output
__P((struct ifnet
*, struct mbuf
*,
174 struct sockaddr
*, struct rtentry
*));
195 * Filter ioctl interface.
197 int iplioctl(dev
, cmd
, data
, mode
)
203 int error
= 0, unit
= 0, uid
;
211 error
= fr_ioctlswitch(unit
, data
, cmd
, mode
, uid
, NULL
);
222 void fr_forgetifp(ifp
)
225 register frentry_t
*f
;
227 WRITE_ENTER(&ipf_mutex
);
228 for (f
= ipacct
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
229 if (f
->fr_ifa
== ifp
)
230 f
->fr_ifa
= (void *)-1;
231 for (f
= ipacct
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
232 if (f
->fr_ifa
== ifp
)
233 f
->fr_ifa
= (void *)-1;
234 for (f
= ipfilter
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
235 if (f
->fr_ifa
== ifp
)
236 f
->fr_ifa
= (void *)-1;
237 for (f
= ipfilter
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
238 if (f
->fr_ifa
== ifp
)
239 f
->fr_ifa
= (void *)-1;
241 for (f
= ipacct6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
242 if (f
->fr_ifa
== ifp
)
243 f
->fr_ifa
= (void *)-1;
244 for (f
= ipacct6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
245 if (f
->fr_ifa
== ifp
)
246 f
->fr_ifa
= (void *)-1;
247 for (f
= ipfilter6
[0][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
248 if (f
->fr_ifa
== ifp
)
249 f
->fr_ifa
= (void *)-1;
250 for (f
= ipfilter6
[1][fr_active
]; (f
!= NULL
); f
= f
->fr_next
)
251 if (f
->fr_ifa
== ifp
)
252 f
->fr_ifa
= (void *)-1;
254 RWLOCK_EXIT(&ipf_mutex
);
259 #if defined(__sgi) && (IRIX < 60500)
260 static int no_output(ifp
, m
, s
)
263 static int no_output (ifp
, m
, s
, rt
, cp
)
266 static int no_output(ifp
, m
, s
, rt
)
272 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
273 const struct sockaddr
*s
;
282 #if defined(__sgi) && (IRIX < 60500)
283 static int write_output(ifp
, m
, s
)
286 static int write_output (ifp
, m
, s
, rt
, cp
)
289 static int write_output(ifp
, m
, s
, rt
)
295 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
296 const struct sockaddr
*s
;
307 ip
= MTOD(mb
, ip_t
*);
309 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
310 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
311 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
312 sprintf(fname
, "/tmp/%s", ifp
->if_xname
);
314 sprintf(fname
, "/tmp/%s%d", ifp
->if_name
, ifp
->if_unit
);
316 fd
= open(fname
, O_WRONLY
|O_APPEND
);
321 write(fd
, (char *)ip
, ntohs(ip
->ip_len
));
327 static void fr_setifpaddr(ifp
, addr
)
332 struct in_ifaddr
*ifa
;
337 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
338 if (ifp
->if_addrlist
.tqh_first
!= NULL
)
341 if (ifp
->in_ifaddr
!= NULL
)
343 if (ifp
->if_addrlist
!= NULL
)
348 ifa
= (struct ifaddr
*)malloc(sizeof(*ifa
));
349 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
350 ifp
->if_addrlist
.tqh_first
= ifa
;
353 ifp
->in_ifaddr
= ifa
;
355 ifp
->if_addrlist
= ifa
;
360 struct sockaddr_in
*sin
;
363 sin
= (struct sockaddr_in
*)&ifa
->ia_addr
;
365 sin
= (struct sockaddr_in
*)&ifa
->ifa_addr
;
367 sin
->sin_addr
.s_addr
= inet_addr(addr
);
368 if (sin
->sin_addr
.s_addr
== 0)
373 struct ifnet
*get_unit(name
, v
)
377 struct ifnet
*ifp
, **ifpp
, **old_ifneta
;
379 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
380 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
381 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
386 addr
= strchr(name
, '=');
390 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
391 if (!strcmp(name
, ifp
->if_xname
)) {
393 fr_setifpaddr(ifp
, addr
);
398 char *s
, ifname
[LIFNAMSIZ
+1];
403 addr
= strchr(name
, '=');
407 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
408 COPYIFNAME(v
, ifp
, ifname
);
409 if (!strcmp(name
, ifname
)) {
411 fr_setifpaddr(ifp
, addr
);
418 ifneta
= (struct ifnet
**)malloc(sizeof(ifp
) * 2);
422 ifneta
[0] = (struct ifnet
*)calloc(1, sizeof(*ifp
));
431 ifneta
= (struct ifnet
**)realloc(ifneta
,
432 (nifs
+ 1) * sizeof(ifp
));
439 ifneta
[nifs
- 1] = (struct ifnet
*)malloc(sizeof(*ifp
));
440 if (!ifneta
[nifs
- 1]) {
445 ifp
= ifneta
[nifs
- 1];
447 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
448 TAILQ_INIT(&ifp
->if_addrlist
);
450 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
451 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
452 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
453 (void) strncpy(ifp
->if_xname
, name
, sizeof(ifp
->if_xname
));
455 for (s
= name
; *s
&& !ISDIGIT(*s
); s
++)
457 if (*s
&& ISDIGIT(*s
)) {
458 ifp
->if_unit
= atoi(s
);
459 ifp
->if_name
= (char *)malloc(s
- name
+ 1);
460 (void) strncpy(ifp
->if_name
, name
, s
- name
);
461 ifp
->if_name
[s
- name
] = '\0';
463 ifp
->if_name
= strdup(name
);
467 ifp
->if_output
= (void *)no_output
;
470 fr_setifpaddr(ifp
, addr
);
477 char *get_ifname(ifp
)
480 static char ifname
[LIFNAMSIZ
];
482 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
483 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
484 sprintf(ifname
, "%s", ifp
->if_xname
);
486 sprintf(ifname
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
495 struct ifnet
*ifp
, **ifpp
;
499 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
500 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
501 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
502 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
503 ifp
->if_output
= (void *)write_output
;
504 sprintf(fname
, "/tmp/%s", ifp
->if_xname
);
505 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
513 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
514 ifp
->if_output
= write_output
;
515 sprintf(fname
, "/tmp/%s%d", ifp
->if_name
, ifp
->if_unit
);
516 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
526 int fr_fastroute(m
, mpp
, fin
, fdp
)
531 struct ifnet
*ifp
= fdp
->fd_ifp
;
532 ip_t
*ip
= fin
->fin_ip
;
538 return 0; /* no routing table out here */
543 if (fin
->fin_out
== 0) {
547 (void) fr_acctpkt(fin
, NULL
);
549 if (!fr
|| !(fr
->fr_flags
& FR_RETMASK
)) {
552 (void) fr_checkstate(fin
, &pass
);
555 switch (fr_checknatout(fin
, NULL
))
572 #if defined(__sgi) && (IRIX < 60500)
573 (*ifp
->if_output
)(ifp
, (void *)ip
, NULL
);
575 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0, 0);
577 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0);
585 int fr_send_reset(fin
)
588 verbose("- TCP RST sent\n");
593 int fr_send_icmp_err(type
, fin
, dst
)
598 verbose("- ICMP unreachable sent\n");
617 void m_copydata(m
, off
, len
, cp
)
622 bcopy((char *)m
+ off
, cp
, len
);
626 int ipfuiomove(buf
, len
, rwflag
, uio
)
631 int left
, ioc
, num
, offset
;
635 if (rwflag
== UIO_READ
) {
639 offset
= uio
->uio_offset
;
641 while ((left
> 0) && (ioc
< uio
->uio_iovcnt
)) {
642 io
= uio
->uio_iov
+ ioc
;
646 start
= (char *)io
->iov_base
+ offset
;
647 if (start
> (char *)io
->iov_base
+ io
->iov_len
) {
648 offset
-= io
->iov_len
;
652 bcopy(buf
, start
, num
);
653 uio
->uio_resid
-= num
;
654 uio
->uio_offset
+= num
;
666 u_32_t
fr_newisn(fin
)
669 static int iss_seq_off
= 0;
675 * Compute the base value of the ISS. It is a hash
676 * of (saddr, sport, daddr, dport, secret).
680 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_src
,
681 sizeof(fin
->fin_fi
.fi_src
));
682 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_dst
,
683 sizeof(fin
->fin_fi
.fi_dst
));
684 MD5Update(&ctx
, (u_char
*) &fin
->fin_dat
, sizeof(fin
->fin_dat
));
686 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
688 MD5Final(hash
, &ctx
);
690 memcpy(&newiss
, hash
, sizeof(newiss
));
693 * Now increment our "timer", and add it in to
694 * the computed value.
697 * XXX TCP_ISSINCR too large to use?
699 iss_seq_off
+= 0x00010000;
700 newiss
+= iss_seq_off
;
705 /* ------------------------------------------------------------------------ */
706 /* Function: fr_nextipid */
707 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
708 /* Parameters: fin(I) - pointer to packet information */
710 /* Returns the next IPv4 ID to use for this packet. */
711 /* ------------------------------------------------------------------------ */
712 INLINE u_short
fr_nextipid(fin
)
715 static u_short ipid
= 0;
718 MUTEX_ENTER(&ipf_rw
);
726 INLINE
void fr_checkv4sum(fin
)
729 if (fr_checkl4sum(fin
) == -1)
730 fin
->fin_flx
|= FI_BAD
;
735 INLINE
void fr_checkv6sum(fin
)
738 if (fr_checkl4sum(fin
) == -1)
739 fin
->fin_flx
|= FI_BAD
;
745 * See above for description, except that all addressing is in user space.
747 int copyoutptr(src
, dst
, size
)
753 bcopy(dst
, (char *)&ca
, sizeof(ca
));
754 bcopy(src
, ca
, size
);
760 * See above for description, except that all addressing is in user space.
762 int copyinptr(src
, dst
, size
)
768 bcopy(src
, (char *)&ca
, sizeof(ca
));
769 bcopy(ca
, dst
, size
);
775 * return the first IP Address associated with an interface
777 int fr_ifpaddr(v
, atype
, ifptr
, inp
, inpmask
)
780 struct in_addr
*inp
, *inpmask
;
782 struct ifnet
*ifp
= ifptr
;
784 struct in_ifaddr
*ifa
;
789 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
790 ifa
= ifp
->if_addrlist
.tqh_first
;
793 ifa
= (struct in_ifaddr
*)ifp
->in_ifaddr
;
795 ifa
= ifp
->if_addrlist
;
799 struct sockaddr_in
*sin
, mask
;
801 mask
.sin_addr
.s_addr
= 0xffffffff;
804 sin
= (struct sockaddr_in
*)&ifa
->ia_addr
;
806 sin
= (struct sockaddr_in
*)&ifa
->ifa_addr
;
809 return fr_ifpfillv4addr(atype
, sin
, &mask
, inp
, inpmask
);
822 * This function is not meant to be random, rather just produce a
823 * sequence of numbers that isn't linear to show "randomness".
828 static int last
= 0xa5a5a5a5;
829 static int calls
= 0;
835 * These are deliberately chosen to ensure that there is some
836 * attempt to test whether the output covers the range in test n18.
860 * So why not use srand/rand/srandom/random? Because the
861 * actual values returned vary from platform to platform
862 * and what is needed is seomthing that is the same everywhere
863 * so that regression tests can work. Well, they could be
864 * built on each platform to suit but that's a whole lot of
865 * work for little gain given that we don't actually need
866 * random numbers here, just a spread to test the NAT code