2 node.c -- node tree management
3 Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
4 2001-2005 Ivo Timmermans
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.
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.
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "control_common.h"
29 #include "splay_tree.h"
33 static digest_t
*sha256
;
35 splay_tree_t
*node_tree
;
36 static splay_tree_t
*node_id_tree
;
37 static hash_t
*node_udp_cache
;
38 static hash_t
*node_id_cache
;
42 static int node_compare(const node_t
*a
, const node_t
*b
) {
43 return strcmp(a
->name
, b
->name
);
46 static int node_id_compare(const node_t
*a
, const node_t
*b
) {
47 return memcmp(&a
->id
, &b
->id
, sizeof(node_id_t
));
50 void init_nodes(void) {
51 sha256
= digest_open_by_name("sha256", sizeof(node_id_t
));
53 node_tree
= splay_alloc_tree((splay_compare_t
) node_compare
, (splay_action_t
) free_node
);
54 node_id_tree
= splay_alloc_tree((splay_compare_t
) node_id_compare
, NULL
);
55 node_udp_cache
= hash_alloc(0x100, sizeof(sockaddr_t
));
56 node_id_cache
= hash_alloc(0x100, sizeof(node_id_t
));
59 void exit_nodes(void) {
60 hash_free(node_id_cache
);
61 hash_free(node_udp_cache
);
62 splay_delete_tree(node_id_tree
);
63 splay_delete_tree(node_tree
);
68 node_t
*new_node(void) {
69 node_t
*n
= xzalloc(sizeof *n
);
71 if(replaywin
) n
->late
= xzalloc(replaywin
);
72 n
->subnet_tree
= new_subnet_tree();
73 n
->edge_tree
= new_edge_tree();
80 void free_node(node_t
*n
) {
82 free_subnet_tree(n
->subnet_tree
);
85 free_edge_tree(n
->edge_tree
);
87 sockaddrfree(&n
->address
);
89 cipher_close(n
->incipher
);
90 digest_close(n
->indigest
);
91 cipher_close(n
->outcipher
);
92 digest_close(n
->outdigest
);
95 sptps_stop(&n
->sptps
);
97 timeout_del(&n
->mtutimeout
);
111 void node_add(node_t
*n
) {
112 digest_create(sha256
, n
->name
, strlen(n
->name
), &n
->id
);
114 splay_insert(node_tree
, n
);
115 splay_insert(node_id_tree
, n
);
118 void node_del(node_t
*n
) {
119 hash_delete(node_udp_cache
, &n
->address
);
120 hash_delete(node_id_cache
, &n
->id
);
122 for splay_each(subnet_t
, s
, n
->subnet_tree
)
125 for splay_each(edge_t
, e
, n
->edge_tree
)
128 splay_delete(node_id_tree
, n
);
129 splay_delete(node_tree
, n
);
132 node_t
*lookup_node(char *name
) {
137 return splay_search(node_tree
, &n
);
140 node_t
*lookup_node_id(const node_id_t
*id
) {
141 node_t
*n
= hash_search(node_id_cache
, id
);
143 node_t tmp
= {.id
= *id
};
144 n
= splay_search(node_id_tree
, &tmp
);
146 hash_insert(node_id_cache
, id
, n
);
152 node_t
*lookup_node_udp(const sockaddr_t
*sa
) {
153 return hash_search(node_udp_cache
, sa
);
156 void update_node_udp(node_t
*n
, const sockaddr_t
*sa
) {
158 logger(DEBUG_ALWAYS
, LOG_WARNING
, "Trying to update UDP address of myself!");
162 hash_delete(node_udp_cache
, &n
->address
);
167 for(int i
= 0; i
< listen_sockets
; i
++) {
168 if(listen_socket
[i
].sa
.sa
.sa_family
== sa
->sa
.sa_family
) {
173 hash_insert(node_udp_cache
, sa
, n
);
175 n
->hostname
= sockaddr2hostname(&n
->address
);
176 logger(DEBUG_PROTOCOL
, LOG_DEBUG
, "UDP address of %s set to %s", n
->name
, n
->hostname
);
179 /* invalidate UDP information - note that this is a security feature as well to make sure
180 we can't be tricked into flooding any random address with UDP packets */
181 n
->status
.udp_confirmed
= false;
187 bool dump_nodes(connection_t
*c
) {
188 for splay_each(node_t
, n
, node_tree
) {
189 char id
[2 * sizeof n
->id
+ 1];
190 for (size_t c
= 0; c
< sizeof n
->id
; ++c
)
191 sprintf(id
+ 2 * c
, "%02hhx", n
->id
.x
[c
]);
192 id
[sizeof id
- 1] = 0;
193 send_request(c
, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL
, REQ_DUMP_NODES
,
194 n
->name
, id
, n
->hostname
?: "unknown port unknown", cipher_get_nid(n
->outcipher
),
195 digest_get_nid(n
->outdigest
), (int)digest_length(n
->outdigest
), n
->outcompression
,
196 n
->options
, bitfield_to_int(&n
->status
, sizeof n
->status
), n
->nexthop
? n
->nexthop
->name
: "-",
197 n
->via
? n
->via
->name
?: "-" : "-", n
->distance
, n
->mtu
, n
->minmtu
, n
->maxmtu
, (long)n
->last_state_change
);
200 return send_request(c
, "%d %d", CONTROL
, REQ_DUMP_NODES
);
203 bool dump_traffic(connection_t
*c
) {
204 for splay_each(node_t
, n
, node_tree
)
205 send_request(c
, "%d %d %s %"PRIu64
" %"PRIu64
" %"PRIu64
" %"PRIu64
, CONTROL
, REQ_DUMP_TRAFFIC
,
206 n
->name
, n
->in_packets
, n
->in_bytes
, n
->out_packets
, n
->out_bytes
);
208 return send_request(c
, "%d %d", CONTROL
, REQ_DUMP_TRAFFIC
);