#include "lib/string.h"
#include "conf/conf.h"
#include "filter/filter.h"
+#include "filter/data.h"
+
+
+/*
+ * In the trie code, the prefix length is internally treated as for the whole
+ * ip_addr, regardless whether it contains an IPv4 or IPv6 address. Therefore,
+ * remaining definitions make sense.
+ */
+
+#define ipa_mkmask(x) ip6_mkmask(x)
+#define ipa_masklen(x) ip6_masklen(&x)
+#define ipa_pxlen(x,y) ip6_pxlen(x,y)
+#define ipa_getbit(x,n) ip6_getbit(x,n)
+
/**
* f_new_trie - allocates and returns a new empty trie
/**
* trie_add_prefix
* @t: trie to add to
- * @px: prefix address
- * @plen: prefix length
+ * @net: IP network prefix
* @l: prefix lower bound
* @h: prefix upper bound
*
- * Adds prefix (prefix pattern) @px/@plen to trie @t. @l and @h are lower
+ * Adds prefix (prefix pattern) @n to trie @t. @l and @h are lower
* and upper bounds on accepted prefix lengths, both inclusive.
* 0 <= l, h <= 32 (128 for IPv6).
*
*/
void *
-trie_add_prefix(struct f_trie *t, ip_addr px, int plen, int l, int h)
+trie_add_prefix(struct f_trie *t, const net_addr *net, uint l, uint h)
{
+ ip_addr px = net_prefix(net);
+ uint plen = net_pxlen(net);
+
+ if (net->type == NET_IP4)
+ {
+ const uint delta = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+ plen += delta;
+ l += delta;
+ h += delta;
+ }
+
if (l == 0)
t->zero = 1;
else
struct f_trie_node *o = NULL;
struct f_trie_node *n = t->root;
- while(n)
+ while (n)
{
ip_addr cmask = ipa_and(n->mask, pmask);
return a;
}
-/**
- * trie_match_prefix
- * @t: trie
- * @px: prefix address
- * @plen: prefix length
- *
- * Tries to find a matching prefix pattern in the trie such that
- * prefix @px/@plen matches that prefix pattern. Returns 1 if there
- * is such prefix pattern in the trie.
- */
-int
-trie_match_prefix(struct f_trie *t, ip_addr px, int plen)
+static int
+trie_match_prefix(const struct f_trie *t, ip_addr px, uint plen)
{
ip_addr pmask = ipa_mkmask(plen);
ip_addr paddr = ipa_and(px, pmask);
return t->zero;
int plentest = plen - 1;
- struct f_trie_node *n = t->root;
+ const struct f_trie_node *n = t->root;
while(n)
{
return 0;
}
+/**
+ * trie_match_net
+ * @t: trie
+ * @n: net address
+ *
+ * Tries to find a matching net in the trie such that
+ * prefix @n matches that prefix pattern. Returns 1 if there
+ * is such prefix pattern in the trie.
+ */
+int
+trie_match_net(const struct f_trie *t, const net_addr *n)
+{
+ uint add = 0;
+
+ switch (n->type) {
+ case NET_IP4:
+ case NET_VPN4:
+ case NET_ROA4:
+ add = IP6_MAX_PREFIX_LENGTH - IP4_MAX_PREFIX_LENGTH;
+ }
+
+ return trie_match_prefix(t, net_prefix(n), net_pxlen(n) + add);
+}
+
static int
-trie_node_same(struct f_trie_node *t1, struct f_trie_node *t2)
+trie_node_same(const struct f_trie_node *t1, const struct f_trie_node *t2)
{
if ((t1 == NULL) && (t2 == NULL))
return 1;
* Compares two tries and returns 1 if they are same
*/
int
-trie_same(struct f_trie *t1, struct f_trie *t2)
+trie_same(const struct f_trie *t1, const struct f_trie *t2)
{
return (t1->zero == t2->zero) && trie_node_same(t1->root, t2->root);
}
static void
-trie_node_format(struct f_trie_node *t, buffer *buf)
+trie_node_format(const struct f_trie_node *t, buffer *buf)
{
if (t == NULL)
return;
* Prints the trie to the supplied buffer.
*/
void
-trie_format(struct f_trie *t, buffer *buf)
+trie_format(const struct f_trie *t, buffer *buf)
{
buffer_puts(buf, "[");
buffer_print(buf, "%I/%d, ", IPA_NONE, 0);
trie_node_format(t->root, buf);
+ if (buf->pos == buf->end)
+ return;
+
/* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;