b55c7317ab45171f6057faf964d75b00e2d5f50d
[tinc] / src / node.c
1 /*
2     node.c -- node tree management
3     Copyright (C) 2001-2009 Guus Sliepen <guus@tinc-vpn.org>,
4                   2001-2005 Ivo Timmermans
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "system.h"
22
23 #include "avl_tree.h"
24 #include "logger.h"
25 #include "net.h"
26 #include "netutl.h"
27 #include "node.h"
28 #include "utils.h"
29 #include "xalloc.h"
30
31 avl_tree_t *node_tree;                  /* Known nodes, sorted by name */
32 avl_tree_t *node_udp_tree;              /* Known nodes, sorted by address and port */
33
34 node_t *myself;
35
36 static int node_compare(const node_t *a, const node_t *b)
37 {
38         return strcmp(a->name, b->name);
39 }
40
41 static int node_udp_compare(const node_t *a, const node_t *b)
42 {
43        return sockaddrcmp(&a->address, &b->address);
44 }
45
46 void init_nodes(void)
47 {
48         cp();
49
50         node_tree = avl_alloc_tree((avl_compare_t) node_compare, (avl_action_t) free_node);
51         node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL);
52 }
53
54 void exit_nodes(void)
55 {
56         cp();
57
58         avl_delete_tree(node_udp_tree);
59         avl_delete_tree(node_tree);
60 }
61
62 node_t *new_node(void)
63 {
64         node_t *n = xmalloc_and_zero(sizeof(*n));
65
66         cp();
67
68         n->subnet_tree = new_subnet_tree();
69         n->edge_tree = new_edge_tree();
70         EVP_CIPHER_CTX_init(&n->inctx);
71         EVP_CIPHER_CTX_init(&n->outctx);
72         n->mtu = MTU;
73         n->maxmtu = MTU;
74
75         return n;
76 }
77
78 void free_node(node_t *n)
79 {
80         cp();
81
82         if(n->inkey)
83                 free(n->inkey);
84
85         if(n->outkey)
86                 free(n->outkey);
87
88         if(n->subnet_tree)
89                 free_subnet_tree(n->subnet_tree);
90
91         if(n->edge_tree)
92                 free_edge_tree(n->edge_tree);
93
94         sockaddrfree(&n->address);
95
96         EVP_CIPHER_CTX_cleanup(&n->inctx);
97         EVP_CIPHER_CTX_cleanup(&n->outctx);
98
99         if(n->mtuevent)
100                 event_del(n->mtuevent);
101         
102         if(n->hostname)
103                 free(n->hostname);
104
105         if(n->name)
106                 free(n->name);
107
108         free(n);
109 }
110
111 void node_add(node_t *n)
112 {
113         cp();
114
115         avl_insert(node_tree, n);
116 }
117
118 void node_del(node_t *n)
119 {
120         avl_node_t *node, *next;
121         edge_t *e;
122         subnet_t *s;
123
124         cp();
125
126         for(node = n->subnet_tree->head; node; node = next) {
127                 next = node->next;
128                 s = node->data;
129                 subnet_del(n, s);
130         }
131
132         for(node = n->edge_tree->head; node; node = next) {
133                 next = node->next;
134                 e = node->data;
135                 edge_del(e);
136         }
137
138         avl_delete(node_udp_tree, n);
139         avl_delete(node_tree, n);
140 }
141
142 node_t *lookup_node(char *name)
143 {
144         node_t n = {0};
145
146         cp();
147         
148         n.name = name;
149
150         return avl_search(node_tree, &n);
151 }
152
153 node_t *lookup_node_udp(const sockaddr_t *sa)
154 {
155         node_t n = {0};
156
157         cp();
158
159         n.address = *sa;
160         n.name = NULL;
161
162         return avl_search(node_udp_tree, &n);
163 }
164
165 void update_node_udp(node_t *n, const sockaddr_t *sa)
166 {
167         avl_delete(node_udp_tree, n);
168
169         if(n->hostname)
170                 free(n->hostname);
171
172         if(sa) {
173                 n->address = *sa;
174                 n->hostname = sockaddr2hostname(&n->address);
175                 avl_insert(node_udp_tree, n);
176                 ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s set to %s", n->name, n->hostname);
177         } else {
178                 memset(&n->address, 0, sizeof n->address);
179                 n->hostname = 0;
180                 ifdebug(PROTOCOL) logger(LOG_DEBUG, "UDP address of %s cleared", n->name);
181         }
182 }
183
184 void dump_nodes(void)
185 {
186         avl_node_t *node;
187         node_t *n;
188
189         cp();
190
191         logger(LOG_DEBUG, _("Nodes:"));
192
193         for(node = node_tree->head; node; node = node->next) {
194                 n = node->data;
195                 logger(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s pmtu %d (min %d max %d)"),
196                            n->name, n->hostname, n->outcipher ? n->outcipher->nid : 0,
197                            n->outdigest ? n->outdigest->type : 0, n->outmaclength, n->outcompression,
198                            n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-",
199                            n->via ? n->via->name : "-", n->mtu, n->minmtu, n->maxmtu);
200         }
201
202         logger(LOG_DEBUG, _("End of nodes."));
203 }