-subnet_t *lookup_subnet_mac(subnet_t *subnets, mac_t address)
-{
- subnet_t *subnet;
-cp
- for(subnet = subnets; subnet != NULL; subnet = subnet->next)
- {
- if(subnet->type == SUBNET_MAC)
- if(memcmp(&address, &subnet->net.mac.address, sizeof(address)) == 0)
- break;
- }
-cp
- return subnet;
-}
-
-subnet_t *lookup_subnet_ipv4(subnet_t *subnets, ipv4_t address)
-{
- subnet_t *subnet;
-cp
- for(subnet = subnets; subnet != NULL; subnet = subnet->next)
- {
- if(subnet->type == SUBNET_IPV4)
- if((address & subnet->net.ipv4.mask) == subnet->net.ipv4.address)
- break;
- }
-cp
- return subnet;
-}
-
-subnet_t *lookup_subnet_ipv6(subnet_t *subnets, ipv6_t address)
-{
- subnet_t *subnet;
- int i;
-cp
- for(subnet = subnets; subnet != NULL; subnet = subnet->next)
- {
- if(subnet->type == SUBNET_IPV6)
- {
- for(i=0; i<8; i++)
- if((address.x[i] & subnet->net.ipv6.mask.x[i]) != subnet->net.ipv6.address.x[i])
- break;
- if(i=8)
- break;
- }
- }
-cp
- return subnet;
+subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet)
+{
+ cp();
+
+ return avl_search(owner->subnet_tree, subnet);
+}
+
+subnet_t *lookup_subnet_mac(mac_t *address)
+{
+ subnet_t subnet, *p;
+
+ cp();
+
+ subnet.type = SUBNET_MAC;
+ memcpy(&subnet.net.mac.address, address, sizeof(mac_t));
+ subnet.owner = NULL;
+
+ p = (subnet_t *) avl_search(subnet_tree, &subnet);
+
+ return p;
+}
+
+subnet_t *lookup_subnet_ipv4(ipv4_t *address)
+{
+ subnet_t subnet, *p;
+
+ cp();
+
+ subnet.type = SUBNET_IPV4;
+ memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t));
+ subnet.net.ipv4.prefixlength = 32;
+ subnet.owner = NULL;
+
+ do {
+ /* Go find subnet */
+
+ p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet);
+
+ /* Check if the found subnet REALLY matches */
+
+ if(p) {
+ if(p->type != SUBNET_IPV4) {
+ p = NULL;
+ break;
+ }
+
+ if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t)))
+ break;
+ else {
+ /* Otherwise, see if there is a bigger enclosing subnet */
+
+ subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1;
+ maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t));
+ }
+ }
+ } while(p);
+
+ return p;
+}
+
+subnet_t *lookup_subnet_ipv6(ipv6_t *address)
+{
+ subnet_t subnet, *p;
+
+ cp();
+
+ subnet.type = SUBNET_IPV6;
+ memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t));
+ subnet.net.ipv6.prefixlength = 128;
+ subnet.owner = NULL;
+
+ do {
+ /* Go find subnet */
+
+ p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet);
+
+ /* Check if the found subnet REALLY matches */
+
+ if(p) {
+ if(p->type != SUBNET_IPV6)
+ return NULL;
+
+ if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t)))
+ break;
+ else {
+ /* Otherwise, see if there is a bigger enclosing subnet */
+
+ subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1;
+ maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t));
+ }
+ }
+ } while(p);
+
+ return p;
+}
+
+void dump_subnets(void)
+{
+ char *netstr;
+ subnet_t *subnet;
+ avl_node_t *node;
+
+ cp();
+
+ syslog(LOG_DEBUG, _("Subnet list:"));
+
+ for(node = subnet_tree->head; node; node = node->next) {
+ subnet = (subnet_t *) node->data;
+ netstr = net2str(subnet);
+ syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name);
+ free(netstr);
+ }
+
+ syslog(LOG_DEBUG, _("End of subnet list."));