blob: a043ef48e567f9d27088b677e5c6a248d23b6e36 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
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"
hassoeef1fe12004-10-03 18:46:08 +000035#include "zebra/interface.h"
paul718e3742002-12-13 20:15:29 +000036
37/* If same interface address is already exist... */
38struct connected *
39connected_check_ipv4 (struct interface *ifp, struct prefix *p)
40{
41 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +000042 struct listnode *node;
paul718e3742002-12-13 20:15:29 +000043
44 for (node = listhead (ifp->connected); node; node = nextnode (node))
45 {
46 ifc = getdata (node);
47
48 if (prefix_same (ifc->address, p))
49 return ifc;
50 }
51 return NULL;
52}
53
54/* Called from if_up(). */
55void
56connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
57{
58 struct prefix_ipv4 p;
59 struct prefix_ipv4 *addr;
60 struct prefix_ipv4 *dest;
61
62 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
63 return;
64
65 addr = (struct prefix_ipv4 *) ifc->address;
66 dest = (struct prefix_ipv4 *) ifc->destination;
67
68 memset (&p, 0, sizeof (struct prefix_ipv4));
69 p.family = AF_INET;
70 p.prefixlen = addr->prefixlen;
71
72 /* Point-to-point check. */
paul2fe28bb2003-10-13 08:59:40 +000073 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +000074 p.prefix = dest->prefix;
75 else
76 p.prefix = addr->prefix;
77
78 /* Apply mask to the network. */
79 apply_mask_ipv4 (&p);
80
81 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
82 address. */
83 if (prefix_ipv4_any (&p))
84 return;
85
86 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
87
88 rib_update ();
89}
90
91/* Add connected IPv4 route to the interface. */
92void
93connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
94 int prefixlen, struct in_addr *broad, char *label)
95{
96 struct prefix_ipv4 *p;
97 struct connected *ifc;
98 struct connected *current;
99
100 /* Make connected structure. */
101 ifc = connected_new ();
102 ifc->ifp = ifp;
103 ifc->flags = flags;
104
105 /* Allocate new connected address. */
106 p = prefix_ipv4_new ();
107 p->family = AF_INET;
108 p->prefix = *addr;
109 p->prefixlen = prefixlen;
110 ifc->address = (struct prefix *) p;
111
112 /* If there is broadcast or pointopoint address. */
113 if (broad)
114 {
115 p = prefix_ipv4_new ();
116 p->family = AF_INET;
117 p->prefix = *broad;
118 ifc->destination = (struct prefix *) p;
119 }
120
121 /* Label of this address. */
122 if (label)
123 ifc->label = strdup (label);
124
125 /* Check same connected route. */
126 current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address);
127 if (current)
128 {
129 connected_free (ifc);
130 ifc = current;
131 }
132 else
133 {
134 listnode_add (ifp->connected, ifc);
135 }
136
137 /* Update interface address information to protocol daemon. */
138 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
139 {
hassoeef1fe12004-10-03 18:46:08 +0000140 if_subnet_add (ifp, ifc);
141
paul718e3742002-12-13 20:15:29 +0000142 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
143
144 zebra_interface_address_add_update (ifp, ifc);
145
146 if (if_is_up(ifp))
147 connected_up_ipv4 (ifp, ifc);
148 }
149}
150
151void
152connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
153{
154 struct prefix_ipv4 p;
155 struct prefix_ipv4 *addr;
156 struct prefix_ipv4 *dest;
157
158 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
159 return;
160
161 addr = (struct prefix_ipv4 *)ifc->address;
162 dest = (struct prefix_ipv4 *)ifc->destination;
163
164 memset (&p, 0, sizeof (struct prefix_ipv4));
165 p.family = AF_INET;
166 p.prefixlen = addr->prefixlen;
167
paul960182a2003-04-09 07:16:04 +0000168 /* Point-to-point check. */
paul2fe28bb2003-10-13 08:59:40 +0000169 if (dest && if_is_pointopoint (ifp))
paul718e3742002-12-13 20:15:29 +0000170 p.prefix = dest->prefix;
171 else
172 p.prefix = addr->prefix;
173
174 /* Apply mask to the network. */
175 apply_mask_ipv4 (&p);
176
177 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
178 address. */
179 if (prefix_ipv4_any (&p))
180 return;
181
182 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
183
184 rib_update ();
185}
186
187/* Delete connected IPv4 route to the interface. */
188void
189connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
190 int prefixlen, struct in_addr *broad, char *label)
191{
192 struct prefix_ipv4 p;
193 struct connected *ifc;
194
195 memset (&p, 0, sizeof (struct prefix_ipv4));
196 p.family = AF_INET;
197 p.prefix = *addr;
198 p.prefixlen = prefixlen;
199
200 ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
201 if (! ifc)
202 return;
203
204 /* Update interface address information to protocol daemon. */
205 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
206 {
207 zebra_interface_address_delete_update (ifp, ifc);
208
hassoeef1fe12004-10-03 18:46:08 +0000209 if_subnet_delete (ifp, ifc);
210
paul718e3742002-12-13 20:15:29 +0000211 connected_down_ipv4 (ifp, ifc);
212
213 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
214 }
215
hassoeef1fe12004-10-03 18:46:08 +0000216 listnode_delete (ifp->connected, ifc);
217 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000218}
219
220#ifdef HAVE_IPV6
221/* If same interface address is already exist... */
222struct connected *
223connected_check_ipv6 (struct interface *ifp, struct prefix *p)
224{
225 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000226 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000227
228 for (node = listhead (ifp->connected); node; node = nextnode (node))
229 {
230 ifc = getdata (node);
231
232 if (prefix_same (ifc->address, p))
233 return ifc;
234 }
235 return 0;
236}
237
238void
239connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
240{
241 struct prefix_ipv6 p;
242 struct prefix_ipv6 *addr;
243 struct prefix_ipv6 *dest;
244
245 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
246 return;
247
248 addr = (struct prefix_ipv6 *) ifc->address;
249 dest = (struct prefix_ipv6 *) ifc->destination;
250
251 memset (&p, 0, sizeof (struct prefix_ipv6));
252 p.family = AF_INET6;
253 p.prefixlen = addr->prefixlen;
254
paul31a476c2003-09-29 19:54:53 +0000255 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000256 {
257 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
258 p.prefix = addr->prefix;
259 else
260 p.prefix = dest->prefix;
261 }
262 else
263 p.prefix = addr->prefix;
264
265 /* Apply mask to the network. */
266 apply_mask_ipv6 (&p);
267
hasso726f9b22003-05-25 21:04:54 +0000268#if ! defined (MUSICA) && ! defined (LINUX)
269 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000270 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
271 return;
hasso726f9b22003-05-25 21:04:54 +0000272#endif
paul718e3742002-12-13 20:15:29 +0000273
274 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
275
276 rib_update ();
277}
278
279/* Add connected IPv6 route to the interface. */
280void
281connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
hassofce954f2004-10-07 20:29:24 +0000282 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000283{
284 struct prefix_ipv6 *p;
285 struct connected *ifc;
286 struct connected *current;
287
288 /* Make connected structure. */
289 ifc = connected_new ();
290 ifc->ifp = ifp;
291
292 /* Allocate new connected address. */
293 p = prefix_ipv6_new ();
294 p->family = AF_INET6;
295 IPV6_ADDR_COPY (&p->prefix, addr);
296 p->prefixlen = prefixlen;
297 ifc->address = (struct prefix *) p;
298
299 /* If there is broadcast or pointopoint address. */
300 if (broad)
301 {
302 p = prefix_ipv6_new ();
303 p->family = AF_INET6;
304 IPV6_ADDR_COPY (&p->prefix, broad);
305 ifc->destination = (struct prefix *) p;
306 }
307
308 current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
309 if (current)
310 {
311 connected_free (ifc);
312 ifc = current;
313 }
314 else
315 {
316 listnode_add (ifp->connected, ifc);
317 }
318
319 /* Update interface address information to protocol daemon. */
320 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
321 {
322 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
323
324 zebra_interface_address_add_update (ifp, ifc);
325
326 if (if_is_up(ifp))
327 connected_up_ipv6 (ifp, ifc);
328 }
329}
330
331void
332connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
333{
334 struct prefix_ipv6 p;
335 struct prefix_ipv6 *addr;
336 struct prefix_ipv6 *dest;
337
338 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
339 return;
340
341 addr = (struct prefix_ipv6 *) ifc->address;
342 dest = (struct prefix_ipv6 *) ifc->destination;
343
344 memset (&p, 0, sizeof (struct prefix_ipv6));
345 p.family = AF_INET6;
346 p.prefixlen = addr->prefixlen;
347
paul31a476c2003-09-29 19:54:53 +0000348 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000349 {
350 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
351 p.prefix = addr->prefix;
352 else
353 p.prefix = dest->prefix;
354 }
355 else
356 p.prefix = addr->prefix;
357
358 apply_mask_ipv6 (&p);
359
360 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
361 return;
362
363 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
364
365 rib_update ();
366}
367
368void
369connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
hassofce954f2004-10-07 20:29:24 +0000370 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000371{
372 struct prefix_ipv6 p;
373 struct connected *ifc;
374
375 memset (&p, 0, sizeof (struct prefix_ipv6));
376 p.family = AF_INET6;
377 memcpy (&p.prefix, address, sizeof (struct in6_addr));
378 p.prefixlen = prefixlen;
379
380 ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
381 if (! ifc)
382 return;
383
384 /* Update interface address information to protocol daemon. */
385 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
386 {
387 zebra_interface_address_delete_update (ifp, ifc);
388
389 connected_down_ipv6 (ifp, ifc);
390
391 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
392 }
393
hassoeef1fe12004-10-03 18:46:08 +0000394 listnode_delete (ifp->connected, ifc);
395 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000396}
397#endif /* HAVE_IPV6 */