ruby-radix 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gemtest +0 -0
- data/History.txt +8 -0
- data/Manifest.txt +15 -0
- data/PostInstall.txt +3 -0
- data/README.rdoc +160 -0
- data/Rakefile +27 -0
- data/ext/extconf.rb +5 -0
- data/ext/radix.c +859 -0
- data/ext/radixlib.c +677 -0
- data/ext/radixlib.h +161 -0
- data/lib/ruby-radix.rb +6 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/test_helper.rb +3 -0
- data/test/test_ruby-radix.rb +127 -0
- metadata +129 -0
data/ext/radixlib.c
ADDED
@@ -0,0 +1,677 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 1999-2000
|
3
|
+
*
|
4
|
+
* The Regents of the University of Michigan ("The Regents") and
|
5
|
+
* Merit Network, Inc. All rights reserved. Redistribution and use
|
6
|
+
* in source and binary forms, with or without modification, are
|
7
|
+
* permitted provided that the following conditions are met:
|
8
|
+
*
|
9
|
+
* 1. Redistributions of source code must retain the above
|
10
|
+
* copyright notice, this list of conditions and the
|
11
|
+
* following disclaimer.
|
12
|
+
*
|
13
|
+
* 2. Redistributions in binary form must reproduce the above
|
14
|
+
* copyright notice, this list of conditions and the
|
15
|
+
* following disclaimer in the documentation and/or other
|
16
|
+
* materials provided with the distribution.
|
17
|
+
*
|
18
|
+
* 3. All advertising materials mentioning features or use of
|
19
|
+
* this software must display the following acknowledgement:
|
20
|
+
*
|
21
|
+
* This product includes software developed by the University of
|
22
|
+
* Michigan, Merit Network, Inc., and their contributors.
|
23
|
+
*
|
24
|
+
* 4. Neither the name of the University, Merit Network, nor the
|
25
|
+
* names of their contributors may be used to endorse or
|
26
|
+
* promote products derived from this software without
|
27
|
+
* specific prior written permission.
|
28
|
+
*
|
29
|
+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS"
|
30
|
+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
31
|
+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
32
|
+
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TH E REGENTS
|
33
|
+
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
34
|
+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
35
|
+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
36
|
+
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HO WEVER CAUSED
|
37
|
+
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
38
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
39
|
+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
40
|
+
* POSSIBILITY OF SUCH DAMAGE.
|
41
|
+
*/
|
42
|
+
/*
|
43
|
+
* Portions Copyright (c) 2004,2005 Damien Miller <djm@mindrot.org>
|
44
|
+
*
|
45
|
+
* Permission to use, copy, modify, and distribute this software for any
|
46
|
+
* purpose with or without fee is hereby granted, provided that the above
|
47
|
+
* copyright notice and this permission notice appear in all copies.
|
48
|
+
*
|
49
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
50
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
51
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
52
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
53
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
54
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
55
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
56
|
+
*/
|
57
|
+
|
58
|
+
#include <sys/types.h>
|
59
|
+
#include <stdlib.h>
|
60
|
+
#include <stdio.h>
|
61
|
+
#include <string.h>
|
62
|
+
|
63
|
+
#include "radixlib.h"
|
64
|
+
#include "ruby.h"
|
65
|
+
|
66
|
+
/* $Id: radix.c,v 1.17 2007/10/24 06:04:31 djm Exp $ */
|
67
|
+
|
68
|
+
/*
|
69
|
+
* Originally from MRT include/defs.h
|
70
|
+
* $MRTId: defs.h,v 1.1.1.1 2000/08/14 18:46:10 labovit Exp $
|
71
|
+
*/
|
72
|
+
#define BIT_TEST(f, b) ((f) & (b))
|
73
|
+
|
74
|
+
/*
|
75
|
+
* Originally from MRT include/mrt.h
|
76
|
+
* $MRTId: mrt.h,v 1.1.1.1 2000/08/14 18:46:10 labovit Exp $
|
77
|
+
*/
|
78
|
+
#define prefix_tochar(prefix) ((char *)&(prefix)->add)
|
79
|
+
#define prefix_touchar(prefix) ((u_char *)&(prefix)->add)
|
80
|
+
|
81
|
+
/*
|
82
|
+
* Originally from MRT lib/mrt/prefix.c
|
83
|
+
* $MRTId: prefix.c,v 1.1.1.1 2000/08/14 18:46:11 labovit Exp $
|
84
|
+
*/
|
85
|
+
|
86
|
+
#define MALLOC xmalloc
|
87
|
+
#define FREE xfree
|
88
|
+
|
89
|
+
static int
|
90
|
+
comp_with_mask(u_char *addr, u_char *dest, u_int mask)
|
91
|
+
{
|
92
|
+
if (memcmp(addr, dest, mask / 8) == 0) {
|
93
|
+
u_int n = mask / 8;
|
94
|
+
u_int m = ((~0) << (8 - (mask % 8)));
|
95
|
+
|
96
|
+
if (mask % 8 == 0 || (addr[n] & m) == (dest[n] & m))
|
97
|
+
return (1);
|
98
|
+
}
|
99
|
+
return (0);
|
100
|
+
}
|
101
|
+
|
102
|
+
static prefix_t
|
103
|
+
*New_Prefix2(int family, void *dest, int bitlen, prefix_t *prefix)
|
104
|
+
{
|
105
|
+
int dynamic_allocated = 0;
|
106
|
+
int default_bitlen = 32;
|
107
|
+
|
108
|
+
if (family == AF_INET6) {
|
109
|
+
default_bitlen = 128;
|
110
|
+
if (prefix == NULL) {
|
111
|
+
if ((prefix = MALLOC(sizeof(*prefix))) == NULL)
|
112
|
+
return (NULL);
|
113
|
+
memset(prefix, '\0', sizeof(*prefix));
|
114
|
+
dynamic_allocated++;
|
115
|
+
}
|
116
|
+
memcpy(&prefix->add.sin6, dest, 16);
|
117
|
+
} else if (family == AF_INET) {
|
118
|
+
if (prefix == NULL) {
|
119
|
+
if ((prefix = MALLOC(sizeof(*prefix))) == NULL)
|
120
|
+
return (NULL);
|
121
|
+
memset(prefix, '\0', sizeof(*prefix));
|
122
|
+
dynamic_allocated++;
|
123
|
+
}
|
124
|
+
memcpy(&prefix->add.sin, dest, 4);
|
125
|
+
} else
|
126
|
+
return (NULL);
|
127
|
+
|
128
|
+
prefix->bitlen = (bitlen >= 0) ? bitlen : default_bitlen;
|
129
|
+
prefix->family = family;
|
130
|
+
prefix->ref_count = 0;
|
131
|
+
if (dynamic_allocated)
|
132
|
+
prefix->ref_count++;
|
133
|
+
return (prefix);
|
134
|
+
}
|
135
|
+
|
136
|
+
|
137
|
+
static prefix_t
|
138
|
+
*Ref_Prefix(prefix_t *prefix)
|
139
|
+
{
|
140
|
+
if (prefix == NULL)
|
141
|
+
return (NULL);
|
142
|
+
if (prefix->ref_count == 0) {
|
143
|
+
/* make a copy in case of a static prefix */
|
144
|
+
return (New_Prefix2(prefix->family, &prefix->add,
|
145
|
+
prefix->bitlen, NULL));
|
146
|
+
}
|
147
|
+
prefix->ref_count++;
|
148
|
+
return (prefix);
|
149
|
+
}
|
150
|
+
|
151
|
+
|
152
|
+
void
|
153
|
+
Deref_Prefix(prefix_t *prefix)
|
154
|
+
{
|
155
|
+
if (prefix == NULL)
|
156
|
+
return;
|
157
|
+
prefix->ref_count--;
|
158
|
+
if (prefix->ref_count <= 0) {
|
159
|
+
FREE(prefix);
|
160
|
+
return;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
/*
|
165
|
+
* Originally from MRT lib/radix/radix.c
|
166
|
+
* $MRTId: radix.c,v 1.1.1.1 2000/08/14 18:46:13 labovit Exp $
|
167
|
+
*/
|
168
|
+
|
169
|
+
/* these routines support continuous mask only */
|
170
|
+
|
171
|
+
radix_tree_t
|
172
|
+
*New_Radix(void)
|
173
|
+
{
|
174
|
+
radix_tree_t *radix;
|
175
|
+
|
176
|
+
if ((radix = MALLOC(sizeof(*radix))) == NULL)
|
177
|
+
return (NULL);
|
178
|
+
memset(radix, '\0', sizeof(*radix));
|
179
|
+
|
180
|
+
radix->maxbits = 128;
|
181
|
+
radix->head = NULL;
|
182
|
+
radix->num_active_node = 0;
|
183
|
+
return (radix);
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* if func is supplied, it will be called as func(node->data)
|
188
|
+
* before deleting the node
|
189
|
+
*/
|
190
|
+
static void
|
191
|
+
Clear_Radix(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
192
|
+
{
|
193
|
+
if (radix->head) {
|
194
|
+
radix_node_t *Xstack[RADIX_MAXBITS + 1];
|
195
|
+
radix_node_t **Xsp = Xstack;
|
196
|
+
radix_node_t *Xrn = radix->head;
|
197
|
+
|
198
|
+
while (Xrn) {
|
199
|
+
radix_node_t *l = Xrn->l;
|
200
|
+
radix_node_t *r = Xrn->r;
|
201
|
+
|
202
|
+
if (Xrn->prefix) {
|
203
|
+
Deref_Prefix(Xrn->prefix);
|
204
|
+
if (Xrn->data && func)
|
205
|
+
func(Xrn, cbctx);
|
206
|
+
}
|
207
|
+
FREE(Xrn);
|
208
|
+
radix->num_active_node--;
|
209
|
+
|
210
|
+
if (l) {
|
211
|
+
if (r)
|
212
|
+
*Xsp++ = r;
|
213
|
+
Xrn = l;
|
214
|
+
} else if (r) {
|
215
|
+
Xrn = r;
|
216
|
+
} else if (Xsp != Xstack) {
|
217
|
+
Xrn = *(--Xsp);
|
218
|
+
} else {
|
219
|
+
Xrn = (radix_node_t *) 0;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
225
|
+
void
|
226
|
+
Destroy_Radix(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
227
|
+
{
|
228
|
+
Clear_Radix(radix, func, cbctx);
|
229
|
+
FREE(radix);
|
230
|
+
}
|
231
|
+
|
232
|
+
/*
|
233
|
+
* if func is supplied, it will be called as func(node->prefix, node->data)
|
234
|
+
*/
|
235
|
+
void
|
236
|
+
radix_process(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
237
|
+
{
|
238
|
+
radix_node_t *node;
|
239
|
+
|
240
|
+
RADIX_WALK(radix->head, node) {
|
241
|
+
func(node, cbctx);
|
242
|
+
} RADIX_WALK_END;
|
243
|
+
}
|
244
|
+
|
245
|
+
radix_node_t
|
246
|
+
*radix_search_exact(radix_tree_t *radix, prefix_t *prefix)
|
247
|
+
{
|
248
|
+
radix_node_t *node;
|
249
|
+
u_char *addr;
|
250
|
+
u_int bitlen;
|
251
|
+
|
252
|
+
if (radix->head == NULL)
|
253
|
+
return (NULL);
|
254
|
+
|
255
|
+
node = radix->head;
|
256
|
+
addr = prefix_touchar(prefix);
|
257
|
+
bitlen = prefix->bitlen;
|
258
|
+
|
259
|
+
while (node->bit < bitlen) {
|
260
|
+
if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
|
261
|
+
node = node->r;
|
262
|
+
else
|
263
|
+
node = node->l;
|
264
|
+
|
265
|
+
if (node == NULL)
|
266
|
+
return (NULL);
|
267
|
+
}
|
268
|
+
|
269
|
+
if (node->bit > bitlen || node->prefix == NULL)
|
270
|
+
return (NULL);
|
271
|
+
|
272
|
+
if (comp_with_mask(prefix_tochar(node->prefix),
|
273
|
+
prefix_tochar(prefix), bitlen))
|
274
|
+
return (node);
|
275
|
+
|
276
|
+
return (NULL);
|
277
|
+
}
|
278
|
+
|
279
|
+
|
280
|
+
/* if inclusive != 0, "best" may be the given prefix itself */
|
281
|
+
static radix_node_t
|
282
|
+
*radix_search_best2(radix_tree_t *radix, prefix_t *prefix, int inclusive)
|
283
|
+
{
|
284
|
+
radix_node_t *node;
|
285
|
+
radix_node_t *stack[RADIX_MAXBITS + 1];
|
286
|
+
u_char *addr;
|
287
|
+
u_int bitlen;
|
288
|
+
int cnt = 0;
|
289
|
+
|
290
|
+
if (radix->head == NULL)
|
291
|
+
return (NULL);
|
292
|
+
|
293
|
+
node = radix->head;
|
294
|
+
addr = prefix_touchar(prefix);
|
295
|
+
bitlen = prefix->bitlen;
|
296
|
+
|
297
|
+
while (node->bit < bitlen) {
|
298
|
+
if (node->prefix)
|
299
|
+
stack[cnt++] = node;
|
300
|
+
if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
|
301
|
+
node = node->r;
|
302
|
+
else
|
303
|
+
node = node->l;
|
304
|
+
|
305
|
+
if (node == NULL)
|
306
|
+
break;
|
307
|
+
}
|
308
|
+
|
309
|
+
if (inclusive && node && node->prefix)
|
310
|
+
stack[cnt++] = node;
|
311
|
+
|
312
|
+
|
313
|
+
if (cnt <= 0)
|
314
|
+
return (NULL);
|
315
|
+
|
316
|
+
while (--cnt >= 0) {
|
317
|
+
node = stack[cnt];
|
318
|
+
if (comp_with_mask(prefix_tochar(node->prefix),
|
319
|
+
prefix_tochar(prefix), node->prefix->bitlen))
|
320
|
+
return (node);
|
321
|
+
}
|
322
|
+
return (NULL);
|
323
|
+
}
|
324
|
+
|
325
|
+
|
326
|
+
radix_node_t
|
327
|
+
*radix_search_best(radix_tree_t *radix, prefix_t *prefix)
|
328
|
+
{
|
329
|
+
return (radix_search_best2(radix, prefix, 1));
|
330
|
+
}
|
331
|
+
|
332
|
+
|
333
|
+
radix_node_t
|
334
|
+
*radix_lookup(radix_tree_t *radix, prefix_t *prefix)
|
335
|
+
{
|
336
|
+
radix_node_t *node, *new_node, *parent, *glue;
|
337
|
+
u_char *addr, *test_addr;
|
338
|
+
u_int bitlen, check_bit, differ_bit;
|
339
|
+
u_int i, j, r;
|
340
|
+
|
341
|
+
if (radix->head == NULL) {
|
342
|
+
if ((node = MALLOC(sizeof(*node))) == NULL)
|
343
|
+
return (NULL);
|
344
|
+
memset(node, '\0', sizeof(*node));
|
345
|
+
node->bit = prefix->bitlen;
|
346
|
+
node->prefix = Ref_Prefix(prefix);
|
347
|
+
node->parent = NULL;
|
348
|
+
node->l = node->r = NULL;
|
349
|
+
node->data = NULL;
|
350
|
+
radix->head = node;
|
351
|
+
radix->num_active_node++;
|
352
|
+
return (node);
|
353
|
+
}
|
354
|
+
addr = prefix_touchar(prefix);
|
355
|
+
bitlen = prefix->bitlen;
|
356
|
+
node = radix->head;
|
357
|
+
|
358
|
+
while (node->bit < bitlen || node->prefix == NULL) {
|
359
|
+
if (node->bit < radix->maxbits && BIT_TEST(addr[node->bit >> 3],
|
360
|
+
0x80 >> (node->bit & 0x07))) {
|
361
|
+
if (node->r == NULL)
|
362
|
+
break;
|
363
|
+
node = node->r;
|
364
|
+
} else {
|
365
|
+
if (node->l == NULL)
|
366
|
+
break;
|
367
|
+
node = node->l;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
371
|
+
test_addr = prefix_touchar(node->prefix);
|
372
|
+
/* find the first bit different */
|
373
|
+
check_bit = (node->bit < bitlen) ? node->bit : bitlen;
|
374
|
+
differ_bit = 0;
|
375
|
+
for (i = 0; i * 8 < check_bit; i++) {
|
376
|
+
if ((r = (addr[i] ^ test_addr[i])) == 0) {
|
377
|
+
differ_bit = (i + 1) * 8;
|
378
|
+
continue;
|
379
|
+
}
|
380
|
+
/* I know the better way, but for now */
|
381
|
+
for (j = 0; j < 8; j++) {
|
382
|
+
if (BIT_TEST(r, (0x80 >> j)))
|
383
|
+
break;
|
384
|
+
}
|
385
|
+
/* must be found */
|
386
|
+
differ_bit = i * 8 + j;
|
387
|
+
break;
|
388
|
+
}
|
389
|
+
if (differ_bit > check_bit)
|
390
|
+
differ_bit = check_bit;
|
391
|
+
|
392
|
+
parent = node->parent;
|
393
|
+
while (parent && parent->bit >= differ_bit) {
|
394
|
+
node = parent;
|
395
|
+
parent = node->parent;
|
396
|
+
}
|
397
|
+
|
398
|
+
if (differ_bit == bitlen && node->bit == bitlen) {
|
399
|
+
if (node->prefix == NULL)
|
400
|
+
node->prefix = Ref_Prefix(prefix);
|
401
|
+
return (node);
|
402
|
+
}
|
403
|
+
if ((new_node = MALLOC(sizeof(*new_node))) == NULL)
|
404
|
+
return (NULL);
|
405
|
+
memset(new_node, '\0', sizeof(*new_node));
|
406
|
+
new_node->bit = prefix->bitlen;
|
407
|
+
new_node->prefix = Ref_Prefix(prefix);
|
408
|
+
new_node->parent = NULL;
|
409
|
+
new_node->l = new_node->r = NULL;
|
410
|
+
new_node->data = NULL;
|
411
|
+
radix->num_active_node++;
|
412
|
+
|
413
|
+
if (node->bit == differ_bit) {
|
414
|
+
new_node->parent = node;
|
415
|
+
if (node->bit < radix->maxbits && BIT_TEST(addr[node->bit >> 3],
|
416
|
+
0x80 >> (node->bit & 0x07)))
|
417
|
+
node->r = new_node;
|
418
|
+
else
|
419
|
+
node->l = new_node;
|
420
|
+
|
421
|
+
return (new_node);
|
422
|
+
}
|
423
|
+
if (bitlen == differ_bit) {
|
424
|
+
if (bitlen < radix->maxbits && BIT_TEST(test_addr[bitlen >> 3],
|
425
|
+
0x80 >> (bitlen & 0x07)))
|
426
|
+
new_node->r = node;
|
427
|
+
else
|
428
|
+
new_node->l = node;
|
429
|
+
|
430
|
+
new_node->parent = node->parent;
|
431
|
+
if (node->parent == NULL)
|
432
|
+
radix->head = new_node;
|
433
|
+
else if (node->parent->r == node)
|
434
|
+
node->parent->r = new_node;
|
435
|
+
else
|
436
|
+
node->parent->l = new_node;
|
437
|
+
|
438
|
+
node->parent = new_node;
|
439
|
+
} else {
|
440
|
+
if ((glue = MALLOC(sizeof(*glue))) == NULL)
|
441
|
+
return (NULL);
|
442
|
+
memset(glue, '\0', sizeof(*glue));
|
443
|
+
glue->bit = differ_bit;
|
444
|
+
glue->prefix = NULL;
|
445
|
+
glue->parent = node->parent;
|
446
|
+
glue->data = NULL;
|
447
|
+
radix->num_active_node++;
|
448
|
+
if (differ_bit < radix->maxbits &&
|
449
|
+
BIT_TEST(addr[differ_bit >> 3],
|
450
|
+
0x80 >> (differ_bit & 0x07))) {
|
451
|
+
glue->r = new_node;
|
452
|
+
glue->l = node;
|
453
|
+
} else {
|
454
|
+
glue->r = node;
|
455
|
+
glue->l = new_node;
|
456
|
+
}
|
457
|
+
new_node->parent = glue;
|
458
|
+
|
459
|
+
if (node->parent == NULL)
|
460
|
+
radix->head = glue;
|
461
|
+
else if (node->parent->r == node)
|
462
|
+
node->parent->r = glue;
|
463
|
+
else
|
464
|
+
node->parent->l = glue;
|
465
|
+
|
466
|
+
node->parent = glue;
|
467
|
+
}
|
468
|
+
return (new_node);
|
469
|
+
}
|
470
|
+
|
471
|
+
|
472
|
+
void
|
473
|
+
radix_remove(radix_tree_t *radix, radix_node_t *node)
|
474
|
+
{
|
475
|
+
radix_node_t *parent, *child;
|
476
|
+
|
477
|
+
if (node->r && node->l) {
|
478
|
+
/*
|
479
|
+
* this might be a placeholder node -- have to check and make
|
480
|
+
* sure there is a prefix aossciated with it !
|
481
|
+
*/
|
482
|
+
if (node->prefix != NULL)
|
483
|
+
Deref_Prefix(node->prefix);
|
484
|
+
node->prefix = NULL;
|
485
|
+
/* Also I needed to clear data pointer -- masaki */
|
486
|
+
node->data = NULL;
|
487
|
+
return;
|
488
|
+
}
|
489
|
+
if (node->r == NULL && node->l == NULL) {
|
490
|
+
parent = node->parent;
|
491
|
+
Deref_Prefix(node->prefix);
|
492
|
+
FREE(node);
|
493
|
+
radix->num_active_node--;
|
494
|
+
|
495
|
+
if (parent == NULL) {
|
496
|
+
radix->head = NULL;
|
497
|
+
return;
|
498
|
+
}
|
499
|
+
if (parent->r == node) {
|
500
|
+
parent->r = NULL;
|
501
|
+
child = parent->l;
|
502
|
+
} else {
|
503
|
+
parent->l = NULL;
|
504
|
+
child = parent->r;
|
505
|
+
}
|
506
|
+
|
507
|
+
if (parent->prefix)
|
508
|
+
return;
|
509
|
+
|
510
|
+
/* we need to remove parent too */
|
511
|
+
if (parent->parent == NULL)
|
512
|
+
radix->head = child;
|
513
|
+
else if (parent->parent->r == parent)
|
514
|
+
parent->parent->r = child;
|
515
|
+
else
|
516
|
+
parent->parent->l = child;
|
517
|
+
|
518
|
+
child->parent = parent->parent;
|
519
|
+
FREE(parent);
|
520
|
+
radix->num_active_node--;
|
521
|
+
return;
|
522
|
+
}
|
523
|
+
if (node->r)
|
524
|
+
child = node->r;
|
525
|
+
else
|
526
|
+
child = node->l;
|
527
|
+
|
528
|
+
parent = node->parent;
|
529
|
+
child->parent = parent;
|
530
|
+
|
531
|
+
Deref_Prefix(node->prefix);
|
532
|
+
FREE(node);
|
533
|
+
radix->num_active_node--;
|
534
|
+
|
535
|
+
if (parent == NULL) {
|
536
|
+
radix->head = child;
|
537
|
+
return;
|
538
|
+
}
|
539
|
+
if (parent->r == node)
|
540
|
+
parent->r = child;
|
541
|
+
else
|
542
|
+
parent->l = child;
|
543
|
+
}
|
544
|
+
|
545
|
+
/* Local additions */
|
546
|
+
static void
|
547
|
+
sanitise_mask(u_char *addr, u_int masklen, u_int maskbits)
|
548
|
+
{
|
549
|
+
u_int i = masklen / 8;
|
550
|
+
u_int j = masklen % 8;
|
551
|
+
|
552
|
+
if (j != 0) {
|
553
|
+
addr[i] &= (~0) << (8 - j);
|
554
|
+
i++;
|
555
|
+
}
|
556
|
+
for (; i < maskbits / 8; i++)
|
557
|
+
addr[i] = 0;
|
558
|
+
}
|
559
|
+
|
560
|
+
prefix_t
|
561
|
+
*prefix_pton(const char *string, long len, const char **errmsg)
|
562
|
+
{
|
563
|
+
char save[256], *cp, *ep;
|
564
|
+
struct addrinfo hints, *ai;
|
565
|
+
void *addr;
|
566
|
+
prefix_t *ret;
|
567
|
+
size_t slen;
|
568
|
+
int r;
|
569
|
+
|
570
|
+
ret = NULL;
|
571
|
+
|
572
|
+
/* Copy the string to parse, because we modify it */
|
573
|
+
if ((slen = strlen(string) + 1) > sizeof(save)) {
|
574
|
+
*errmsg = "string too long";
|
575
|
+
return (NULL);
|
576
|
+
}
|
577
|
+
memcpy(save, string, slen);
|
578
|
+
|
579
|
+
if ((cp = strchr(save, '/')) != NULL) {
|
580
|
+
if (len != -1 ) {
|
581
|
+
*errmsg = "masklen specified twice";
|
582
|
+
return (NULL);
|
583
|
+
}
|
584
|
+
*cp++ = '\0';
|
585
|
+
len = strtol(cp, &ep, 10);
|
586
|
+
if (*cp == '\0' || *ep != '\0' || len < 0) {
|
587
|
+
*errmsg = "could not parse masklen";
|
588
|
+
return (NULL);
|
589
|
+
}
|
590
|
+
/* More checks below */
|
591
|
+
}
|
592
|
+
memset(&hints, '\0', sizeof(hints));
|
593
|
+
hints.ai_flags = AI_NUMERICHOST;
|
594
|
+
|
595
|
+
if ((r = getaddrinfo(save, NULL, &hints, &ai)) != 0) {
|
596
|
+
snprintf(save, sizeof(save), "getaddrinfo: %s:",
|
597
|
+
gai_strerror(r));
|
598
|
+
*errmsg = save;
|
599
|
+
return NULL;
|
600
|
+
}
|
601
|
+
if (ai == NULL || ai->ai_addr == NULL) {
|
602
|
+
*errmsg = "getaddrinfo returned no result";
|
603
|
+
goto out;
|
604
|
+
}
|
605
|
+
switch (ai->ai_addr->sa_family) {
|
606
|
+
case AF_INET:
|
607
|
+
if (len == -1)
|
608
|
+
len = 32;
|
609
|
+
else if (len < 0 || len > 32)
|
610
|
+
goto out;
|
611
|
+
addr = &((struct sockaddr_in *) ai->ai_addr)->sin_addr;
|
612
|
+
sanitise_mask(addr, len, 32);
|
613
|
+
break;
|
614
|
+
case AF_INET6:
|
615
|
+
if (len == -1)
|
616
|
+
len = 128;
|
617
|
+
else if (len < 0 || len > 128)
|
618
|
+
goto out;
|
619
|
+
addr = &((struct sockaddr_in6 *) ai->ai_addr)->sin6_addr;
|
620
|
+
sanitise_mask(addr, len, 128);
|
621
|
+
break;
|
622
|
+
default:
|
623
|
+
goto out;
|
624
|
+
}
|
625
|
+
|
626
|
+
ret = New_Prefix2(ai->ai_addr->sa_family, addr, len, NULL);
|
627
|
+
if (ret == NULL)
|
628
|
+
*errmsg = "New_Prefix2 failed";
|
629
|
+
out:
|
630
|
+
freeaddrinfo(ai);
|
631
|
+
return (ret);
|
632
|
+
}
|
633
|
+
|
634
|
+
prefix_t
|
635
|
+
*prefix_from_blob(u_char *blob, int len, int prefixlen)
|
636
|
+
{
|
637
|
+
int family, maxprefix;
|
638
|
+
|
639
|
+
switch (len) {
|
640
|
+
case 4:
|
641
|
+
/* Assume AF_INET */
|
642
|
+
family = AF_INET;
|
643
|
+
maxprefix = 32;
|
644
|
+
break;
|
645
|
+
case 16:
|
646
|
+
/* Assume AF_INET6 */
|
647
|
+
family = AF_INET6;
|
648
|
+
maxprefix = 128;
|
649
|
+
break;
|
650
|
+
default:
|
651
|
+
/* Who knows? */
|
652
|
+
return NULL;
|
653
|
+
}
|
654
|
+
if (prefixlen == -1)
|
655
|
+
prefixlen = maxprefix;
|
656
|
+
if (prefixlen < 0 || prefixlen > maxprefix)
|
657
|
+
return NULL;
|
658
|
+
return (New_Prefix2(family, blob, prefixlen, NULL));
|
659
|
+
}
|
660
|
+
|
661
|
+
const char *
|
662
|
+
prefix_addr_ntop(prefix_t *prefix, char *buf, size_t len)
|
663
|
+
{
|
664
|
+
return (inet_ntop(prefix->family, &prefix->add, buf, len));
|
665
|
+
}
|
666
|
+
|
667
|
+
const char *
|
668
|
+
prefix_ntop(prefix_t *prefix, char *buf, size_t len)
|
669
|
+
{
|
670
|
+
char addrbuf[128];
|
671
|
+
|
672
|
+
if (prefix_addr_ntop(prefix, addrbuf, sizeof(addrbuf)) == NULL)
|
673
|
+
return (NULL);
|
674
|
+
snprintf(buf, len, "%s/%d", addrbuf, prefix->bitlen);
|
675
|
+
|
676
|
+
return (buf);
|
677
|
+
}
|