1255332Scy/* $FreeBSD$ */ 2255332Scy 3255332Scy/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5255332Scy * (C)opyright 1997 by Marc Boucher. 6255332Scy * 7255332Scy * See the IPFILTER.LICENCE file for details on licencing. 8255332Scy * 9255332Scy */ 10255332Scy 11255332Scy/* TODO: (MARCXXX) 12255332Scy - ipl_init failure -> open ENODEV or whatever 13255332Scy - prevent multiple LKM loads 14255332Scy - surround access to ifnet structures by IFNET_LOCK()/IFNET_UNLOCK() ? 15255332Scy - m != m1 problem 16255332Scy*/ 17255332Scy 18255332Scy#include <sys/types.h> 19255332Scy#include <sys/conf.h> 20255332Scy#ifdef IPFILTER_LKM 21255332Scy#include <sys/mload.h> 22255332Scy#endif 23255332Scy#include <sys/systm.h> 24255332Scy#include <sys/errno.h> 25255332Scy#include <net/if.h> 26255332Scy#include <net/route.h> 27255332Scy#include <netinet/in.h> 28255332Scy#ifdef IFF_DRVRLOCK /* IRIX6 */ 29255332Scy#include <sys/hashing.h> 30255332Scy#include <netinet/in_var.h> 31255332Scy#endif 32255332Scy#include <sys/mbuf.h> 33255332Scy#include <netinet/in_systm.h> 34255332Scy#include <netinet/ip.h> 35255332Scy#include <netinet/ip_var.h> 36255332Scy#include <netinet/tcp.h> 37255332Scy#include <netinet/udp.h> 38255332Scy#include <netinet/tcpip.h> 39255332Scy#include <netinet/ip_icmp.h> 40255332Scy#include <netinet/ipfilter.h> 41255332Scy#include "ipl.h" 42255332Scy#include "ip_compat.h" 43255332Scy#include "ip_fil.h" 44255332Scy#include "ip_nat.h" 45255332Scy 46255332Scy#ifndef MBUF_IS_CLUSTER 47255332Scy# define MBUF_IS_CLUSTER(m) ((m)->m_flags & MCL_CLUSTER) 48255332Scy#endif 49255332Scy#undef IPFDEBUG /* #define IPFDEBUG 9 */ 50255332Scy 51255332Scy#ifdef IPFILTER_LKM 52255332Scyu_int ipldevflag = D_MP; 53255332Scychar *iplmversion = M_VERSION; 54255332Scy#else 55255332Scyu_int ipfilterdevflag = D_MP; 56255332Scychar *ipfiltermversion = M_VERSION; 57255332Scy#endif 58255332Scy 59255332Scyipfmutex_t ipl_mutex, ipfi_mutex, ipf_rw, ipf_stinsert, ipf_auth_mx; 60255332Scyipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; 61255332Scyipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth; 62255332Scyipfrwlock_t ipf_global, ipf_mutex, ipf_ipidfrag, ipf_frcache, ipf_tokens; 63255332Scy 64255332Scyint (*ipf_checkp) __P((struct ip *, int, void *, int, mb_t **)); 65255332Scy 66255332Scy#ifdef IPFILTER_LKM 67255332Scystatic int *ipff_addr = 0; 68255332Scystatic int ipff_value; 69255332Scystatic __psunsigned_t *ipfk_addr = 0; 70255332Scystatic __psunsigned_t ipfk_code[4]; 71255332Scy#endif 72255332Scystatic void nifattach(); 73255332Scystatic void nifdetach(); 74255332Scy 75255332Scytypedef struct nif { 76255332Scy struct nif *nf_next; 77255332Scy struct ifnet *nf_ifp; 78255332Scy#if (IRIX < 60500) 79255332Scy int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *); 80255332Scy#else 81255332Scy int (*nf_output)(struct ifnet *, struct mbuf *, struct sockaddr *, 82255332Scy struct rtentry *); 83255332Scy#endif 84255332Scy char nf_name[LIFNAMSIZ]; 85255332Scy int nf_unit; 86255332Scy} nif_t; 87255332Scy 88255332Scystatic nif_t *nif_head = 0; 89255332Scystatic int nif_interfaces = 0; 90255332Scyextern int in_interfaces; 91255332Scy#if IRIX >= 60500 92255332Scytoid_t ipf_timer_id; 93255332Scy#endif 94255332Scy 95255332Scyextern ipnat_t *nat_list; 96255332Scy 97255332Scy#ifdef IPFDEBUG 98255332Scystatic void ipf_dumppacket(m) 99255332Scy struct mbuf *m; 100255332Scy{ 101255332Scy u_char *s; 102255332Scy char *t, line[80]; 103255332Scy int len, off, i; 104255332Scy 105255332Scy off = 0; 106255332Scy 107255332Scy while (m != NULL) { 108255332Scy len = M_LEN(m); 109255332Scy s = mtod(m, u_char *); 110255332Scy printf("mbuf 0x%lx len %d flags %x type %d\n", 111255332Scy m, len, m->m_flags, m->m_type); 112255332Scy printf("dat 0x%lx off 0x%lx/%d s 0x%lx next 0x%lx\n", 113255332Scy m->m_dat, m->m_off, m->m_off, s, m->m_next); 114255332Scy while (len > 0) { 115255332Scy t = line; 116255332Scy for (i = 0; (i < 16) && (len > 0); len--, i++) 117255332Scy sprintf(t, " %02x", *s++), t += strlen(t); 118255332Scy *s = '\0'; 119255332Scy printf("mbuf:%x:%s\n", off, line); 120255332Scy off += 16; 121255332Scy } 122255332Scy m = m->m_next; 123255332Scy } 124255332Scy} 125255332Scy#endif 126255332Scy 127255332Scy 128255332Scystatic int 129255332Scy#if IRIX < 60500 130255332Scyipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst) 131255332Scy#else 132255332Scyipl_if_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 133255332Scy struct rtentry *rt) 134255332Scy#endif 135255332Scy{ 136255332Scy#if (IPFDEBUG >= 0) 137255332Scy static unsigned int cnt = 0; 138255332Scy#endif 139255332Scy nif_t *nif; 140255332Scy 141255332Scy MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ 142255332Scy for (nif = nif_head; nif; nif = nif->nf_next) 143255332Scy if (nif->nf_ifp == ifp) 144255332Scy break; 145255332Scy MUTEX_EXIT(&ipfi_mutex); 146255332Scy 147255332Scy if (nif == NULL) { 148255332Scy printf("IP Filter: ipl_if_output intf %x NOT FOUND\n", ifp); 149255332Scy return ENETDOWN; 150255332Scy } 151255332Scy 152255332Scy#if (IPFDEBUG >= 7) 153255332Scy if ((++cnt % 200) == 0) 154255332Scy 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); 155255332Scy#endif 156255332Scy 157255332Scy if (ipf_checkp) { 158255332Scy struct mbuf *m1 = m; 159255332Scy struct ip *ip; 160255332Scy int hlen; 161255332Scy 162255332Scy switch(m->m_type) 163255332Scy { 164255332Scy case MT_HEADER: 165255332Scy if (m->m_len == 0) { 166255332Scy if (m->m_next == NULL) 167255332Scy break; 168255332Scy m = m->m_next; 169255332Scy } 170255332Scy /* FALLTHROUGH */ 171255332Scy case MT_DATA: 172255332Scy if (!MBUF_IS_CLUSTER(m) && 173255332Scy ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { 174255332Scy#if (IPFDEBUG >= 4) 175255332Scy 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); 176255332Scy#endif 177255332Scy break; 178255332Scy } 179255332Scy if (m->m_len < sizeof(char)) { 180255332Scy#if (IPFDEBUG >= 3) 181255332Scy 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); 182255332Scy#endif 183255332Scy break; 184255332Scy } 185255332Scy ip = mtod(m, struct ip *); 186255332Scy if (ip->ip_v != IPVERSION) { 187255332Scy#if (IPFDEBUG >= 2) 188255332Scy ipf_dumppacket(m); 189255332Scy 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); 190255332Scy#endif 191255332Scy break; 192255332Scy } 193255332Scy 194255332Scy hlen = ip->ip_hl << 2; 195255332Scy if ((*ipf_checkp)(ip, hlen, ifp, 1, &m1) || (m1 == NULL)) 196255332Scy return EHOSTUNREACH; 197255332Scy 198255332Scy m = m1; 199255332Scy break; 200255332Scy 201255332Scy default: 202255332Scy#if (IPFDEBUG >= 2) 203255332Scy 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); 204255332Scy#endif 205255332Scy break; 206255332Scy } 207255332Scy } 208255332Scy#if (IRIX < 60500) 209255332Scy return (*nif->nf_output)(ifp, m, dst); 210255332Scy#else 211255332Scy return (*nif->nf_output)(ifp, m, dst, rt); 212255332Scy#endif 213255332Scy} 214255332Scy 215255332Scyint 216255332Scy 217255332Scy 218255332Scy#if !defined(IPFILTER_LKM) && (IRIX >= 60500) 219255332Scyipfilter_kernel(struct ifnet *rcvif, struct mbuf *m) 220255332Scy#else 221255332Scyipl_kernel(struct ifnet *rcvif, struct mbuf *m) 222255332Scy#endif 223255332Scy{ 224255332Scy#if (IPFDEBUG >= 7) 225255332Scy static unsigned int cnt = 0; 226255332Scy 227255332Scy if ((++cnt % 200) == 0) 228255332Scy printf("IP Filter: ipl_kernel(rcvif=0x%lx, m=0x%lx\n", 229255332Scy rcvif, m); 230255332Scy#endif 231255332Scy 232255332Scy if (ipf_running <= 0) 233255332Scy return IPF_ACCEPTIT; 234255332Scy 235255332Scy /* 236255332Scy * Check if we want to allow this packet to be processed. 237255332Scy * Consider it to be bad if not. 238255332Scy */ 239255332Scy if (ipf_checkp) { 240255332Scy struct mbuf *m1 = m; 241255332Scy struct ip *ip; 242255332Scy int hlen; 243255332Scy 244255332Scy if ((m->m_type != MT_DATA) && (m->m_type != MT_HEADER)) { 245255332Scy#if (IPFDEBUG >= 4) 246255332Scy 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); 247255332Scy#endif 248255332Scy return IPF_ACCEPTIT; 249255332Scy } 250255332Scy 251255332Scy if (!MBUF_IS_CLUSTER(m) && 252255332Scy ((m->m_off < MMINOFF) || (m->m_off > MMAXOFF))) { 253255332Scy#if (IPFDEBUG >= 4) 254255332Scy 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); 255255332Scy#endif 256255332Scy return IPF_ACCEPTIT; 257255332Scy } 258255332Scy 259255332Scy if (m->m_len < sizeof(char)) { 260255332Scy#if (IPFDEBUG >= 1) 261255332Scy 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); 262255332Scy#endif 263255332Scy return IPF_ACCEPTIT; 264255332Scy } 265255332Scy 266255332Scy ip = mtod(m, struct ip *); 267255332Scy if (ip->ip_v != IPVERSION) { 268255332Scy#if (IPFDEBUG >= 4) 269255332Scy printf("IP Filter: ipl_kernel: bad ip_v\n"); 270255332Scy#endif 271255332Scy m_freem(m); 272255332Scy return IPF_DROPIT; 273255332Scy } 274255332Scy 275255332Scy ip->ip_len = htons(ip->ip_len); 276255332Scy ip->ip_off = htons(ip->ip_off); 277255332Scy hlen = ip->ip_hl << 2; 278255332Scy if ((*ipf_checkp)(ip, hlen, rcvif, 0, &m1) || !m1) 279255332Scy return IPF_DROPIT; 280255332Scy ip = mtod(m1, struct ip *); 281255332Scy ip->ip_len = ntohs(ip->ip_len); 282255332Scy ip->ip_off = ntohs(ip->ip_off); 283255332Scy 284255332Scy#if (IPFDEBUG >= 2) 285255332Scy if (m != m1) 286255332Scy printf("IP Filter: ipl_kernel: m != m1\n"); 287255332Scy#endif 288255332Scy } 289255332Scy 290255332Scy return IPF_ACCEPTIT; 291255332Scy} 292255332Scy 293255332Scyint 294255332Scyipl_ipfilter_attach(void) 295255332Scy{ 296255332Scy#if defined(IPFILTER_LKM) 297255332Scy __psunsigned_t *addr_ff, *addr_fk; 298255332Scy 299255332Scy st_findaddr("ipfilterflag", &addr_ff); 300255332Scy# if (IPFDEBUG >= 1) 301255332Scy printf("IP Filter: st_findaddr ipfilterflag=0x%lx\n", addr_ff); 302255332Scy# endif 303255332Scy if (!addr_ff) 304255332Scy return ESRCH; 305255332Scy 306255332Scy st_findaddr("ipfilter_kernel", &addr_fk); 307255332Scy# if (IPFDEBUG >= 1) 308255332Scy printf("IP Filter: st_findaddr ipfilter_kernel=0x%lx\n", addr_fk); 309255332Scy# endif 310255332Scy if (!addr_fk) 311255332Scy return ESRCH; 312255332Scy 313255332Scy MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ 314255332Scy 315255332Scy ipff_addr = (int *)addr_ff; 316255332Scy 317255332Scy ipff_value = *ipff_addr; 318255332Scy *ipff_addr = 0; 319255332Scy 320255332Scy 321255332Scy ipfk_addr = addr_fk; 322255332Scy 323255332Scy bcopy(ipfk_addr, ipfk_code, sizeof(ipfk_code)); 324255332Scy 325255332Scy /* write a "li t4, ipl_kernel" instruction */ 326255332Scy ipfk_addr[0] = 0x3c0c0000 | 327255332Scy (((__psunsigned_t)ipl_kernel >> 16) & 0xffff); 328255332Scy ipfk_addr[1] = 0x358c0000 | 329255332Scy ((__psunsigned_t)ipl_kernel & 0xffff); 330255332Scy /* write a "jr t4" instruction" */ 331255332Scy ipfk_addr[2] = 0x01800008; 332255332Scy 333255332Scy /* write a "nop" instruction */ 334255332Scy ipfk_addr[3] = 0; 335255332Scy 336255332Scy icache_inval(ipfk_addr, sizeof(ipfk_code)); 337255332Scy 338255332Scy *ipff_addr = 1; /* enable ipfilter_kernel */ 339255332Scy 340255332Scy MUTEX_EXIT(&ipfi_mutex); 341255332Scy#else 342255332Scy extern int ipfilterflag; 343255332Scy 344255332Scy ipfilterflag = 1; 345255332Scy#endif 346255332Scy nif_interfaces = 0; 347255332Scy nifattach(); 348255332Scy 349255332Scy return 0; 350255332Scy} 351255332Scy 352255332Scy 353255332Scy/* 354255332Scy * attach the packet filter to each non-loopback interface that is running 355255332Scy */ 356255332Scystatic void 357255332Scynifattach() 358255332Scy{ 359255332Scy nif_t *nif, *qf2; 360255332Scy struct ifnet *ifp; 361255332Scy struct frentry *f; 362255332Scy ipnat_t *np; 363255332Scy 364255332Scy MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ 365255332Scy 366255332Scy for (ifp = ifnet; ifp; ifp = ifp->if_next) { 367255332Scy if ((!(ifp->if_flags & IFF_RUNNING)) || 368255332Scy (ifp->if_flags & IFF_LOOPBACK)) 369255332Scy continue; 370255332Scy 371255332Scy /* 372255332Scy * Look for entry already setup for this device 373255332Scy */ 374255332Scy for (nif = nif_head; nif; nif = nif->nf_next) 375255332Scy if (nif->nf_ifp == ifp) 376255332Scy break; 377255332Scy if (nif) 378255332Scy continue; 379255332Scy 380255332Scy if (ifp->if_output == ipl_if_output) { 381255332Scy printf("IP Filter: ERROR INTF 0x%lx STILL ATTACHED\n", 382255332Scy ifp); 383255332Scy continue; 384255332Scy } 385255332Scy#if (IPFDEBUG >= 2) 386255332Scy printf("IP Filter: nifattach nif %x opt %x\n", 387255332Scy ifp, ifp->if_output); 388255332Scy#endif 389255332Scy KMALLOC(nif, nif_t *); 390255332Scy if (!nif) { 391255332Scy printf("IP Filter: malloc(%d) for nif_t failed\n", 392255332Scy sizeof(nif_t)); 393255332Scy continue; 394255332Scy } 395255332Scy 396255332Scy nif->nf_ifp = ifp; 397255332Scy (void) strncpy(nif->nf_name, ifp->if_name, 398255332Scy sizeof(nif->nf_name)); 399255332Scy nif->nf_name[sizeof(nif->nf_name) - 1] = '\0'; 400255332Scy nif->nf_unit = ifp->if_unit; 401255332Scy 402255332Scy nif->nf_next = nif_head; 403255332Scy nif_head = nif; 404255332Scy 405255332Scy /* 406255332Scy * Activate any rules directly associated with this interface 407255332Scy */ 408255332Scy WRITE_ENTER(&ipf_mutex); 409255332Scy for (f = ipf_rules[0][0]; f; f = f->fr_next) { 410255332Scy if ((f->fr_ifa == (struct ifnet *)-1)) { 411255332Scy if (f->fr_ifname[0] && 412255332Scy (GETIFP(f->fr_ifname, 4) == ifp)) 413255332Scy f->fr_ifa = ifp; 414255332Scy } 415255332Scy } 416255332Scy for (f = ipf_rules[1][0]; f; f = f->fr_next) { 417255332Scy if ((f->fr_ifa == (struct ifnet *)-1)) { 418255332Scy if (f->fr_ifname[0] && 419255332Scy (GETIFP(f->fr_ifname, 4) == ifp)) 420255332Scy f->fr_ifa = ifp; 421255332Scy } 422255332Scy } 423255332Scy RWLOCK_EXIT(&ipf_mutex); 424255332Scy WRITE_ENTER(&ipf_nat); 425255332Scy for (np = nat_list; np; np = np->in_next) { 426255332Scy if ((np->in_ifps[0] == (void *)-1)) { 427255332Scy if (np->in_ifnames[0][0] && 428255332Scy (GETIFP(np->in_ifnames[0], 4) == ifp)) 429255332Scy np->in_ifps[0] = (void *)ifp; 430255332Scy } 431255332Scy if ((np->in_ifps[1] == (void *)-1)) { 432255332Scy if (np->in_ifnames[1][0] && 433255332Scy (GETIFP(np->in_ifnames[1], 4) == ifp)) 434255332Scy np->in_ifps[1] = (void *)ifp; 435255332Scy } 436255332Scy } 437255332Scy RWLOCK_EXIT(&ipf_nat); 438255332Scy 439255332Scy nif->nf_output = ifp->if_output; 440255332Scy ifp->if_output = ipl_if_output; 441255332Scy 442255332Scy#if (IPFDEBUG >= 2) 443255332Scy printf("IP Filter: nifattach: ifp(%lx)->if_output FROM %lx TO %lx\n", 444255332Scy ifp, nif->nf_output, ifp->if_output); 445255332Scy#endif 446255332Scy 447255332Scy printf("IP Filter: attach to [%s,%d]\n", 448255332Scy nif->nf_name, ifp->if_unit); 449255332Scy } 450255332Scy if (!nif_head) 451255332Scy printf("IP Filter: not attached to any interfaces\n"); 452255332Scy 453255332Scy nif_interfaces = in_interfaces; 454255332Scy 455255332Scy MUTEX_EXIT(&ipfi_mutex); 456255332Scy 457255332Scy return; 458255332Scy} 459255332Scy 460255332Scy 461255332Scy/* 462255332Scy * unhook the IP filter from all defined interfaces with IP addresses 463255332Scy */ 464255332Scystatic void 465255332Scynifdetach() 466255332Scy{ 467255332Scy nif_t *nif, *qf2, **qp; 468255332Scy struct ifnet *ifp; 469255332Scy 470255332Scy MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ 471255332Scy /* 472255332Scy * Make two passes, first get rid of all the unknown devices, next 473255332Scy * unlink known devices. 474255332Scy */ 475255332Scy for (qp = &nif_head; (nif = *qp); ) { 476255332Scy for (ifp = ifnet; ifp; ifp = ifp->if_next) 477255332Scy if (nif->nf_ifp == ifp) 478255332Scy break; 479255332Scy if (ifp) { 480255332Scy qp = &nif->nf_next; 481255332Scy continue; 482255332Scy } 483255332Scy printf("IP Filter: removing [%s]\n", nif->nf_name); 484255332Scy *qp = nif->nf_next; 485255332Scy KFREE(nif); 486255332Scy } 487255332Scy 488255332Scy while ((nif = nif_head)) { 489255332Scy nif_head = nif->nf_next; 490255332Scy for (ifp = ifnet; ifp; ifp = ifp->if_next) 491255332Scy if (nif->nf_ifp == ifp) 492255332Scy break; 493255332Scy if (ifp) { 494255332Scy printf("IP Filter: detaching [%s,%d]\n", 495255332Scy nif->nf_name, ifp->if_unit); 496255332Scy 497255332Scy#if (IPFDEBUG >= 4) 498255332Scy printf("IP Filter: nifdetach: ifp(%lx)->if_output FROM %lx TO %lx\n", 499255332Scy ifp, ifp->if_output, nif->nf_output); 500255332Scy#endif 501255332Scy ifp->if_output = nif->nf_output; 502255332Scy } 503255332Scy KFREE(nif); 504255332Scy } 505255332Scy MUTEX_EXIT(&ipfi_mutex); 506255332Scy 507255332Scy return; 508255332Scy} 509255332Scy 510255332Scy 511255332Scyvoid 512255332Scyipl_ipfilter_detach(void) 513255332Scy{ 514255332Scy#ifdef IPFILTER_LKM 515255332Scy nifdetach(); 516255332Scy MUTEX_ENTER(&ipfi_mutex); /* sets interrupt priority level to splhi */ 517255332Scy 518255332Scy if (ipff_addr) { 519255332Scy *ipff_addr = 0; 520255332Scy 521255332Scy if (ipfk_addr) { 522255332Scy bcopy(ipfk_code, ipfk_addr, sizeof(ipfk_code)); 523255332Scy icache_inval(ipfk_addr - 16, sizeof(ipfk_code)+32); 524255332Scy } 525255332Scy 526255332Scy *ipff_addr = ipff_value; 527255332Scy } 528255332Scy 529255332Scy MUTEX_EXIT(&ipfi_mutex); 530255332Scy#else 531255332Scy extern int ipfilterflag; 532255332Scy 533255332Scy nifdetach(); 534255332Scy 535255332Scy ipfilterflag = 0; 536255332Scy#endif 537255332Scy} 538255332Scy 539255332Scy 540255332Scy/* this function is called from ipf_slowtimer at 500ms intervals to 541255332Scy keep our interface list in sync */ 542255332Scyvoid 543255332Scyipl_ipfilter_intfsync(void) 544255332Scy{ 545255332Scy MUTEX_ENTER(&ipfi_mutex); 546255332Scy if (nif_interfaces != in_interfaces) { 547255332Scy /* if the number of interfaces has changed, resync */ 548255332Scy MUTEX_EXIT(&ipfi_mutex); 549255332Scy ipf_sync(&ipfmain, NULL); 550255332Scy } else 551255332Scy MUTEX_EXIT(&ipfi_mutex); 552255332Scy} 553255332Scy 554255332Scy#ifdef IPFILTER_LKM 555255332Scy/* this routine should be treated as an interrupt routine and should 556255332Scy not call any routines that would cause it to sleep, such as: biowait(), 557255332Scy sleep(), psema() or delay(). 558255332Scy*/ 559255332Scyint 560255332Scyiplunload(void) 561255332Scy{ 562255332Scy int error = 0; 563255332Scy 564255332Scy if (ipf_refcnt) 565255332Scy return EBUSY; 566255332Scy 567255332Scy WRITE_ENTER(&ipf_global); 568255332Scy error = ipl_detach(); 569255332Scy if (error != 0) { 570255332Scy RWLOCK_EXIT(&ipf_global); 571255332Scy return error; 572255332Scy } 573255332Scy ipf_running = -2; 574255332Scy 575255332Scy#if (IRIX < 60500) 576255332Scy LOCK_DEALLOC(ipl_mutex.l); 577255332Scy LOCK_DEALLOC(ipf_rw.l); 578255332Scy LOCK_DEALLOC(ipf_auth.l); 579255332Scy LOCK_DEALLOC(ipf_natfrag.l); 580255332Scy LOCK_DEALLOC(ipf_ipidfrag.l); 581255332Scy LOCK_DEALLOC(ipf_tokens.l); 582255332Scy LOCK_DEALLOC(ipf_stinsert.l); 583255332Scy LOCK_DEALLOC(ipf_nat_new.l); 584255332Scy LOCK_DEALLOC(ipf_natio.l); 585255332Scy LOCK_DEALLOC(ipf_nat.l); 586255332Scy LOCK_DEALLOC(ipf_state.l); 587255332Scy LOCK_DEALLOC(ipf_frag.l); 588255332Scy LOCK_DEALLOC(ipf_auth_mx.l); 589255332Scy LOCK_DEALLOC(ipf_mutex.l); 590255332Scy LOCK_DEALLOC(ipf_frcache.l); 591255332Scy LOCK_DEALLOC(ipfi_mutex.l); 592255332Scy RWLOCK_EXIT(&ipf_global); 593255332Scy LOCK_DEALLOC(ipf_global.l); 594255332Scy#else 595255332Scy MUTEX_DESTROY(&ipf_rw); 596255332Scy MUTEX_DESTROY(&ipfi_mutex); 597255332Scy MUTEX_DESTROY(&ipf_timeoutlock); 598255332Scy RW_DESTROY(&ipf_mutex); 599255332Scy RW_DESTROY(&ipf_frcache); 600255332Scy RW_DESTROY(&ipf_tokens); 601255332Scy RWLOCK_EXIT(&ipf_global); 602255332Scy delay(hz); 603255332Scy RW_DESTROY(&ipf_global); 604255332Scy#endif 605255332Scy 606255332Scy printf("%s unloaded\n", ipfilter_version); 607255332Scy 608255332Scy delay(hz); 609255332Scy 610255332Scy return 0; 611255332Scy} 612255332Scy#endif 613255332Scy 614255332Scyvoid 615255332Scyipfilterinit(void) 616255332Scy{ 617255332Scy#ifdef IPFILTER_LKM 618255332Scy int error; 619255332Scy#endif 620255332Scy 621255332Scy#if (IRIX < 60500) 622255332Scy ipfi_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 623255332Scyipf_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 624255332Scyipf_frcache.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 625255332Scyipf_timeoutlock.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 626255332Scy ipf_global.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 627255332Scy ipf_frag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 628255332Scy ipf_state.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 629255332Scy ipf_nat.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 630255332Scy ipf_stinsert.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 631255332Scy ipf_natfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 632255332Scy ipf_ipidfrag.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 633255332Scy ipf_tokens.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 634255332Scy ipf_auth.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 635255332Scy ipf_rw.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 636255332Scy ipl_mutex.l = LOCK_ALLOC((uchar_t)-1, IPF_LOCK_PL, (lkinfo_t *)-1, KM_NOSLEEP); 637255332Scy 638255332Scy if (!ipfi_mutex.l || !ipf_mutex.l || !ipf_timeoutlock.l || 639255332Scy !ipf_frag.l || !ipf_state.l || !ipf_nat.l || !ipf_natfrag.l || 640255332Scy !ipf_auth.l || !ipf_rw.l || !ipf_ipidfrag.l || !ipl_mutex.l || 641255332Scy !ipf_stinsert.l || !ipf_auth_mx.l || !ipf_frcache.l || 642255332Scy !ipf_tokens.l) 643255332Scy panic("IP Filter: LOCK_ALLOC failed"); 644255332Scy#else 645255332Scy MUTEX_INIT(&ipf_rw, "ipf rw mutex"); 646255332Scy MUTEX_INIT(&ipf_timeoutlock, "ipf timeout mutex"); 647255332Scy RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); 648255332Scy RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); 649255332Scy RWLOCK_INIT(&ipf_frcache, "ipf cache rwlock"); 650255332Scy#endif 651255332Scy 652255332Scy#ifdef IPFILTER_LKM 653255332Scy error = ipl_attach(); 654255332Scy if (error) { 655255332Scy iplunload(); 656255332Scy } else { 657255332Scy char *defpass; 658255332Scy 659255332Scy if (FR_ISPASS(ipf_pass)) 660255332Scy defpass = "pass"; 661255332Scy else if (FR_ISBLOCK(ipf_pass)) 662255332Scy defpass = "block"; 663255332Scy else 664255332Scy defpass = "no-match -> block"; 665255332Scy 666255332Scy printf("%s initialized. Default = %s all, Logging = %s%s\n", 667255332Scy ipfilter_version, defpass, 668255332Scy# ifdef IPFILTER_LOG 669255332Scy "enabled", 670255332Scy# else 671255332Scy "disabled", 672255332Scy# endif 673255332Scy# ifdef IPFILTER_COMPILED 674255332Scy " (COMPILED)" 675255332Scy# else 676255332Scy "" 677255332Scy# endif 678255332Scy ); 679255332Scy } 680255332Scy#endif 681255332Scy 682255332Scy return; 683255332Scy} 684