|  | /* | 
|  | * Copyright (C) 1993-2001 by Darren Reed. | 
|  | * (C)opyright 1997 by Marc Boucher. | 
|  | * | 
|  | * See the IPFILTER.LICENCE file for details on licencing. | 
|  | * | 
|  | */ | 
|  |  | 
|  | /* TODO: (MARCXXX) | 
|  | - ipl_init failure -> open ENODEV or whatever | 
|  | - prevent multiple LKM loads | 
|  | - surround access to ifnet structures by IFNET_LOCK()/IFNET_UNLOCK() ? | 
|  | - m != m1 problem | 
|  | */ | 
|  |  | 
|  | #include <sys/types.h> | 
|  | #include <sys/conf.h> | 
|  | #ifdef IPFILTER_LKM | 
|  | #include <sys/mload.h> | 
|  | #endif | 
|  | #include <sys/systm.h> | 
|  | #include <sys/errno.h> | 
|  | #include <net/if.h> | 
|  | #include <net/route.h> | 
|  | #include <netinet/in.h> | 
|  | #ifdef IFF_DRVRLOCK /* IRIX6 */ | 
|  | #include <sys/hashing.h> | 
|  | #include <netinet/in_var.h> | 
|  | #endif | 
|  | #include <sys/mbuf.h> | 
|  | #include <netinet/in_systm.h> | 
|  | #include <netinet/ip.h> | 
|  | #include <netinet/ip_var.h> | 
|  | #include <netinet/tcp.h> | 
|  | #include <netinet/udp.h> | 
|  | #include <netinet/tcpip.h> | 
|  | #include <netinet/ip_icmp.h> | 
|  | #include <netinet/ipfilter.h> | 
|  | #include "ipl.h" | 
|  | #include "ip_compat.h" | 
|  | #include "ip_fil.h" | 
|  | #include "ip_nat.h" | 
|  |  | 
|  | #ifndef	MBUF_IS_CLUSTER | 
|  | # define	MBUF_IS_CLUSTER(m)	((m)->m_flags & MCL_CLUSTER) | 
|  | #endif | 
|  | #undef	IPFDEBUG	/* #define IPFDEBUG 9 */ | 
|  |  | 
|  | #ifdef IPFILTER_LKM | 
|  | u_int	ipldevflag = D_MP; | 
|  | char	*iplmversion = M_VERSION; | 
|  | #else | 
|  | u_int	ipfilterdevflag = D_MP; | 
|  | char	*ipfiltermversion = M_VERSION; | 
|  | #endif | 
|  |  | 
|  | ipfmutex_t	ipl_mutex, ipfi_mutex, ipf_rw, ipf_stinsert, ipf_authmx; | 
|  | ipfmutex_t	ipf_nat_new, ipf_natio, ipf_timeoutlock; | 
|  | ipfrwlock_t	ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; | 
|  | ipfrwlock_t	ipf_global, ipf_mutex, ipf_ipidfrag, ipf_frcache, ipf_tokens; | 
|  |  | 
|  | int     (*fr_checkp) __P((struct ip *, int, void *, int, mb_t **)); | 
|  |  | 
|  | #ifdef IPFILTER_LKM | 
|  | static int *ipff_addr = 0; | 
|  | static int ipff_value; | 
|  | static __psunsigned_t *ipfk_addr = 0; | 
|  | static __psunsigned_t ipfk_code[4]; | 
|  | #endif | 
|  | static void nifattach(); | 
|  | static void nifdetach(); | 
|  |  | 
|  | typedef	struct	nif	{ | 
|  | struct	nif	*nf_next; | 
|  | struct ifnet	*nf_ifp; | 
|  | #if (IRIX < 60500) | 
|  | int     (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *); | 
|  | #else | 
|  | int     (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *, | 
|  | struct rtentry *); | 
|  | #endif | 
|  | char	nf_name[LIFNAMSIZ]; | 
|  | int	nf_unit; | 
|  | } nif_t; | 
|  |  | 
|  | static nif_t *nif_head = 0; | 
|  | static int nif_interfaces = 0; | 
|  | extern int in_interfaces; | 
|  | #if IRIX >= 60500 | 
|  | toid_t	fr_timer_id; | 
|  | #endif | 
|  |  | 
|  | extern ipnat_t *nat_list; | 
|  |  | 
|  | #ifdef IPFDEBUG | 
|  | static void ipf_dumppacket(m) | 
|  | struct mbuf *m; | 
|  | { | 
|  | u_char *s; | 
|  | char *t, line[80]; | 
|  | int len, off, i; | 
|  |  | 
|  | off = 0; | 
|  |  | 
|  | while (m != NULL) { | 
|  | len = M_LEN(m); | 
|  | s = mtod(m, u_char *); | 
|  | printf("mbuf 0x%lx len %d flags %x type %d\n", | 
|  | m, len, m->m_flags, m->m_type); | 
|  | printf("dat 0x%lx off 0x%lx/%d s 0x%lx next 0x%lx\n", | 
|  | m->m_dat, m->m_off, m->m_off, s, m->m_next); | 
|  | while (len > 0) { | 
|  | t = line; | 
|  | for (i = 0; (i < 16) && (len > 0); len--, i++) | 
|  | sprintf(t, " %02x", *s++), t += strlen(t); | 
|  | *s = '\0'; | 
|  | printf("mbuf:%x:%s\n", off, line); | 
|  | off += 16; | 
|  | } | 
|  | m = m->m_next; | 
|  | } | 
|  | } | 
|  | #endif | 
|  |  | 
|  |  | 
|  | static int | 
|  | #if IRIX < 60500 | 
|  | ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst) | 
|  | #else | 
|  | ipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, | 
|  | struct rtentry *rt) | 
|  | #endif | 
|  | { | 
|  | #if (IPFDEBUG >= 0) | 
|  | static unsigned int cnt = 0; | 
|  | #endif | 
|  | nif_t *nif; | 
|  |  | 
|  | MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ | 
|  | for (nif = nif_head; nif; nif = nif->nf_next) | 
|  | if (nif->nf_ifp == ifp) | 
|  | break; | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  |  | 
|  | if (nif == NULL) { | 
|  | printf("IP Filter: ipl_if_output intf %x NOT FOUND\n", ifp); | 
|  | return ENETDOWN; | 
|  | } | 
|  |  | 
|  | #if (IPFDEBUG >= 7) | 
|  | if ((++cnt % 200) == 0) | 
|  | 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); | 
|  | #endif | 
|  |  | 
|  | if (fr_checkp) { | 
|  | struct mbuf *m1 = m; | 
|  | struct ip *ip; | 
|  | int hlen; | 
|  |  | 
|  | switch(m->m_type) | 
|  | { | 
|  | case MT_HEADER: | 
|  | if (m->m_len == 0) { | 
|  | if (m->m_next == NULL) | 
|  | break; | 
|  | m = m->m_next; | 
|  | } | 
|  | /* FALLTHROUGH */ | 
|  | case MT_DATA: | 
|  | if (!MBUF_IS_CLUSTER(m) && | 
|  | ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { | 
|  | #if (IPFDEBUG >= 4) | 
|  | 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); | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | if (m->m_len < sizeof(char)) { | 
|  | #if (IPFDEBUG >= 3) | 
|  | 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); | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | ip = mtod(m, struct ip *); | 
|  | if (ip->ip_v != IPVERSION) { | 
|  | #if (IPFDEBUG >= 2) | 
|  | ipf_dumppacket(m); | 
|  | 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); | 
|  | #endif | 
|  | break; | 
|  | } | 
|  |  | 
|  | hlen = ip->ip_hl << 2; | 
|  | if ((*fr_checkp)(ip, hlen, ifp, 1, &m1) || (m1 == NULL)) | 
|  | return EHOSTUNREACH; | 
|  |  | 
|  | m = m1; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | #if (IPFDEBUG >= 2) | 
|  | 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); | 
|  | #endif | 
|  | break; | 
|  | } | 
|  | } | 
|  | #if (IRIX < 60500) | 
|  | return (*nif->nf_output)(ifp, m, dst); | 
|  | #else | 
|  | return (*nif->nf_output)(ifp, m, dst, rt); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | int | 
|  |  | 
|  |  | 
|  | #if !defined(IPFILTER_LKM) && (IRIX >= 60500) | 
|  | ipfilter_kernel(struct ifnet *rcvif, struct mbuf *m) | 
|  | #else | 
|  | ipl_kernel(struct ifnet *rcvif, struct mbuf *m) | 
|  | #endif | 
|  | { | 
|  | #if (IPFDEBUG >= 7) | 
|  | static unsigned int cnt = 0; | 
|  |  | 
|  | if ((++cnt % 200) == 0) | 
|  | printf("IP Filter: ipl_kernel(rcvif=0x%lx, m=0x%lx\n", | 
|  | rcvif, m); | 
|  | #endif | 
|  |  | 
|  | if (fr_running <= 0) | 
|  | return IPF_ACCEPTIT; | 
|  |  | 
|  | /* | 
|  | * Check if we want to allow this packet to be processed. | 
|  | * Consider it to be bad if not. | 
|  | */ | 
|  | if (fr_checkp) { | 
|  | struct mbuf *m1 = m; | 
|  | struct ip *ip; | 
|  | int hlen; | 
|  |  | 
|  | if ((m->m_type != MT_DATA) && (m->m_type != MT_HEADER)) { | 
|  | #if (IPFDEBUG >= 4) | 
|  | 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); | 
|  | #endif | 
|  | return IPF_ACCEPTIT; | 
|  | } | 
|  |  | 
|  | if (!MBUF_IS_CLUSTER(m) && | 
|  | ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { | 
|  | #if (IPFDEBUG >= 4) | 
|  | 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); | 
|  | #endif | 
|  | return IPF_ACCEPTIT; | 
|  | } | 
|  |  | 
|  | if (m->m_len < sizeof(char)) { | 
|  | #if (IPFDEBUG >= 1) | 
|  | 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); | 
|  | #endif | 
|  | return IPF_ACCEPTIT; | 
|  | } | 
|  |  | 
|  | ip = mtod(m, struct ip *); | 
|  | if (ip->ip_v != IPVERSION) { | 
|  | #if (IPFDEBUG >= 4) | 
|  | printf("IP Filter: ipl_kernel: bad ip_v\n"); | 
|  | #endif | 
|  | m_freem(m); | 
|  | return IPF_DROPIT; | 
|  | } | 
|  |  | 
|  | hlen = ip->ip_hl << 2; | 
|  | if ((*fr_checkp)(ip, hlen, rcvif, 0, &m1) || !m1) | 
|  | return IPF_DROPIT; | 
|  |  | 
|  | #if (IPFDEBUG >= 2) | 
|  | if (m != m1) | 
|  | printf("IP Filter: ipl_kernel: m != m1\n"); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | return IPF_ACCEPTIT; | 
|  | } | 
|  |  | 
|  | int | 
|  | ipl_ipfilter_attach(void) | 
|  | { | 
|  | #if defined(IPFILTER_LKM) | 
|  | __psunsigned_t *addr_ff, *addr_fk; | 
|  |  | 
|  | st_findaddr("ipfilterflag", &addr_ff); | 
|  | # if (IPFDEBUG >= 1) | 
|  | printf("IP Filter: st_findaddr ipfilterflag=0x%lx\n", addr_ff); | 
|  | # endif | 
|  | if (!addr_ff) | 
|  | return ESRCH; | 
|  |  | 
|  | st_findaddr("ipfilter_kernel", &addr_fk); | 
|  | # if (IPFDEBUG >= 1) | 
|  | printf("IP Filter: st_findaddr ipfilter_kernel=0x%lx\n", addr_fk); | 
|  | # endif | 
|  | if (!addr_fk) | 
|  | return ESRCH; | 
|  |  | 
|  | MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ | 
|  |  | 
|  | ipff_addr = (int *)addr_ff; | 
|  |  | 
|  | ipff_value = *ipff_addr; | 
|  | *ipff_addr = 0; | 
|  |  | 
|  |  | 
|  | ipfk_addr = addr_fk; | 
|  |  | 
|  | bcopy(ipfk_addr, ipfk_code, sizeof(ipfk_code)); | 
|  |  | 
|  | /* write a "li t4, ipl_kernel" instruction */ | 
|  | ipfk_addr[0] = 0x3c0c0000 | | 
|  | (((__psunsigned_t)ipl_kernel >> 16) & 0xffff); | 
|  | ipfk_addr[1] = 0x358c0000 | | 
|  | ((__psunsigned_t)ipl_kernel & 0xffff); | 
|  | /* write a "jr t4" instruction" */ | 
|  | ipfk_addr[2] = 0x01800008; | 
|  |  | 
|  | /* write a "nop" instruction */ | 
|  | ipfk_addr[3] = 0; | 
|  |  | 
|  | icache_inval(ipfk_addr, sizeof(ipfk_code)); | 
|  |  | 
|  | *ipff_addr = 1; /* enable ipfilter_kernel */ | 
|  |  | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  | #else | 
|  | extern int ipfilterflag; | 
|  |  | 
|  | ipfilterflag = 1; | 
|  | #endif | 
|  | nif_interfaces = 0; | 
|  | nifattach(); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* | 
|  | * attach the packet filter to each non-loopback interface that is running | 
|  | */ | 
|  | static void | 
|  | nifattach() | 
|  | { | 
|  | nif_t *nif, *qf2; | 
|  | struct ifnet *ifp; | 
|  | struct frentry *f; | 
|  | ipnat_t *np; | 
|  |  | 
|  | MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ | 
|  |  | 
|  | for (ifp = ifnet; ifp; ifp = ifp->if_next) { | 
|  | if ((!(ifp->if_flags & IFF_RUNNING)) || | 
|  | (ifp->if_flags & IFF_LOOPBACK)) | 
|  | continue; | 
|  |  | 
|  | /* | 
|  | * Look for entry already setup for this device | 
|  | */ | 
|  | for (nif = nif_head; nif; nif = nif->nf_next) | 
|  | if (nif->nf_ifp == ifp) | 
|  | break; | 
|  | if (nif) | 
|  | continue; | 
|  |  | 
|  | if (ifp->if_output == ipl_if_output) { | 
|  | printf("IP Filter: ERROR INTF 0x%lx STILL ATTACHED\n", | 
|  | ifp); | 
|  | continue; | 
|  | } | 
|  | #if (IPFDEBUG >= 2) | 
|  | printf("IP Filter: nifattach nif %x opt %x\n", | 
|  | ifp, ifp->if_output); | 
|  | #endif | 
|  | KMALLOC(nif, nif_t *); | 
|  | if (!nif) { | 
|  | printf("IP Filter: malloc(%d) for nif_t failed\n", | 
|  | sizeof(nif_t)); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | nif->nf_ifp = ifp; | 
|  | (void) strncpy(nif->nf_name, ifp->if_name, | 
|  | sizeof(nif->nf_name)); | 
|  | nif->nf_name[sizeof(nif->nf_name) - 1] = '\0'; | 
|  | nif->nf_unit = ifp->if_unit; | 
|  |  | 
|  | nif->nf_next = nif_head; | 
|  | nif_head = nif; | 
|  |  | 
|  | /* | 
|  | * Activate any rules directly associated with this interface | 
|  | */ | 
|  | WRITE_ENTER(&ipf_mutex); | 
|  | for (f = ipfilter[0][0]; f; f = f->fr_next) { | 
|  | if ((f->fr_ifa == (struct ifnet *)-1)) { | 
|  | if (f->fr_ifname[0] && | 
|  | (GETIFP(f->fr_ifname, 4) == ifp)) | 
|  | f->fr_ifa = ifp; | 
|  | } | 
|  | } | 
|  | for (f = ipfilter[1][0]; f; f = f->fr_next) { | 
|  | if ((f->fr_ifa == (struct ifnet *)-1)) { | 
|  | if (f->fr_ifname[0] && | 
|  | (GETIFP(f->fr_ifname, 4) == ifp)) | 
|  | f->fr_ifa = ifp; | 
|  | } | 
|  | } | 
|  | RWLOCK_EXIT(&ipf_mutex); | 
|  | WRITE_ENTER(&ipf_nat); | 
|  | for (np = nat_list; np; np = np->in_next) { | 
|  | if ((np->in_ifps[0] == (void *)-1)) { | 
|  | if (np->in_ifnames[0][0] && | 
|  | (GETIFP(np->in_ifnames[0], 4) == ifp)) | 
|  | np->in_ifps[0] = (void *)ifp; | 
|  | } | 
|  | if ((np->in_ifps[1] == (void *)-1)) { | 
|  | if (np->in_ifnames[1][0] && | 
|  | (GETIFP(np->in_ifnames[1], 4) == ifp)) | 
|  | np->in_ifps[1] = (void *)ifp; | 
|  | } | 
|  | } | 
|  | RWLOCK_EXIT(&ipf_nat); | 
|  |  | 
|  | nif->nf_output = ifp->if_output; | 
|  | ifp->if_output = ipl_if_output; | 
|  |  | 
|  | #if (IPFDEBUG >= 2) | 
|  | printf("IP Filter: nifattach: ifp(%lx)->if_output FROM %lx TO %lx\n", | 
|  | ifp, nif->nf_output, ifp->if_output); | 
|  | #endif | 
|  |  | 
|  | printf("IP Filter: attach to [%s,%d]\n", | 
|  | nif->nf_name, ifp->if_unit); | 
|  | } | 
|  | if (!nif_head) | 
|  | printf("IP Filter: not attached to any interfaces\n"); | 
|  |  | 
|  | nif_interfaces = in_interfaces; | 
|  |  | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* | 
|  | * unhook the IP filter from all defined interfaces with IP addresses | 
|  | */ | 
|  | static void | 
|  | nifdetach() | 
|  | { | 
|  | nif_t *nif, *qf2, **qp; | 
|  | struct ifnet *ifp; | 
|  |  | 
|  | MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ | 
|  | /* | 
|  | * Make two passes, first get rid of all the unknown devices, next | 
|  | * unlink known devices. | 
|  | */ | 
|  | for (qp = &nif_head; (nif = *qp); ) { | 
|  | for (ifp = ifnet; ifp; ifp = ifp->if_next) | 
|  | if (nif->nf_ifp == ifp) | 
|  | break; | 
|  | if (ifp) { | 
|  | qp = &nif->nf_next; | 
|  | continue; | 
|  | } | 
|  | printf("IP Filter: removing [%s]\n", nif->nf_name); | 
|  | *qp = nif->nf_next; | 
|  | KFREE(nif); | 
|  | } | 
|  |  | 
|  | while ((nif = nif_head)) { | 
|  | nif_head = nif->nf_next; | 
|  | for (ifp = ifnet; ifp; ifp = ifp->if_next) | 
|  | if (nif->nf_ifp == ifp) | 
|  | break; | 
|  | if (ifp) { | 
|  | printf("IP Filter: detaching [%s,%d]\n", | 
|  | nif->nf_name, ifp->if_unit); | 
|  |  | 
|  | #if (IPFDEBUG >= 4) | 
|  | printf("IP Filter: nifdetach: ifp(%lx)->if_output FROM %lx TO %lx\n", | 
|  | ifp, ifp->if_output, nif->nf_output); | 
|  | #endif | 
|  | ifp->if_output = nif->nf_output; | 
|  | } | 
|  | KFREE(nif); | 
|  | } | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  |  | 
|  | void | 
|  | ipl_ipfilter_detach(void) | 
|  | { | 
|  | #ifdef IPFILTER_LKM | 
|  | nifdetach(); | 
|  | MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ | 
|  |  | 
|  | if (ipff_addr) { | 
|  | *ipff_addr = 0; | 
|  |  | 
|  | if (ipfk_addr) { | 
|  | bcopy(ipfk_code, ipfk_addr, sizeof(ipfk_code)); | 
|  | icache_inval(ipfk_addr - 16, sizeof(ipfk_code)+32); | 
|  | } | 
|  |  | 
|  | *ipff_addr = ipff_value; | 
|  | } | 
|  |  | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  | #else | 
|  | extern int ipfilterflag; | 
|  |  | 
|  | nifdetach(); | 
|  |  | 
|  | ipfilterflag = 0; | 
|  | #endif | 
|  | } | 
|  |  | 
|  |  | 
|  | /* this function is called from fr_slowtimer at 500ms intervals to | 
|  | keep our interface list in sync */ | 
|  | void | 
|  | ipl_ipfilter_intfsync(void) | 
|  | { | 
|  | MUTEX_ENTER(&ipfi_mutex); | 
|  | if (nif_interfaces != in_interfaces) { | 
|  | /* if the number of interfaces has changed, resync */ | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  | frsync(NULL); | 
|  | } else | 
|  | MUTEX_EXIT(&ipfi_mutex); | 
|  | } | 
|  |  | 
|  | #ifdef IPFILTER_LKM | 
|  | /* this routine should be treated as an interrupt routine and should | 
|  | not call any routines that would cause it to sleep, such as: biowait(), | 
|  | sleep(), psema() or delay(). | 
|  | */ | 
|  | int | 
|  | iplunload(void) | 
|  | { | 
|  | int error = 0; | 
|  |  | 
|  | if (fr_refcnt) | 
|  | return EBUSY; | 
|  |  | 
|  | WRITE_ENTER(&ipf_global); | 
|  | error = ipl_detach(); | 
|  | if (error != 0) { | 
|  | RWLOCK_EXIT(&ipf_global); | 
|  | return error; | 
|  | } | 
|  | fr_running = -2; | 
|  |  | 
|  | #if (IRIX < 60500) | 
|  | LOCK_DEALLOC(ipl_mutex.l); | 
|  | LOCK_DEALLOC(ipf_rw.l); | 
|  | LOCK_DEALLOC(ipf_auth.l); | 
|  | LOCK_DEALLOC(ipf_natfrag.l); | 
|  | LOCK_DEALLOC(ipf_ipidfrag.l); | 
|  | LOCK_DEALLOC(ipf_tokens.l); | 
|  | LOCK_DEALLOC(ipf_stinsert.l); | 
|  | LOCK_DEALLOC(ipf_nat_new.l); | 
|  | LOCK_DEALLOC(ipf_natio.l); | 
|  | LOCK_DEALLOC(ipf_nat.l); | 
|  | LOCK_DEALLOC(ipf_state.l); | 
|  | LOCK_DEALLOC(ipf_frag.l); | 
|  | LOCK_DEALLOC(ipf_authmx.l); | 
|  | LOCK_DEALLOC(ipf_mutex.l); | 
|  | LOCK_DEALLOC(ipf_frcache.l); | 
|  | LOCK_DEALLOC(ipfi_mutex.l); | 
|  | RWLOCK_EXIT(&ipf_global); | 
|  | LOCK_DEALLOC(ipf_global.l); | 
|  | #else | 
|  | MUTEX_DESTROY(&ipf_rw); | 
|  | MUTEX_DESTROY(&ipfi_mutex); | 
|  | MUTEX_DESTROY(&ipf_timeoutlock); | 
|  | RW_DESTROY(&ipf_mutex); | 
|  | RW_DESTROY(&ipf_frcache); | 
|  | RW_DESTROY(&ipf_tokens); | 
|  | RWLOCK_EXIT(&ipf_global); | 
|  | delay(hz); | 
|  | RW_DESTROY(&ipf_global); | 
|  | #endif | 
|  |  | 
|  | printf("%s unloaded\n", ipfilter_version); | 
|  |  | 
|  | delay(hz); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | void | 
|  | ipfilterinit(void) | 
|  | { | 
|  | #ifdef IPFILTER_LKM | 
|  | int error; | 
|  | #endif | 
|  |  | 
|  | #if (IRIX < 60500) | 
|  | ipfi_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_frcache.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_timeoutlock.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_global.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_frag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_state.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_nat.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_stinsert.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_natfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_ipidfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_tokens.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_auth.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipf_rw.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  | ipl_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); | 
|  |  | 
|  | if (!ipfi_mutex.l || !ipf_mutex.l || !ipf_timeoutlock.l || | 
|  | !ipf_frag.l || !ipf_state.l || !ipf_nat.l || !ipf_natfrag.l || | 
|  | !ipf_auth.l || !ipf_rw.l || !ipf_ipidfrag.l || !ipl_mutex.l || | 
|  | !ipf_stinsert.l || !ipf_authmx.l || !ipf_frcache.l || !ipf_tokens.l) | 
|  | panic("IP Filter: LOCK_ALLOC failed"); | 
|  | #else | 
|  | MUTEX_INIT(&ipf_rw, "ipf rw mutex"); | 
|  | MUTEX_INIT(&ipf_timeoutlock, "ipf timeout mutex"); | 
|  | RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); | 
|  | RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); | 
|  | RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); | 
|  | #endif | 
|  |  | 
|  | #ifdef IPFILTER_LKM | 
|  | error = ipl_attach(); | 
|  | if (error) { | 
|  | iplunload(); | 
|  | } else { | 
|  | char *defpass; | 
|  |  | 
|  | if (FR_ISPASS(fr_pass)) | 
|  | defpass = "pass"; | 
|  | else if (FR_ISBLOCK(fr_pass)) | 
|  | defpass = "block"; | 
|  | else | 
|  | defpass = "no-match -> block"; | 
|  |  | 
|  | printf("%s initialized.  Default = %s all, Logging = %s%s\n", | 
|  | ipfilter_version, defpass, | 
|  | # ifdef  IPFILTER_LOG | 
|  | "enabled", | 
|  | # else | 
|  | "disabled", | 
|  | # endif | 
|  | # ifdef IPFILTER_COMPILED | 
|  | " (COMPILED)" | 
|  | # else | 
|  | "" | 
|  | # endif | 
|  | ); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | return; | 
|  | } |