4 * Copyright (C) 2012 by Darren Reed.
5 * (C)opyright 1997 by Marc Boucher.
7 * See the IPFILTER.LICENCE file for details on licencing.
12 - ipl_init failure -> open ENODEV or whatever
13 - prevent multiple LKM loads
14 - surround access to ifnet structures by IFNET_LOCK()/IFNET_UNLOCK() ?
18 #include <sys/types.h>
21 #include <sys/mload.h>
23 #include <sys/systm.h>
24 #include <sys/errno.h>
26 #include <net/route.h>
27 #include <netinet/in.h>
28 #ifdef IFF_DRVRLOCK /* IRIX6 */
29 #include <sys/hashing.h>
30 #include <netinet/in_var.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/ip_var.h>
36 #include <netinet/tcp.h>
37 #include <netinet/udp.h>
38 #include <netinet/tcpip.h>
39 #include <netinet/ip_icmp.h>
40 #include <netinet/ipfilter.h>
42 #include "ip_compat.h"
46 #ifndef MBUF_IS_CLUSTER
47 # define MBUF_IS_CLUSTER(m) ((m)->m_flags & MCL_CLUSTER)
49 #undef IPFDEBUG /* #define IPFDEBUG 9 */
52 u_int ipldevflag = D_MP;
53 char *iplmversion = M_VERSION;
55 u_int ipfilterdevflag = D_MP;
56 char *ipfiltermversion = M_VERSION;
59 ipfmutex_t ipl_mutex, ipfi_mutex, ipf_rw, ipf_stinsert, ipf_auth_mx;
60 ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
61 ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
62 ipfrwlock_t ipf_global, ipf_mutex, ipf_ipidfrag, ipf_frcache, ipf_tokens;
64 int (*ipf_checkp) __P((struct ip *, int, void *, int, mb_t **));
67 static int *ipff_addr = 0;
68 static int ipff_value;
69 static __psunsigned_t *ipfk_addr = 0;
70 static __psunsigned_t ipfk_code[4];
72 static void nifattach();
73 static void nifdetach();
79 int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *);
81 int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *,
84 char nf_name[LIFNAMSIZ];
88 static nif_t *nif_head = 0;
89 static int nif_interfaces = 0;
90 extern int in_interfaces;
95 extern ipnat_t *nat_list;
98 static void ipf_dumppacket(m)
109 s = mtod(m, u_char *);
110 printf("mbuf 0x%lx len %d flags %x type %d\n",
111 m, len, m->m_flags, m->m_type);
112 printf("dat 0x%lx off 0x%lx/%d s 0x%lx next 0x%lx\n",
113 m->m_dat, m->m_off, m->m_off, s, m->m_next);
116 for (i = 0; (i < 16) && (len > 0); len--, i++)
117 sprintf(t, " %02x", *s++), t += strlen(t);
119 printf("mbuf:%x:%s\n", off, line);
130 ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst)
132 ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
137 static unsigned int cnt = 0;
141 MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */
142 for (nif = nif_head; nif; nif = nif->nf_next)
143 if (nif->nf_ifp == ifp)
145 MUTEX_EXIT(&ipfi_mutex);
148 printf("IP Filter: ipl_if_output intf %x NOT FOUND\n", ifp);
153 if ((++cnt % 200) == 0)
154 printf("IP Filter: ipl_if_output(ifp=0x%lx, m=0x%lx, dst=0x%lx), m_type=%d m_flags=0x%lx m_off=0x%lx\n", ifp, m, dst, m->m_type, (u_long)m->m_flags, m->m_off);
166 if (m->m_next == NULL)
172 if (!MBUF_IS_CLUSTER(m) &&
173 ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) {
175 printf("IP Filter: ipl_if_output: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off);
179 if (m->m_len < sizeof(char)) {
181 printf("IP Filter: ipl_if_output: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (u_long)m->m_flags);
185 ip = mtod(m, struct ip *);
186 if (ip->ip_v != IPVERSION) {
189 printf("IP Filter: ipl_if_output: bad ip_v m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off);
194 hlen = ip->ip_hl << 2;
195 if ((*ipf_checkp)(ip, hlen, ifp, 1, &m1) || (m1 == NULL))
203 printf("IP Filter: ipl_if_output: bad m_type=%d m_flags=0x%lxm_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off);
209 return (*nif->nf_output)(ifp, m, dst);
211 return (*nif->nf_output)(ifp, m, dst, rt);
218 #if !defined(IPFILTER_LKM) && (IRIX >= 60500)
219 ipfilter_kernel(struct ifnet *rcvif, struct mbuf *m)
221 ipl_kernel(struct ifnet *rcvif, struct mbuf *m)
225 static unsigned int cnt = 0;
227 if ((++cnt % 200) == 0)
228 printf("IP Filter: ipl_kernel(rcvif=0x%lx, m=0x%lx\n",
232 if (ipf_running <= 0)
236 * Check if we want to allow this packet to be processed.
237 * Consider it to be bad if not.
244 if ((m->m_type != MT_DATA) && (m->m_type != MT_HEADER)) {
246 printf("IP Filter: ipl_kernel: bad m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off);
251 if (!MBUF_IS_CLUSTER(m) &&
252 ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) {
254 printf("IP Filter: ipl_kernel: bad m_off m_type=%d m_flags=0x%lx m_off=0x%lx\n", m->m_type, (u_long)m->m_flags, m->m_off);
259 if (m->m_len < sizeof(char)) {
261 printf("IP Filter: ipl_kernel: mbuf block too small (m_len=%d) for IP vers+hlen, m_type=%d m_flags=0x%lx\n", m->m_len, m->m_type, (u_long)m->m_flags);
266 ip = mtod(m, struct ip *);
267 if (ip->ip_v != IPVERSION) {
269 printf("IP Filter: ipl_kernel: bad ip_v\n");
275 ip->ip_len = htons(ip->ip_len);
276 ip->ip_off = htons(ip->ip_off);
277 hlen = ip->ip_hl << 2;
278 if ((*ipf_checkp)(ip, hlen, rcvif, 0, &m1) || !m1)
280 ip = mtod(m1, struct ip *);
281 ip->ip_len = ntohs(ip->ip_len);
282 ip->ip_off = ntohs(ip->ip_off);
286 printf("IP Filter: ipl_kernel: m != m1\n");
294 ipl_ipfilter_attach(void)
296 #if defined(IPFILTER_LKM)
297 __psunsigned_t *addr_ff, *addr_fk;
299 st_findaddr("ipfilterflag", &addr_ff);
301 printf("IP Filter: st_findaddr ipfilterflag=0x%lx\n", addr_ff);
306 st_findaddr("ipfilter_kernel", &addr_fk);
308 printf("IP Filter: st_findaddr ipfilter_kernel=0x%lx\n", addr_fk);
313 MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */
315 ipff_addr = (int *)addr_ff;
317 ipff_value = *ipff_addr;
323 bcopy(ipfk_addr, ipfk_code, sizeof(ipfk_code));
325 /* write a "li t4, ipl_kernel" instruction */
326 ipfk_addr[0] = 0x3c0c0000 |
327 (((__psunsigned_t)ipl_kernel >> 16) & 0xffff);
328 ipfk_addr[1] = 0x358c0000 |
329 ((__psunsigned_t)ipl_kernel & 0xffff);
330 /* write a "jr t4" instruction" */
331 ipfk_addr[2] = 0x01800008;
333 /* write a "nop" instruction */
336 icache_inval(ipfk_addr, sizeof(ipfk_code));
338 *ipff_addr = 1; /* enable ipfilter_kernel */
340 MUTEX_EXIT(&ipfi_mutex);
342 extern int ipfilterflag;
354 * attach the packet filter to each non-loopback interface that is running
364 MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */
366 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
367 if ((!(ifp->if_flags & IFF_RUNNING)) ||
368 (ifp->if_flags & IFF_LOOPBACK))
372 * Look for entry already setup for this device
374 for (nif = nif_head; nif; nif = nif->nf_next)
375 if (nif->nf_ifp == ifp)
380 if (ifp->if_output == ipl_if_output) {
381 printf("IP Filter: ERROR INTF 0x%lx STILL ATTACHED\n",
386 printf("IP Filter: nifattach nif %x opt %x\n",
387 ifp, ifp->if_output);
389 KMALLOC(nif, nif_t *);
391 printf("IP Filter: malloc(%d) for nif_t failed\n",
397 (void) strncpy(nif->nf_name, ifp->if_name,
398 sizeof(nif->nf_name));
399 nif->nf_name[sizeof(nif->nf_name) - 1] = '\0';
400 nif->nf_unit = ifp->if_unit;
402 nif->nf_next = nif_head;
406 * Activate any rules directly associated with this interface
408 WRITE_ENTER(&ipf_mutex);
409 for (f = ipf_rules[0][0]; f; f = f->fr_next) {
410 if ((f->fr_ifa == (struct ifnet *)-1)) {
411 if (f->fr_ifname[0] &&
412 (GETIFP(f->fr_ifname, 4) == ifp))
416 for (f = ipf_rules[1][0]; f; f = f->fr_next) {
417 if ((f->fr_ifa == (struct ifnet *)-1)) {
418 if (f->fr_ifname[0] &&
419 (GETIFP(f->fr_ifname, 4) == ifp))
423 RWLOCK_EXIT(&ipf_mutex);
424 WRITE_ENTER(&ipf_nat);
425 for (np = nat_list; np; np = np->in_next) {
426 if ((np->in_ifps[0] == (void *)-1)) {
427 if (np->in_ifnames[0][0] &&
428 (GETIFP(np->in_ifnames[0], 4) == ifp))
429 np->in_ifps[0] = (void *)ifp;
431 if ((np->in_ifps[1] == (void *)-1)) {
432 if (np->in_ifnames[1][0] &&
433 (GETIFP(np->in_ifnames[1], 4) == ifp))
434 np->in_ifps[1] = (void *)ifp;
437 RWLOCK_EXIT(&ipf_nat);
439 nif->nf_output = ifp->if_output;
440 ifp->if_output = ipl_if_output;
443 printf("IP Filter: nifattach: ifp(%lx)->if_output FROM %lx TO %lx\n",
444 ifp, nif->nf_output, ifp->if_output);
447 printf("IP Filter: attach to [%s,%d]\n",
448 nif->nf_name, ifp->if_unit);
451 printf("IP Filter: not attached to any interfaces\n");
453 nif_interfaces = in_interfaces;
455 MUTEX_EXIT(&ipfi_mutex);
462 * unhook the IP filter from all defined interfaces with IP addresses
467 nif_t *nif, *qf2, **qp;
470 MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */
472 * Make two passes, first get rid of all the unknown devices, next
473 * unlink known devices.
475 for (qp = &nif_head; (nif = *qp); ) {
476 for (ifp = ifnet; ifp; ifp = ifp->if_next)
477 if (nif->nf_ifp == ifp)
483 printf("IP Filter: removing [%s]\n", nif->nf_name);
488 while ((nif = nif_head)) {
489 nif_head = nif->nf_next;
490 for (ifp = ifnet; ifp; ifp = ifp->if_next)
491 if (nif->nf_ifp == ifp)
494 printf("IP Filter: detaching [%s,%d]\n",
495 nif->nf_name, ifp->if_unit);
498 printf("IP Filter: nifdetach: ifp(%lx)->if_output FROM %lx TO %lx\n",
499 ifp, ifp->if_output, nif->nf_output);
501 ifp->if_output = nif->nf_output;
505 MUTEX_EXIT(&ipfi_mutex);
512 ipl_ipfilter_detach(void)
516 MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */
522 bcopy(ipfk_code, ipfk_addr, sizeof(ipfk_code));
523 icache_inval(ipfk_addr - 16, sizeof(ipfk_code)+32);
526 *ipff_addr = ipff_value;
529 MUTEX_EXIT(&ipfi_mutex);
531 extern int ipfilterflag;
540 /* this function is called from ipf_slowtimer at 500ms intervals to
541 keep our interface list in sync */
543 ipl_ipfilter_intfsync(void)
545 MUTEX_ENTER(&ipfi_mutex);
546 if (nif_interfaces != in_interfaces) {
547 /* if the number of interfaces has changed, resync */
548 MUTEX_EXIT(&ipfi_mutex);
549 ipf_sync(&ipfmain, NULL);
551 MUTEX_EXIT(&ipfi_mutex);
555 /* this routine should be treated as an interrupt routine and should
556 not call any routines that would cause it to sleep, such as: biowait(),
557 sleep(), psema() or delay().
567 WRITE_ENTER(&ipf_global);
568 error = ipl_detach();
570 RWLOCK_EXIT(&ipf_global);
576 LOCK_DEALLOC(ipl_mutex.l);
577 LOCK_DEALLOC(ipf_rw.l);
578 LOCK_DEALLOC(ipf_auth.l);
579 LOCK_DEALLOC(ipf_natfrag.l);
580 LOCK_DEALLOC(ipf_ipidfrag.l);
581 LOCK_DEALLOC(ipf_tokens.l);
582 LOCK_DEALLOC(ipf_stinsert.l);
583 LOCK_DEALLOC(ipf_nat_new.l);
584 LOCK_DEALLOC(ipf_natio.l);
585 LOCK_DEALLOC(ipf_nat.l);
586 LOCK_DEALLOC(ipf_state.l);
587 LOCK_DEALLOC(ipf_frag.l);
588 LOCK_DEALLOC(ipf_auth_mx.l);
589 LOCK_DEALLOC(ipf_mutex.l);
590 LOCK_DEALLOC(ipf_frcache.l);
591 LOCK_DEALLOC(ipfi_mutex.l);
592 RWLOCK_EXIT(&ipf_global);
593 LOCK_DEALLOC(ipf_global.l);
595 MUTEX_DESTROY(&ipf_rw);
596 MUTEX_DESTROY(&ipfi_mutex);
597 MUTEX_DESTROY(&ipf_timeoutlock);
598 RW_DESTROY(&ipf_mutex);
599 RW_DESTROY(&ipf_frcache);
600 RW_DESTROY(&ipf_tokens);
601 RWLOCK_EXIT(&ipf_global);
603 RW_DESTROY(&ipf_global);
606 printf("%s unloaded\n", ipfilter_version);
622 ipfi_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
623 ipf_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
624 ipf_frcache.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
625 ipf_timeoutlock.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
626 ipf_global.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
627 ipf_frag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
628 ipf_state.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
629 ipf_nat.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
630 ipf_stinsert.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
631 ipf_natfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
632 ipf_ipidfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
633 ipf_tokens.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
634 ipf_auth.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
635 ipf_rw.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
636 ipl_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP);
638 if (!ipfi_mutex.l || !ipf_mutex.l || !ipf_timeoutlock.l ||
639 !ipf_frag.l || !ipf_state.l || !ipf_nat.l || !ipf_natfrag.l ||
640 !ipf_auth.l || !ipf_rw.l || !ipf_ipidfrag.l || !ipl_mutex.l ||
641 !ipf_stinsert.l || !ipf_auth_mx.l || !ipf_frcache.l ||
643 panic("IP Filter: LOCK_ALLOC failed");
645 MUTEX_INIT(&ipf_rw, "ipf rw mutex");
646 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout mutex");
647 RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex");
648 RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock");
649 RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock");
653 error = ipl_attach();
659 if (FR_ISPASS(ipf_pass))
661 else if (FR_ISBLOCK(ipf_pass))
664 defpass = "no-match -> block";
666 printf("%s initialized. Default = %s all, Logging = %s%s\n",
667 ipfilter_version, defpass,
673 # ifdef IPFILTER_COMPILED