radix_ipf.c revision 1.1 1 /* $NetBSD: radix_ipf.c,v 1.1 2012/03/23 20:37:04 christos Exp $ */
2
3 /*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #include <sys/types.h>
9 #include <sys/time.h>
10 #include <sys/socket.h>
11 #include <sys/param.h>
12 #include <netinet/in.h>
13 #include <net/if.h>
14 #if !defined(_KERNEL)
15 # include <stddef.h>
16 # include <stdlib.h>
17 # include <strings.h>
18 # include <string.h>
19 #endif
20 #include "netinet/ip_compat.h"
21 #include "netinet/ip_fil.h"
22 #ifdef RDX_DEBUG
23 # include <arpa/inet.h>
24 # include <stdlib.h>
25 # include <stdio.h>
26 #endif
27 #include "netinet/radix_ipf.h"
28
29 #define ADF_OFF offsetof(addrfamily_t, adf_addr)
30 #define ADF_OFF_BITS (ADF_OFF << 3)
31
32 static ipf_rdx_node_t *ipf_rx_insert __P((ipf_rdx_head_t *,
33 ipf_rdx_node_t nodes[2], int *));
34 static void ipf_rx_attach_mask __P((ipf_rdx_node_t *, ipf_rdx_mask_t *));
35 static int count_mask_bits __P((addrfamily_t *, u_32_t **));
36 static void buildnodes __P((addrfamily_t *, addrfamily_t *,
37 ipf_rdx_node_t n[2]));
38 static ipf_rdx_node_t *ipf_rx_find_addr __P((ipf_rdx_node_t *, u_32_t *));
39 static ipf_rdx_node_t *ipf_rx_lookup __P((ipf_rdx_head_t *, addrfamily_t *,
40 addrfamily_t *));
41 static ipf_rdx_node_t *ipf_rx_match __P((ipf_rdx_head_t *, addrfamily_t *));
42
43 /*
44 * Foreword.
45 * ---------
46 * The code in this file has been written to target using the addrfamily_t
47 * data structure to house the address information and no other. Thus there
48 * are certain aspects of thise code (such as offsets to the address itself)
49 * that are hard coded here whilst they might be more variable elsewhere.
50 * Similarly, this code enforces no maximum key length as that's implied by
51 * all keys needing to be stored in addrfamily_t.
52 */
53
54 /* ------------------------------------------------------------------------ */
55 /* Function: count_mask_bits */
56 /* Returns: number of consecutive bits starting at "mask". */
57 /* */
58 /* Count the number of bits set in the address section of addrfamily_t and */
59 /* return both that number and a pointer to the last word with a bit set if */
60 /* lastp is not NULL. The bit count is performed using network byte order */
61 /* as the guide for which bit is the most significant bit. */
62 /* ------------------------------------------------------------------------ */
63 static int
64 count_mask_bits(mask, lastp)
65 addrfamily_t *mask;
66 u_32_t **lastp;
67 {
68 u_32_t *mp = (u_32_t *)&mask->adf_addr;
69 u_32_t m;
70 int count = 0;
71 int mlen;
72
73 mlen = mask->adf_len - offsetof(addrfamily_t, adf_addr);
74 for (mlen = mask->adf_len; mlen > 0; mlen -= 4, mp++) {
75 if ((m = ntohl(*mp)) == 0)
76 break;
77 if (lastp != NULL)
78 *lastp = mp;
79 for (; m & 0x80000000; m <<= 1)
80 count++;
81 }
82
83 return count;
84 }
85
86
87 /* ------------------------------------------------------------------------ */
88 /* Function: buildnodes */
89 /* Returns: Nil */
90 /* Parameters: addr(I) - network address for this radix node */
91 /* mask(I) - netmask associated with the above address */
92 /* nodes(O) - pair of ipf_rdx_node_t's to initialise with data */
93 /* associated with addr and mask. */
94 /* */
95 /* Initialise the fields in a pair of radix tree nodes according to the */
96 /* data supplied in the paramters "addr" and "mask". It is expected that */
97 /* "mask" will contain a consecutive string of bits set. Masks with gaps in */
98 /* the middle are not handled by this implementation. */
99 /* ------------------------------------------------------------------------ */
100 static void
101 buildnodes(addr, mask, nodes)
102 addrfamily_t *addr, *mask;
103 ipf_rdx_node_t nodes[2];
104 {
105 u_32_t maskbits;
106 u_32_t lastbits;
107 u_32_t lastmask;
108 u_32_t *last;
109 int masklen;
110
111 last = NULL;
112 maskbits = count_mask_bits(mask, &last);
113 if (last == NULL) {
114 masklen = 0;
115 lastmask = 0;
116 } else {
117 masklen = last - (u_32_t *)mask;
118 lastmask = *last;
119 }
120 lastbits = maskbits & 0x1f;
121
122 bzero(&nodes[0], sizeof(ipf_rdx_node_t) * 2);
123 nodes[0].maskbitcount = maskbits;
124 nodes[0].index = -1 - (ADF_OFF_BITS + maskbits);
125 nodes[0].addrkey = (u_32_t *)addr;
126 nodes[0].maskkey = (u_32_t *)mask;
127 nodes[0].addroff = nodes[0].addrkey + masklen;
128 nodes[0].maskoff = nodes[0].maskkey + masklen;
129 nodes[0].parent = &nodes[1];
130 nodes[0].offset = masklen;
131 nodes[0].lastmask = lastmask;
132 nodes[1].offset = masklen;
133 nodes[1].left = &nodes[0];
134 nodes[1].maskbitcount = maskbits;
135 #ifdef RDX_DEBUG
136 (void) strcpy(nodes[0].name, "_BUILD.0");
137 (void) strcpy(nodes[1].name, "_BUILD.1");
138 #endif
139 }
140
141
142 /* ------------------------------------------------------------------------ */
143 /* Function: ipf_rx_find_addr */
144 /* Returns: ipf_rdx_node_t * - pointer to a node in the radix tree. */
145 /* Parameters: tree(I) - pointer to first right node in tree to search */
146 /* addr(I) - pointer to address to match */
147 /* */
148 /* Walk the radix tree given by "tree", looking for a leaf node that is a */
149 /* match for the address given by "addr". */
150 /* ------------------------------------------------------------------------ */
151 static ipf_rdx_node_t *
152 ipf_rx_find_addr(tree, addr)
153 ipf_rdx_node_t *tree;
154 u_32_t *addr;
155 {
156 ipf_rdx_node_t *cur;
157
158 for (cur = tree; cur->index >= 0;) {
159 if (cur->bitmask & addr[cur->offset]) {
160 cur = cur->right;
161 } else {
162 cur = cur->left;
163 }
164 }
165
166 return (cur);
167 }
168
169
170 /* ------------------------------------------------------------------------ */
171 /* Function: ipf_rx_match */
172 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */
173 /* added to the tree. */
174 /* Paramters: head(I) - pointer to tree head to search */
175 /* addr(I) - pointer to address to find */
176 /* */
177 /* Search the radix tree for the best match to the address pointed to by */
178 /* "addr" and return a pointer to that node. This search will not match the */
179 /* address information stored in either of the root leaves as neither of */
180 /* them are considered to be part of the tree of data being stored. */
181 /* ------------------------------------------------------------------------ */
182 static ipf_rdx_node_t *
183 ipf_rx_match(head, addr)
184 ipf_rdx_head_t *head;
185 addrfamily_t *addr;
186 {
187 ipf_rdx_mask_t *masknode;
188 ipf_rdx_node_t *prev;
189 ipf_rdx_node_t *node;
190 ipf_rdx_node_t *cur;
191 u_32_t *data;
192 u_32_t *mask;
193 u_32_t *key;
194 u_32_t *end;
195 int len;
196 int i;
197
198 len = addr->adf_len;
199 end = (u_32_t *)((u_char *)addr + len);
200 node = ipf_rx_find_addr(head->root, (u_32_t *)addr);
201
202 /*
203 * Search the dupkey list for a potential match.
204 */
205 for (cur = node; (cur != NULL) && (cur->root == 0); cur = cur->dupkey) {
206 data = cur[0].addroff;
207 mask = cur[0].maskoff;
208 key = (u_32_t *)addr + cur[0].offset;
209 for (; key < end; data++, key++, mask++)
210 if ((*key & *mask) != *data)
211 break;
212 if ((end == key) && (cur->root == 0))
213 return (cur); /* Equal keys */
214 }
215 prev = node->parent;
216 key = (u_32_t *)addr;
217
218 for (node = prev; node->root == 0; node = node->parent) {
219 /*
220 * We know that the node hasn't matched so therefore only
221 * the entries in the mask list are searched, not the top
222 * node nor the dupkey list.
223 */
224 masknode = node->masks;
225 for (; masknode != NULL; masknode = masknode->next) {
226 if (masknode->maskbitcount > node->maskbitcount)
227 continue;
228 cur = masknode->node;
229 for (i = ADF_OFF >> 2; i <= node->offset; i++) {
230 if ((key[i] & masknode->mask[i]) ==
231 cur->addrkey[i])
232 return (cur);
233 }
234 }
235 }
236
237 return NULL;
238 }
239
240
241 /* ------------------------------------------------------------------------ */
242 /* Function: ipf_rx_lookup */
243 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */
244 /* added to the tree. */
245 /* Paramters: head(I) - pointer to tree head to search */
246 /* addr(I) - address part of the key to match */
247 /* mask(I) - netmask part of the key to match */
248 /* */
249 /* ipf_rx_lookup searches for an exact match on (addr,mask). The intention */
250 /* is to see if a given key is in the tree, not to see if a route exists. */
251 /* ------------------------------------------------------------------------ */
252 ipf_rdx_node_t *
253 ipf_rx_lookup(head, addr, mask)
254 ipf_rdx_head_t *head;
255 addrfamily_t *addr, *mask;
256 {
257 ipf_rdx_node_t *found;
258 ipf_rdx_node_t *node;
259 u_32_t *akey;
260 int count;
261
262 found = ipf_rx_find_addr(head->root, (u_32_t *)addr);
263 if (found->root == 1)
264 return NULL;
265
266 /*
267 * It is possible to find a matching address in the tree but for the
268 * netmask to not match. If the netmask does not match and there is
269 * no list of alternatives present at dupkey, return a failure.
270 */
271 count = count_mask_bits(mask, NULL);
272 if (count != found->maskbitcount && found->dupkey == NULL)
273 return (NULL);
274
275 akey = (u_32_t *)addr;
276 if ((found->addrkey[found->offset] & found->maskkey[found->offset]) !=
277 akey[found->offset])
278 return NULL;
279
280 if (found->dupkey != NULL) {
281 node = found;
282 while (node != NULL && node->maskbitcount != count)
283 node = node->dupkey;
284 if (node == NULL)
285 return (NULL);
286 found = node;
287 }
288 return found;
289 }
290
291
292 /* ------------------------------------------------------------------------ */
293 /* Function: ipf_rx_attach_mask */
294 /* Returns: Nil */
295 /* Parameters: node(I) - pointer to a radix tree node */
296 /* mask(I) - pointer to mask structure to add */
297 /* */
298 /* Add the netmask to the given node in an ordering where the most specific */
299 /* netmask is at the top of the list. */
300 /* ------------------------------------------------------------------------ */
301 static void
302 ipf_rx_attach_mask(node, mask)
303 ipf_rdx_node_t *node;
304 ipf_rdx_mask_t *mask;
305 {
306 ipf_rdx_mask_t **pm;
307 ipf_rdx_mask_t *m;
308
309 for (pm = &node->masks; (m = *pm) != NULL; pm = &m->next)
310 if (m->maskbitcount < mask->maskbitcount)
311 break;
312 mask->next = *pm;
313 *pm = mask;
314 }
315
316
317 /* ------------------------------------------------------------------------ */
318 /* Function: ipf_rx_insert */
319 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */
320 /* added to the tree. */
321 /* Paramters: head(I) - pointer to tree head to add nodes to */
322 /* nodes(I) - pointer to radix nodes to be added */
323 /* dup(O) - set to 1 if node is a duplicate, else 0. */
324 /* */
325 /* Add the new radix tree entry that owns nodes[] to the tree given by head.*/
326 /* If there is already a matching key in the table, "dup" will be set to 1 */
327 /* and the existing node pointer returned if there is a complete key match. */
328 /* A complete key match is a matching of all key data that is presented by */
329 /* by the netmask. */
330 /* ------------------------------------------------------------------------ */
331 static ipf_rdx_node_t *
332 ipf_rx_insert(head, nodes, dup)
333 ipf_rdx_head_t *head;
334 ipf_rdx_node_t nodes[2];
335 int *dup;
336 {
337 ipf_rdx_mask_t **pmask;
338 ipf_rdx_node_t *node;
339 ipf_rdx_node_t *prev;
340 ipf_rdx_mask_t *mask;
341 ipf_rdx_node_t *cur;
342 u_32_t nodemask;
343 u_32_t *addr;
344 u_32_t *data;
345 int nodebits;
346 u_32_t *key;
347 u_32_t *end;
348 u_32_t bits;
349 int nodekey;
350 int nodeoff;
351 int nlen;
352 int len;
353
354 addr = nodes[0].addrkey;
355
356 node = ipf_rx_find_addr(head->root, addr);
357 len = ((addrfamily_t *)addr)->adf_len;
358 key = (u_32_t *)&((addrfamily_t *)addr)->adf_addr;
359 data= (u_32_t *)&((addrfamily_t *)node->addrkey)->adf_addr;
360 end = (u_32_t *)((u_char *)addr + len);
361 for (; key < end; data++, key++)
362 if (*key != *data)
363 break;
364 if (end == data) {
365 *dup = 1;
366 return (node); /* Equal keys */
367 }
368 *dup = 0;
369
370 bits = (ntohl(*data) ^ ntohl(*key));
371 for (nlen = 0; bits != 0; nlen++) {
372 if ((bits & 0x80000000) != 0)
373 break;
374 bits <<= 1;
375 }
376 nlen += ADF_OFF_BITS;
377 nodes[1].index = nlen;
378 nodes[1].bitmask = htonl(0x80000000 >> (nlen & 0x1f));
379
380 /*
381 * Walk through the tree and look for the correct place to attach
382 * this node. ipf_rx_fin_addr is not used here because the place
383 * to attach this node may be an internal node (same key, different
384 * netmask.) Additionally, the depth of the search is forcibly limited
385 * here to not exceed the netmask, so that a short netmask will be
386 * added higher up the tree even if there are lower branches.
387 */
388 cur = head->root;
389 key = nodes[0].addrkey;
390 do {
391 prev = cur;
392 if (key[cur->offset] & cur->bitmask) {
393 cur = cur->right;
394 } else {
395 cur = cur->left;
396 }
397 } while (nlen > (unsigned)cur->index);
398
399 if ((key[prev->offset] & prev->bitmask) == 0) {
400 prev->left = &nodes[1];
401 } else {
402 prev->right = &nodes[1];
403 }
404 cur->parent = &nodes[1];
405 nodes[1].parent = prev;
406 if ((key[cur->offset] & nodes[1].bitmask) == 0) {
407 nodes[1].right = cur;
408 } else {
409 nodes[1].right = &nodes[0];
410 nodes[1].left = cur;
411 }
412
413 nodeoff = nodes[0].offset;
414 nodekey = nodes[0].addrkey[nodeoff];
415 nodemask = nodes[0].lastmask;
416 nodebits = nodes[0].maskbitcount;
417 prev = NULL;
418 /*
419 * Find the node up the tree with the largest pattern that still
420 * matches the node being inserted to see if this mask can be
421 * moved there.
422 */
423 for (cur = nodes[1].parent; cur->root == 0; cur = cur->parent) {
424 if (cur->maskbitcount <= nodebits)
425 break;
426 if (((cur - 1)->addrkey[nodeoff] & nodemask) != nodekey)
427 break;
428 prev = cur;
429 }
430
431 KMALLOC(mask, ipf_rdx_mask_t *);
432 if (mask == NULL)
433 return NULL;
434 bzero(mask, sizeof(*mask));
435 mask->next = NULL;
436 mask->node = &nodes[0];
437 mask->maskbitcount = nodebits;
438 mask->mask = nodes[0].maskkey;
439 nodes[0].mymask = mask;
440
441 if (prev != NULL) {
442 ipf_rdx_mask_t *m;
443
444 for (pmask = &prev->masks; (m = *pmask) != NULL;
445 pmask = &m->next) {
446 if (m->maskbitcount < nodebits)
447 break;
448 }
449 } else {
450 /*
451 * No higher up nodes qualify, so attach mask locally.
452 */
453 pmask = &nodes[0].masks;
454 }
455 mask->next = *pmask;
456 *pmask = mask;
457
458 /*
459 * Search the mask list on each child to see if there are any masks
460 * there that can be moved up to this newly inserted node.
461 */
462 cur = nodes[1].right;
463 if (cur->root == 0) {
464 for (pmask = &cur->masks; (mask = *pmask) != NULL; ) {
465 if (mask->maskbitcount < nodebits) {
466 *pmask = mask->next;
467 ipf_rx_attach_mask(&nodes[0], mask);
468 } else {
469 pmask = &mask->next;
470 }
471 }
472 }
473 cur = nodes[1].left;
474 if (cur->root == 0 && cur != &nodes[0]) {
475 for (pmask = &cur->masks; (mask = *pmask) != NULL; ) {
476 if (mask->maskbitcount < nodebits) {
477 *pmask = mask->next;
478 ipf_rx_attach_mask(&nodes[0], mask);
479 } else {
480 pmask = &mask->next;
481 }
482 }
483 }
484 return (&nodes[0]);
485 }
486
487 /* ------------------------------------------------------------------------ */
488 /* Function: ipf_rx_addroute */
489 /* Returns: ipf_rdx_node_t * - NULL on error, else pointer to the node */
490 /* added to the tree. */
491 /* Paramters: head(I) - pointer to tree head to search */
492 /* addr(I) - address portion of "route" to add */
493 /* mask(I) - netmask portion of "route" to add */
494 /* nodes(I) - radix tree data nodes inside allocate structure */
495 /* */
496 /* Attempt to add a node to the radix tree. The key for the node is the */
497 /* (addr,mask). No memory allocation for the radix nodes themselves is */
498 /* performed here, the data structure that this radix node is being used to */
499 /* find is expected to house the node data itself however the call to */
500 /* ipf_rx_insert() will attempt to allocate memory in order for netmask to */
501 /* be promoted further up the tree. */
502 /* In this case, the ip_pool_node_t structure from ip_pool.h contains both */
503 /* the key material (addr,mask) and the radix tree nodes[]. */
504 /* */
505 /* The mechanics of inserting the node into the tree is handled by the */
506 /* function ipf_rx_insert() above. Here, the code deals with the case */
507 /* where the data to be inserted is a duplicate. */
508 /* ------------------------------------------------------------------------ */
509 ipf_rdx_node_t *
510 ipf_rx_addroute(head, addr, mask, nodes)
511 ipf_rdx_head_t *head;
512 addrfamily_t *addr, *mask;
513 ipf_rdx_node_t *nodes;
514 {
515 ipf_rdx_node_t *node;
516 ipf_rdx_node_t *prev;
517 ipf_rdx_node_t *x;
518 int dup;
519
520 buildnodes(addr, mask, nodes);
521 x = ipf_rx_insert(head, nodes, &dup);
522 if (x == NULL)
523 return NULL;
524
525 if (dup == 1) {
526 node = &nodes[0];
527 prev = NULL;
528 /*
529 * The duplicate list is kept sorted with the longest
530 * mask at the top, meaning that the most specific entry
531 * in the listis found first. This list thus allows for
532 * duplicates such as 128.128.0.0/32 and 128.128.0.0/16.
533 */
534 while ((x != NULL) && (x->maskbitcount > node->maskbitcount)) {
535 prev = x;
536 x = x->dupkey;
537 }
538
539 /*
540 * Is it a complete duplicate? If so, return NULL and
541 * fail the insert. Otherwise, insert it into the list
542 * of netmasks active for this key.
543 */
544 if ((x != NULL) && (x->maskbitcount == node->maskbitcount))
545 return (NULL);
546
547 if (prev != NULL) {
548 nodes[0].dupkey = x;
549 prev->dupkey = &nodes[0];
550 nodes[0].parent = prev;
551 if (x != NULL)
552 x->parent = &nodes[0];
553 } else {
554 nodes[0].dupkey = x->dupkey;
555 prev = x->parent;
556 nodes[0].parent = prev;
557 x->parent = &nodes[0];
558 if (prev->left == x)
559 prev->left = &nodes[0];
560 else
561 prev->right = &nodes[0];
562 }
563 }
564
565 return &nodes[0];
566 }
567
568
569 /* ------------------------------------------------------------------------ */
570 /* Function: ipf_rx_delete */
571 /* Returns: ipf_rdx_node_t * - NULL on error, else node removed from */
572 /* the tree. */
573 /* Paramters: head(I) - pointer to tree head to search */
574 /* addr(I) - pointer to the address part of the key */
575 /* mask(I) - pointer to the netmask part of the key */
576 /* */
577 /* Search for an entry in the radix tree that is an exact match for (addr, */
578 /* mask) and remove it if it exists. In the case where (addr,mask) is a not */
579 /* a unique key, the tree structure itself is not changed - only the list */
580 /* of duplicate keys. */
581 /* ------------------------------------------------------------------------ */
582 ipf_rdx_node_t *
583 ipf_rx_delete(head, addr, mask)
584 ipf_rdx_head_t *head;
585 addrfamily_t *addr, *mask;
586 {
587 ipf_rdx_mask_t **pmask;
588 ipf_rdx_node_t *parent;
589 ipf_rdx_node_t *found;
590 ipf_rdx_node_t *prev;
591 ipf_rdx_node_t *node;
592 ipf_rdx_node_t *cur;
593 ipf_rdx_mask_t *m;
594 int count;
595
596 found = ipf_rx_find_addr(head->root, (u_32_t *)addr);
597 if (found->root == 1)
598 return NULL;
599 count = count_mask_bits(mask, NULL);
600 parent = found->parent;
601 if (found->dupkey != NULL) {
602 node = found;
603 while (node != NULL && node->maskbitcount != count)
604 node = node->dupkey;
605 if (node == NULL)
606 return (NULL);
607 if (node != found) {
608 /*
609 * Remove from the dupkey list. Here, "parent" is
610 * the previous node on the list (rather than tree)
611 * and "dupkey" is the next node on the list.
612 */
613 parent = node->parent;
614 parent->dupkey = node->dupkey;
615 node->dupkey->parent = parent;
616 } else {
617 /*
618 *
619 * When removing the top node of the dupkey list,
620 * the pointers at the top of the list that point
621 * to other tree nodes need to be preserved and
622 * any children must have their parent updated.
623 */
624 node = node->dupkey;
625 node->parent = found->parent;
626 node->right = found->right;
627 node->left = found->left;
628 found->right->parent = node;
629 found->left->parent = node;
630 if (parent->left == found)
631 parent->left = node;
632 else
633 parent->right= node;
634 }
635 } else {
636 if (count != found->maskbitcount)
637 return (NULL);
638 /*
639 * Remove the node from the tree and reconnect the subtree
640 * below.
641 */
642 /*
643 * If there is a tree to the left, look for something to
644 * attach in place of "found".
645 */
646 prev = found + 1;
647 if (parent != found + 1) {
648 cur = parent->parent;
649 if (cur->right == parent) {
650 if (prev->right != parent)
651 prev->right->parent = parent;
652 if (cur != prev) {
653 if (parent->left != parent - 1) {
654 cur->right = parent->left;
655 parent->left->parent = cur;
656 } else {
657 cur->right = parent - 1;
658 (parent - 1)->parent = cur;
659 }
660 }
661
662 if (cur != prev) {
663 if (parent->left == found)
664 (parent - 1)->parent = parent;
665 }
666 if (prev->parent->right == prev) {
667 prev->parent->right = parent;
668 } else {
669 prev->parent->left = parent;
670 }
671 if (prev->left->index > 0) {
672 prev->left->parent = parent;
673 if (parent->left != found)
674 parent->right = parent->left;
675 parent->left = prev->left;
676 }
677 if (prev->right->index > 0) {
678 if (prev->right != parent) {
679 prev->right->parent = parent;
680 parent->right = prev->right;
681 } else if (parent->left->index < 0) {
682 parent->right = parent - 1;
683 }
684 } else if (parent->right == found) {
685 parent->right = parent - 1;
686 }
687 parent->parent = prev->parent;
688 } else {
689 parent->left = parent - 1;
690
691 if (cur->parent->right == cur)
692 cur->parent->right = parent;
693 else
694 cur->parent->left = parent;
695 cur->right->parent = parent;
696 parent->parent = cur->parent;
697 parent->right = cur->right;
698 }
699 parent->bitmask = prev->bitmask;
700 parent->offset = prev->offset;
701 parent->index = prev->index;
702 } else {
703 /*
704 * We found an edge node.
705 */
706 cur = parent->parent;
707 if (cur->left == parent) {
708 if (parent->left == found) {
709 cur->left = parent->right;
710 parent->right->parent = cur;
711 } else {
712 cur->left = parent->left;
713 parent->left->parent = cur;
714 }
715 } else {
716 if (parent->right != found) {
717 cur->right = parent->right;
718 parent->right->parent = cur;
719 } else {
720 cur->right = parent->left;
721 prev->left->parent = cur;
722 }
723 }
724 }
725 }
726
727 /*
728 * Remove mask associated with this node.
729 */
730 for (cur = parent; cur->root == 0; cur = cur->parent) {
731 ipf_rdx_mask_t **pm;
732
733 if (cur->maskbitcount <= found->maskbitcount)
734 break;
735 if (((cur - 1)->addrkey[found->offset] & found->bitmask) !=
736 found->addrkey[found->offset])
737 break;
738 for (pm = &cur->masks; (m = *pm) != NULL; )
739 if (m->node == cur) {
740 *pm = m->next;
741 break;
742 } else {
743 pm = &m->next;
744 }
745 }
746 KFREE(found->mymask);
747
748 /*
749 * Masks that have been brought up to this node from below need to
750 * be sent back down.
751 */
752 for (pmask = &parent->masks; (m = *pmask) != NULL; ) {
753 *pmask = m->next;
754 cur = m->node;
755 if (cur == found)
756 continue;
757 if (found->addrkey[cur->offset] & cur->lastmask) {
758 ipf_rx_attach_mask(parent->right, m);
759 } else if (parent->left != found) {
760 ipf_rx_attach_mask(parent->left, m);
761 }
762 }
763
764 return (found);
765 }
766
767
768 /* ------------------------------------------------------------------------ */
769 /* Function: ipf_rx_walktree */
770 /* Returns: Nil */
771 /* Paramters: head(I) - pointer to tree head to search */
772 /* walker(I) - function to call for each node in the tree */
773 /* arg(I) - parameter to pass to walker, in addition to the */
774 /* node pointer */
775 /* */
776 /* A standard tree walking function except that it is iterative, rather */
777 /* than recursive and tracks the next node in case the "walker" function */
778 /* should happen to delete and free the current node. It thus goes without */
779 /* saying that the "walker" function is not permitted to cause any change */
780 /* in the validity of the data found at either the left or right child. */
781 /* ------------------------------------------------------------------------ */
782 void
783 ipf_rx_walktree(head, walker, arg)
784 ipf_rdx_head_t *head;
785 radix_walk_func_t walker;
786 void *arg;
787 {
788 ipf_rdx_node_t *next;
789 ipf_rdx_node_t *node = head->root;
790 ipf_rdx_node_t *base;
791
792 while (node->index >= 0)
793 node = node->left;
794
795 for (;;) {
796 base = node;
797 while ((node->parent->right == node) && (node->root == 0))
798 node = node->parent;
799
800 for (node = node->parent->right; node->index >= 0; )
801 node = node->left;
802 next = node;
803
804 for (node = base; node != NULL; node = base) {
805 base = node->dupkey;
806 if (node->root == 0)
807 walker(node, arg);
808 }
809 node = next;
810 if (node->root)
811 return;
812 }
813 }
814
815
816 /* ------------------------------------------------------------------------ */
817 /* Function: ipf_rx_inithead */
818 /* Returns: int - 0 = success, else failure */
819 /* Paramters: softr(I) - pointer to radix context */
820 /* headp(O) - location for where to store allocated tree head */
821 /* */
822 /* This function allocates and initialises a radix tree head structure. */
823 /* As a traditional radix tree, node 0 is used as the "0" sentinel and node */
824 /* "2" is used as the all ones sentinel, leaving node "1" as the root from */
825 /* which the tree is hung with node "0" on its left and node "2" to the */
826 /* right. The context, "softr", is used here to provide a common source of */
827 /* the zeroes and ones data rather than have one per head. */
828 /* ------------------------------------------------------------------------ */
829 int
830 ipf_rx_inithead(softr, headp)
831 radix_softc_t *softr;
832 ipf_rdx_head_t **headp;
833 {
834 ipf_rdx_head_t *ptr;
835 ipf_rdx_node_t *node;
836
837 KMALLOC(ptr, ipf_rdx_head_t *);
838 *headp = ptr;
839 if (ptr == NULL)
840 return -1;
841 bzero(ptr, sizeof(*ptr));
842 node = ptr->nodes;
843 ptr->root = node + 1;
844 node[0].index = ADF_OFF_BITS;
845 node[0].index = -1 - node[0].index;
846 node[1].index = ADF_OFF_BITS;
847 node[2].index = node[0].index;
848 node[0].parent = node + 1;
849 node[1].parent = node + 1;
850 node[2].parent = node + 1;
851 node[1].bitmask = htonl(0x80000000);
852 node[0].root = 1;
853 node[1].root = 1;
854 node[2].root = 1;
855 node[0].offset = ADF_OFF_BITS >> 5;
856 node[1].offset = ADF_OFF_BITS >> 5;
857 node[2].offset = ADF_OFF_BITS >> 5;
858 node[1].left = &node[0];
859 node[1].right = &node[2];
860 node[0].addrkey = (u_32_t *)softr->zeros;
861 node[2].addrkey = (u_32_t *)softr->ones;
862 #ifdef RDX_DEBUG
863 (void) strcpy(node[0].name, "0_ROOT");
864 (void) strcpy(node[1].name, "1_ROOT");
865 (void) strcpy(node[2].name, "2_ROOT");
866 #endif
867
868 ptr->addaddr = ipf_rx_addroute;
869 ptr->deladdr = ipf_rx_delete;
870 ptr->lookup = ipf_rx_lookup;
871 ptr->matchaddr = ipf_rx_match;
872 ptr->walktree = ipf_rx_walktree;
873 return 0;
874 }
875
876 void
877 ipf_rx_freehead(head)
878 ipf_rdx_head_t *head;
879 {
880 KFREE(head);
881 }
882
883 void *
884 ipf_rx_create()
885 {
886 radix_softc_t *softr;
887
888 KMALLOC(softr, radix_softc_t *);
889 if (softr == NULL)
890 return NULL;
891 bzero((char *)softr, sizeof(*softr));
892
893 return softr;
894 }
895
896 int
897 ipf_rx_init(ctx)
898 void *ctx;
899 {
900 radix_softc_t *softr = ctx;
901
902 KMALLOCS(softr->zeros, u_char *, 3 * sizeof(addrfamily_t));
903 if (softr->zeros == NULL)
904 return (-1);
905 softr->ones = softr->zeros + sizeof(addrfamily_t);
906 memset(softr->ones, 0xff, sizeof(addrfamily_t));
907 return (0);
908 }
909
910 void
911 ipf_rx_destroy(ctx)
912 void *ctx;
913 {
914 radix_softc_t *softr = ctx;
915
916 if (softr->zeros != NULL)
917 KFREES(softr->zeros, 3 * sizeof(addrfamily_t));
918 KFREE(softr);
919 }
920
921 /* ====================================================================== */
922
923 #ifdef RDX_DEBUG
924
925 #define NAME(x) ((x)->index < 0 ? (x)->name : (x)->name)
926 #define GNAME(y) ((y) == NULL ? "NULL" : NAME(y))
927
928 typedef struct myst {
929 struct ipf_rdx_node nodes[2];
930 addrfamily_t dst;
931 addrfamily_t mask;
932 struct myst *next;
933 int printed;
934 } myst_t;
935
936 static int nodecount = 0;
937 myst_t *myst_top = NULL;
938
939 void add_addr(ipf_rdx_head_t *, int , int);
940 void checktree(ipf_rdx_head_t *);
941 void delete_addr(ipf_rdx_head_t *rnh, int item);
942 void dumptree(ipf_rdx_head_t *rnh);
943 void nodeprinter(ipf_rdx_node_t *, void *);
944 void printroots(ipf_rdx_head_t *);
945 void random_add(ipf_rdx_head_t *);
946 void random_delete(ipf_rdx_head_t *);
947 void test_addr(ipf_rdx_head_t *rnh, int pref, u_32_t addr, int);
948
949 static void
950 ipf_rx_freenode(node, arg)
951 ipf_rdx_node_t *node;
952 void *arg;
953 {
954 ipf_rdx_head_t *head = arg;
955 ipf_rdx_node_t *rv;
956 myst_t *stp;
957
958 stp = (myst_t *)node;
959 rv = ipf_rx_delete(head, &stp->dst, &stp->mask);
960 if (rv != NULL) {
961 free(rv);
962 }
963 }
964
965 void
966 nodeprinter(node, arg)
967 ipf_rdx_node_t *node;
968 void *arg;
969 {
970 myst_t *stp = (myst_t *)node;
971
972 printf("Node %-9.9s L %-9.9s R %-9.9s P %9.9s/%-9.9s %s/%d\n",
973 node[0].name,
974 GNAME(node[1].left), GNAME(node[1].right),
975 GNAME(node[0].parent), GNAME(node[1].parent),
976 inet_ntoa(stp->dst.adf_addr.in4), node[0].maskbitcount);
977 }
978
979 void
980 printnode(stp)
981 myst_t *stp;
982 {
983 ipf_rdx_node_t *node = &stp->nodes[0];
984
985 if (stp->nodes[0].index > 0)
986 stp = (myst_t *)&stp->nodes[-1];
987
988 printf("Node %-9.9s ", node[0].name);
989 printf("L %-9.9s ", GNAME(node[1].left));
990 printf("R %-9.9s ", GNAME(node[1].right));
991 printf("P %9.9s", GNAME(node[0].parent));
992 printf("/%-9.9s ", GNAME(node[1].parent));
993 printf("%s\n", inet_ntoa(stp->dst.adf_addr.in4));
994 }
995
996 char *ttable[22][3] = {
997 { "127.192.0.0", "255.255.255.0", "d" },
998 { "127.128.0.0", "255.255.255.0", "d" },
999 { "127.96.0.0", "255.255.255.0", "d" },
1000 { "127.80.0.0", "255.255.255.0", "d" },
1001 { "127.72.0.0", "255.255.255.0", "d" },
1002 { "127.64.0.0", "255.255.255.0", "d" },
1003 { "127.56.0.0", "255.255.255.0", "d" },
1004 { "127.48.0.0", "255.255.255.0", "d" },
1005 { "127.40.0.0", "255.255.255.0", "d" },
1006 { "127.32.0.0", "255.255.255.0", "d" },
1007 { "127.24.0.0", "255.255.255.0", "d" },
1008 { "127.16.0.0", "255.255.255.0", "d" },
1009 { "127.8.0.0", "255.255.255.0", "d" },
1010 { "124.0.0.0", "255.0.0.0", "d" },
1011 { "125.0.0.0", "255.0.0.0", "d" },
1012 { "126.0.0.0", "255.0.0.0", "d" },
1013 { "127.0.0.0", "255.0.0.0", "d" },
1014 { "10.0.0.0", "255.0.0.0", "d" },
1015 { "128.250.0.0", "255.255.0.0", "d" },
1016 { "192.168.0.0", "255.255.0.0", "d" },
1017 { "192.168.1.0", "255.255.255.0", "d" },
1018 { NULL, NULL }
1019 };
1020
1021 char *mtable[15][1] = {
1022 { "9.0.0.0" },
1023 { "9.0.0.1" },
1024 { "11.0.0.0" },
1025 { "11.0.0.1" },
1026 { "127.0.0.1" },
1027 { "127.0.1.0" },
1028 { "255.255.255.0" },
1029 { "126.0.0.1" },
1030 { "128.251.0.0" },
1031 { "128.251.0.1" },
1032 { "128.251.255.255" },
1033 { "129.250.0.0" },
1034 { "129.250.0.1" },
1035 { "192.168.255.255" },
1036 { NULL }
1037 };
1038
1039 int forder[22] = {
1040 14, 13, 12, 5, 10, 3, 19, 7, 4, 20, 8,
1041 2, 17, 9, 16, 11, 15, 1, 6, 18, 0, 21
1042 };
1043
1044 void
1045 printroots(rnh)
1046 ipf_rdx_head_t *rnh;
1047 {
1048 printf("Root.0.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n",
1049 GNAME(&rnh->nodes[0]),
1050 rnh->nodes[0].index, GNAME(rnh->nodes[0].parent),
1051 GNAME(rnh->nodes[0].left), GNAME(rnh->nodes[0].right));
1052 printf("Root.1.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n",
1053 GNAME(&rnh->nodes[1]),
1054 rnh->nodes[1].index, GNAME(rnh->nodes[1].parent),
1055 GNAME(rnh->nodes[1].left), GNAME(rnh->nodes[1].right));
1056 printf("Root.2.%s b %3d p %-9.9s l %-9.9s r %-9.9s\n",
1057 GNAME(&rnh->nodes[2]),
1058 rnh->nodes[2].index, GNAME(rnh->nodes[2].parent),
1059 GNAME(rnh->nodes[2].left), GNAME(rnh->nodes[2].right));
1060 }
1061
1062 int
1063 main(int argc, char *argv[])
1064 {
1065 ipf_rdx_head_t *rnh;
1066 radix_softc_t *ctx;
1067 int j;
1068 int i;
1069
1070 rnh = NULL;
1071
1072 ctx = ipf_rx_create();
1073 ipf_rx_init(ctx);
1074 ipf_rx_inithead(ctx, &rnh);
1075
1076 printf("=== ADD-0 ===\n");
1077 for (i = 0; ttable[i][0] != NULL; i++) {
1078 add_addr(rnh, i, i);
1079 checktree(rnh);
1080 }
1081 ipf_rx_walktree(rnh, nodeprinter, NULL);
1082 printf("=== DELETE-0 ===\n");
1083 for (i = 0; ttable[i][0] != NULL; i++) {
1084 delete_addr(rnh, i);
1085 ipf_rx_walktree(rnh, nodeprinter, NULL);
1086 }
1087 printf("=== ADD-1 ===\n");
1088 for (i = 0; ttable[i][0] != NULL; i++) {
1089 add_addr(rnh, i, forder[i]);
1090 checktree(rnh);
1091 }
1092 printroots(rnh);
1093 dumptree(rnh);
1094 ipf_rx_walktree(rnh, nodeprinter, NULL);
1095 printf("=== TEST-1 ===\n");
1096 for (i = 0; ttable[i][0] != NULL; i++) {
1097 test_addr(rnh, i, inet_addr(ttable[i][0]), -1);
1098 }
1099
1100 printf("=== TEST-2 ===\n");
1101 for (i = 0; mtable[i][0] != NULL; i++) {
1102 test_addr(rnh, i, inet_addr(mtable[i][0]), -1);
1103 }
1104 printf("=== DELETE-1 ===\n");
1105 for (i = 0; ttable[i][0] != NULL; i++) {
1106 if (ttable[i][2][0] != 'd')
1107 continue;
1108 delete_addr(rnh, i);
1109 for (j = 0; ttable[j][0] != NULL; j++) {
1110 test_addr(rnh, i, inet_addr(ttable[j][0]), 3);
1111 }
1112 ipf_rx_walktree(rnh, nodeprinter, NULL);
1113 }
1114
1115 printroots(rnh);
1116 dumptree(rnh);
1117
1118 printf("=== ADD-2 ===\n");
1119 random_add(rnh);
1120 checktree(rnh);
1121 printroots(rnh);
1122 dumptree(rnh);
1123 ipf_rx_walktree(rnh, nodeprinter, NULL);
1124 printf("=== DELETE-2 ===\n");
1125 random_delete(rnh);
1126 checktree(rnh);
1127 printroots(rnh);
1128 dumptree(rnh);
1129
1130 ipf_rx_walktree(rnh, ipf_rx_freenode, rnh);
1131
1132 return 0;
1133 }
1134
1135 void
1136 dumptree(rnh)
1137 ipf_rdx_head_t *rnh;
1138 {
1139 myst_t *stp;
1140
1141 printf("VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV\n");
1142 for (stp = myst_top; stp; stp = stp->next)
1143 printnode(stp);
1144 printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
1145 }
1146
1147 void
1148 test_addr(rnh, pref, addr, limit)
1149 ipf_rdx_head_t *rnh;
1150 int pref;
1151 u_32_t addr;
1152 {
1153 static int extras[14] = { 0, -1, 1, 3, 5, 8, 9,
1154 15, 16, 19, 255, 256, 65535, 65536
1155 };
1156 ipf_rdx_node_t *rn;
1157 addrfamily_t af;
1158 myst_t *stp;
1159 int i;
1160
1161 memset(&af, 0, sizeof(af));
1162 af.adf_len = sizeof(af.adf_addr);
1163 if (limit < 0 || limit > 14)
1164 limit = 14;
1165
1166 for (i = 0; i < limit; i++) {
1167 af.adf_addr.in4.s_addr = htonl(ntohl(addr) + extras[i]);
1168 printf("%d.%d.LOOKUP(%s)", pref, i, inet_ntoa(af.adf_addr.in4));
1169 rn = ipf_rx_match(rnh, &af);
1170 stp = (myst_t *)rn;
1171 printf(" = %s (%s/%d)\n", GNAME(rn),
1172 rn ? inet_ntoa(stp->dst.adf_addr.in4) : "NULL",
1173 rn ? rn->maskbitcount : 0);
1174 }
1175 }
1176
1177 void
1178 delete_addr(rnh, item)
1179 ipf_rdx_head_t *rnh;
1180 int item;
1181 {
1182 ipf_rdx_node_t *rn;
1183 addrfamily_t mask;
1184 addrfamily_t af;
1185 myst_t **pstp;
1186 myst_t *stp;
1187
1188 memset(&af, 0, sizeof(af));
1189 memset(&mask, 0, sizeof(mask));
1190 af.adf_family = AF_INET;
1191 af.adf_len = sizeof(af.adf_addr);
1192 mask.adf_len = sizeof(mask.adf_addr);
1193
1194 af.adf_addr.in4.s_addr = inet_addr(ttable[item][0]);
1195 mask.adf_addr.in4.s_addr = inet_addr(ttable[item][1]);
1196 printf("DELETE(%s)\n", inet_ntoa(af.adf_addr.in4));
1197 rn = ipf_rx_delete(rnh, &af, &mask);
1198 printf("%d.delete(%s) = %s\n", item,
1199 inet_ntoa(af.adf_addr.in4), GNAME(rn));
1200
1201 for (pstp = &myst_top; (stp = *pstp) != NULL; pstp = &stp->next)
1202 if (stp == (myst_t *)rn)
1203 break;
1204 *pstp = stp->next;
1205 free(stp);
1206 nodecount--;
1207 checktree(rnh);
1208 }
1209
1210 void
1211 add_addr(rnh, n, item)
1212 ipf_rdx_head_t *rnh;
1213 int n, item;
1214 {
1215 ipf_rdx_node_t *rn;
1216 myst_t *stp;
1217
1218 stp = calloc(1, sizeof(*stp));
1219 rn = (ipf_rdx_node_t *)stp;
1220 stp->dst.adf_family = AF_INET;
1221 stp->dst.adf_len = sizeof(stp->dst.adf_addr);
1222 stp->dst.adf_addr.in4.s_addr = inet_addr(ttable[item][0]);
1223 memset(&stp->mask, 0xff, offsetof(addrfamily_t, adf_addr));
1224 stp->mask.adf_len = sizeof(stp->mask.adf_addr);
1225 stp->mask.adf_addr.in4.s_addr = inet_addr(ttable[item][1]);
1226 stp->next = myst_top;
1227 myst_top = stp;
1228 (void) sprintf(rn[0].name, "_BORN.0");
1229 (void) sprintf(rn[1].name, "_BORN.1");
1230 rn = ipf_rx_addroute(rnh, &stp->dst, &stp->mask, stp->nodes);
1231 (void) sprintf(rn[0].name, "%d_NODE.0", item);
1232 (void) sprintf(rn[1].name, "%d_NODE.1", item);
1233 printf("ADD %d/%d %s/%s\n", n, item, rn[0].name, rn[1].name);
1234 nodecount++;
1235 checktree(rnh);
1236 }
1237
1238 void
1239 checktree(ipf_rdx_head_t *head)
1240 {
1241 myst_t *s1;
1242 ipf_rdx_node_t *rn;
1243
1244 if (nodecount <= 1)
1245 return;
1246
1247 for (s1 = myst_top; s1 != NULL; s1 = s1->next) {
1248 int fault = 0;
1249 rn = &s1->nodes[1];
1250 if (rn->right->parent != rn)
1251 fault |= 1;
1252 if (rn->left->parent != rn)
1253 fault |= 2;
1254 if (rn->parent->left != rn && rn->parent->right != rn)
1255 fault |= 4;
1256 if (fault != 0) {
1257 printf("FAULT %#x %s\n", fault, rn->name);
1258 printroots(head);
1259 dumptree(head);
1260 ipf_rx_walktree(head, nodeprinter, NULL);
1261 }
1262 }
1263 }
1264
1265 int *
1266 randomize(int *pnitems)
1267 {
1268 int *order;
1269 int nitems;
1270 int choice;
1271 int j;
1272 int i;
1273
1274 nitems = sizeof(ttable) / sizeof(ttable[0]);
1275 *pnitems = nitems;
1276 order = calloc(nitems, sizeof(*order));
1277 srandom(getpid() * time(NULL));
1278 memset(order, 0xff, nitems * sizeof(*order));
1279 order[21] = 21;
1280 for (i = 0; i < nitems - 1; i++) {
1281 do {
1282 choice = rand() % (nitems - 1);
1283 for (j = 0; j < nitems; j++)
1284 if (order[j] == choice)
1285 break;
1286 } while (j != nitems);
1287 order[i] = choice;
1288 }
1289
1290 return order;
1291 }
1292
1293 void
1294 random_add(rnh)
1295 ipf_rdx_head_t *rnh;
1296 {
1297 int *order;
1298 int nitems;
1299 int i;
1300
1301 order = randomize(&nitems);
1302
1303 for (i = 0; i < nitems - 1; i++) {
1304 add_addr(rnh, i, order[i]);
1305 checktree(rnh);
1306 }
1307 }
1308
1309 void
1310 random_delete(rnh)
1311 ipf_rdx_head_t *rnh;
1312 {
1313 int *order;
1314 int nitems;
1315 int i;
1316
1317 order = randomize(&nitems);
1318
1319 for (i = 0; i < nitems - 1; i++) {
1320 delete_addr(rnh, i);
1321 checktree(rnh);
1322 }
1323 }
1324 #endif /* RDX_DEBUG */
1325