diff options
Diffstat (limited to 'sys/contrib')
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_htable.h | 15 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c | 6 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_irc_pxy.c | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_lookup.c | 178 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_lookup.h | 35 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_pool.c | 375 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_pool.h | 15 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_pptp_pxy.c | 7 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c | 12 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_scan.c | 34 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_scan.h | 4 | ||||
-rw-r--r-- | sys/contrib/ipfilter/netinet/ip_sync.h | 24 |
12 files changed, 555 insertions, 154 deletions
diff --git a/sys/contrib/ipfilter/netinet/ip_htable.h b/sys/contrib/ipfilter/netinet/ip_htable.h index ebee58d..2c08812 100644 --- a/sys/contrib/ipfilter/netinet/ip_htable.h +++ b/sys/contrib/ipfilter/netinet/ip_htable.h @@ -5,10 +5,12 @@ typedef struct iphtent_s { struct iphtent_s *ipe_next, **ipe_pnext; + struct iphtent_s *ipe_hnext, **ipe_phnext; void *ipe_ptr; i6addr_t ipe_addr; i6addr_t ipe_mask; int ipe_ref; + int ipe_unit; union { char ipeu_char[16]; u_long ipeu_long; @@ -26,6 +28,7 @@ typedef struct iphtable_s { ipfrwlock_t iph_rwlock; struct iphtable_s *iph_next, **iph_pnext; struct iphtent_s **iph_table; + struct iphtent_s *iph_list; size_t iph_size; /* size of hash table */ u_long iph_seed; /* hashing seed */ u_32_t iph_flags; @@ -39,6 +42,7 @@ typedef struct iphtable_s { /* iph_type */ #define IPHASH_LOOKUP 0 #define IPHASH_GROUPMAP 1 +#define IPHASH_DELETE 2 #define IPHASH_ANON 0x80000000 @@ -53,17 +57,22 @@ typedef struct iphtstat_s { extern iphtable_t *ipf_htables[IPL_LOGSIZE]; +extern iphtable_t *fr_existshtable __P((int, char *)); +extern int fr_clearhtable __P((iphtable_t *)); extern void fr_htable_unload __P((void)); extern int fr_newhtable __P((iplookupop_t *)); extern iphtable_t *fr_findhtable __P((int, char *)); -extern int fr_removehtable __P((iplookupop_t *)); +extern int fr_removehtable __P((int, char *)); extern size_t fr_flushhtable __P((iplookupflush_t *)); extern int fr_addhtent __P((iphtable_t *, iphtent_t *)); extern int fr_delhtent __P((iphtable_t *, iphtent_t *)); -extern void fr_derefhtable __P((iphtable_t *)); -extern void fr_delhtable __P((iphtable_t *)); +extern int fr_derefhtable __P((iphtable_t *)); +extern int fr_derefhtent __P((iphtent_t *)); +extern int fr_delhtable __P((iphtable_t *)); extern void *fr_iphmfindgroup __P((void *, void *)); extern int fr_iphmfindip __P((void *, int, void *)); extern int fr_gethtablestat __P((iplookupop_t *)); +extern int fr_htable_getnext __P((ipftoken_t *, ipflookupiter_t *)); +extern void fr_htable_iterderef __P((u_int, int, void *)); #endif /* __IP_HTABLE_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c b/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c index 93cf070..e88a6b9 100644 --- a/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_ipsec_pxy.c @@ -6,7 +6,7 @@ * Simple ISAKMP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_ipsec_pxy.c,v 2.20.2.7 2005/08/20 13:48:22 darrenr Exp $ + * $Id: ip_ipsec_pxy.c,v 2.20.2.8 2006/07/14 06:12:14 darrenr Exp $ * */ #define IPF_IPSEC_PROXY @@ -177,7 +177,7 @@ nat_t *nat; ipsec->ipsc_state = fr_addstate(&fi, &ipsec->ipsc_state, SI_WILDP); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p & 0xff; return 0; @@ -256,7 +256,7 @@ nat_t *nat; &ipsec->ipsc_state, SI_WILDP); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p; } diff --git a/sys/contrib/ipfilter/netinet/ip_irc_pxy.c b/sys/contrib/ipfilter/netinet/ip_irc_pxy.c index 0aa5710..5bb252a 100644 --- a/sys/contrib/ipfilter/netinet/ip_irc_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_irc_pxy.c @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_irc_pxy.c,v 2.39.2.5 2005/12/04 23:39:27 darrenr Exp $ + * $Id: ip_irc_pxy.c,v 2.39.2.6 2006/07/14 06:12:14 darrenr Exp $ */ #define IPF_IRC_PROXY @@ -415,7 +415,7 @@ nat_t *nat; (void) fr_addstate(&fi, NULL, SI_W_DPORT); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_src = swip; } diff --git a/sys/contrib/ipfilter/netinet/ip_lookup.c b/sys/contrib/ipfilter/netinet/ip_lookup.c index 3c7eb5f..12b1f4a 100644 --- a/sys/contrib/ipfilter/netinet/ip_lookup.c +++ b/sys/contrib/ipfilter/netinet/ip_lookup.c @@ -34,9 +34,6 @@ struct file; #endif #include <sys/socket.h> #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) -# ifdef __osf__ -# include <net/radix.h> -# endif # include "radix_ipf_local.h" # define _RADIX_H_ #endif @@ -61,7 +58,7 @@ struct file; /* END OF INCLUDES */ #if !defined(lint) -static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.8 2005/11/13 15:35:45 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.15 2007/05/26 13:05:13 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -129,10 +126,11 @@ void ip_lookup_unload() /* involves just calling another function to handle the specifics of each */ /* command. */ /* ------------------------------------------------------------------------ */ -int ip_lookup_ioctl(data, cmd, mode) +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { int err; SPL_INT(s); @@ -182,6 +180,10 @@ int mode; RWLOCK_EXIT(&ip_poolrw); break; + case SIOCLOOKUPITER : + err = ip_lookup_iterate(data, uid, ctx); + break; + default : err = EINVAL; break; @@ -210,8 +212,13 @@ caddr_t data; ip_pool_t *p; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -283,6 +290,9 @@ caddr_t data; err = 0; BCOPYIN(data, &op, sizeof(op)); + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; switch (op.iplo_type) @@ -341,8 +351,12 @@ caddr_t data; iplookupop_t op; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; @@ -371,8 +385,10 @@ caddr_t data; * For anonymous pools, copy back the operation struct because in the * case of success it will contain the new table's name. */ - if ((err == 0) && ((op.iplo_arg & IPOOL_ANON) != 0)) { - BCOPYOUT(&op, data, sizeof(op)); + if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { + err = BCOPYOUT(&op, data, sizeof(op)); + if (err != 0) + err = EFAULT; } return err; @@ -393,11 +409,14 @@ caddr_t data; iplookupop_t op; int err; - BCOPYIN(data, &op, sizeof(op)); - op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; - if (op.iplo_arg & IPLT_ANON) - op.iplo_arg &= IPLT_ANON; + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; + + op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; /* * create a new pool - fail if one already exists with @@ -406,11 +425,11 @@ caddr_t data; switch (op.iplo_type) { case IPLT_POOL : - err = ip_pool_destroy(&op); + err = ip_pool_destroy(op.iplo_unit, op.iplo_name); break; case IPLT_HASH : - err = fr_removehtable(&op); + err = fr_removehtable(op.iplo_unit, op.iplo_name); break; default : @@ -434,8 +453,12 @@ caddr_t data; iplookupop_t op; int err; - err = 0; - BCOPYIN(data, &op, sizeof(op)); + err = BCOPYIN(data, &op, sizeof(op)); + if (err != 0) + return EFAULT; + + if (op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) + return EINVAL; switch (op.iplo_type) { @@ -469,15 +492,16 @@ caddr_t data; int err, unit, num, type; iplookupflush_t flush; - err = 0; - BCOPYIN(data, &flush, sizeof(flush)); - - flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + err = BCOPYIN(data, &flush, sizeof(flush)); + if (err != 0) + return EFAULT; unit = flush.iplf_unit; if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) return EINVAL; + flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; + type = flush.iplf_type; err = EINVAL; num = 0; @@ -494,12 +518,23 @@ caddr_t data; if (err == 0) { flush.iplf_count = num; - err = COPYOUT(&flush, data, sizeof(flush)); + err = BCOPYOUT(&flush, data, sizeof(flush)); + if (err != 0) + err = EFAULT; } return err; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_delref */ +/* Returns: void */ +/* Parameters: type(I) - table type to operate on */ +/* ptr(I) - pointer to object to remove reference for */ +/* */ +/* This function organises calling the correct deref function for a given */ +/* type of object being passed into it. */ +/* ------------------------------------------------------------------------ */ void ip_lookup_deref(type, ptr) int type; void *ptr; @@ -522,13 +557,102 @@ void *ptr; } +/* ------------------------------------------------------------------------ */ +/* Function: ip_lookup_iterate */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to step through either hash tables or pools. */ +/* ------------------------------------------------------------------------ */ +int ip_lookup_iterate(data, uid, ctx) +void *data; +int uid; +void *ctx; +{ + ipflookupiter_t iter; + ipftoken_t *token; + int err; + SPL_INT(s); + + err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); + if (err != 0) + return err; + + if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) + return EINVAL; + + if (iter.ili_ival != IPFGENITER_LOOKUP) + return EINVAL; + + SPL_SCHED(s); + token = ipf_findtoken(iter.ili_key, uid, ctx); + if (token == NULL) { + RWLOCK_EXIT(&ipf_tokens); + SPL_X(s); + return ESRCH; + } + + switch (iter.ili_type) + { + case IPLT_POOL : + err = ip_pool_getnext(token, &iter); + break; + case IPLT_HASH : + err = fr_htable_getnext(token, &iter); + break; + default : + err = EINVAL; + break; + } + RWLOCK_EXIT(&ipf_tokens); + SPL_X(s); + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: iplookup_iterderef */ +/* Returns: int - 0 = success, else error */ +/* Parameters: data(I) - pointer to data from ioctl call */ +/* */ +/* Decodes ioctl request to remove a particular hash table or pool and */ +/* calls the relevant function to do the cleanup. */ +/* ------------------------------------------------------------------------ */ +void ip_lookup_iterderef(type, data) +u_32_t type; +void *data; +{ + iplookupiterkey_t key; + + key.ilik_key = type; + + if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) + return; + + switch (key.ilik_unstr.ilik_type) + { + case IPLT_HASH : + fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + case IPLT_POOL : + ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, + (int)key.ilik_unstr.ilik_unit, data); + break; + } +} + + + #else /* IPFILTER_LOOKUP */ /*ARGSUSED*/ -int ip_lookup_ioctl(data, cmd, mode) +int ip_lookup_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { return EIO; } diff --git a/sys/contrib/ipfilter/netinet/ip_lookup.h b/sys/contrib/ipfilter/netinet/ip_lookup.h index 953dde1..4b90655 100644 --- a/sys/contrib/ipfilter/netinet/ip_lookup.h +++ b/sys/contrib/ipfilter/netinet/ip_lookup.h @@ -33,6 +33,9 @@ typedef struct iplookupop { void *iplo_struct; } iplookupop_t; +#define LOOKUP_ANON 0x80000000 + + typedef struct iplookupflush { int iplf_type; /* IPLT_* */ int iplf_unit; /* IPL_LOG* */ @@ -55,9 +58,39 @@ typedef struct iplookuplink { #define IPLT_ANON 0x80000000 + +typedef union { + struct iplookupiterkey { + char ilik_ival; + u_char ilik_type; /* IPLT_* */ + u_char ilik_otype; + char ilik_unit; /* IPL_LOG* */ + } ilik_unstr; + u_32_t ilik_key; +} iplookupiterkey_t; + +typedef struct ipflookupiter { + int ili_nitems; + iplookupiterkey_t ili_lkey; + char ili_name[FR_GROUPLEN]; + void *ili_data; +} ipflookupiter_t; + +#define ili_key ili_lkey.ilik_key +#define ili_ival ili_lkey.ilik_unstr.ilik_ival +#define ili_unit ili_lkey.ilik_unstr.ilik_unit +#define ili_type ili_lkey.ilik_unstr.ilik_type +#define ili_otype ili_lkey.ilik_unstr.ilik_otype + +#define IPFLOOKUPITER_LIST 0 +#define IPFLOOKUPITER_NODE 1 + + extern int ip_lookup_init __P((void)); -extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern int ip_lookup_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); extern void ip_lookup_unload __P((void)); extern void ip_lookup_deref __P((int, void *)); +extern int ip_lookup_iterate __P((void *, int, void *)); +extern void ip_lookup_iterderef __P((u_32_t, void *)); #endif /* __IP_LOOKUP_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_pool.c b/sys/contrib/ipfilter/netinet/ip_pool.c index 3d19afb..b7e9946 100644 --- a/sys/contrib/ipfilter/netinet/ip_pool.c +++ b/sys/contrib/ipfilter/netinet/ip_pool.c @@ -55,9 +55,6 @@ struct file; #if defined(_KERNEL) && (defined(__osf__) || defined(AIX) || \ defined(__hpux) || defined(__sgi)) -# ifdef __osf__ -# include <net/radix.h> -# endif # include "radix_ipf_local.h" # define _RADIX_H_ #endif @@ -78,7 +75,7 @@ static int rn_freenode __P((struct radix_node *, void *)); #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.15 2005/11/13 15:38:37 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.20 2007/05/31 12:27:35 darrenr Exp $"; #endif #ifdef IPFILTER_LOOKUP @@ -90,6 +87,9 @@ static const char rcsid[] = "@(#)$Id: ip_pool.c,v 2.55.2.15 2005/11/13 15:38:37 # define RADIX_NODE_HEAD_UNLOCK(x) ; # endif +static void ip_pool_clearnodes __P((ip_pool_t *)); +static void *ip_pool_exists __P((int, char *)); + ip_pool_stat_t ipoolstat; ipfrwlock_t ip_poolrw; @@ -137,7 +137,7 @@ main(argc, argv) strcpy(op.iplo_name, "0"); if (ip_pool_create(&op) == 0) - ipo = ip_pool_find(0, "0"); + ipo = ip_pool_exists(0, "0"); a.adf_addr.in4.s_addr = 0x0a010203; b.adf_addr.in4.s_addr = 0xffffffff; @@ -262,18 +262,14 @@ int ip_pool_init() void ip_pool_fini() { ip_pool_t *p, *q; - iplookupop_t op; int i; ASSERT(rw_read_locked(&ipf_global.ipf_lk) == 0); for (i = 0; i <= IPL_LOGMAX; i++) { for (q = ip_pool_list[i]; (p = q) != NULL; ) { - op.iplo_unit = i; - (void)strncpy(op.iplo_name, p->ipo_name, - sizeof(op.iplo_name)); q = p->ipo_next; - (void) ip_pool_destroy(&op); + (void) ip_pool_destroy(i, p->ipo_name); } } @@ -307,8 +303,8 @@ iplookupop_t *op; stats.ipls_list[i] = ip_pool_list[i]; } else if (unit >= 0 && unit < IPL_LOGSIZE) { if (op->iplo_name[0] != '\0') - stats.ipls_list[unit] = ip_pool_find(unit, - op->iplo_name); + stats.ipls_list[unit] = ip_pool_exists(unit, + op->iplo_name); else stats.ipls_list[unit] = ip_pool_list[unit]; } else @@ -319,16 +315,15 @@ iplookupop_t *op; } - /* ------------------------------------------------------------------------ */ -/* Function: ip_pool_find */ +/* Function: ip_pool_exists */ /* Returns: int - 0 = success, else error */ /* Parameters: ipo(I) - pointer to the pool getting the new node. */ /* */ /* Find a matching pool inside the collection of pools for a particular */ /* device, indicated by the unit number. */ /* ------------------------------------------------------------------------ */ -void *ip_pool_find(unit, name) +static void *ip_pool_exists(unit, name) int unit; char *name; { @@ -342,6 +337,29 @@ char *name; /* ------------------------------------------------------------------------ */ +/* Function: ip_pool_find */ +/* Returns: int - 0 = success, else error */ +/* Parameters: ipo(I) - pointer to the pool getting the new node. */ +/* */ +/* Find a matching pool inside the collection of pools for a particular */ +/* device, indicated by the unit number. If it is marked for deletion then */ +/* pretend it does not exist. */ +/* ------------------------------------------------------------------------ */ +void *ip_pool_find(unit, name) +int unit; +char *name; +{ + ip_pool_t *p; + + p = ip_pool_exists(unit, name); + if ((p != NULL) && (p->ipo_flags & IPOOL_DELETE)) + return NULL; + + return p; +} + + +/* ------------------------------------------------------------------------ */ /* Function: ip_pool_findeq */ /* Returns: int - 0 = success, else error */ /* Parameters: ipo(I) - pointer to the pool getting the new node. */ @@ -375,9 +393,9 @@ addrfamily_t *addr, *mask; /* */ /* Search the pool for a given address and return a search result. */ /* ------------------------------------------------------------------------ */ -int ip_pool_search(tptr, version, dptr) +int ip_pool_search(tptr, ipversion, dptr) void *tptr; -int version; +int ipversion; void *dptr; { struct radix_node *rn; @@ -397,11 +415,11 @@ void *dptr; bzero(&v, sizeof(v)); v.adf_len = offsetof(addrfamily_t, adf_addr); - if (version == 4) { + if (ipversion == 4) { v.adf_len += sizeof(addr->in4); v.adf_addr.in4 = addr->in4; #ifdef USE_INET6 - } else if (version == 6) { + } else if (ipversion == 6) { v.adf_len += sizeof(addr->in6); v.adf_addr.in6 = addr->in6; #endif @@ -475,6 +493,7 @@ int info; return ENOMEM; } + x->ipn_ref = 1; x->ipn_next = ipo->ipo_list; x->ipn_pnext = &ipo->ipo_list; if (ipo->ipo_list != NULL) @@ -498,6 +517,10 @@ int info; /* when being inserted - assume this has already been done. If the pool is */ /* marked as being anonymous, give it a new, unique, identifier. Call any */ /* other functions required to initialise the structure. */ +/* */ +/* If the structure is flagged for deletion then reset the flag and return, */ +/* as this likely means we've tried to free a pool that is in use (flush) */ +/* and now want to repopulate it with "new" data. */ /* ------------------------------------------------------------------------ */ int ip_pool_create(op) iplookupop_t *op; @@ -508,23 +531,37 @@ iplookupop_t *op; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - KMALLOC(h, ip_pool_t *); - if (h == NULL) - return ENOMEM; - bzero(h, sizeof(*h)); + unit = op->iplo_unit; - if (rn_inithead((void **)&h->ipo_head, - offsetof(addrfamily_t, adf_addr) << 3) == 0) { - KFREE(h); - return ENOMEM; - } + if ((op->iplo_arg & LOOKUP_ANON) == 0) + h = ip_pool_exists(unit, op->iplo_name); + else + h = NULL; - unit = op->iplo_unit; + if (h != NULL) { + if ((h->ipo_flags & IPOOL_DELETE) != 0) { + h->ipo_flags &= ~IPOOL_DELETE; + return 0; + } + return EEXIST; + } else { + KMALLOC(h, ip_pool_t *); + if (h == NULL) + return ENOMEM; + bzero(h, sizeof(*h)); + + if (rn_inithead((void **)&h->ipo_head, + offsetof(addrfamily_t, adf_addr) << 3) == 0) { + KFREE(h); + return ENOMEM; + } + } - if ((op->iplo_arg & IPOOL_ANON) != 0) { + if ((op->iplo_arg & LOOKUP_ANON) != 0) { ip_pool_t *p; - poolnum = IPOOL_ANON; + h->ipo_flags |= IPOOL_ANON; + poolnum = LOOKUP_ANON; #if defined(SNPRINTF) && defined(_KERNEL) SNPRINTF(name, sizeof(name), "%x", poolnum); @@ -549,19 +586,21 @@ iplookupop_t *op; (void)strncpy(h->ipo_name, name, sizeof(h->ipo_name)); (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); } else { - (void) strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); + (void)strncpy(h->ipo_name, op->iplo_name, sizeof(h->ipo_name)); } - h->ipo_ref = 1; - h->ipo_list = NULL; - h->ipo_unit = unit; - h->ipo_next = ip_pool_list[unit]; - if (ip_pool_list[unit] != NULL) - ip_pool_list[unit]->ipo_pnext = &h->ipo_next; - h->ipo_pnext = &ip_pool_list[unit]; - ip_pool_list[unit] = h; - - ipoolstat.ipls_pools++; + if ((h->ipo_flags & IPOOL_DELETE) == 0) { + h->ipo_ref = 1; + h->ipo_list = NULL; + h->ipo_unit = unit; + h->ipo_next = ip_pool_list[unit]; + if (ip_pool_list[unit] != NULL) + ip_pool_list[unit]->ipo_pnext = &h->ipo_next; + h->ipo_pnext = &ip_pool_list[unit]; + ip_pool_list[unit] = h; + + ipoolstat.ipls_pools++; + } return 0; } @@ -574,36 +613,26 @@ iplookupop_t *op; /* ipe(I) - address being deleted as a node */ /* Locks: WRITE(ip_poolrw) */ /* */ -/* Add another node to the pool given by ipo. The three parameters passed */ -/* in (addr, mask, info) shold all be stored in the node. */ +/* Remove a node from the pool given by ipo. */ /* ------------------------------------------------------------------------ */ int ip_pool_remove(ipo, ipe) ip_pool_t *ipo; ip_pool_node_t *ipe; { - ip_pool_node_t **ipp, *n; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); - for (ipp = &ipo->ipo_list; (n = *ipp) != NULL; ipp = &n->ipn_next) { - if (ipe == n) { - *n->ipn_pnext = n->ipn_next; - if (n->ipn_next) - n->ipn_next->ipn_pnext = n->ipn_pnext; - break; - } - } - - if (n == NULL) - return ENOENT; + if (ipe->ipn_pnext != NULL) + *ipe->ipn_pnext = ipe->ipn_next; + if (ipe->ipn_next != NULL) + ipe->ipn_next->ipn_pnext = ipe->ipn_pnext; RADIX_NODE_HEAD_LOCK(ipo->ipo_head); - ipo->ipo_head->rnh_deladdr(&n->ipn_addr, &n->ipn_mask, + ipo->ipo_head->rnh_deladdr(&ipe->ipn_addr, &ipe->ipn_mask, ipo->ipo_head); RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); - KFREE(n); - ipoolstat.ipls_nodes--; + ip_pool_node_deref(ipe); return 0; } @@ -616,23 +645,28 @@ ip_pool_node_t *ipe; /* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ /* */ /* Search for a pool using paramters passed in and if it's not otherwise */ -/* busy, free it. */ +/* busy, free it. If it is busy, clear all of its nodes, mark it for being */ +/* deleted and return an error saying it is busy. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ -int ip_pool_destroy(op) -iplookupop_t *op; +int ip_pool_destroy(unit, name) +int unit; +char *name; { ip_pool_t *ipo; - ipo = ip_pool_find(op->iplo_unit, op->iplo_name); + ipo = ip_pool_exists(unit, name); if (ipo == NULL) return ESRCH; - if (ipo->ipo_ref != 1) - return EBUSY; + if (ipo->ipo_ref != 1) { + ip_pool_clearnodes(ipo); + ipo->ipo_flags |= IPOOL_DELETE; + return 0; + } ip_pool_free(ipo); return 0; @@ -648,7 +682,7 @@ iplookupop_t *op; /* Free all pools associated with the device that matches the unit number */ /* passed in with operation. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ @@ -669,7 +703,7 @@ iplookupflush_t *fp; (void)strncpy(op.iplo_name, p->ipo_name, sizeof(op.iplo_name)); q = p->ipo_next; - err = ip_pool_destroy(&op); + err = ip_pool_destroy(op.iplo_unit, op.iplo_name); if (err == 0) num++; else @@ -690,13 +724,37 @@ iplookupflush_t *fp; /* all of the address information stored in it, including any tree data */ /* structures also allocated. */ /* */ -/* NOTE: Because this function is called out of ipldetach() where ip_poolrw */ +/* NOTE: Because this function is called out of ipfdetach() where ip_poolrw */ /* may not be initialised, we can't use an ASSERT to enforce the locking */ /* assertion that one of the two (ip_poolrw,ipf_global) is held. */ /* ------------------------------------------------------------------------ */ void ip_pool_free(ipo) ip_pool_t *ipo; { + + ip_pool_clearnodes(ipo); + + if (ipo->ipo_next != NULL) + ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; + *ipo->ipo_pnext = ipo->ipo_next; + rn_freehead(ipo->ipo_head); + KFREE(ipo); + + ipoolstat.ipls_pools--; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_clearnodes */ +/* Returns: void */ +/* Parameters: ipo(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) or WRITE(ipf_global) */ +/* */ +/* Deletes all nodes stored in a pool structure. */ +/* ------------------------------------------------------------------------ */ +static void ip_pool_clearnodes(ipo) +ip_pool_t *ipo; +{ ip_pool_node_t *n; RADIX_NODE_HEAD_LOCK(ipo->ipo_head); @@ -715,13 +773,6 @@ ip_pool_t *ipo; RADIX_NODE_HEAD_UNLOCK(ipo->ipo_head); ipo->ipo_list = NULL; - if (ipo->ipo_next != NULL) - ipo->ipo_next->ipo_pnext = ipo->ipo_pnext; - *ipo->ipo_pnext = ipo->ipo_next; - rn_freehead(ipo->ipo_head); - KFREE(ipo); - - ipoolstat.ipls_pools--; } @@ -741,8 +792,179 @@ ip_pool_t *ipo; ASSERT(rw_read_locked(&ip_poolrw.ipf_lk) == 0); ipo->ipo_ref--; + if (ipo->ipo_ref == 0) ip_pool_free(ipo); + + else if ((ipo->ipo_ref == 1) && (ipo->ipo_flags & IPOOL_DELETE)) + ip_pool_destroy(ipo->ipo_unit, ipo->ipo_name); +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_node_deref */ +/* Returns: void */ +/* Parameters: ipn(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) */ +/* */ +/* Drop a reference to the pool node passed in and if we're the last, free */ +/* it all up and adjust the stats accordingly. */ +/* ------------------------------------------------------------------------ */ +void ip_pool_node_deref(ipn) +ip_pool_node_t *ipn; +{ + + ipn->ipn_ref--; + + if (ipn->ipn_ref == 0) { + KFREE(ipn); + ipoolstat.ipls_nodes--; + } +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_getnext */ +/* Returns: void */ +/* Parameters: token(I) - pointer to pool structure */ +/* Parameters: ilp(IO) - pointer to pool iterating structure */ +/* */ +/* ------------------------------------------------------------------------ */ +int ip_pool_getnext(token, ilp) +ipftoken_t *token; +ipflookupiter_t *ilp; +{ + ip_pool_node_t *node, zn, *nextnode; + ip_pool_t *ipo, zp, *nextipo; + int err; + + err = 0; + node = NULL; + nextnode = NULL; + ipo = NULL; + nextipo = NULL; + + READ_ENTER(&ip_poolrw); + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + ipo = token->ipt_data; + if (ipo == NULL) { + nextipo = ip_pool_list[(int)ilp->ili_unit]; + } else { + nextipo = ipo->ipo_next; + } + + if (nextipo != NULL) { + ATOMIC_INC(nextipo->ipo_ref); + if (nextipo->ipo_next == NULL) + token->ipt_alive = 0; + } else { + bzero((char *)&zp, sizeof(zp)); + nextipo = &zp; + } + break; + + case IPFLOOKUPITER_NODE : + node = token->ipt_data; + if (node == NULL) { + ipo = ip_pool_exists(ilp->ili_unit, ilp->ili_name); + if (ipo == NULL) + err = ESRCH; + else { + nextnode = ipo->ipo_list; + ipo = NULL; + } + } else { + nextnode = node->ipn_next; + } + + if (nextnode != NULL) { + ATOMIC_INC(nextnode->ipn_ref); + if (nextnode->ipn_next == NULL) + token->ipt_alive = 0; + } else { + bzero((char *)&zn, sizeof(zn)); + nextnode = &zn; + } + break; + default : + err = EINVAL; + break; + } + + RWLOCK_EXIT(&ip_poolrw); + + if (err != 0) + return err; + + switch (ilp->ili_otype) + { + case IPFLOOKUPITER_LIST : + if (ipo != NULL) { + WRITE_ENTER(&ip_poolrw); + ip_pool_deref(ipo); + RWLOCK_EXIT(&ip_poolrw); + } + token->ipt_data = nextipo; + err = COPYOUT(nextipo, ilp->ili_data, sizeof(*nextipo)); + if (err != 0) + err = EFAULT; + break; + + case IPFLOOKUPITER_NODE : + if (node != NULL) { + WRITE_ENTER(&ip_poolrw); + ip_pool_node_deref(node); + RWLOCK_EXIT(&ip_poolrw); + } + token->ipt_data = nextnode; + err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); + if (err != 0) + err = EFAULT; + break; + } + + return err; +} + + +/* ------------------------------------------------------------------------ */ +/* Function: ip_pool_iterderef */ +/* Returns: void */ +/* Parameters: ipn(I) - pointer to pool structure */ +/* Locks: WRITE(ip_poolrw) */ +/* */ +/* ------------------------------------------------------------------------ */ +void ip_pool_iterderef(otype, unit, data) +u_int otype; +int unit; +void *data; +{ + + if (data == NULL) + return; + + if (unit < 0 || unit > IPL_LOGMAX) + return; + + switch (otype) + { + case IPFLOOKUPITER_LIST : + WRITE_ENTER(&ip_poolrw); + ip_pool_deref((ip_pool_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + + case IPFLOOKUPITER_NODE : + WRITE_ENTER(&ip_poolrw); + ip_pool_node_deref((ip_pool_node_t *)data); + RWLOCK_EXIT(&ip_poolrw); + break; + default : + break; + } } @@ -780,5 +1002,4 @@ rn_freehead(rnh) Free(rnh); } # endif - #endif /* IPFILTER_LOOKUP */ diff --git a/sys/contrib/ipfilter/netinet/ip_pool.h b/sys/contrib/ipfilter/netinet/ip_pool.h index 3731fe9..927276f 100644 --- a/sys/contrib/ipfilter/netinet/ip_pool.h +++ b/sys/contrib/ipfilter/netinet/ip_pool.h @@ -3,7 +3,7 @@ * * See the IPFILTER.LICENCE file for details on licencing. * - * $Id: ip_pool.h,v 2.26.2.3 2005/06/12 07:18:27 darrenr Exp $ + * $Id: ip_pool.h,v 2.26.2.5 2007/01/14 14:06:12 darrenr Exp $ */ #ifndef __IP_POOL_H__ @@ -35,8 +35,9 @@ typedef struct ip_pool_node { addrfamily_t ipn_addr; addrfamily_t ipn_mask; int ipn_info; - char ipn_name[FR_GROUPLEN]; - u_long ipn_hits; + int ipn_ref; +char ipn_name[FR_GROUPLEN]; +u_long ipn_hits; struct ip_pool_node *ipn_next, **ipn_pnext; } ip_pool_node_t; @@ -53,7 +54,8 @@ typedef struct ip_pool_s { char ipo_name[FR_GROUPLEN]; } ip_pool_t; -#define IPOOL_ANON 0x80000000 +#define IPOOL_DELETE 0x01 +#define IPOOL_ANON 0x02 typedef struct ip_pool_stat { @@ -73,13 +75,16 @@ extern void ip_pool_fini __P((void)); extern int ip_pool_create __P((iplookupop_t *)); extern int ip_pool_insert __P((ip_pool_t *, i6addr_t *, i6addr_t *, int)); extern int ip_pool_remove __P((ip_pool_t *, ip_pool_node_t *)); -extern int ip_pool_destroy __P((iplookupop_t *)); +extern int ip_pool_destroy __P((int, char *)); extern void ip_pool_free __P((ip_pool_t *)); extern void ip_pool_deref __P((ip_pool_t *)); +extern void ip_pool_node_deref __P((ip_pool_node_t *)); extern void *ip_pool_find __P((int, char *)); extern ip_pool_node_t *ip_pool_findeq __P((ip_pool_t *, addrfamily_t *, addrfamily_t *)); extern int ip_pool_flush __P((iplookupflush_t *)); extern int ip_pool_statistics __P((iplookupop_t *)); +extern int ip_pool_getnext __P((ipftoken_t *, ipflookupiter_t *)); +extern void ip_pool_iterderef __P((u_int, int, void *)); #endif /* __IP_POOL_H__ */ diff --git a/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c b/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c index 2ef2e17..3924d4b 100644 --- a/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_pptp_pxy.c @@ -4,7 +4,7 @@ * Simple PPTP transparent proxy for in-kernel use. For use with the NAT * code. * - * $Id: ip_pptp_pxy.c,v 2.10.2.13 2006/03/17 10:40:05 darrenr Exp $ + * $Id: ip_pptp_pxy.c,v 2.10.2.15 2006/10/31 12:11:23 darrenr Exp $ * */ #define IPF_PPTP_PROXY @@ -78,6 +78,9 @@ void ippr_pptp_fini() /* * Setup for a new PPTP proxy. + * + * NOTE: The printf's are broken up with %s in them to prevent them being + * optimised into puts statements on FreeBSD (this doesn't exist in the kernel) */ int ippr_pptp_new(fin, aps, nat) fr_info_t *fin; @@ -220,7 +223,7 @@ pptp_pxy_t *pptp; pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0); if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } ip->ip_p = p; return; diff --git a/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c index 112e4da..4350bf4 100644 --- a/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c +++ b/sys/contrib/ipfilter/netinet/ip_rpcb_pxy.c @@ -37,7 +37,7 @@ * o The enclosed hack of STREAMS support is pretty sick and most likely * broken. * - * $Id: ip_rpcb_pxy.c,v 2.25.2.3 2005/02/04 10:22:56 darrenr Exp $ + * $Id: ip_rpcb_pxy.c,v 2.25.2.6 2007/01/17 11:34:54 darrenr Exp $ */ #define IPF_RPCB_PROXY @@ -290,6 +290,7 @@ ippr_rpcb_out(fin, aps, nat) /* Perform basic variable initialization. */ rs = (rpcb_session_t *)aps->aps_data; + rx = NULL; m = fin->fin_m; off = (char *)fin->fin_dp - (char *)fin->fin_ip; @@ -307,6 +308,8 @@ ippr_rpcb_out(fin, aps, nat) COPYDATA(m, off, dlen, (caddr_t)&rm->rm_msgbuf); rm->rm_buflen = dlen; + rx = NULL; /* XXX gcc */ + /* Send off to decode reply. */ rv = ippr_rpcb_decoderep(fin, nat, rs, rm, &rx); @@ -1156,6 +1159,8 @@ ippr_rpcb_getnat(fin, nat, proto, port) /* Generate dummy fr_info */ bcopy((char *)fin, (char *)&fi, sizeof(fi)); + fi.fin_state = NULL; + fi.fin_nat = NULL; fi.fin_out = 0; fi.fin_src = fin->fin_dst; fi.fin_dst = nat->nat_outip; @@ -1191,8 +1196,9 @@ ippr_rpcb_getnat(fin, nat, proto, port) * no use for this lock, so simply unlock it if necessary. */ is = fr_stlookup(&fi, &tcp, NULL); - if (is != NULL) + if (is != NULL) { RWLOCK_EXIT(&ipf_state); + } RWLOCK_EXIT(&ipf_nat); @@ -1271,7 +1277,7 @@ ippr_rpcb_getnat(fin, nat, proto, port) return(-1); } if (fi.fin_state != NULL) - fr_statederef(&fi, (ipstate_t **)&fi.fin_state); + fr_statederef((ipstate_t **)&fi.fin_state); } return(0); diff --git a/sys/contrib/ipfilter/netinet/ip_scan.c b/sys/contrib/ipfilter/netinet/ip_scan.c index 13a5a60..ad37216 100644 --- a/sys/contrib/ipfilter/netinet/ip_scan.c +++ b/sys/contrib/ipfilter/netinet/ip_scan.c @@ -58,7 +58,7 @@ struct file; #if !defined(lint) static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.6 2006/03/26 23:06:49 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ip_scan.c,v 2.40.2.9 2007/03/13 09:42:05 darrenr Exp $"; #endif #ifdef IPFILTER_SCAN /* endif at bottom of file */ @@ -115,8 +115,10 @@ caddr_t data; return ENOMEM; err = copyinptr(data, isc, sizeof(*isc)); - if (err) + if (err) { + KFREE(isc); return err; + } WRITE_ENTER(&ipsc_rwlock); @@ -230,20 +232,17 @@ struct ipstate *is; fr = is->is_rule; if (fr) { i = fr->fr_isc; - if (!i || (i != (ipscan_t *)-1)) { + if ((i != NULL) && (i != (ipscan_t *)-1)) { is->is_isc = i; - if (i) { - ATOMIC_INC32(i->ipsc_sref); - if (i->ipsc_clen) - is->is_flags |= IS_SC_CLIENT; - else - is->is_flags |= IS_SC_MATCHC; - if (i->ipsc_slen) - is->is_flags |= IS_SC_SERVER; - else - is->is_flags |= IS_SC_MATCHS; - } else - is->is_flags |= (IS_SC_CLIENT|IS_SC_SERVER); + ATOMIC_INC32(i->ipsc_sref); + if (i->ipsc_clen) + is->is_flags |= IS_SC_CLIENT; + else + is->is_flags |= IS_SC_MATCHC; + if (i->ipsc_slen) + is->is_flags |= IS_SC_SERVER; + else + is->is_flags |= IS_SC_MATCHS; } } RWLOCK_EXIT(&ipsc_rwlock); @@ -568,10 +567,11 @@ ipstate_t *is; } -int fr_scan_ioctl(data, cmd, mode) +int fr_scan_ioctl(data, cmd, mode, uid, ctx) caddr_t data; ioctlcmd_t cmd; -int mode; +int mode, uid; +void *ctx; { ipscanstat_t ipscs; int err = 0; diff --git a/sys/contrib/ipfilter/netinet/ip_scan.h b/sys/contrib/ipfilter/netinet/ip_scan.h index d857453..4772d28 100644 --- a/sys/contrib/ipfilter/netinet/ip_scan.h +++ b/sys/contrib/ipfilter/netinet/ip_scan.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_scan.h,v 2.9.2.1 2005/06/12 07:18:29 darrenr Exp $ + * $Id: ip_scan.h,v 2.9.2.2 2006/07/14 06:12:19 darrenr Exp $ */ #ifndef __IP_SCAN_H__ @@ -94,7 +94,7 @@ typedef struct ipscanstat { } ipscanstat_t; -extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int)); +extern int fr_scan_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); extern int ipsc_init __P((void)); extern int ipsc_attachis __P((struct ipstate *)); extern int ipsc_attachfr __P((struct frentry *)); diff --git a/sys/contrib/ipfilter/netinet/ip_sync.h b/sys/contrib/ipfilter/netinet/ip_sync.h index 76862f7..8104db3 100644 --- a/sys/contrib/ipfilter/netinet/ip_sync.h +++ b/sys/contrib/ipfilter/netinet/ip_sync.h @@ -4,7 +4,7 @@ * See the IPFILTER.LICENCE file for details on licencing. * * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_sync.h,v 2.11.2.3 2006/03/19 14:59:39 darrenr Exp $ + * $Id: ip_sync.h,v 2.11.2.4 2006/07/14 06:12:20 darrenr Exp $ */ #ifndef __IP_SYNC_H__ @@ -102,16 +102,16 @@ typedef struct syncupdent { /* 28 or 32 bytes */ extern synclogent_t synclog[SYNCLOG_SZ]; -extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int)); -extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *)); -extern void ipfsync_del __P((synclist_t *)); -extern void ipfsync_update __P((int, fr_info_t *, synclist_t *)); -extern int ipfsync_init __P((void)); -extern int ipfsync_nat __P((synchdr_t *sp, void *data)); -extern int ipfsync_state __P((synchdr_t *sp, void *data)); -extern int ipfsync_read __P((struct uio *uio)); -extern int ipfsync_write __P((struct uio *uio)); -extern int ipfsync_canread __P((void)); -extern int ipfsync_canwrite __P((void)); +extern int fr_sync_ioctl __P((caddr_t, ioctlcmd_t, int, int, void *)); +extern synclist_t *ipfsync_new __P((int, fr_info_t *, void *)); +extern void ipfsync_del __P((synclist_t *)); +extern void ipfsync_update __P((int, fr_info_t *, synclist_t *)); +extern int ipfsync_init __P((void)); +extern int ipfsync_nat __P((synchdr_t *sp, void *data)); +extern int ipfsync_state __P((synchdr_t *sp, void *data)); +extern int ipfsync_read __P((struct uio *uio)); +extern int ipfsync_write __P((struct uio *uio)); +extern int ipfsync_canread __P((void)); +extern int ipfsync_canwrite __P((void)); #endif /* IP_SYNC */ |