Split connection list into two lists:
[tinc] / src / connection.c
1 /*
2     connection.c -- connection list management
3     Copyright (C) 2000,2001 Guus Sliepen <guus@sliepen.warande.net>,
4                   2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
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     $Id: connection.c,v 1.1.2.13 2001/07/15 18:07:31 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <syslog.h>
27 #include <string.h>
28
29 #include <avl_tree.h>
30 #include <list.h>
31
32 #include "net.h"        /* Don't ask. */
33 #include "netutl.h"
34 #include "config.h"
35 #include "conf.h"
36 #include <utils.h>
37 #include "subnet.h"
38
39 #include "xalloc.h"
40 #include "system.h"
41
42 /* Root of the connection list */
43
44 avl_tree_t *connection_tree;
45 avl_tree_t *active_tree;
46 avl_tree_t *id_tree;
47
48 /* Pointer to connection describing myself */
49
50 connection_t *myself = NULL;
51
52 /* Initialization and callbacks */
53
54 int connection_compare(connection_t *a, connection_t *b)
55 {
56   return a->meta_socket - b->meta_socket;
57 }
58
59 int active_compare(connection_t *a, connection_t *b)
60 {
61   ipv4_t result;
62
63   result = a->address - b->address;
64   if(result)
65     return result;
66   else
67     return a->port - b->port;
68 }
69
70 int id_compare(connection_t *a, connection_t *b)
71 {
72   return strcmp(a->name, b->name);
73 }
74
75 void init_connections(void)
76 {
77   connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, (avl_action_t)free_connection);
78   active_tree = avl_alloc_tree((avl_compare_t)active_compare, NULL);
79   id_tree = avl_alloc_tree((avl_compare_t)id_compare, NULL);
80 }
81
82 /* Creation and deletion of connection elements */
83
84 connection_t *new_connection(void)
85 {
86   connection_t *p = (connection_t *)xmalloc_and_zero(sizeof(*p));
87 cp
88   p->subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, NULL);
89   p->queue = list_alloc((list_action_t)free);
90 cp
91   return p;
92 }
93
94 void free_connection(connection_t *p)
95 {
96 cp
97   if(p->queue)
98     list_delete_list(p->queue);
99   if(p->name)
100     free(p->name);
101   if(p->hostname)
102     free(p->hostname);
103   if(p->rsa_key)
104     RSA_free(p->rsa_key);
105   if(p->cipher_pktkey)
106     free(p->cipher_pktkey);
107   if(p->buffer)
108     free(p->buffer);
109   if(p->config)
110     clear_config(&p->config);
111   free(p);
112 cp
113 }
114
115 /*
116   remove all marked connections
117 */
118 void prune_connection_tree(void)
119 {
120   avl_node_t *node, *next;
121   connection_t *cl;
122 cp
123   for(node = connection_tree->head; node; node = next)
124     {
125       next = node->next;
126       cl = (connection_t *)node->data;
127       if(cl->status.remove)
128         connection_del(cl);
129     }
130 cp
131 }
132
133 /*
134   free all elements of connection
135 */
136 void destroy_connection_tree(void)
137 {
138 cp
139   avl_delete_tree(id_tree);
140   avl_delete_tree(active_tree);
141   avl_delete_tree(connection_tree);
142 cp
143 }
144
145 /* Linked list management */
146
147 void connection_add(connection_t *cl)
148 {
149 cp
150   avl_insert(connection_tree, cl);
151 cp
152 }
153
154 void active_add(connection_t *cl)
155 {
156 cp
157   avl_insert(active_tree, cl);
158 cp
159 }
160
161 void id_add(connection_t *cl)
162 {
163 cp
164   avl_insert(id_tree, cl);
165 cp
166 }
167
168 void connection_del(connection_t *cl)
169 {
170 cp
171   avl_delete(id_tree, cl);
172   avl_delete(active_tree, cl);
173   avl_delete(connection_tree, cl);
174 cp
175 }
176
177 /* Lookup functions */
178
179 connection_t *lookup_active(ipv4_t address, short unsigned int port)
180 {
181   connection_t cl;
182 cp
183   cl.address = address;
184   cl.port = port;
185
186   return avl_search(active_tree, &cl);
187 }
188
189 connection_t *lookup_id(char *name)
190 {
191   connection_t cl, *p;
192 cp
193   cl.name = name;
194   p = avl_search(id_tree, &cl);
195   if(p && p->status.active)
196     return p;
197   else
198     return NULL;
199 }
200
201 /* Debugging */
202
203 void dump_connection_list(void)
204 {
205   avl_node_t *node;
206   connection_t *cl;
207 cp
208   syslog(LOG_DEBUG, _("Connection list:"));
209
210   syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld sockets %d, %d status %04x"),
211          myself->name, myself->hostname, myself->port, myself->options,
212          myself->socket, myself->meta_socket, myself->status);
213
214   for(node = connection_tree->head; node; node = node->next)
215     {
216       cl = (connection_t *)node->data;
217       syslog(LOG_DEBUG, _(" %s at %s port %hd options %ld sockets %d, %d status %04x"),
218              cl->name, cl->hostname, cl->port, cl->options,
219              cl->socket, cl->meta_socket, cl->status);
220     }
221     
222   syslog(LOG_DEBUG, _("End of connection list."));
223 cp
224 }
225
226 int read_host_config(connection_t *cl)
227 {
228   char *fname;
229   int x;
230 cp
231   asprintf(&fname, "%s/hosts/%s", confbase, cl->name);
232   x = read_config_file(&cl->config, fname);
233   free(fname);
234 cp
235   return x;
236 }