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