2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
13 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
19 #include <sys/param.h>
20 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
21 # if defined(IPFILTER_LKM)
22 # ifndef __FreeBSD_cc_version
23 # include <osreldate.h>
25 # if __FreeBSD_cc_version < 430000
26 # include <osreldate.h>
31 #include <sys/errno.h>
32 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
33 # include <sys/kern_svcs.h>
35 #include <sys/types.h>
45 #include <sys/ioctl.h>
47 # include <sys/ptimers.h>
51 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
52 # include <sys/dirent.h>
57 # include <sys/filio.h>
60 # include <sys/protosw.h>
62 #include <sys/socket.h>
70 #include <arpa/inet.h>
73 # define _NET_ROUTE_INCLUDED
79 #if __FreeBSD_version >= 300000
80 # include <net/if_var.h>
83 #include <sys/debug.h>
84 # ifdef IFF_DRVRLOCK /* IRIX6 */
85 #include <sys/hashing.h>
88 #if defined(__FreeBSD__)
89 # include "radix_ipf.h"
91 #include <net/route.h>
92 #include <netinet/in.h>
93 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \
94 !defined(__hpux) && !defined(linux)
95 # include <netinet/in_var.h>
97 #include <netinet/in_systm.h>
98 #include <netinet/ip.h>
100 # include <netinet/ip_var.h>
102 #include <netinet/tcp.h>
104 # include <netinet/tcp_timer.h>
106 #if defined(__osf__) || defined(__hpux) || defined(__sgi)
107 # include "radix_ipf_local.h"
110 #include <netinet/udp.h>
111 #include <netinet/tcpip.h>
112 #include <netinet/ip_icmp.h>
116 # undef _NET_ROUTE_INCLUDED
118 #include "netinet/ip_compat.h"
119 #include "netinet/ip_fil.h"
120 #include "netinet/ip_nat.h"
121 #include "netinet/ip_frag.h"
122 #include "netinet/ip_state.h"
123 #include "netinet/ip_proxy.h"
124 #include "netinet/ip_auth.h"
126 #include "netinet/ip_sync.h"
129 #include "netinet/ip_scan.h"
131 #include "netinet/ip_pool.h"
132 #ifdef IPFILTER_COMPILED
133 # include "netinet/ip_rules.h"
135 #include "netinet/ipf_stack.h"
136 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
137 # include <sys/malloc.h>
145 #if !defined(__osf__)
146 extern struct protosw inetsw
[];
150 static struct ifnet
**ifneta
= NULL
;
153 static int frzerostats
__P((caddr_t
, ipf_stack_t
*ifs
));
154 static void fr_setifpaddr
__P((struct ifnet
*, char *));
155 void init_ifp
__P((void));
156 #if defined(__sgi) && (IRIX < 60500)
157 static int no_output
__P((struct ifnet
*, struct mbuf
*,
159 static int write_output
__P((struct ifnet
*, struct mbuf
*,
163 static int no_output
__P((struct ifnet
*, struct mbuf
*,
164 struct sockaddr
*, struct rtentry
*, char *));
165 static int write_output
__P((struct ifnet
*, struct mbuf
*,
166 struct sockaddr
*, struct rtentry
*, char *));
168 static int no_output
__P((struct ifnet
*, struct mbuf
*,
169 struct sockaddr
*, struct rtentry
*));
170 static int write_output
__P((struct ifnet
*, struct mbuf
*,
171 struct sockaddr
*, struct rtentry
*));
179 ifs
->ifs_fr_running
= 1;
187 ifs
->ifs_fr_running
= -1;
192 static int frzerostats(data
, ifs
)
199 fr_getstat(&fio
, ifs
);
200 error
= copyoutptr(&fio
, data
, sizeof(fio
));
204 bzero((char *)ifs
->ifs_frstats
, sizeof(*ifs
->ifs_frstats
) * 2);
211 * Filter ioctl interface.
213 int iplioctl(dev
, cmd
, data
, mode
)
219 int error
= 0, unit
= 0, tmp
, uid
;
222 extern ipf_stack_t
*get_ifs();
231 if (unit
== IPL_LOGNAT
) {
232 if (ifs
->ifs_fr_running
> 0)
233 error
= fr_nat_ioctl(data
, cmd
, mode
, uid
, NULL
, ifs
);
239 if (unit
== IPL_LOGSTATE
) {
240 if (ifs
->ifs_fr_running
> 0)
241 error
= fr_state_ioctl(data
, cmd
, mode
, uid
, NULL
, ifs
);
247 if (unit
== IPL_LOGAUTH
) {
248 if (ifs
->ifs_fr_running
> 0) {
249 if ((cmd
== (ioctlcmd_t
)SIOCADAFR
) ||
250 (cmd
== (ioctlcmd_t
)SIOCRMAFR
)) {
251 if (!(mode
& FWRITE
)) {
254 error
= frrequest(unit
, cmd
, data
,
255 ifs
->ifs_fr_active
, 1, ifs
);
258 error
= fr_auth_ioctl(data
, cmd
, mode
, uid
,
266 if (unit
== IPL_LOGSYNC
) {
268 if (ifs
->ifs_fr_running
> 0)
269 error
= fr_sync_ioctl(data
, cmd
, mode
);
276 if (unit
== IPL_LOGSCAN
) {
278 if (ifs
->ifs_fr_running
> 0)
279 error
= fr_scan_ioctl(data
, cmd
, mode
);
286 if (unit
== IPL_LOGLOOKUP
) {
287 if (ifs
->ifs_fr_running
> 0)
288 error
= ip_lookup_ioctl(data
, cmd
, mode
, uid
,
300 error
= COPYOUT(&ifs
->ifs_iplused
[IPL_LOGIPF
], (caddr_t
)data
,
301 sizeof(ifs
->ifs_iplused
[IPL_LOGIPF
]));
305 if (!(mode
& FWRITE
))
308 error
= COPYIN(data
, &tmp
, sizeof(tmp
));
312 error
= iplattach(ifs
);
314 error
= ipldetach(ifs
);
318 if (!(mode
& FWRITE
)) {
323 case SIOCIPFGETNEXT
:
325 error
= fr_ipftune(cmd
, (void *)data
, ifs
);
328 if (!(mode
& FWRITE
))
331 error
= COPYIN(data
, &ifs
->ifs_fr_flags
,
332 sizeof(ifs
->ifs_fr_flags
));
335 error
= COPYOUT(&ifs
->ifs_fr_flags
, data
,
336 sizeof(ifs
->ifs_fr_flags
));
339 error
= fr_resolvefunc(data
);
345 if (!(mode
& FWRITE
))
348 error
= frrequest(unit
, cmd
, data
,
349 ifs
->ifs_fr_active
, 1, ifs
);
354 if (!(mode
& FWRITE
))
357 error
= frrequest(unit
, cmd
, data
,
358 1 - ifs
->ifs_fr_active
, 1, ifs
);
361 if (!(mode
& FWRITE
))
364 *(u_int
*)data
= ifs
->ifs_fr_active
;
365 ifs
->ifs_fr_active
= 1 - ifs
->ifs_fr_active
;
369 fr_getstat(&fio
, ifs
);
370 error
= fr_outobj(data
, &fio
, IPFOBJ_IPFSTAT
);
373 if (!(mode
& FWRITE
))
376 error
= frzerostats(data
, ifs
);
379 if (!(mode
& FWRITE
))
382 error
= COPYIN(data
, &tmp
, sizeof(tmp
));
384 tmp
= frflush(unit
, 4, tmp
, ifs
);
385 error
= COPYOUT(&tmp
, data
, sizeof(tmp
));
391 if (!(mode
& FWRITE
))
394 error
= COPYIN(data
, &tmp
, sizeof(tmp
));
396 tmp
= frflush(unit
, 6, tmp
, ifs
);
397 error
= COPYOUT(&tmp
, data
, sizeof(tmp
));
403 error
= COPYIN(data
, &tmp
, sizeof(tmp
));
405 ifs
->ifs_fr_state_lock
= tmp
;
406 ifs
->ifs_fr_nat_lock
= tmp
;
407 ifs
->ifs_fr_frag_lock
= tmp
;
408 ifs
->ifs_fr_auth_lock
= tmp
;
414 if (!(mode
& FWRITE
))
417 *(int *)data
= ipflog_clear(unit
, ifs
);
419 #endif /* IPFILTER_LOG */
421 error
= fr_outobj(data
, fr_fragstats(ifs
), IPFOBJ_FRAGSTAT
);
424 if (!(mode
& FWRITE
))
427 frsync(IPFSYNC_RESYNC
, IPFSYNC_RESYNC
, NULL
, NULL
, ifs
);
439 void fr_forgetifp(ifp
, ifs
)
443 register frentry_t
*f
;
445 WRITE_ENTER(&ifs
->ifs_ipf_mutex
);
446 for (f
= ifs
->ifs_ipacct
[0][ifs
->ifs_fr_active
]; (f
!= NULL
);
448 if (f
->fr_ifa
== ifp
)
449 f
->fr_ifa
= (void *)-1;
450 for (f
= ifs
->ifs_ipacct
[1][ifs
->ifs_fr_active
]; (f
!= NULL
);
452 if (f
->fr_ifa
== ifp
)
453 f
->fr_ifa
= (void *)-1;
454 for (f
= ifs
->ifs_ipfilter
[0][ifs
->ifs_fr_active
]; (f
!= NULL
);
456 if (f
->fr_ifa
== ifp
)
457 f
->fr_ifa
= (void *)-1;
458 for (f
= ifs
->ifs_ipfilter
[1][ifs
->ifs_fr_active
]; (f
!= NULL
);
460 if (f
->fr_ifa
== ifp
)
461 f
->fr_ifa
= (void *)-1;
463 for (f
= ifs
->ifs_ipacct6
[0][ifs
->ifs_fr_active
]; (f
!= NULL
);
465 if (f
->fr_ifa
== ifp
)
466 f
->fr_ifa
= (void *)-1;
467 for (f
= ifs
->ifs_ipacct6
[1][ifs
->ifs_fr_active
]; (f
!= NULL
);
469 if (f
->fr_ifa
== ifp
)
470 f
->fr_ifa
= (void *)-1;
471 for (f
= ifs
->ifs_ipfilter6
[0][ifs
->ifs_fr_active
]; (f
!= NULL
);
473 if (f
->fr_ifa
== ifp
)
474 f
->fr_ifa
= (void *)-1;
475 for (f
= ifs
->ifs_ipfilter6
[1][ifs
->ifs_fr_active
]; (f
!= NULL
);
477 if (f
->fr_ifa
== ifp
)
478 f
->fr_ifa
= (void *)-1;
480 RWLOCK_EXIT(&ifs
->ifs_ipf_mutex
);
481 fr_natifpsync(IPFSYNC_OLDIFP
, 4, ifp
, NULL
, ifs
);
482 fr_natifpsync(IPFSYNC_OLDIFP
, 6, ifp
, NULL
, ifs
);
486 void fr_resolvedest(fdp
, v
, ifs
)
493 if (*fdp
->fd_ifname
) {
494 fdp
->fd_ifp
= GETIFP(fdp
->fd_ifname
, v
, ifs
);
496 fdp
->fd_ifp
= (struct ifnet
*)-1;
501 #if defined(__sgi) && (IRIX < 60500)
502 static int no_output(ifp
, m
, s
)
505 static int no_output (ifp
, m
, s
, rt
, cp
)
508 static int no_output(ifp
, m
, s
, rt
)
520 #if defined(__sgi) && (IRIX < 60500)
521 static int write_output(ifp
, m
, s
)
524 static int write_output (ifp
, m
, s
, rt
, cp
)
527 static int write_output(ifp
, m
, s
, rt
)
541 ip
= MTOD(mb
, ip_t
*);
543 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
544 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
545 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
546 sprintf(fname
, "/tmp/%s", ifp
->if_xname
);
548 sprintf(fname
, "/tmp/%s%d", ifp
->if_name
, ifp
->if_unit
);
550 fd
= open(fname
, O_WRONLY
|O_APPEND
);
555 write(fd
, (char *)ip
, ntohs(ip
->ip_len
));
561 static void fr_setifpaddr(ifp
, addr
)
566 struct in_ifaddr
*ifa
;
571 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
572 if (ifp
->if_addrlist
.tqh_first
!= NULL
)
575 if (ifp
->in_ifaddr
!= NULL
)
577 if (ifp
->if_addrlist
!= NULL
)
582 ifa
= (struct ifaddr
*)malloc(sizeof(*ifa
));
583 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
584 ifp
->if_addrlist
.tqh_first
= ifa
;
587 ifp
->in_ifaddr
= ifa
;
589 ifp
->if_addrlist
= ifa
;
594 struct sockaddr_in
*sin
;
597 sin
= (struct sockaddr_in
*)&ifa
->ia_addr
;
599 sin
= (struct sockaddr_in
*)&ifa
->ifa_addr
;
601 sin
->sin_addr
.s_addr
= inet_addr(addr
);
602 if (sin
->sin_addr
.s_addr
== 0)
608 struct ifnet
*get_unit(name
, v
, ifs
)
613 struct ifnet
*ifp
, **ifpp
, **old_ifneta
;
615 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
616 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
617 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
622 addr
= strchr(name
, '=');
626 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
627 if (!strcmp(name
, ifp
->if_xname
)) {
629 fr_setifpaddr(ifp
, addr
);
634 char *s
, ifname
[LIFNAMSIZ
+1];
639 addr
= strchr(name
, '=');
643 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
644 COPYIFNAME(ifp
, ifname
, 0);
645 if (!strcmp(name
, ifname
)) {
647 fr_setifpaddr(ifp
, addr
);
654 ifneta
= (struct ifnet
**)malloc(sizeof(ifp
) * 2);
658 ifneta
[0] = (struct ifnet
*)calloc(1, sizeof(*ifp
));
667 ifneta
= (struct ifnet
**)reallocarray(ifneta
, nifs
+ 1,
675 ifneta
[nifs
- 1] = (struct ifnet
*)malloc(sizeof(*ifp
));
676 if (!ifneta
[nifs
- 1]) {
681 ifp
= ifneta
[nifs
- 1];
683 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
684 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
685 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
686 (void) strncpy(ifp
->if_xname
, name
, sizeof(ifp
->if_xname
));
688 for (s
= name
; *s
&& !ISDIGIT(*s
); s
++)
690 if (*s
&& ISDIGIT(*s
)) {
691 ifp
->if_unit
= atoi(s
);
692 ifp
->if_name
= (char *)malloc(s
- name
+ 1);
693 if (ifp
->if_name
== NULL
) {
695 * XXX do it more elegantly: free up mem,
701 (void) strncpy(ifp
->if_name
, name
, s
- name
);
702 ifp
->if_name
[s
- name
] = '\0';
704 ifp
->if_name
= strdup(name
);
708 ifp
->if_output
= no_output
;
711 fr_setifpaddr(ifp
, addr
);
718 char *get_ifname(ifp
)
721 static char ifname
[LIFNAMSIZ
];
723 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
724 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
725 sprintf(ifname
, "%s", ifp
->if_xname
);
727 sprintf(ifname
, "%s%d", ifp
->if_name
, ifp
->if_unit
);
736 struct ifnet
*ifp
, **ifpp
;
740 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
741 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
742 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
743 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
744 ifp
->if_output
= write_output
;
745 sprintf(fname
, "/tmp/%s", ifp
->if_xname
);
746 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
754 for (ifpp
= ifneta
; ifpp
&& (ifp
= *ifpp
); ifpp
++) {
755 ifp
->if_output
= write_output
;
756 sprintf(fname
, "/tmp/%s%d", ifp
->if_name
, ifp
->if_unit
);
757 fd
= open(fname
, O_WRONLY
|O_CREAT
|O_EXCL
|O_TRUNC
, 0600);
767 int fr_fastroute(m
, mpp
, fin
, fdp
)
772 struct ifnet
*ifp
= fdp
->fd_ifp
;
773 ip_t
*ip
= fin
->fin_ip
;
776 return 0; /* no routing table out here */
778 ip
->ip_len
= htons((u_short
)ip
->ip_len
);
779 ip
->ip_off
= htons((u_short
)(ip
->ip_off
| IP_MF
));
781 #if defined(__sgi) && (IRIX < 60500)
782 (*ifp
->if_output
)(ifp
, (void *)ip
, NULL
);
784 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0, 0);
786 (*ifp
->if_output
)(ifp
, (void *)m
, NULL
, 0);
793 int fr_send_reset(fin
)
796 verbose("- TCP RST sent\n");
801 int fr_send_icmp_err(type
, fin
, dst
)
806 verbose("- ICMP unreachable sent\n");
811 void frsync(command
, version
, nic
, data
, ifs
)
812 int command
, version
;
828 void m_copydata(m
, off
, len
, cp
)
833 bcopy((char *)m
+ off
, cp
, len
);
837 int ipfuiomove(buf
, len
, rwflag
, uio
)
842 int left
, ioc
, num
, offset
;
846 if (rwflag
== UIO_READ
) {
850 offset
= uio
->uio_offset
;
852 while ((left
> 0) && (ioc
< uio
->uio_iovcnt
)) {
853 io
= uio
->uio_iov
+ ioc
;
857 start
= (char *)io
->iov_base
+ offset
;
858 if (start
> (char *)io
->iov_base
+ io
->iov_len
) {
859 offset
-= io
->iov_len
;
863 bcopy(buf
, start
, num
);
864 uio
->uio_resid
-= num
;
865 uio
->uio_offset
+= num
;
877 u_32_t
fr_newisn(fin
)
880 static int iss_seq_off
= 0;
886 * Compute the base value of the ISS. It is a hash
887 * of (saddr, sport, daddr, dport, secret).
891 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_src
,
892 sizeof(fin
->fin_fi
.fi_src
));
893 MD5Update(&ctx
, (u_char
*) &fin
->fin_fi
.fi_dst
,
894 sizeof(fin
->fin_fi
.fi_dst
));
895 MD5Update(&ctx
, (u_char
*) &fin
->fin_dat
, sizeof(fin
->fin_dat
));
897 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
899 MD5Final(hash
, &ctx
);
901 memcpy(&newiss
, hash
, sizeof(newiss
));
904 * Now increment our "timer", and add it in to
905 * the computed value.
908 * XXX TCP_ISSINCR too large to use?
910 iss_seq_off
+= 0x00010000;
911 newiss
+= iss_seq_off
;
916 /* ------------------------------------------------------------------------ */
917 /* Function: fr_nextipid */
918 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
919 /* Parameters: fin(I) - pointer to packet information */
921 /* Returns the next IPv4 ID to use for this packet. */
922 /* ------------------------------------------------------------------------ */
923 INLINE u_short
fr_nextipid(fin
)
926 static u_short ipid
= 0;
928 ipf_stack_t
*ifs
= fin
->fin_ifs
;
930 MUTEX_ENTER(&ifs
->ifs_ipf_rw
);
932 MUTEX_EXIT(&ifs
->ifs_ipf_rw
);
938 INLINE
void fr_checkv4sum(fin
)
941 if (fr_checkl4sum(fin
) == -1)
942 fin
->fin_flx
|= FI_BAD
;
947 INLINE
void fr_checkv6sum(fin
)
950 if (fr_checkl4sum(fin
) == -1)
951 fin
->fin_flx
|= FI_BAD
;
957 * See above for description, except that all addressing is in user space.
959 int copyoutptr(src
, dst
, size
)
965 bcopy(dst
, (char *)&ca
, sizeof(ca
));
966 bcopy(src
, ca
, size
);
972 * See above for description, except that all addressing is in user space.
974 int copyinptr(src
, dst
, size
)
980 bcopy(src
, (char *)&ca
, sizeof(ca
));
981 bcopy(ca
, dst
, size
);
987 * return the first IP Address associated with an interface
989 int fr_ifpaddr(v
, atype
, ifptr
, inp
, inpmask
, ifs
)
992 struct in_addr
*inp
, *inpmask
;
995 struct ifnet
*ifp
= ifptr
;
997 struct in_ifaddr
*ifa
;
1002 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
1003 ifa
= ifp
->if_addrlist
.tqh_first
;
1006 ifa
= (struct in_ifaddr
*)ifp
->in_ifaddr
;
1008 ifa
= ifp
->if_addrlist
;
1012 struct sockaddr_in
*sin
, mask
;
1014 mask
.sin_addr
.s_addr
= 0xffffffff;
1017 sin
= (struct sockaddr_in
*)&ifa
->ia_addr
;
1019 sin
= (struct sockaddr_in
*)&ifa
->ifa_addr
;
1022 return fr_ifpfillv4addr(atype
, sin
, &mask
, inp
, inpmask
);
1029 * This function is not meant to be random, rather just produce a
1030 * sequence of numbers that isn't linear to show "randomness".
1034 static u_int last
= 0xa5a5a5a5;
1035 static int calls
= 0;
1041 * These are deliberately chosen to ensure that there is some
1042 * attempt to test whether the output covers the range in test n18.