www.usr.com/support/gpl/USR9108_release1.5.tar.gz
[bcm963xx.git] / userapps / opensource / zebra / zebra / connected.c
1 /*
2  * Address linked list routine.
3  * Copyright (C) 1997, 98 Kunihiro Ishiguro
4  *
5  * This file is part of GNU Zebra.
6  *
7  * GNU Zebra is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2, or (at your option) any
10  * later version.
11  *
12  * GNU Zebra is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
19  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20  * 02111-1307, USA.  
21  */
22
23 #include <zebra.h>
24
25 #include "prefix.h"
26 #include "linklist.h"
27 #include "if.h"
28 #include "table.h"
29 #include "rib.h"
30 #include "table.h"
31 #include "log.h"
32
33 #include "zebra/zserv.h"
34 #include "zebra/redistribute.h"
35 \f
36 /* If same interface address is already exist... */
37 struct connected *
38 connected_check_ipv4 (struct interface *ifp, struct prefix *p)
39 {
40   struct connected *ifc;
41   listnode node;
42
43   for (node = listhead (ifp->connected); node; node = nextnode (node))
44     {
45       ifc = getdata (node);
46
47       if (prefix_same (ifc->address, p))
48         return ifc;
49     }
50   return NULL;
51 }
52
53 /* Called from if_up(). */
54 void
55 connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
56 {
57   struct prefix_ipv4 p;
58   struct prefix_ipv4 *addr;
59   struct prefix_ipv4 *dest;
60
61   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
62     return;
63
64   addr = (struct prefix_ipv4 *) ifc->address;
65   dest = (struct prefix_ipv4 *) ifc->destination;
66
67   memset (&p, 0, sizeof (struct prefix_ipv4));
68   p.family = AF_INET;
69   p.prefixlen = addr->prefixlen;
70
71   /* Point-to-point check. */
72   if (if_is_pointopoint (ifp))
73     p.prefix = dest->prefix;
74   else
75     p.prefix = addr->prefix;
76
77   /* Apply mask to the network. */
78   apply_mask_ipv4 (&p);
79
80   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
81      address. */
82   if (prefix_ipv4_any (&p))
83     return;
84
85   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
86
87   rib_update ();
88 }
89
90 /* Add connected IPv4 route to the interface. */
91 void
92 connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, 
93                     int prefixlen, struct in_addr *broad, char *label)
94 {
95   struct prefix_ipv4 *p;
96   struct connected *ifc;
97   struct connected *current;
98
99   /* Make connected structure. */
100   ifc = connected_new ();
101   ifc->ifp = ifp;
102   ifc->flags = flags;
103
104   /* Allocate new connected address. */
105   p = prefix_ipv4_new ();
106   p->family = AF_INET;
107   p->prefix = *addr;
108   p->prefixlen = prefixlen;
109   ifc->address = (struct prefix *) p;
110
111   /* If there is broadcast or pointopoint address. */
112   if (broad)
113     {
114       p = prefix_ipv4_new ();
115       p->family = AF_INET;
116       p->prefix = *broad;
117       ifc->destination = (struct prefix *) p;
118     }
119
120   /* Label of this address. */
121   if (label)
122     ifc->label = strdup (label);
123
124   /* Check same connected route. */
125   current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address);
126   if (current)
127     {
128       connected_free (ifc);
129       ifc = current;
130     }
131   else
132     {
133       listnode_add (ifp->connected, ifc);
134     }
135
136   /* Update interface address information to protocol daemon. */
137   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
138     {
139       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
140
141       zebra_interface_address_add_update (ifp, ifc);
142
143       if (if_is_up(ifp))
144         connected_up_ipv4 (ifp, ifc);
145     }
146 }
147
148 void
149 connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
150 {
151   struct prefix_ipv4 p;
152   struct prefix_ipv4 *addr;
153   struct prefix_ipv4 *dest;
154
155   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
156     return;
157
158   addr = (struct prefix_ipv4 *)ifc->address;
159   dest = (struct prefix_ipv4 *)ifc->destination;
160
161   memset (&p, 0, sizeof (struct prefix_ipv4));
162   p.family = AF_INET;
163   p.prefixlen = addr->prefixlen;
164
165   if (if_is_pointopoint (ifp))
166     p.prefix = dest->prefix;
167   else
168     p.prefix = addr->prefix;
169
170   /* Apply mask to the network. */
171   apply_mask_ipv4 (&p);
172
173   /* In case of connected address is 0.0.0.0/0 we treat it tunnel
174      address. */
175   if (prefix_ipv4_any (&p))
176     return;
177
178   rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
179
180   rib_update ();
181 }
182
183 /* Delete connected IPv4 route to the interface. */
184 void
185 connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
186                        int prefixlen, struct in_addr *broad, char *label)
187 {
188   struct prefix_ipv4 p;
189   struct connected *ifc;
190
191   memset (&p, 0, sizeof (struct prefix_ipv4));
192   p.family = AF_INET;
193   p.prefix = *addr;
194   p.prefixlen = prefixlen;
195
196   ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
197   if (! ifc)
198     return;
199
200   /* Update interface address information to protocol daemon. */
201   if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
202     {
203       zebra_interface_address_delete_update (ifp, ifc);
204
205       connected_down_ipv4 (ifp, ifc);
206
207       UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
208     }
209
210   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
211     {
212       listnode_delete (ifp->connected, ifc);
213       connected_free (ifc);
214     }
215 }
216
217 #ifdef HAVE_IPV6
218 /* If same interface address is already exist... */
219 struct connected *
220 connected_check_ipv6 (struct interface *ifp, struct prefix *p)
221 {
222   struct connected *ifc;
223   listnode node;
224
225   for (node = listhead (ifp->connected); node; node = nextnode (node))
226     {
227       ifc = getdata (node);
228
229       if (prefix_same (ifc->address, p))
230         return ifc;
231     }
232   return 0;
233 }
234
235 void
236 connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
237 {
238   struct prefix_ipv6 p;
239   struct prefix_ipv6 *addr;
240   struct prefix_ipv6 *dest;
241
242   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
243     return;
244
245   addr = (struct prefix_ipv6 *) ifc->address;
246   dest = (struct prefix_ipv6 *) ifc->destination;
247
248   memset (&p, 0, sizeof (struct prefix_ipv6));
249   p.family = AF_INET6;
250   p.prefixlen = addr->prefixlen;
251
252   if (if_is_pointopoint (ifp) && dest)
253     {
254       if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
255         p.prefix = addr->prefix;
256       else
257         p.prefix = dest->prefix;
258     }
259   else
260     p.prefix = addr->prefix;
261
262   /* Apply mask to the network. */
263   apply_mask_ipv6 (&p);
264
265   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
266     return;
267
268   rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
269
270   rib_update ();
271 }
272
273 /* Add connected IPv6 route to the interface. */
274 void
275 connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
276                     int prefixlen, struct in6_addr *broad)
277 {
278   struct prefix_ipv6 *p;
279   struct connected *ifc;
280   struct connected *current;
281
282   /* Make connected structure. */
283   ifc = connected_new ();
284   ifc->ifp = ifp;
285
286   /* Allocate new connected address. */
287   p = prefix_ipv6_new ();
288   p->family = AF_INET6;
289   IPV6_ADDR_COPY (&p->prefix, addr);
290   p->prefixlen = prefixlen;
291   ifc->address = (struct prefix *) p;
292
293   /* If there is broadcast or pointopoint address. */
294   if (broad)
295     {
296       p = prefix_ipv6_new ();
297       p->family = AF_INET6;
298       IPV6_ADDR_COPY (&p->prefix, broad);
299       ifc->destination = (struct prefix *) p;
300     }
301
302   current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
303   if (current)
304     {
305       connected_free (ifc);
306       ifc = current;
307     }
308   else
309     {
310       listnode_add (ifp->connected, ifc);
311     }
312
313   /* Update interface address information to protocol daemon. */
314   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
315     {
316       SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
317
318       zebra_interface_address_add_update (ifp, ifc);
319
320       if (if_is_up(ifp))
321         connected_up_ipv6 (ifp, ifc);
322     }
323 }
324
325 void
326 connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
327 {
328   struct prefix_ipv6 p;
329   struct prefix_ipv6 *addr;
330   struct prefix_ipv6 *dest;
331
332   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
333     return;
334
335   addr = (struct prefix_ipv6 *) ifc->address;
336   dest = (struct prefix_ipv6 *) ifc->destination;
337
338   memset (&p, 0, sizeof (struct prefix_ipv6));
339   p.family = AF_INET6;
340   p.prefixlen = addr->prefixlen;
341
342   if (if_is_pointopoint (ifp) && dest)
343     {
344       if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
345         p.prefix = addr->prefix;
346       else
347         p.prefix = dest->prefix;
348     }
349   else
350     p.prefix = addr->prefix;
351
352   apply_mask_ipv6 (&p);
353
354   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
355     return;
356
357   rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
358
359   rib_update ();
360 }
361
362 void
363 connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
364                     int prefixlen, struct in6_addr *broad)
365 {
366   struct prefix_ipv6 p;
367   struct connected *ifc;
368   
369   memset (&p, 0, sizeof (struct prefix_ipv6));
370   p.family = AF_INET6;
371   memcpy (&p.prefix, address, sizeof (struct in6_addr));
372   p.prefixlen = prefixlen;
373
374   ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
375   if (! ifc)
376     return;
377
378   /* Update interface address information to protocol daemon. */
379   if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
380     {
381       zebra_interface_address_delete_update (ifp, ifc);
382
383       connected_down_ipv6 (ifp, ifc);
384
385       UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
386     }
387
388   if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
389     {
390       listnode_delete (ifp->connected, ifc);
391       connected_free (ifc);
392     }
393 }
394 #endif /* HAVE_IPV6 */