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