blob: 5f581915be95b4a52dc1e562da35d28947d252a1 [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. */
hasso3fb9cd62004-10-19 19:44:43 +000073 if (CONNECTED_POINTOPOINT_HOST(ifc))
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;
hasso3fb9cd62004-10-19 19:44:43 +0000119
120 /* validate the destination address */
121 if (ifp->flags & IFF_POINTOPOINT)
122 {
123 if (IPV4_ADDR_SAME(addr,broad))
124 zlog_warn("warning: PtP interface %s has same local and peer "
125 "address %s, routing protocols may malfunction",
126 ifp->name,inet_ntoa(*addr));
127 else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
128 (ipv4_network_addr(addr->s_addr,prefixlen) !=
129 ipv4_network_addr(broad->s_addr,prefixlen)))
130 {
131 char buf[2][INET_ADDRSTRLEN];
132 zlog_warn("warning: PtP interface %s network mismatch: local "
133 "%s/%d vs. peer %s, routing protocols may malfunction",
134 ifp->name,
135 inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
136 prefixlen,
137 inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
138 }
139 }
140 else
141 {
142 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
143 {
144 char buf[2][INET_ADDRSTRLEN];
145 struct in_addr bcalc;
146 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
147 zlog_warn("warning: interface %s broadcast addr %s/%d != "
148 "calculated %s, routing protocols may malfunction",
149 ifp->name,
150 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
151 prefixlen,
152 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
153 }
154 }
155
paul718e3742002-12-13 20:15:29 +0000156 }
hasso3fb9cd62004-10-19 19:44:43 +0000157 else
158 /* no broadcast or destination address was supplied */
ajs341a8f12004-12-22 16:32:16 +0000159 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
160 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
161 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
paul718e3742002-12-13 20:15:29 +0000162
163 /* Label of this address. */
164 if (label)
165 ifc->label = strdup (label);
166
167 /* Check same connected route. */
168 current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address);
169 if (current)
170 {
171 connected_free (ifc);
172 ifc = current;
173 }
174 else
175 {
176 listnode_add (ifp->connected, ifc);
177 }
178
179 /* Update interface address information to protocol daemon. */
180 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
181 {
hassoeef1fe12004-10-03 18:46:08 +0000182 if_subnet_add (ifp, ifc);
183
paul718e3742002-12-13 20:15:29 +0000184 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
185
186 zebra_interface_address_add_update (ifp, ifc);
187
188 if (if_is_up(ifp))
189 connected_up_ipv4 (ifp, ifc);
190 }
191}
192
193void
194connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
195{
196 struct prefix_ipv4 p;
197 struct prefix_ipv4 *addr;
198 struct prefix_ipv4 *dest;
199
200 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
201 return;
202
203 addr = (struct prefix_ipv4 *)ifc->address;
204 dest = (struct prefix_ipv4 *)ifc->destination;
205
206 memset (&p, 0, sizeof (struct prefix_ipv4));
207 p.family = AF_INET;
208 p.prefixlen = addr->prefixlen;
209
paul960182a2003-04-09 07:16:04 +0000210 /* Point-to-point check. */
hasso3fb9cd62004-10-19 19:44:43 +0000211 if (CONNECTED_POINTOPOINT_HOST(ifc))
paul718e3742002-12-13 20:15:29 +0000212 p.prefix = dest->prefix;
213 else
214 p.prefix = addr->prefix;
215
216 /* Apply mask to the network. */
217 apply_mask_ipv4 (&p);
218
219 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
220 address. */
221 if (prefix_ipv4_any (&p))
222 return;
223
224 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
225
226 rib_update ();
227}
228
229/* Delete connected IPv4 route to the interface. */
230void
231connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
232 int prefixlen, struct in_addr *broad, char *label)
233{
234 struct prefix_ipv4 p;
235 struct connected *ifc;
236
237 memset (&p, 0, sizeof (struct prefix_ipv4));
238 p.family = AF_INET;
239 p.prefix = *addr;
240 p.prefixlen = prefixlen;
241
242 ifc = connected_check_ipv4 (ifp, (struct prefix *) &p);
243 if (! ifc)
244 return;
245
246 /* Update interface address information to protocol daemon. */
247 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
248 {
249 zebra_interface_address_delete_update (ifp, ifc);
250
hassoeef1fe12004-10-03 18:46:08 +0000251 if_subnet_delete (ifp, ifc);
252
paul718e3742002-12-13 20:15:29 +0000253 connected_down_ipv4 (ifp, ifc);
254
255 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
256 }
257
hassoeef1fe12004-10-03 18:46:08 +0000258 listnode_delete (ifp->connected, ifc);
259 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000260}
261
262#ifdef HAVE_IPV6
263/* If same interface address is already exist... */
264struct connected *
265connected_check_ipv6 (struct interface *ifp, struct prefix *p)
266{
267 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000268 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000269
270 for (node = listhead (ifp->connected); node; node = nextnode (node))
271 {
272 ifc = getdata (node);
273
274 if (prefix_same (ifc->address, p))
275 return ifc;
276 }
277 return 0;
278}
279
280void
281connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
282{
283 struct prefix_ipv6 p;
284 struct prefix_ipv6 *addr;
285 struct prefix_ipv6 *dest;
286
287 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
288 return;
289
290 addr = (struct prefix_ipv6 *) ifc->address;
291 dest = (struct prefix_ipv6 *) ifc->destination;
292
293 memset (&p, 0, sizeof (struct prefix_ipv6));
294 p.family = AF_INET6;
295 p.prefixlen = addr->prefixlen;
296
paul31a476c2003-09-29 19:54:53 +0000297 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000298 {
299 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
300 p.prefix = addr->prefix;
301 else
302 p.prefix = dest->prefix;
303 }
304 else
305 p.prefix = addr->prefix;
306
307 /* Apply mask to the network. */
308 apply_mask_ipv6 (&p);
309
hasso726f9b22003-05-25 21:04:54 +0000310#if ! defined (MUSICA) && ! defined (LINUX)
311 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000312 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
313 return;
hasso726f9b22003-05-25 21:04:54 +0000314#endif
paul718e3742002-12-13 20:15:29 +0000315
316 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
317
318 rib_update ();
319}
320
321/* Add connected IPv6 route to the interface. */
322void
323connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
hassofce954f2004-10-07 20:29:24 +0000324 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000325{
326 struct prefix_ipv6 *p;
327 struct connected *ifc;
328 struct connected *current;
329
330 /* Make connected structure. */
331 ifc = connected_new ();
332 ifc->ifp = ifp;
333
334 /* Allocate new connected address. */
335 p = prefix_ipv6_new ();
336 p->family = AF_INET6;
337 IPV6_ADDR_COPY (&p->prefix, addr);
338 p->prefixlen = prefixlen;
339 ifc->address = (struct prefix *) p;
340
341 /* If there is broadcast or pointopoint address. */
342 if (broad)
343 {
344 p = prefix_ipv6_new ();
345 p->family = AF_INET6;
346 IPV6_ADDR_COPY (&p->prefix, broad);
347 ifc->destination = (struct prefix *) p;
348 }
349
350 current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address);
351 if (current)
352 {
353 connected_free (ifc);
354 ifc = current;
355 }
356 else
357 {
358 listnode_add (ifp->connected, ifc);
359 }
360
361 /* Update interface address information to protocol daemon. */
362 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
363 {
364 SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
365
366 zebra_interface_address_add_update (ifp, ifc);
367
368 if (if_is_up(ifp))
369 connected_up_ipv6 (ifp, ifc);
370 }
371}
372
373void
374connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
375{
376 struct prefix_ipv6 p;
377 struct prefix_ipv6 *addr;
378 struct prefix_ipv6 *dest;
379
380 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
381 return;
382
383 addr = (struct prefix_ipv6 *) ifc->address;
384 dest = (struct prefix_ipv6 *) ifc->destination;
385
386 memset (&p, 0, sizeof (struct prefix_ipv6));
387 p.family = AF_INET6;
388 p.prefixlen = addr->prefixlen;
389
paul31a476c2003-09-29 19:54:53 +0000390 if (if_is_pointopoint (ifp) && dest)
paul718e3742002-12-13 20:15:29 +0000391 {
392 if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
393 p.prefix = addr->prefix;
394 else
395 p.prefix = dest->prefix;
396 }
397 else
398 p.prefix = addr->prefix;
399
400 apply_mask_ipv6 (&p);
401
402 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
403 return;
404
405 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0);
406
407 rib_update ();
408}
409
410void
411connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
hassofce954f2004-10-07 20:29:24 +0000412 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000413{
414 struct prefix_ipv6 p;
415 struct connected *ifc;
416
417 memset (&p, 0, sizeof (struct prefix_ipv6));
418 p.family = AF_INET6;
419 memcpy (&p.prefix, address, sizeof (struct in6_addr));
420 p.prefixlen = prefixlen;
421
422 ifc = connected_check_ipv6 (ifp, (struct prefix *) &p);
423 if (! ifc)
424 return;
425
426 /* Update interface address information to protocol daemon. */
427 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
428 {
429 zebra_interface_address_delete_update (ifp, ifc);
430
431 connected_down_ipv6 (ifp, ifc);
432
433 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
434 }
435
hassoeef1fe12004-10-03 18:46:08 +0000436 listnode_delete (ifp->connected, ifc);
437 connected_free (ifc);
paul718e3742002-12-13 20:15:29 +0000438}
439#endif /* HAVE_IPV6 */