- Updated subnet list handling. Subnets are added to two lists now, the
[tinc] / src / subnet.c
1 /*
2     subnet.c -- handle subnet lookups and lists
3     Copyright (C) 2000 Guus Sliepen <guus@sliepen.warande.net>,
4                   2000 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: subnet.c,v 1.1.2.6 2000/10/28 16:41:40 guus Exp $
21 */
22
23 #include "config.h"
24 #include <utils.h>
25
26 #include <xalloc.h>
27 #include "subnet.h"
28 #include "net.h"
29
30 /* lists type of subnet */
31
32 subnet_t *subnet_list[SUBNET_TYPES] = { NULL };
33
34 /* Allocating and freeing space for subnets */
35
36 subnet_t *new_subnet(void)
37 {
38 cp
39   return (subnet_t *)xmalloc(sizeof(subnet_t));
40 }
41
42 void free_subnet(subnet_t *subnet)
43 {
44 cp
45   free(subnet);
46 }
47
48 /* Linked list management */
49
50 void subnet_add(conn_list_t *cl, subnet_t *subnet)
51 {
52   subnet_t *p = NULL;
53   subnet_t *q = NULL;
54 cp
55   subnet->owner = cl;
56
57   /* Link it into the owners list of subnets (unsorted) */
58
59   subnet->next = cl->subnets->next;
60   subnet->prev = NULL;
61   if(subnet->next)
62     subnet->next->prev = subnet;
63   cl->subnets = subnet;
64   
65   /* And now add it to the global subnet list (sorted) */
66
67   /* Sort on size of subnet mask (IPv4 only at the moment!)
68   
69      Three cases: subnet_list[] = NULL -> just add this subnet
70                   insert before first -> add it in front of list
71                   rest: insert after another subnet
72    */
73
74   if(subnet_list[subnet->type])
75     {
76       p = q = subnet_list[subnet->type];
77
78       for(; p; p = p->global_next)
79         {
80           if(subnet->net.ipv4.mask >= p->net.ipv4.mask)
81             break;
82
83           q = p;
84         }
85      }
86   
87   if(!subnet_list[subnet->type] || p == subnet_list[subnet->type])  /* First two cases */
88     {
89       /* Insert in front */
90       subnet->global_next = subnet_list[subnet->type];
91       subnet->global_prev = NULL;
92       subnet_list[subnet->type] = subnet;
93     }
94   else                                  /* Third case */
95     {
96       /* Insert after q */
97       subnet->global_next = q->global_next;
98       subnet->global_prev = q;
99       q->global_next = subnet;
100     }
101
102   if(subnet->global_next)
103     subnet->global_next->global_prev = subnet;
104 cp
105 }
106
107 void subnet_del(subnet_t *subnet)
108 {
109 cp
110   /* Remove it from owner's list */
111
112   if(subnet->prev)
113     {
114       subnet->prev->next = subnet->next;
115     }
116   else
117     {
118       subnet->owner->subnets = subnet->next;
119     }
120
121   subnet->next->prev = subnet->prev;
122
123   /* Remove it from the global list */
124   
125   if(subnet->global_prev)
126     {
127       subnet->global_prev->global_next = subnet->global_next;
128     }
129   else
130     {
131       subnet_list[subnet->type] = subnet->global_next;
132     }
133
134   subnet->global_next->global_prev = subnet->global_prev;
135   
136   free_subnet(subnet);
137 cp
138 }
139
140 /* Ascii representation of subnets */
141
142 subnet_t *str2net(char *subnetstr)
143 {
144   int type;
145   subnet_t *subnet;
146 cp
147   if(sscanf(subnetstr, "%d,", &type) != 1)
148     return NULL;
149
150   subnet = new_subnet();
151
152   switch(type)
153     {
154       case SUBNET_MAC:
155         if(sscanf(subnetstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &subnet->type,
156                    &subnet->net.mac.address.x[0],
157                    &subnet->net.mac.address.x[1],
158                    &subnet->net.mac.address.x[2],
159                    &subnet->net.mac.address.x[3],
160                    &subnet->net.mac.address.x[4],
161                    &subnet->net.mac.address.x[5]) != 7)
162           {
163             free_subnet(subnet);
164             return NULL;
165           }
166         break;
167       case SUBNET_IPV4:
168         if(sscanf(subnetstr, "%d,%lx/%lx", &subnet->type, &subnet->net.ipv4.address, &subnet->net.ipv4.mask) != 3)
169           {
170             free_subnet(subnet);
171             return NULL;
172           }
173         break;
174       case SUBNET_IPV6:
175         if(sscanf(subnetstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", &subnet->type,
176                    &subnet->net.ipv6.address.x[0],
177                    &subnet->net.ipv6.address.x[1],
178                    &subnet->net.ipv6.address.x[2],
179                    &subnet->net.ipv6.address.x[3],
180                    &subnet->net.ipv6.address.x[4],
181                    &subnet->net.ipv6.address.x[5],
182                    &subnet->net.ipv6.address.x[6],
183                    &subnet->net.ipv6.address.x[7],
184                    &subnet->net.ipv6.mask.x[0],
185                    &subnet->net.ipv6.mask.x[1],
186                    &subnet->net.ipv6.mask.x[2],
187                    &subnet->net.ipv6.mask.x[3],
188                    &subnet->net.ipv6.mask.x[4],
189                    &subnet->net.ipv6.mask.x[5],
190                    &subnet->net.ipv6.mask.x[6],
191                    &subnet->net.ipv6.mask.x[7]) != 17)
192           {
193             free_subnet(subnet);
194             return NULL;
195           }
196         break;
197                 break;
198       default:
199         free_subnet(subnet);
200         return NULL;
201     }
202 cp
203   return subnet;
204 }
205
206 char *net2str(subnet_t *subnet)
207 {
208   char *netstr;
209 cp
210   switch(subnet->type)
211     {
212       case SUBNET_MAC:
213         asprintf(&netstr, "%d,%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", subnet->type,
214                    subnet->net.mac.address.x[0],
215                    subnet->net.mac.address.x[1],
216                    subnet->net.mac.address.x[2],
217                    subnet->net.mac.address.x[3],
218                    subnet->net.mac.address.x[4],
219                    subnet->net.mac.address.x[5]);
220       case SUBNET_IPV4:
221         asprintf(&netstr, "%d,%lx/%lx", subnet->type, subnet->net.ipv4.address, subnet->net.ipv4.mask);
222       case SUBNET_IPV6:
223         asprintf(&netstr, "%d,%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
224                    subnet->net.ipv6.address.x[0],
225                    subnet->net.ipv6.address.x[1],
226                    subnet->net.ipv6.address.x[2],
227                    subnet->net.ipv6.address.x[3],
228                    subnet->net.ipv6.address.x[4],
229                    subnet->net.ipv6.address.x[5],
230                    subnet->net.ipv6.address.x[6],
231                    subnet->net.ipv6.address.x[7],
232                    subnet->net.ipv6.mask.x[0],
233                    subnet->net.ipv6.mask.x[1],
234                    subnet->net.ipv6.mask.x[2],
235                    subnet->net.ipv6.mask.x[3],
236                    subnet->net.ipv6.mask.x[4],
237                    subnet->net.ipv6.mask.x[5],
238                    subnet->net.ipv6.mask.x[6],
239                    subnet->net.ipv6.mask.x[7]);
240       default:
241         netstr = NULL;
242     }
243 cp
244   return netstr;
245 }
246
247 /* Subnet lookup routines */
248
249 subnet_t *lookup_subnet_mac(mac_t address)
250 {
251   subnet_t *subnet;
252 cp
253   for(subnet = subnet_list[SUBNET_MAC]; subnet != NULL; subnet = subnet->next)
254     {
255       if(memcmp(&address, &subnet->net.mac.address, sizeof(address)) == 0)
256         break;
257     }
258 cp
259   return subnet;
260 }
261
262 subnet_t *lookup_subnet_ipv4(ipv4_t address)
263 {
264   subnet_t *subnet;
265 cp
266   for(subnet = subnet_list[SUBNET_IPV4]; subnet != NULL; subnet = subnet->next)
267     {
268       if((address & subnet->net.ipv4.mask) == subnet->net.ipv4.address)
269         break;
270     }
271 cp
272   return subnet;
273 }
274
275 subnet_t *lookup_subnet_ipv6(ipv6_t address)
276 {
277   subnet_t *subnet;
278   int i;
279 cp
280   for(subnet = subnet_list[SUBNET_IPV6]; subnet != NULL; subnet = subnet->next)
281     {
282       for(i=0; i<8; i++)
283         if((address.x[i] & subnet->net.ipv6.mask.x[i]) != subnet->net.ipv6.address.x[i])
284           break;
285       if(i=8)
286         break;
287     }
288 cp
289   return subnet;
290 }