1ab25eeb5Syz155240 /* 2ab25eeb5Syz155240 * Copyright (C) 2002-2003 by Darren Reed. 3ab25eeb5Syz155240 * 4ab25eeb5Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 5ab25eeb5Syz155240 * 6*bb1d9de5SJohn Ojemann * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 7ab25eeb5Syz155240 * Use is subject to license terms. 8ab25eeb5Syz155240 */ 9ab25eeb5Syz155240 10ab25eeb5Syz155240 #if defined(KERNEL) || defined(_KERNEL) 11ab25eeb5Syz155240 # undef KERNEL 12ab25eeb5Syz155240 # undef _KERNEL 13ab25eeb5Syz155240 # define KERNEL 1 14ab25eeb5Syz155240 # define _KERNEL 1 15ab25eeb5Syz155240 #endif 16ab25eeb5Syz155240 #if defined(__osf__) 17ab25eeb5Syz155240 # define _PROTO_NET_H_ 18ab25eeb5Syz155240 #endif 19ab25eeb5Syz155240 #include <sys/param.h> 20ab25eeb5Syz155240 #include <sys/errno.h> 21ab25eeb5Syz155240 #include <sys/types.h> 22ab25eeb5Syz155240 #include <sys/time.h> 23ab25eeb5Syz155240 #include <sys/file.h> 24ab25eeb5Syz155240 #if __FreeBSD_version >= 220000 && defined(_KERNEL) 25ab25eeb5Syz155240 # include <sys/fcntl.h> 26ab25eeb5Syz155240 # include <sys/filio.h> 27ab25eeb5Syz155240 #else 28ab25eeb5Syz155240 # include <sys/ioctl.h> 29ab25eeb5Syz155240 #endif 30ab25eeb5Syz155240 #if !defined(_KERNEL) 31ab25eeb5Syz155240 # include <string.h> 32ab25eeb5Syz155240 # define _KERNEL 33ab25eeb5Syz155240 # ifdef __OpenBSD__ 34ab25eeb5Syz155240 struct file; 35ab25eeb5Syz155240 # endif 36ab25eeb5Syz155240 # include <sys/uio.h> 37ab25eeb5Syz155240 # undef _KERNEL 38ab25eeb5Syz155240 #endif 39ab25eeb5Syz155240 #include <sys/socket.h> 40ab25eeb5Syz155240 #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL) 41ab25eeb5Syz155240 # ifdef __osf__ 42ab25eeb5Syz155240 # include <net/radix.h> 43ab25eeb5Syz155240 # endif 44ab25eeb5Syz155240 # include "radix_ipf_local.h" 45ab25eeb5Syz155240 # define _RADIX_H_ 46ab25eeb5Syz155240 #endif 47ab25eeb5Syz155240 #include <net/if.h> 48ab25eeb5Syz155240 #if defined(__FreeBSD__) 49ab25eeb5Syz155240 # include <sys/cdefs.h> 50ab25eeb5Syz155240 # include <sys/proc.h> 51ab25eeb5Syz155240 #endif 52ab25eeb5Syz155240 #if defined(_KERNEL) 53ab25eeb5Syz155240 # include <sys/systm.h> 54ab25eeb5Syz155240 # if !defined(__SVR4) && !defined(__svr4__) 55ab25eeb5Syz155240 # include <sys/mbuf.h> 56ab25eeb5Syz155240 # endif 57ab25eeb5Syz155240 #endif 58ab25eeb5Syz155240 #include <netinet/in.h> 59ab25eeb5Syz155240 60ab25eeb5Syz155240 #include "netinet/ip_compat.h" 61ab25eeb5Syz155240 #include "netinet/ip_fil.h" 62ab25eeb5Syz155240 #include "netinet/ip_pool.h" 63ab25eeb5Syz155240 #include "netinet/ip_htable.h" 64ab25eeb5Syz155240 #include "netinet/ip_lookup.h" 65f4b3ec61Sdh155122 #include "netinet/ipf_stack.h" 66ab25eeb5Syz155240 /* END OF INCLUDES */ 67ab25eeb5Syz155240 68ab25eeb5Syz155240 #if !defined(lint) 69ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $"; 70ab25eeb5Syz155240 #endif 71ab25eeb5Syz155240 72ab25eeb5Syz155240 #ifdef IPFILTER_LOOKUP 73f4b3ec61Sdh155122 static int iplookup_addnode __P((caddr_t, ipf_stack_t *)); 74f4b3ec61Sdh155122 static int iplookup_delnode __P((caddr_t data, ipf_stack_t *)); 75f4b3ec61Sdh155122 static int iplookup_addtable __P((caddr_t, ipf_stack_t *)); 76f4b3ec61Sdh155122 static int iplookup_deltable __P((caddr_t, ipf_stack_t *)); 77f4b3ec61Sdh155122 static int iplookup_stats __P((caddr_t, ipf_stack_t *)); 78f4b3ec61Sdh155122 static int iplookup_flush __P((caddr_t, ipf_stack_t *)); 79ab25eeb5Syz155240 80ab25eeb5Syz155240 81ab25eeb5Syz155240 82ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 83ab25eeb5Syz155240 /* Function: iplookup_init */ 84ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 85ab25eeb5Syz155240 /* Parameters: Nil */ 86ab25eeb5Syz155240 /* */ 87ab25eeb5Syz155240 /* Initialise all of the subcomponents of the lookup infrstructure. */ 88ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 89f4b3ec61Sdh155122 int ip_lookup_init(ifs) 90f4b3ec61Sdh155122 ipf_stack_t *ifs; 91ab25eeb5Syz155240 { 92ab25eeb5Syz155240 93f4b3ec61Sdh155122 if (ip_pool_init(ifs) == -1) 94ab25eeb5Syz155240 return -1; 95ab25eeb5Syz155240 96f4b3ec61Sdh155122 RWLOCK_INIT(&ifs->ifs_ip_poolrw, "ip pool rwlock"); 97ab25eeb5Syz155240 98f4b3ec61Sdh155122 ifs->ifs_ip_lookup_inited = 1; 99f4b3ec61Sdh155122 ifs->ifs_ipftokenhead = NULL; 100f4b3ec61Sdh155122 ifs->ifs_ipftokentail = &ifs->ifs_ipftokenhead; 101ab25eeb5Syz155240 return 0; 102ab25eeb5Syz155240 } 103ab25eeb5Syz155240 104ab25eeb5Syz155240 105ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 106ab25eeb5Syz155240 /* Function: iplookup_unload */ 107ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 108ab25eeb5Syz155240 /* Parameters: Nil */ 109ab25eeb5Syz155240 /* */ 110ab25eeb5Syz155240 /* Free up all pool related memory that has been allocated whilst IPFilter */ 111ab25eeb5Syz155240 /* has been running. Also, do any other deinitialisation required such */ 112ab25eeb5Syz155240 /* ip_lookup_init() can be called again, safely. */ 113ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 114f4b3ec61Sdh155122 void ip_lookup_unload(ifs) 115f4b3ec61Sdh155122 ipf_stack_t *ifs; 116ab25eeb5Syz155240 { 117f4b3ec61Sdh155122 ip_pool_fini(ifs); 118f4b3ec61Sdh155122 fr_htable_unload(ifs); 119ab25eeb5Syz155240 120f4b3ec61Sdh155122 if (ifs->ifs_ip_lookup_inited == 1) { 121f4b3ec61Sdh155122 RW_DESTROY(&ifs->ifs_ip_poolrw); 122f4b3ec61Sdh155122 ifs->ifs_ip_lookup_inited = 0; 123ab25eeb5Syz155240 } 124ab25eeb5Syz155240 } 125ab25eeb5Syz155240 126ab25eeb5Syz155240 127ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 128ab25eeb5Syz155240 /* Function: iplookup_ioctl */ 129ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 130ab25eeb5Syz155240 /* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */ 131ab25eeb5Syz155240 /* space. */ 132ab25eeb5Syz155240 /* cmd(I) - ioctl command number */ 133ab25eeb5Syz155240 /* mode(I) - file mode bits used with open */ 134ab25eeb5Syz155240 /* */ 135ab25eeb5Syz155240 /* Handle ioctl commands sent to the ioctl device. For the most part, this */ 136ab25eeb5Syz155240 /* involves just calling another function to handle the specifics of each */ 137ab25eeb5Syz155240 /* command. */ 138ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 139f4b3ec61Sdh155122 int ip_lookup_ioctl(data, cmd, mode, uid, ctx, ifs) 140ab25eeb5Syz155240 caddr_t data; 141ab25eeb5Syz155240 ioctlcmd_t cmd; 142f4b3ec61Sdh155122 int mode, uid; 143f4b3ec61Sdh155122 void *ctx; 144f4b3ec61Sdh155122 ipf_stack_t *ifs; 145ab25eeb5Syz155240 { 146ab25eeb5Syz155240 int err; 147ab25eeb5Syz155240 SPL_INT(s); 148ab25eeb5Syz155240 149ab25eeb5Syz155240 mode = mode; /* LINT */ 150ab25eeb5Syz155240 151ab25eeb5Syz155240 SPL_NET(s); 152ab25eeb5Syz155240 153ab25eeb5Syz155240 switch (cmd) 154ab25eeb5Syz155240 { 155ab25eeb5Syz155240 case SIOCLOOKUPADDNODE : 156ab25eeb5Syz155240 case SIOCLOOKUPADDNODEW : 157f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 158f4b3ec61Sdh155122 err = iplookup_addnode(data, ifs); 159f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 160ab25eeb5Syz155240 break; 161ab25eeb5Syz155240 162ab25eeb5Syz155240 case SIOCLOOKUPDELNODE : 163ab25eeb5Syz155240 case SIOCLOOKUPDELNODEW : 164f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 165f4b3ec61Sdh155122 err = iplookup_delnode(data, ifs); 166f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 167ab25eeb5Syz155240 break; 168ab25eeb5Syz155240 169ab25eeb5Syz155240 case SIOCLOOKUPADDTABLE : 170f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 171f4b3ec61Sdh155122 err = iplookup_addtable(data, ifs); 172f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 173ab25eeb5Syz155240 break; 174ab25eeb5Syz155240 175ab25eeb5Syz155240 case SIOCLOOKUPDELTABLE : 176f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 177f4b3ec61Sdh155122 err = iplookup_deltable(data, ifs); 178f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 179ab25eeb5Syz155240 break; 180ab25eeb5Syz155240 181ab25eeb5Syz155240 case SIOCLOOKUPSTAT : 182ab25eeb5Syz155240 case SIOCLOOKUPSTATW : 183f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 184f4b3ec61Sdh155122 err = iplookup_stats(data, ifs); 185f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 186ab25eeb5Syz155240 break; 187ab25eeb5Syz155240 188ab25eeb5Syz155240 case SIOCLOOKUPFLUSH : 189f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 190f4b3ec61Sdh155122 err = iplookup_flush(data, ifs); 191f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 192f4b3ec61Sdh155122 break; 193f4b3ec61Sdh155122 194f4b3ec61Sdh155122 case SIOCLOOKUPITER : 195f4b3ec61Sdh155122 err = ip_lookup_iterate(data, uid, ctx, ifs); 196ab25eeb5Syz155240 break; 197ab25eeb5Syz155240 198ab25eeb5Syz155240 default : 199ab25eeb5Syz155240 err = EINVAL; 200ab25eeb5Syz155240 break; 201ab25eeb5Syz155240 } 202ab25eeb5Syz155240 SPL_X(s); 203ab25eeb5Syz155240 return err; 204ab25eeb5Syz155240 } 205ab25eeb5Syz155240 206ab25eeb5Syz155240 207ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 208ab25eeb5Syz155240 /* Function: iplookup_addnode */ 209ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 210ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 211ab25eeb5Syz155240 /* */ 212ab25eeb5Syz155240 /* Add a new data node to a lookup structure. First, check to see if the */ 213ab25eeb5Syz155240 /* parent structure refered to by name exists and if it does, then go on to */ 214ab25eeb5Syz155240 /* add a node to it. */ 215ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 216f4b3ec61Sdh155122 static int iplookup_addnode(data, ifs) 217ab25eeb5Syz155240 caddr_t data; 218f4b3ec61Sdh155122 ipf_stack_t *ifs; 219ab25eeb5Syz155240 { 220ab25eeb5Syz155240 ip_pool_node_t node, *m; 221ab25eeb5Syz155240 iplookupop_t op; 222ab25eeb5Syz155240 iphtable_t *iph; 223ab25eeb5Syz155240 iphtent_t hte; 224ab25eeb5Syz155240 ip_pool_t *p; 225ab25eeb5Syz155240 int err; 226ab25eeb5Syz155240 227*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 228*bb1d9de5SJohn Ojemann if (err != 0) 229*bb1d9de5SJohn Ojemann return EFAULT; 230*bb1d9de5SJohn Ojemann 231ab25eeb5Syz155240 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 232ab25eeb5Syz155240 233ab25eeb5Syz155240 switch (op.iplo_type) 234ab25eeb5Syz155240 { 235ab25eeb5Syz155240 case IPLT_POOL : 236ab25eeb5Syz155240 if (op.iplo_size != sizeof(node)) 237ab25eeb5Syz155240 return EINVAL; 238ab25eeb5Syz155240 239ab25eeb5Syz155240 err = COPYIN(op.iplo_struct, &node, sizeof(node)); 240ab25eeb5Syz155240 if (err != 0) 241ab25eeb5Syz155240 return EFAULT; 242ab25eeb5Syz155240 243f4b3ec61Sdh155122 p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs); 244ab25eeb5Syz155240 if (p == NULL) 245ab25eeb5Syz155240 return ESRCH; 246ab25eeb5Syz155240 247ab25eeb5Syz155240 /* 248ab25eeb5Syz155240 * add an entry to a pool - return an error if it already 249ab25eeb5Syz155240 * exists remove an entry from a pool - if it exists 250ab25eeb5Syz155240 * - in both cases, the pool *must* exist! 251ab25eeb5Syz155240 */ 252ab25eeb5Syz155240 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); 253ab25eeb5Syz155240 if (m) 254ab25eeb5Syz155240 return EEXIST; 255ab25eeb5Syz155240 err = ip_pool_insert(p, &node.ipn_addr, 256f4b3ec61Sdh155122 &node.ipn_mask, node.ipn_info, ifs); 257ab25eeb5Syz155240 break; 258ab25eeb5Syz155240 259ab25eeb5Syz155240 case IPLT_HASH : 260ab25eeb5Syz155240 if (op.iplo_size != sizeof(hte)) 261ab25eeb5Syz155240 return EINVAL; 262ab25eeb5Syz155240 263ab25eeb5Syz155240 err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); 264ab25eeb5Syz155240 if (err != 0) 265ab25eeb5Syz155240 return EFAULT; 266ab25eeb5Syz155240 267f4b3ec61Sdh155122 iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs); 268ab25eeb5Syz155240 if (iph == NULL) 269ab25eeb5Syz155240 return ESRCH; 270f4b3ec61Sdh155122 err = fr_addhtent(iph, &hte, ifs); 271ab25eeb5Syz155240 break; 272ab25eeb5Syz155240 273ab25eeb5Syz155240 default : 274ab25eeb5Syz155240 err = EINVAL; 275ab25eeb5Syz155240 break; 276ab25eeb5Syz155240 } 277ab25eeb5Syz155240 return err; 278ab25eeb5Syz155240 } 279ab25eeb5Syz155240 280ab25eeb5Syz155240 281ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 282ab25eeb5Syz155240 /* Function: iplookup_delnode */ 283ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 284ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 285ab25eeb5Syz155240 /* */ 286ab25eeb5Syz155240 /* Delete a node from a lookup table by first looking for the table it is */ 287ab25eeb5Syz155240 /* in and then deleting the entry that gets found. */ 288ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 289f4b3ec61Sdh155122 static int iplookup_delnode(data, ifs) 290ab25eeb5Syz155240 caddr_t data; 291f4b3ec61Sdh155122 ipf_stack_t *ifs; 292ab25eeb5Syz155240 { 293ab25eeb5Syz155240 ip_pool_node_t node, *m; 294ab25eeb5Syz155240 iplookupop_t op; 295ab25eeb5Syz155240 iphtable_t *iph; 296ab25eeb5Syz155240 iphtent_t hte; 297ab25eeb5Syz155240 ip_pool_t *p; 298ab25eeb5Syz155240 int err; 299ab25eeb5Syz155240 300*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 301*bb1d9de5SJohn Ojemann if (err != 0) 302*bb1d9de5SJohn Ojemann return EFAULT; 303ab25eeb5Syz155240 304ab25eeb5Syz155240 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 305ab25eeb5Syz155240 306ab25eeb5Syz155240 switch (op.iplo_type) 307ab25eeb5Syz155240 { 308ab25eeb5Syz155240 case IPLT_POOL : 309ab25eeb5Syz155240 if (op.iplo_size != sizeof(node)) 310ab25eeb5Syz155240 return EINVAL; 311ab25eeb5Syz155240 312ab25eeb5Syz155240 err = COPYIN(op.iplo_struct, &node, sizeof(node)); 313ab25eeb5Syz155240 if (err != 0) 314ab25eeb5Syz155240 return EFAULT; 315ab25eeb5Syz155240 316f4b3ec61Sdh155122 p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs); 317ab25eeb5Syz155240 if (!p) 318ab25eeb5Syz155240 return ESRCH; 319ab25eeb5Syz155240 320ab25eeb5Syz155240 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask); 321ab25eeb5Syz155240 if (m == NULL) 322ab25eeb5Syz155240 return ENOENT; 323f4b3ec61Sdh155122 err = ip_pool_remove(p, m, ifs); 324ab25eeb5Syz155240 break; 325ab25eeb5Syz155240 326ab25eeb5Syz155240 case IPLT_HASH : 327ab25eeb5Syz155240 if (op.iplo_size != sizeof(hte)) 328ab25eeb5Syz155240 return EINVAL; 329ab25eeb5Syz155240 330ab25eeb5Syz155240 err = COPYIN(op.iplo_struct, &hte, sizeof(hte)); 331ab25eeb5Syz155240 if (err != 0) 332ab25eeb5Syz155240 return EFAULT; 333ab25eeb5Syz155240 334f4b3ec61Sdh155122 iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs); 335ab25eeb5Syz155240 if (iph == NULL) 336ab25eeb5Syz155240 return ESRCH; 337f4b3ec61Sdh155122 err = fr_delhtent(iph, &hte, ifs); 338ab25eeb5Syz155240 break; 339ab25eeb5Syz155240 340ab25eeb5Syz155240 default : 341ab25eeb5Syz155240 err = EINVAL; 342ab25eeb5Syz155240 break; 343ab25eeb5Syz155240 } 344ab25eeb5Syz155240 return err; 345ab25eeb5Syz155240 } 346ab25eeb5Syz155240 347ab25eeb5Syz155240 348ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 349ab25eeb5Syz155240 /* Function: iplookup_addtable */ 350ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 351ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 352ab25eeb5Syz155240 /* */ 353ab25eeb5Syz155240 /* Create a new lookup table, if one doesn't already exist using the name */ 354ab25eeb5Syz155240 /* for this one. */ 355ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 356f4b3ec61Sdh155122 static int iplookup_addtable(data, ifs) 357ab25eeb5Syz155240 caddr_t data; 358f4b3ec61Sdh155122 ipf_stack_t *ifs; 359ab25eeb5Syz155240 { 360ab25eeb5Syz155240 iplookupop_t op; 361ab25eeb5Syz155240 int err; 362ab25eeb5Syz155240 363*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 364*bb1d9de5SJohn Ojemann if (err != 0) 365*bb1d9de5SJohn Ojemann return EFAULT; 366ab25eeb5Syz155240 367ab25eeb5Syz155240 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 368ab25eeb5Syz155240 369ab25eeb5Syz155240 switch (op.iplo_type) 370ab25eeb5Syz155240 { 371ab25eeb5Syz155240 case IPLT_POOL : 372f4b3ec61Sdh155122 if (ip_pool_find(op.iplo_unit, op.iplo_name, ifs) != NULL) 373ab25eeb5Syz155240 err = EEXIST; 374ab25eeb5Syz155240 else 375f4b3ec61Sdh155122 err = ip_pool_create(&op, ifs); 376ab25eeb5Syz155240 break; 377ab25eeb5Syz155240 378ab25eeb5Syz155240 case IPLT_HASH : 379f4b3ec61Sdh155122 if (fr_findhtable(op.iplo_unit, op.iplo_name, ifs) != NULL) 380ab25eeb5Syz155240 err = EEXIST; 381ab25eeb5Syz155240 else 382f4b3ec61Sdh155122 err = fr_newhtable(&op, ifs); 383ab25eeb5Syz155240 break; 384ab25eeb5Syz155240 385ab25eeb5Syz155240 default : 386ab25eeb5Syz155240 err = EINVAL; 387ab25eeb5Syz155240 break; 388ab25eeb5Syz155240 } 389ab25eeb5Syz155240 return err; 390ab25eeb5Syz155240 } 391ab25eeb5Syz155240 392ab25eeb5Syz155240 393ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 394ab25eeb5Syz155240 /* Function: iplookup_deltable */ 395ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 396ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 397ab25eeb5Syz155240 /* */ 398ab25eeb5Syz155240 /* Decodes ioctl request to remove a particular hash table or pool and */ 399ab25eeb5Syz155240 /* calls the relevant function to do the cleanup. */ 400ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 401f4b3ec61Sdh155122 static int iplookup_deltable(data, ifs) 402ab25eeb5Syz155240 caddr_t data; 403f4b3ec61Sdh155122 ipf_stack_t *ifs; 404ab25eeb5Syz155240 { 405ab25eeb5Syz155240 iplookupop_t op; 406ab25eeb5Syz155240 int err; 407ab25eeb5Syz155240 408*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 409*bb1d9de5SJohn Ojemann if (err != 0) 410*bb1d9de5SJohn Ojemann return EFAULT; 411*bb1d9de5SJohn Ojemann 412ab25eeb5Syz155240 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 413ab25eeb5Syz155240 414ab25eeb5Syz155240 if (op.iplo_arg & IPLT_ANON) 415ab25eeb5Syz155240 op.iplo_arg &= IPLT_ANON; 416ab25eeb5Syz155240 417ab25eeb5Syz155240 /* 418ab25eeb5Syz155240 * create a new pool - fail if one already exists with 419ab25eeb5Syz155240 * the same # 420ab25eeb5Syz155240 */ 421ab25eeb5Syz155240 switch (op.iplo_type) 422ab25eeb5Syz155240 { 423ab25eeb5Syz155240 case IPLT_POOL : 424f4b3ec61Sdh155122 err = ip_pool_destroy(&op, ifs); 425ab25eeb5Syz155240 break; 426ab25eeb5Syz155240 427ab25eeb5Syz155240 case IPLT_HASH : 428f4b3ec61Sdh155122 err = fr_removehtable(&op, ifs); 429ab25eeb5Syz155240 break; 430ab25eeb5Syz155240 431ab25eeb5Syz155240 default : 432ab25eeb5Syz155240 err = EINVAL; 433ab25eeb5Syz155240 break; 434ab25eeb5Syz155240 } 435ab25eeb5Syz155240 return err; 436ab25eeb5Syz155240 } 437ab25eeb5Syz155240 438ab25eeb5Syz155240 439ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 440ab25eeb5Syz155240 /* Function: iplookup_stats */ 441ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 442ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 443ab25eeb5Syz155240 /* */ 444ab25eeb5Syz155240 /* Copy statistical information from inside the kernel back to user space. */ 445ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 446f4b3ec61Sdh155122 static int iplookup_stats(data, ifs) 447ab25eeb5Syz155240 caddr_t data; 448f4b3ec61Sdh155122 ipf_stack_t *ifs; 449ab25eeb5Syz155240 { 450ab25eeb5Syz155240 iplookupop_t op; 451ab25eeb5Syz155240 int err; 452ab25eeb5Syz155240 453*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &op, sizeof(op)); 454*bb1d9de5SJohn Ojemann if (err != 0) 455*bb1d9de5SJohn Ojemann return EFAULT; 456ab25eeb5Syz155240 457ab25eeb5Syz155240 switch (op.iplo_type) 458ab25eeb5Syz155240 { 459ab25eeb5Syz155240 case IPLT_POOL : 460f4b3ec61Sdh155122 err = ip_pool_statistics(&op, ifs); 461ab25eeb5Syz155240 break; 462ab25eeb5Syz155240 463ab25eeb5Syz155240 case IPLT_HASH : 464f4b3ec61Sdh155122 err = fr_gethtablestat(&op, ifs); 465ab25eeb5Syz155240 break; 466ab25eeb5Syz155240 467ab25eeb5Syz155240 default : 468ab25eeb5Syz155240 err = EINVAL; 469ab25eeb5Syz155240 break; 470ab25eeb5Syz155240 } 471ab25eeb5Syz155240 return err; 472ab25eeb5Syz155240 } 473ab25eeb5Syz155240 474ab25eeb5Syz155240 475ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 476ab25eeb5Syz155240 /* Function: iplookup_flush */ 477ab25eeb5Syz155240 /* Returns: int - 0 = success, else error */ 478ab25eeb5Syz155240 /* Parameters: data(I) - pointer to data from ioctl call */ 479ab25eeb5Syz155240 /* */ 480ab25eeb5Syz155240 /* A flush is called when we want to flush all the nodes from a particular */ 481ab25eeb5Syz155240 /* entry in the hash table/pool or want to remove all groups from those. */ 482ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */ 483f4b3ec61Sdh155122 static int iplookup_flush(data, ifs) 484ab25eeb5Syz155240 caddr_t data; 485f4b3ec61Sdh155122 ipf_stack_t *ifs; 486ab25eeb5Syz155240 { 487ab25eeb5Syz155240 int err, unit, num, type; 488ab25eeb5Syz155240 iplookupflush_t flush; 489ab25eeb5Syz155240 490*bb1d9de5SJohn Ojemann err = BCOPYIN(data, &flush, sizeof(flush)); 491*bb1d9de5SJohn Ojemann if (err != 0) 492*bb1d9de5SJohn Ojemann return EFAULT; 493ab25eeb5Syz155240 494ab25eeb5Syz155240 flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; 495ab25eeb5Syz155240 496ab25eeb5Syz155240 unit = flush.iplf_unit; 497ab25eeb5Syz155240 if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) 498ab25eeb5Syz155240 return EINVAL; 499ab25eeb5Syz155240 500ab25eeb5Syz155240 type = flush.iplf_type; 501ab25eeb5Syz155240 err = EINVAL; 502ab25eeb5Syz155240 num = 0; 503ab25eeb5Syz155240 504ab25eeb5Syz155240 if (type == IPLT_POOL || type == IPLT_ALL) { 505ab25eeb5Syz155240 err = 0; 506f4b3ec61Sdh155122 num = ip_pool_flush(&flush, ifs); 507ab25eeb5Syz155240 } 508ab25eeb5Syz155240 509ab25eeb5Syz155240 if (type == IPLT_HASH || type == IPLT_ALL) { 510ab25eeb5Syz155240 err = 0; 511f4b3ec61Sdh155122 num += fr_flushhtable(&flush, ifs); 512ab25eeb5Syz155240 } 513ab25eeb5Syz155240 514ab25eeb5Syz155240 if (err == 0) { 515ab25eeb5Syz155240 flush.iplf_count = num; 516ab25eeb5Syz155240 err = COPYOUT(&flush, data, sizeof(flush)); 517ab25eeb5Syz155240 } 518ab25eeb5Syz155240 return err; 519ab25eeb5Syz155240 } 520ab25eeb5Syz155240 521ab25eeb5Syz155240 522f4b3ec61Sdh155122 523f4b3ec61Sdh155122 void ip_lookup_deref(type, ptr, ifs) 524ab25eeb5Syz155240 int type; 525ab25eeb5Syz155240 void *ptr; 526f4b3ec61Sdh155122 ipf_stack_t *ifs; 527ab25eeb5Syz155240 { 528ab25eeb5Syz155240 if (ptr == NULL) 529ab25eeb5Syz155240 return; 530ab25eeb5Syz155240 531f4b3ec61Sdh155122 WRITE_ENTER(&ifs->ifs_ip_poolrw); 532ab25eeb5Syz155240 switch (type) 533ab25eeb5Syz155240 { 534ab25eeb5Syz155240 case IPLT_POOL : 535f4b3ec61Sdh155122 ip_pool_deref(ptr, ifs); 536ab25eeb5Syz155240 break; 537ab25eeb5Syz155240 538ab25eeb5Syz155240 case IPLT_HASH : 539f4b3ec61Sdh155122 fr_derefhtable(ptr, ifs); 540ab25eeb5Syz155240 break; 541ab25eeb5Syz155240 } 542f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 543f4b3ec61Sdh155122 } 544f4b3ec61Sdh155122 545f4b3ec61Sdh155122 546f4b3ec61Sdh155122 int ip_lookup_iterate(data, uid, ctx, ifs) 547f4b3ec61Sdh155122 void *data; 548f4b3ec61Sdh155122 int uid; 549f4b3ec61Sdh155122 void *ctx; 550f4b3ec61Sdh155122 ipf_stack_t *ifs; 551f4b3ec61Sdh155122 { 552f4b3ec61Sdh155122 ipflookupiter_t iter; 553f4b3ec61Sdh155122 ipftoken_t *token; 554f4b3ec61Sdh155122 int err; 555f4b3ec61Sdh155122 556f4b3ec61Sdh155122 err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER); 557f4b3ec61Sdh155122 if (err != 0) { 558f4b3ec61Sdh155122 #ifdef _KERNEL 559f4b3ec61Sdh155122 (void) printf("fr_inobj\n"); 560f4b3ec61Sdh155122 #endif 561f4b3ec61Sdh155122 return err; 562f4b3ec61Sdh155122 } 563f4b3ec61Sdh155122 564f4b3ec61Sdh155122 if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) { 565f4b3ec61Sdh155122 #ifdef _KERNEL 566f4b3ec61Sdh155122 (void) printf("unit=%d\n", iter.ili_unit); 567f4b3ec61Sdh155122 #endif 568f4b3ec61Sdh155122 return EINVAL; 569f4b3ec61Sdh155122 } 570f4b3ec61Sdh155122 571f4b3ec61Sdh155122 if (iter.ili_ival != IPFGENITER_LOOKUP) { 572f4b3ec61Sdh155122 #ifdef _KERNEL 573f4b3ec61Sdh155122 (void) printf("ival=%d\n", iter.ili_ival); 574f4b3ec61Sdh155122 #endif 575f4b3ec61Sdh155122 return EINVAL; 576f4b3ec61Sdh155122 } 577f4b3ec61Sdh155122 578f4b3ec61Sdh155122 token = ipf_findtoken(iter.ili_key, uid, ctx, ifs); 579f4b3ec61Sdh155122 if (token == NULL) { 580f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_tokens); 581f4b3ec61Sdh155122 return ESRCH; 582f4b3ec61Sdh155122 } 583f4b3ec61Sdh155122 584f4b3ec61Sdh155122 switch (iter.ili_type) 585f4b3ec61Sdh155122 { 586f4b3ec61Sdh155122 case IPLT_POOL : 587f4b3ec61Sdh155122 err = ip_pool_getnext(token, &iter, ifs); 588f4b3ec61Sdh155122 break; 589f4b3ec61Sdh155122 case IPLT_HASH : 590f4b3ec61Sdh155122 err = fr_htable_getnext(token, &iter, ifs); 591f4b3ec61Sdh155122 break; 592f4b3ec61Sdh155122 default : 593f4b3ec61Sdh155122 #ifdef _KERNEL 594f4b3ec61Sdh155122 (void) printf("type=%d\n", iter.ili_type); 595f4b3ec61Sdh155122 #endif 596f4b3ec61Sdh155122 err = EINVAL; 597f4b3ec61Sdh155122 break; 598f4b3ec61Sdh155122 } 599f4b3ec61Sdh155122 RWLOCK_EXIT(&ifs->ifs_ipf_tokens); 600f4b3ec61Sdh155122 601f4b3ec61Sdh155122 return err; 602f4b3ec61Sdh155122 } 603f4b3ec61Sdh155122 604f4b3ec61Sdh155122 605f4b3ec61Sdh155122 void ip_lookup_iterderef(type, data, ifs) 606f4b3ec61Sdh155122 u_32_t type; 607f4b3ec61Sdh155122 void *data; 608f4b3ec61Sdh155122 ipf_stack_t *ifs; 609f4b3ec61Sdh155122 { 610f4b3ec61Sdh155122 iplookupiterkey_t key; 611f4b3ec61Sdh155122 612f4b3ec61Sdh155122 key.ilik_key = type; 613f4b3ec61Sdh155122 614f4b3ec61Sdh155122 if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP) 615f4b3ec61Sdh155122 return; 616f4b3ec61Sdh155122 617f4b3ec61Sdh155122 switch (key.ilik_unstr.ilik_type) 618f4b3ec61Sdh155122 { 619f4b3ec61Sdh155122 case IPLT_HASH : 620f4b3ec61Sdh155122 fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype, 621f4b3ec61Sdh155122 (int)key.ilik_unstr.ilik_unit, data, ifs); 622f4b3ec61Sdh155122 break; 623f4b3ec61Sdh155122 case IPLT_POOL : 624f4b3ec61Sdh155122 ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype, 625f4b3ec61Sdh155122 (int)key.ilik_unstr.ilik_unit, data, ifs); 626f4b3ec61Sdh155122 break; 627f4b3ec61Sdh155122 } 628ab25eeb5Syz155240 } 629ab25eeb5Syz155240 630ab25eeb5Syz155240 631ab25eeb5Syz155240 #else /* IPFILTER_LOOKUP */ 632ab25eeb5Syz155240 633ab25eeb5Syz155240 /*ARGSUSED*/ 634f4b3ec61Sdh155122 int ip_lookup_ioctl(data, cmd, mode, uid, ifs) 635ab25eeb5Syz155240 caddr_t data; 636ab25eeb5Syz155240 ioctlcmd_t cmd; 637f4b3ec61Sdh155122 int mode, uid; 638f4b3ec61Sdh155122 ipf_stack_t *ifs; 639ab25eeb5Syz155240 { 640ab25eeb5Syz155240 return EIO; 641ab25eeb5Syz155240 } 642ab25eeb5Syz155240 #endif /* IPFILTER_LOOKUP */ 643