4 * Copyright (C) 2002-2003 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
8 #if defined(KERNEL) || defined(_KERNEL)
15 # define _PROTO_NET_H_
17 #include <sys/param.h>
18 #include <sys/errno.h>
19 #include <sys/types.h>
22 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
23 # include <sys/fcntl.h>
24 # include <sys/filio.h>
26 # include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #if (defined(__osf__) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
40 # include <net/radix.h>
42 # include "radix_ipf_local.h"
46 #if defined(__FreeBSD__)
47 # include <sys/cdefs.h>
48 # include <sys/proc.h>
51 # include <sys/systm.h>
52 # if !defined(__SVR4) && !defined(__svr4__)
53 # include <sys/mbuf.h>
56 #include <netinet/in.h>
58 #include "netinet/ip_compat.h"
59 #include "netinet/ip_fil.h"
60 #include "netinet/ip_pool.h"
61 #include "netinet/ip_htable.h"
62 #include "netinet/ip_lookup.h"
66 static const char rcsid[] = "@(#)Id: ip_lookup.c,v 2.35.2.5 2004/07/06 11:16:25 darrenr Exp";
69 #ifdef IPFILTER_LOOKUP
70 int ip_lookup_inited = 0;
72 static int iplookup_addnode __P((caddr_t));
73 static int iplookup_delnode __P((caddr_t data));
74 static int iplookup_addtable __P((caddr_t));
75 static int iplookup_deltable __P((caddr_t));
76 static int iplookup_stats __P((caddr_t));
77 static int iplookup_flush __P((caddr_t));
80 /* ------------------------------------------------------------------------ */
81 /* Function: iplookup_init */
82 /* Returns: int - 0 = success, else error */
85 /* Initialise all of the subcomponents of the lookup infrstructure. */
86 /* ------------------------------------------------------------------------ */
90 if (ip_pool_init() == -1)
93 RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
101 /* ------------------------------------------------------------------------ */
102 /* Function: iplookup_unload */
103 /* Returns: int - 0 = success, else error */
104 /* Parameters: Nil */
106 /* Free up all pool related memory that has been allocated whilst IPFilter */
107 /* has been running. Also, do any other deinitialisation required such */
108 /* ip_lookup_init() can be called again, safely. */
109 /* ------------------------------------------------------------------------ */
110 void ip_lookup_unload()
115 if (ip_lookup_inited == 1) {
116 RW_DESTROY(&ip_poolrw);
117 ip_lookup_inited = 0;
122 /* ------------------------------------------------------------------------ */
123 /* Function: iplookup_ioctl */
124 /* Returns: int - 0 = success, else error */
125 /* Parameters: data(IO) - pointer to ioctl data to be copied to/from user */
127 /* cmd(I) - ioctl command number */
128 /* mode(I) - file mode bits used with open */
130 /* Handle ioctl commands sent to the ioctl device. For the most part, this */
131 /* involves just calling another function to handle the specifics of each */
133 /* ------------------------------------------------------------------------ */
134 int ip_lookup_ioctl(data, cmd, mode)
140 # if defined(_KERNEL) && !defined(MENTAT) && defined(USE_SPL)
144 mode = mode; /* LINT */
150 case SIOCLOOKUPADDNODE :
151 case SIOCLOOKUPADDNODEW :
152 WRITE_ENTER(&ip_poolrw);
153 err = iplookup_addnode(data);
154 RWLOCK_EXIT(&ip_poolrw);
157 case SIOCLOOKUPDELNODE :
158 case SIOCLOOKUPDELNODEW :
159 WRITE_ENTER(&ip_poolrw);
160 err = iplookup_delnode(data);
161 RWLOCK_EXIT(&ip_poolrw);
164 case SIOCLOOKUPADDTABLE :
165 WRITE_ENTER(&ip_poolrw);
166 err = iplookup_addtable(data);
167 RWLOCK_EXIT(&ip_poolrw);
170 case SIOCLOOKUPDELTABLE :
171 WRITE_ENTER(&ip_poolrw);
172 err = iplookup_deltable(data);
173 RWLOCK_EXIT(&ip_poolrw);
176 case SIOCLOOKUPSTAT :
177 case SIOCLOOKUPSTATW :
178 WRITE_ENTER(&ip_poolrw);
179 err = iplookup_stats(data);
180 RWLOCK_EXIT(&ip_poolrw);
183 case SIOCLOOKUPFLUSH :
184 WRITE_ENTER(&ip_poolrw);
185 err = iplookup_flush(data);
186 RWLOCK_EXIT(&ip_poolrw);
198 /* ------------------------------------------------------------------------ */
199 /* Function: iplookup_addnode */
200 /* Returns: int - 0 = success, else error */
201 /* Parameters: data(I) - pointer to data from ioctl call */
203 /* Add a new data node to a lookup structure. First, check to see if the */
204 /* parent structure refered to by name exists and if it does, then go on to */
205 /* add a node to it. */
206 /* ------------------------------------------------------------------------ */
207 static int iplookup_addnode(data)
210 ip_pool_node_t node, *m;
218 BCOPYIN(data, &op, sizeof(op));
219 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
221 switch (op.iplo_type)
224 if (op.iplo_size != sizeof(node))
227 err = COPYIN(op.iplo_struct, &node, sizeof(node));
231 p = ip_pool_find(op.iplo_unit, op.iplo_name);
236 * add an entry to a pool - return an error if it already
237 * exists remove an entry from a pool - if it exists
238 * - in both cases, the pool *must* exist!
240 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
243 err = ip_pool_insert(p, &node.ipn_addr.adf_addr,
244 &node.ipn_mask.adf_addr, node.ipn_info);
248 if (op.iplo_size != sizeof(hte))
251 err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
255 iph = fr_findhtable(op.iplo_unit, op.iplo_name);
258 err = fr_addhtent(iph, &hte);
269 /* ------------------------------------------------------------------------ */
270 /* Function: iplookup_delnode */
271 /* Returns: int - 0 = success, else error */
272 /* Parameters: data(I) - pointer to data from ioctl call */
274 /* Delete a node from a lookup table by first looking for the table it is */
275 /* in and then deleting the entry that gets found. */
276 /* ------------------------------------------------------------------------ */
277 static int iplookup_delnode(data)
280 ip_pool_node_t node, *m;
288 BCOPYIN(data, &op, sizeof(op));
290 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
292 switch (op.iplo_type)
295 if (op.iplo_size != sizeof(node))
298 err = COPYIN(op.iplo_struct, &node, sizeof(node));
302 p = ip_pool_find(op.iplo_unit, op.iplo_name);
306 m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
309 err = ip_pool_remove(p, m);
313 if (op.iplo_size != sizeof(hte))
316 err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
320 iph = fr_findhtable(op.iplo_unit, op.iplo_name);
323 err = fr_delhtent(iph, &hte);
334 /* ------------------------------------------------------------------------ */
335 /* Function: iplookup_addtable */
336 /* Returns: int - 0 = success, else error */
337 /* Parameters: data(I) - pointer to data from ioctl call */
339 /* Create a new lookup table, if one doesn't already exist using the name */
341 /* ------------------------------------------------------------------------ */
342 static int iplookup_addtable(data)
349 BCOPYIN(data, &op, sizeof(op));
351 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
353 switch (op.iplo_type)
356 if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
359 err = ip_pool_create(&op);
363 if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
366 err = fr_newhtable(&op);
377 /* ------------------------------------------------------------------------ */
378 /* Function: iplookup_deltable */
379 /* Returns: int - 0 = success, else error */
380 /* Parameters: data(I) - pointer to data from ioctl call */
382 /* Decodes ioctl request to remove a particular hash table or pool and */
383 /* calls the relevant function to do the cleanup. */
384 /* ------------------------------------------------------------------------ */
385 static int iplookup_deltable(data)
391 BCOPYIN(data, &op, sizeof(op));
392 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
394 if (op.iplo_arg & IPLT_ANON)
395 op.iplo_arg &= IPLT_ANON;
398 * create a new pool - fail if one already exists with
401 switch (op.iplo_type)
404 err = ip_pool_destroy(&op);
408 err = fr_removehtable(&op);
419 /* ------------------------------------------------------------------------ */
420 /* Function: iplookup_stats */
421 /* Returns: int - 0 = success, else error */
422 /* Parameters: data(I) - pointer to data from ioctl call */
424 /* Copy statistical information from inside the kernel back to user space. */
425 /* ------------------------------------------------------------------------ */
426 static int iplookup_stats(data)
433 BCOPYIN(data, &op, sizeof(op));
435 switch (op.iplo_type)
438 err = ip_pool_statistics(&op);
442 err = fr_gethtablestat(&op);
453 /* ------------------------------------------------------------------------ */
454 /* Function: iplookup_flush */
455 /* Returns: int - 0 = success, else error */
456 /* Parameters: data(I) - pointer to data from ioctl call */
458 /* A flush is called when we want to flush all the nodes from a particular */
459 /* entry in the hash table/pool or want to remove all groups from those. */
460 /* ------------------------------------------------------------------------ */
461 static int iplookup_flush(data)
464 int err, unit, num, type;
465 iplookupflush_t flush;
468 BCOPYIN(data, &flush, sizeof(flush));
470 flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
472 unit = flush.iplf_unit;
473 if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
476 type = flush.iplf_type;
480 if (type == IPLT_POOL || type == IPLT_ALL) {
482 num = ip_pool_flush(&flush);
485 if (type == IPLT_HASH || type == IPLT_ALL) {
487 num += fr_flushhtable(&flush);
491 flush.iplf_count = num;
492 err = COPYOUT(&flush, data, sizeof(flush));
498 void ip_lookup_deref(type, ptr)
505 WRITE_ENTER(&ip_poolrw);
516 RWLOCK_EXIT(&ip_poolrw);
520 #else /* IPFILTER_LOOKUP */
523 int ip_lookup_ioctl(data, cmd, mode)
530 #endif /* IPFILTER_LOOKUP */