Hm.
[tinc] / src / pokey / protocol_subnet.c
1 /*
2     protocol_subnet.c -- handle the meta-protocol, subnets
3     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>,
4                   2000-2002 Guus Sliepen <guus@sliepen.warande.net>
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: protocol_subnet.c,v 1.1 2002/04/28 12:46:26 zarq Exp $
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <errno.h>
30
31 #include <utils.h>
32 #include <xalloc.h>
33 #include <avl_tree.h>
34
35 #include "conf.h"
36 #include "interface.h"
37 #include "net.h"
38 #include "netutl.h"
39 #include "protocol.h"
40 #include "meta.h"
41 #include "connection.h"
42 #include "node.h"
43 #include "edge.h"
44 #include "graph.h"
45 #include "logging.h"
46
47 #include "system.h"
48
49 int send_add_subnet(connection_t *c, subnet_t *subnet)
50 {
51   int x;
52   char *netstr;
53 cp
54   x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(),
55                       subnet->owner->name, netstr = net2str(subnet));
56   free(netstr);
57 cp
58   return x;
59 }
60
61 int add_subnet_h(connection_t *c)
62 {
63   char subnetstr[MAX_STRING_SIZE];
64   char name[MAX_STRING_SIZE];
65   node_t *owner;
66   connection_t *other;
67   subnet_t *s;
68   avl_node_t *node;
69 cp
70   if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
71     {
72       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname);
73       return -1;
74     }
75
76   /* Check if owner name is a valid */
77
78   if(check_id(name))
79     {
80       syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid name"));
81       return -1;
82     }
83
84   /* Check if subnet string is valid */
85
86   if(!(s = str2net(subnetstr)))
87     {
88       syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid subnet string"));
89       return -1;
90     }
91
92   if(seen_request(c->buffer))
93     return 0;
94  
95   /* Check if the owner of the new subnet is in the connection list */
96
97   owner = lookup_node(name);
98
99   if(!owner)
100     {
101       owner = new_node();
102       owner->name = xstrdup(name);
103       node_add(owner);
104     }
105
106   /* Check if we already know this subnet */
107   
108   if(lookup_subnet(owner, s))
109     {
110       free_subnet(s);
111       return 0;
112     }
113
114   /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */
115
116   if(owner == myself)
117   {
118     if(debug_lvl >= DEBUG_PROTOCOL)
119       syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "ADD_SUBNET", c->name, c->hostname);
120     s->owner = myself;
121     send_del_subnet(c, s);
122     return 0;
123   }
124
125   /* If everything is correct, add the subnet to the list of the owner */
126
127   subnet_add(owner, s);
128
129   /* Tell the rest */
130   
131   for(node = connection_tree->head; node; node = node->next)
132     {
133       other = (connection_t *)node->data;
134       if(other->status.active && other != c)
135         send_request(other, "%s", c->buffer);
136     }
137 cp
138   return 0;
139 }
140
141 int send_del_subnet(connection_t *c, subnet_t *s)
142 {
143   int x;
144   char *netstr;
145 cp
146   netstr = net2str(s);
147   x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr);
148   free(netstr);
149 cp
150   return x;
151 }
152
153 int del_subnet_h(connection_t *c)
154 {
155   char subnetstr[MAX_STRING_SIZE];
156   char name[MAX_STRING_SIZE];
157   node_t *owner;
158   connection_t *other;
159   subnet_t *s, *find;
160   avl_node_t *node;
161 cp
162   if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
163     {
164       syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname);
165       return -1;
166     }
167
168   /* Check if owner name is a valid */
169
170   if(check_id(name))
171     {
172       syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid name"));
173       return -1;
174     }
175
176   /* Check if the owner of the new subnet is in the connection list */
177
178   if(!(owner = lookup_node(name)))
179     {
180       if(debug_lvl >= DEBUG_PROTOCOL)
181         syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"),
182              "DEL_SUBNET", c->name, c->hostname, name);
183       return 0;
184     }
185
186   /* Check if subnet string is valid */
187
188   if(!(s = str2net(subnetstr)))
189     {
190       syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid subnet string"));
191       return -1;
192     }
193
194   if(seen_request(c->buffer))
195     return 0;
196
197   /* If everything is correct, delete the subnet from the list of the owner */
198
199   s->owner = owner;
200
201   find = lookup_subnet(owner, s);
202   
203   free_subnet(s);
204
205   if(!find)
206     {
207       if(debug_lvl >= DEBUG_PROTOCOL)
208         syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"),
209              "DEL_SUBNET", c->name, c->hostname, name);
210       return 0;
211     }
212   
213   /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */
214   
215   if(owner == myself)
216   {
217     if(debug_lvl >= DEBUG_PROTOCOL)
218       syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_SUBNET", c->name, c->hostname);
219     send_add_subnet(c, find);
220     return 0;
221   }
222
223   /* Tell the rest */
224   
225   for(node = connection_tree->head; node; node = node->next)
226     {
227       other = (connection_t *)node->data;
228       if(other->status.active && other != c)
229         send_request(other, "%s", c->buffer);
230     }
231
232   /* Finally, delete it. */
233
234   subnet_del(owner, find);
235
236 cp
237   return 0;
238 }