X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fsubnet.c;h=9d84ec2b946427b60d36d03cfd89a6e35198fded;hb=6eaefb4dbce240334e35f67d9f3db5d4f44e49c9;hp=d5eca5830b72043034d833da8fd8a81298f9bba1;hpb=5a1406adefd8b51981af0da5ac0ebec830eb43b4;p=meshlink diff --git a/src/subnet.c b/src/subnet.c index d5eca583..9d84ec2b 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -1,7 +1,7 @@ /* subnet.c -- handle subnet lookups and lists - Copyright (C) 2000-2003 Guus Sliepen , - 2000-2003 Ivo Timmermans + Copyright (C) 2000-2006 Guus Sliepen , + 2000-2005 Ivo Timmermans This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,23 +17,25 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.c,v 1.1.2.52 2003/12/12 19:52:25 guus Exp $ + $Id$ */ #include "system.h" -#include "avl_tree.h" +#include "splay_tree.h" +#include "device.h" #include "logger.h" #include "net.h" #include "netutl.h" #include "node.h" +#include "process.h" #include "subnet.h" #include "utils.h" #include "xalloc.h" /* lists type of subnet */ -avl_tree_t *subnet_tree; +splay_tree_t *subnet_tree; /* Subnet comparison */ @@ -115,28 +117,28 @@ void init_subnets(void) { cp(); - subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet); + subnet_tree = splay_alloc_tree((splay_compare_t) subnet_compare, (splay_action_t) free_subnet); } void exit_subnets(void) { cp(); - avl_delete_tree(subnet_tree); + splay_delete_tree(subnet_tree); } -avl_tree_t *new_subnet_tree(void) +splay_tree_t *new_subnet_tree(void) { cp(); - return avl_alloc_tree((avl_compare_t) subnet_compare, NULL); + return splay_alloc_tree((splay_compare_t) subnet_compare, NULL); } -void free_subnet_tree(avl_tree_t *subnet_tree) +void free_subnet_tree(splay_tree_t *subnet_tree) { cp(); - avl_delete_tree(subnet_tree); + splay_delete_tree(subnet_tree); } /* Allocating and freeing space for subnets */ @@ -163,16 +165,16 @@ void subnet_add(node_t *n, subnet_t *subnet) subnet->owner = n; - avl_insert(subnet_tree, subnet); - avl_insert(n->subnet_tree, subnet); + splay_insert(subnet_tree, subnet); + splay_insert(n->subnet_tree, subnet); } void subnet_del(node_t *n, subnet_t *subnet) { cp(); - avl_delete(n->subnet_tree, subnet); - avl_delete(subnet_tree, subnet); + splay_delete(n->subnet_tree, subnet); + splay_delete(subnet_tree, subnet); } /* Ascii representation of subnets */ @@ -245,6 +247,11 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) { cp(); + if(!netstr || !subnet) { + logger(LOG_ERR, _("net2str() was called with netstr=%p, subnet=%p!\n"), netstr, subnet); + return false; + } + switch (subnet->type) { case SUBNET_MAC: snprintf(netstr, len, "%hx:%hx:%hx:%hx:%hx:%hx", @@ -284,7 +291,7 @@ bool net2str(char *netstr, int len, const subnet_t *subnet) exit(0); } - return netstr; + return true; } /* Subnet lookup routines */ @@ -293,7 +300,7 @@ subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) { cp(); - return avl_search(owner->subnet_tree, subnet); + return splay_search(owner->subnet_tree, subnet); } subnet_t *lookup_subnet_mac(const mac_t *address) @@ -306,7 +313,7 @@ subnet_t *lookup_subnet_mac(const mac_t *address) subnet.net.mac.address = *address; subnet.owner = NULL; - p = avl_search(subnet_tree, &subnet); + p = splay_search(subnet_tree, &subnet); return p; } @@ -325,7 +332,7 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) do { /* Go find subnet */ - p = avl_search_closest_smaller(subnet_tree, &subnet); + p = splay_search_closest_smaller(subnet_tree, &subnet); /* Check if the found subnet REALLY matches */ @@ -335,7 +342,7 @@ subnet_t *lookup_subnet_ipv4(const ipv4_t *address) break; } - if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t))) + if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength)) break; else { /* Otherwise, see if there is a bigger enclosing subnet */ @@ -363,7 +370,7 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) do { /* Go find subnet */ - p = avl_search_closest_smaller(subnet_tree, &subnet); + p = splay_search_closest_smaller(subnet_tree, &subnet); /* Check if the found subnet REALLY matches */ @@ -371,7 +378,7 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) if(p->type != SUBNET_IPV6) return NULL; - if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t))) + if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength)) break; else { /* Otherwise, see if there is a bigger enclosing subnet */ @@ -385,22 +392,68 @@ subnet_t *lookup_subnet_ipv6(const ipv6_t *address) return p; } -void dump_subnets(void) +void subnet_update(node_t *owner, subnet_t *subnet, bool up) { + splay_node_t *node; + int i; + char *envp[8]; + char netstr[MAXNETSTR + 7] = "SUBNET="; + char *name, *address, *port; + + asprintf(&envp[0], "NETNAME=%s", netname ? : ""); + asprintf(&envp[1], "DEVICE=%s", device ? : ""); + asprintf(&envp[2], "INTERFACE=%s", iface ? : ""); + asprintf(&envp[3], "NODE=%s", owner->name); + + if(owner != myself) { + sockaddr2str(&owner->address, &address, &port); + asprintf(&envp[4], "REMOTEADDRESS=%s", address); + asprintf(&envp[5], "REMOTEPORT=%s", port); + envp[6] = netstr; + envp[7] = NULL; + } else { + envp[4] = netstr; + envp[5] = NULL; + } + + name = up ? "subnet-up" : "subnet-down"; + + if(!subnet) { + for(node = owner->subnet_tree->head; node; node = node->next) { + subnet = node->data; + if(!net2str(netstr + 7, sizeof netstr - 7, subnet)) + continue; + execute_script(name, envp); + } + } else { + if(net2str(netstr + 7, sizeof netstr - 7, subnet)) + execute_script(name, envp); + } + + for(i = 0; i < (owner != myself ? 6 : 4); i++) + free(envp[i]); + + if(owner != myself) { + free(address); + free(port); + } +} + +int dump_subnets(struct evbuffer *out) { char netstr[MAXNETSTR]; subnet_t *subnet; - avl_node_t *node; + splay_node_t *node; cp(); - logger(LOG_DEBUG, _("Subnet list:")); - for(node = subnet_tree->head; node; node = node->next) { subnet = node->data; if(!net2str(netstr, sizeof netstr, subnet)) continue; - logger(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name); + if(evbuffer_add_printf(out, _(" %s owner %s\n"), + netstr, subnet->owner->name) == -1) + return errno; } - logger(LOG_DEBUG, _("End of subnet list.")); + return 0; }