2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
7 static const char rcsid
[] = "@(#)$Id: ip_lfil.c,v 2.6.2.5 2002/10/03 13:47:19 darrenr Exp $";
10 #if defined(KERNEL) && !defined(_KERNEL)
13 #include <sys/errno.h>
14 #include <sys/types.h>
15 #include <sys/param.h>
17 #include <sys/ioctl.h>
20 #include <sys/socket.h>
27 # include <linux/module.h>
31 #include <net/route.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/tcp.h>
36 #include <netinet/udp.h>
37 #include <netinet/ip_icmp.h>
41 #include "netinet/ip_compat.h"
42 #include <netinet/tcpip.h>
43 #include "netinet/ip_fil.h"
44 #include "netinet/ip_nat.h"
45 #include "netinet/ip_proxy.h"
46 #include "netinet/ip_frag.h"
47 #include "netinet/ip_state.h"
48 #include "netinet/ip_auth.h"
50 #include <net/ip_forward.h>
53 #define MIN(a,b) (((a)<(b))?(a):(b))
59 static struct ifnet
**ifneta
= NULL
;
64 int ipl_unreach
= ICMP_UNREACH_FILTER
;
65 u_long ipl_frouteok
[2] = {0, 0};
67 static int frzerostats
__P((caddr_t
));
68 static void frsync
__P((void));
69 #if defined(__NetBSD__) || defined(__OpenBSD__)
70 static int frrequest
__P((int, u_long
, caddr_t
, int));
72 static int frrequest
__P((int, u_long
, caddr_t
, int));
75 static int (*fr_savep
) __P((ip_t
*, int, void *, int, mb_t
**));
77 int ipllog
__P((void));
78 void init_ifp
__P((void));
79 static int no_output
__P((mb_t
*, struct ifnet
*));
80 static int write_output
__P((mb_t
*, struct ifnet
*));
85 int fr_precheck(struct iphdr
*ip
, struct device
*dev
, int out
, struct device
**ifp
)
87 int hlen
= ip
->ihl
<< 2;
89 return fr_check((ip_t
*)ip
, hlen
, dev
, out
, (mb_t
**)ifp
);
98 if (fr_running
|| (fr_checkp
== fr_precheck
)) {
99 printk("IP Filter: already initialized\n");
104 bzero((char *)frcache
, sizeof(frcache
));
105 bzero((char *)nat_table
, sizeof(nat_table
));
106 fr_savep
= fr_checkp
;
107 fr_checkp
= fr_precheck
;
112 if (fr_pass
& FR_PASS
)
114 else if (fr_pass
& FR_BLOCK
)
117 defpass
= "no-match -> block";
119 printk("IP Filter: initialized. Default = %s all, Logging = %s\n",
131 * Disable the filter by removing the hooks from the IP input/output
136 int s
, i
= FR_INQUE
|FR_OUTQUE
;
140 printk("IP Filter: not initialized\n");
144 fr_checkp
= fr_savep
;
145 i
= frflush(IPL_LOGIPF
, i
);
153 printk("IP Filter: unloaded\n");
160 static int frzerostats(data
)
166 bcopy((char *)frstats
, (char *)fio
.f_st
,
167 sizeof(struct filterstats
) * 2);
168 fio
.f_fin
[0] = ipfilter
[0][0];
169 fio
.f_fin
[1] = ipfilter
[0][1];
170 fio
.f_fout
[0] = ipfilter
[1][0];
171 fio
.f_fout
[1] = ipfilter
[1][1];
172 fio
.f_acctin
[0] = ipacct
[0][0];
173 fio
.f_acctin
[1] = ipacct
[0][1];
174 fio
.f_acctout
[0] = ipacct
[1][0];
175 fio
.f_acctout
[1] = ipacct
[1][1];
176 fio
.f_active
= fr_active
;
177 fio
.f_froute
[0] = ipl_frouteok
[0];
178 fio
.f_froute
[1] = ipl_frouteok
[1];
179 error
= IWCOPYPTR((caddr_t
)&fio
, data
, sizeof(fio
));
181 bzero((char *)frstats
, sizeof(*frstats
) * 2);
187 * Filter ioctl interface.
190 int iplioctl(struct inode
*inode
, struct file
*file
, u_int cmd
, u_long arg
)
193 caddr_t data
= (caddr_t
)arg
;
195 int mode
= file
->f_mode
;
197 int iplioctl(dev_t dev
, int cmd
, caddr_t data
, int mode
)
200 int error
= 0, unit
= 0, tmp
;
203 unit
= GET_MINOR(inode
->i_rdev
);
204 if ((IPL_LOGMAX
< unit
) || (unit
< 0))
208 if (unit
== IPL_LOGNAT
) {
209 error
= nat_ioctl(data
, cmd
, mode
);
212 if (unit
== IPL_LOGSTATE
) {
213 error
= fr_state_ioctl(data
, cmd
, mode
);
220 error
= IWCOPY((caddr_t
)&iplused
[IPL_LOGIPF
], data
,
221 sizeof(iplused
[IPL_LOGIPF
]));
224 #if !defined(IPFILTER_LKM) && defined(_KERNEL)
229 if (!(mode
& FWRITE
))
232 error
= IRCOPY(data
, (caddr_t
)&enable
, sizeof(enable
));
244 if (!(mode
& FWRITE
))
247 error
= IRCOPY(data
, (caddr_t
)&fr_flags
,
251 error
= IWCOPY((caddr_t
)&fr_flags
, data
, sizeof(fr_flags
));
257 if (!(mode
& FWRITE
))
260 error
= frrequest(unit
, cmd
, data
, fr_active
);
265 if (!(mode
& FWRITE
))
268 error
= frrequest(unit
, cmd
, data
, 1 - fr_active
);
271 if (!(mode
& FWRITE
))
274 bzero((char *)frcache
, sizeof(frcache
[0]) * 2);
275 *(u_int
*)data
= fr_active
;
276 fr_active
= 1 - fr_active
;
283 bcopy((char *)frstats
, (char *)fio
.f_st
,
284 sizeof(struct filterstats
) * 2);
285 fio
.f_fin
[0] = ipfilter
[0][0];
286 fio
.f_fin
[1] = ipfilter
[0][1];
287 fio
.f_fout
[0] = ipfilter
[1][0];
288 fio
.f_fout
[1] = ipfilter
[1][1];
289 fio
.f_acctin
[0] = ipacct
[0][0];
290 fio
.f_acctin
[1] = ipacct
[0][1];
291 fio
.f_acctout
[0] = ipacct
[1][0];
292 fio
.f_acctout
[1] = ipacct
[1][1];
294 fio
.f_active
= fr_active
;
295 fio
.f_froute
[0] = ipl_frouteok
[0];
296 fio
.f_froute
[1] = ipl_frouteok
[1];
297 error
= IWCOPYPTR((caddr_t
)&fio
, data
, sizeof(fio
));
301 if (!(mode
& FWRITE
))
304 error
= frzerostats(data
);
307 if (!(mode
& FWRITE
))
310 error
= IRCOPY(data
, (caddr_t
)&tmp
, sizeof(tmp
));
312 tmp
= frflush(unit
, tmp
);
313 error
= IWCOPY((caddr_t
)&tmp
, data
,
320 if (!(mode
& FWRITE
))
323 *(int *)data
= ipflog_clear(unit
);
325 #endif /* IPFILTER_LOG */
327 error
= IWCOPYPTR((caddr_t
)ipfr_fragstats(), data
,
331 if (!(mode
& FWRITE
))
334 #if defined(_KERNEL) && defined(__sgi)
353 for (dev
= dev_base
; dev
; dev
= dev
->next
)
359 static int frrequest(unit
, req
, data
, set
)
365 register frentry_t
*fp
, *f
, **fprev
;
366 register frentry_t
**ftail
;
369 frgroup_t
*fg
= NULL
;
374 error
= IRCOPYPTR(data
, (caddr_t
)fp
, sizeof(*fp
));
379 * Check that the group number does exist and that if a head group
380 * has been specified, doesn't exist.
383 fr_findgroup((u_int
)fp
->fr_grhead
, fp
->fr_flags
, unit
, set
, NULL
))
386 !fr_findgroup((u_int
)fp
->fr_group
, fp
->fr_flags
, unit
, set
, NULL
))
389 in
= (fp
->fr_flags
& FR_INQUE
) ? 0 : 1;
391 if (unit
== IPL_LOGAUTH
)
392 ftail
= fprev
= &ipauth
;
393 else if (fp
->fr_flags
& FR_ACCOUNT
)
394 ftail
= fprev
= &ipacct
[in
][set
];
395 else if (fp
->fr_flags
& (FR_OUTQUE
|FR_INQUE
))
396 ftail
= fprev
= &ipfilter
[in
][set
];
400 if ((group
= fp
->fr_group
)) {
401 if (!(fg
= fr_findgroup(group
, fp
->fr_flags
, unit
, set
, NULL
)))
403 ftail
= fprev
= fg
->fg_start
;
406 bzero((char *)frcache
, sizeof(frcache
[0]) * 2);
408 if (*fp
->fr_ifname
) {
409 fp
->fr_ifa
= GETUNIT(fp
->fr_ifname
, fp
->fr_ip
.fi_v
);
411 fp
->fr_ifa
= (void *)-1;
415 fp
->fr_flags
&= ~FR_DUP
;
416 if (*fdp
->fd_ifname
) {
417 fdp
->fd_ifp
= GETUNIT(fdp
->fd_ifname
, fp
->fr_ip
.fi_v
);
419 fdp
->fd_ifp
= (struct ifnet
*)-1;
421 fp
->fr_flags
|= FR_DUP
;
425 if (*fdp
->fd_ifname
) {
426 fdp
->fd_ifp
= GETUNIT(fdp
->fd_ifname
, fp
->fr_ip
.fi_v
);
428 fdp
->fd_ifp
= (struct ifnet
*)-1;
432 * Look for a matching filter rule, but don't include the next or
433 * interface pointer in the comparison (fr_next, fr_ifa).
435 for (; (f
= *ftail
); ftail
= &f
->fr_next
)
436 if (bcmp((char *)&f
->fr_ip
, (char *)&fp
->fr_ip
,
441 * If zero'ing statistics, copy current to caller and zero.
443 if (req
== SIOCZRLST
) {
446 error
= IWCOPYPTR((caddr_t
)f
, data
, sizeof(*f
));
455 if (req
== SIOCINAFR
|| req
== SIOCINIFR
) {
458 while (--fp
->fr_hits
&& (f
= *ftail
)) {
466 if (req
== SIOCRMAFR
|| req
== SIOCRMIFR
) {
472 if (fg
&& fg
->fg_head
)
473 fg
->fg_head
->fr_ref
--;
474 if (unit
== IPL_LOGAUTH
)
475 return fr_auth_ioctl(data
, mode
, req
, f
, ftail
);
477 fr_delgroup((u_int
)f
->fr_grhead
, fp
->fr_flags
,
479 fixskip(fprev
, f
, -1);
487 if (unit
== IPL_LOGAUTH
)
488 return fr_auth_ioctl(data
, mode
, req
, f
, ftail
);
489 KMALLOC(f
, frentry_t
*);
491 if (fg
&& fg
->fg_head
)
492 fg
->fg_head
->fr_ref
++;
493 bcopy((char *)fp
, (char *)f
, sizeof(*f
));
498 if (req
== SIOCINIFR
|| req
== SIOCINAFR
)
499 fixskip(fprev
, f
, 1);
501 if ((group
= f
->fr_grhead
))
502 fg
= fr_addgroup(group
, f
, unit
, set
);
513 * routines below for saving IP headers to buffer
515 int iplopen(struct inode
*inode
, struct file
*file
)
517 u_int min
= GET_MINOR(inode
->i_rdev
);
519 if (IPL_LOGMAX
< min
)
529 void iplclose(struct inode
*inode
, struct file
*file
)
531 u_int min
= GET_MINOR(inode
->i_rdev
);
533 if (IPL_LOGMAX
>= min
) {
540 * both of these must operate with at least splnet() lest they be
541 * called during packet processing and cause an inconsistancy to appear in
544 int iplread(struct inode
*inode
, struct file
*file
, char *buf
, int nbytes
)
546 struct uio uiob
, *uio
= &uiob
;
549 uio
->uio_resid
= nbytes
;
551 return ipflog_read(GET_MINOR(inode
->i_rdev
), uio
);
559 * send_reset - this could conceivably be a call to tcp_respond(), but that
560 * requires a large amount of setting up and isn't any more efficient.
562 int send_reset(ti
, ifp
)
571 if (ti
->ti_flags
& TH_RST
)
572 return -1; /* feedback loop */
574 m
= alloc_skb(sizeof(tcpiphdr_t
), GFP_ATOMIC
);
578 if (ti
->ti_flags
& TH_SYN
)
583 ip
= mtod(m
, ip_t
*);
586 m
->m_len
= sizeof(tcpiphdr_t
);
587 tcp
= (tcphdr_t
*)((char *)ip
+ sizeof(ip_t
));
588 bzero((char *)ip
, sizeof(tcpiphdr_t
));
590 ip
->ip_v
= IPVERSION
;
591 ip
->ip_hl
= sizeof(ip_t
) >> 2;
592 ip
->ip_tos
= ((ip_t
*)ti
)->ip_tos
;
593 ip
->ip_p
= ((ip_t
*)ti
)->ip_p
;
594 ip
->ip_id
= ((ip_t
*)ti
)->ip_id
;
595 ip
->ip_len
= htons(sizeof(tcpiphdr_t
));
597 ip
->ip_src
.s_addr
= ti
->ti_dst
.s_addr
;
598 ip
->ip_dst
.s_addr
= ti
->ti_src
.s_addr
;
599 tcp
->th_dport
= ti
->ti_sport
;
600 tcp
->th_sport
= ti
->ti_dport
;
601 tcp
->th_ack
= htonl(ntohl(ti
->ti_seq
) + tlen
);
602 tcp
->th_off
= sizeof(tcphdr_t
) >> 2;
603 tcp
->th_flags
= TH_RST
|TH_ACK
;
606 ip
->ip_sum
= ipf_cksum((u_short
*)ip
, sizeof(ip_t
));
607 tcp
->th_sum
= fr_tcpsum(m
, ip
, tcp
);
608 return ip_forward(m
, NULL
, IPFWD_NOTTLDEC
, ip
->ip_dst
.s_addr
);
612 size_t mbufchainlen(m0
)
615 register size_t len
= 0;
617 for (; m0
; m0
= m0
->m_next
)
623 void ipfr_fastroute(m0
, fin
, fdp
)
629 register ip_t
*ip
, *mhip
;
630 register mb_t
*m
= m0
;
631 register struct route
*ro
;
632 struct ifnet
*ifp
= fdp
->fd_ifp
;
633 int len
, off
, error
= 0;
634 int hlen
= fin
->fin_hlen
;
635 struct route iproute
;
636 struct sockaddr_in
*dst
;
638 ip
= mtod(m0
, ip_t
*);
643 bzero((caddr_t
)ro
, sizeof (*ro
));
644 dst
= (struct sockaddr_in
*)&ro
->ro_dst
;
645 dst
->sin_family
= AF_INET
;
646 dst
->sin_addr
= fdp
->fd_ip
.s_addr
? fdp
->fd_ip
: ip
->ip_dst
;
648 * XXX -allocate route here
651 if (!(fin
->fin_fr
->fr_flags
& FR_FASTROUTE
)) {
655 if (ro
->ro_rt
== 0 || (ifp
= ro
->ro_rt
->rt_ifp
) == 0) {
656 if (in_localaddr(ip
->ip_dst
))
657 error
= EHOSTUNREACH
;
662 if (ro
->ro_rt
->rt_flags
& RTF_GATEWAY
)
663 dst
= (struct sockaddr_in
*)&ro
->ro_rt
->rt_gateway
;
668 * For input packets which are being "fastrouted", they won't
669 * go back through output filtering and miss their chance to get
672 (void) ip_natout(ip
, hlen
, fin
);
676 * If small enough for interface, can just send directly.
678 if (ip
->ip_len
<= ifp
->if_mtu
) {
680 ip
->ip_id
= htons(ip
->ip_id
);
681 ip
->ip_len
= htons(ip
->ip_len
);
682 ip
->ip_off
= htons(ip
->ip_off
);
685 ip
->ip_sum
= in_cksum(m
, hlen
);
686 error
= (*ifp
->hard_start_xmit
)(m
, ifp
, m
);
690 * Too large for interface; fragment if possible.
691 * Must be able to put at least 8 bytes per fragment.
693 if (ip
->ip_off
& IP_DF
) {
697 len
= (ifp
->if_mtu
- hlen
) &~ 7;
704 int mhlen
, firstlen
= len
;
705 mb_t
**mnext
= &m
->m_act
;
708 * Loop through length of segment after first fragment,
709 * make new header and copy data of each part and link onto chain.
712 mhlen
= sizeof (struct ip
);
713 for (off
= hlen
+ len
; off
< ip
->ip_len
; off
+= len
) {
714 MGET(m
, M_DONTWAIT
, MT_HEADER
);
719 m
->m_data
+= max_linkhdr
;
720 mhip
= mtod(m
, struct ip
*);
721 bcopy((char *)ip
, (char *)mhip
, sizeof(*ip
));
722 if (hlen
> sizeof (struct ip
)) {
723 mhlen
= ip_optcopy(ip
, mhip
) + sizeof (struct ip
);
724 mhip
->ip_hl
= mhlen
>> 2;
727 mhip
->ip_off
= ((off
- hlen
) >> 3) + (ip
->ip_off
& ~IP_MF
);
728 if (ip
->ip_off
& IP_MF
)
729 mhip
->ip_off
|= IP_MF
;
730 if (off
+ len
>= ip
->ip_len
)
731 len
= ip
->ip_len
- off
;
733 mhip
->ip_off
|= IP_MF
;
734 mhip
->ip_len
= htons((u_short
)(len
+ mhlen
));
735 m
->m_next
= m_copy(m0
, off
, len
);
736 if (m
->m_next
== 0) {
737 error
= ENOBUFS
; /* ??? */
741 mhip
->ip_off
= htons((u_short
)mhip
->ip_off
);
744 mhip
->ip_sum
= in_cksum(m
, mhlen
);
749 * Update first fragment by trimming what's been copied out
750 * and updating header, then send each fragment (in order).
752 m_adj(m0
, hlen
+ firstlen
- ip
->ip_len
);
753 ip
->ip_len
= htons((u_short
)(hlen
+ firstlen
));
754 ip
->ip_off
= htons((u_short
)(ip
->ip_off
| IP_MF
));
756 ip
->ip_sum
= in_cksum(m0
, hlen
);
758 for (m
= m0
; m
; m
= m0
) {
762 error
= (*ifp
->if_output
)(ifp
, m
,
763 (struct sockaddr
*)dst
);
786 * Fake BSD uiomove() call.
788 int uiomove(caddr_t src
, size_t ssize
, int rw
, struct uio
*uio
)
791 size_t mv
= MIN(ssize
, uio
->uio_resid
);
793 if (rw
== UIO_READ
) {
794 error
= IWCOPY(src
, (caddr_t
)uio
->uio_buf
, mv
);
795 } else if (rw
== UIO_WRITE
) {
796 error
= IRCOPY((caddr_t
)uio
->uio_buf
, src
, mv
);
800 uio
->uio_resid
-= mv
;
808 # define IPL_MAJOR 95
812 # define IPL_NAME "/dev/ipl"
815 static struct file_operations ipl_fops
= {
821 iplioctl
, /* ioctl */
824 iplclose
, /* release */
827 NULL
, /* check_media_change */
828 NULL
, /* revalidate */
832 int init_module(void)
834 int error
= 0, major
;
836 if (register_chrdev(IPL_MAJOR
, "ipf", &ipl_fops
)) {
837 printk("ipf: unable to get major number: %d\n", IPL_MAJOR
);
847 void cleanup_module(void)
849 unregister_chrdev(IPL_MAJOR
, "ipf");
852 # endif /* IPFILTER_LKM */
853 #else /* #ifdef _KERNEL */
856 static int no_output
__P((mb_t
*m
, struct ifnet
*ifp
))
862 static int write_output
__P((mb_t
*m
, struct ifnet
*ifp
))
868 ip
= mtod(m
, ip_t
*);
869 sprintf(fname
, "/tmp/%s", ifp
->name
);
870 if ((fp
= fopen(fname
, "a"))) {
871 fwrite((char *)ip
, ntohs(ip
->ip_len
), 1, fp
);
878 struct ifnet
*get_unit(name
, v
)
882 struct ifnet
*ifp
, **ifa
;
885 for (ifa
= ifneta
; ifa
&& (ifp
= *ifa
); ifa
++) {
886 (void) sprintf(ifname
, "%s", ifp
->name
);
887 if (!strcmp(name
, ifname
))
892 ifneta
= (struct ifnet
**)malloc(sizeof(ifp
) * 2);
894 ifneta
[0] = (struct ifnet
*)calloc(1, sizeof(*ifp
));
898 ifneta
= (struct ifnet
**)realloc(ifneta
,
899 (nifs
+ 1) * sizeof(*ifa
));
901 ifneta
[nifs
- 1] = (struct ifnet
*)malloc(sizeof(*ifp
));
903 ifp
= ifneta
[nifs
- 1];
905 for (s
= name
; *s
&& !isdigit(*s
); s
++)
907 if (*s
&& isdigit(*s
)) {
908 ifp
->name
= (char *)malloc(s
- name
+ 1);
909 strncpy(ifp
->name
, name
, s
- name
);
910 ifp
->name
[s
- name
] = '\0';
912 ifp
->name
= strdup(name
);
914 ifp
->hard_start_xmit
= no_output
;
923 struct ifnet
*ifp
, **ifa
;
926 for (ifa
= ifneta
; ifa
&& (ifp
= *ifa
); ifa
++) {
927 ifp
->hard_start_xmit
= write_output
;
928 sprintf(fname
, "/tmp/%s", ifp
->name
);
929 if ((fp
= fopen(fname
, "w")))
935 void ipfr_fastroute(ip
, fin
, fdp
)
940 struct ifnet
*ifp
= fdp
->fd_ifp
;
943 return; /* no routing table out here */
945 ip
->ip_len
= htons((u_short
)ip
->ip_len
);
946 ip
->ip_off
= htons((u_short
)(ip
->ip_off
| IP_MF
));
948 (*ifp
->hard_start_xmit
)((mb_t
*)ip
, ifp
);
952 int ipllog
__P((void))
959 int send_reset(ip
, ifp
)
963 verbose("- TCP RST sent\n");
968 int icmp_error(ip
, ifp
)
972 verbose("- TCP RST sent\n");