blob: 4802f2ba0c7cbf6538ea306dc8b6fe0c1b27442c [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"
paul0752ef02005-11-03 12:35:21 +000032#include "memory.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "zebra/zserv.h"
35#include "zebra/redistribute.h"
hassoeef1fe12004-10-03 18:46:08 +000036#include "zebra/interface.h"
paula1ac18c2005-06-28 17:17:12 +000037#include "zebra/connected.h"
Denis Ovsienko6ce80bd2007-11-12 14:55:01 +000038extern struct zebra_t zebrad;
paul718e3742002-12-13 20:15:29 +000039
Christian Franke02b48052013-01-24 14:04:49 +000040/* communicate the withdrawal of a connected address */
paulca162182005-09-12 16:58:52 +000041static void
42connected_withdraw (struct connected *ifc)
43{
44 if (! ifc)
45 return;
46
47 /* Update interface address information to protocol daemon. */
48 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
49 {
50 zebra_interface_address_delete_update (ifc->ifp, ifc);
51
Christian Franke9db047f2013-01-24 14:04:44 +000052 if (ifc->address->family == AF_INET)
53 if_subnet_delete (ifc->ifp, ifc);
54
paulca162182005-09-12 16:58:52 +000055 if (ifc->address->family == AF_INET)
56 connected_down_ipv4 (ifc->ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000057#ifdef HAVE_IPV6
paulca162182005-09-12 16:58:52 +000058 else
59 connected_down_ipv6 (ifc->ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000060#endif
paulca162182005-09-12 16:58:52 +000061
62 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
63 }
64
Christian Frankef7f740f2013-01-24 14:04:48 +000065 /* The address is not in the kernel anymore, so clear the flag */
66 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
67
Andrew J. Schorr9c378512006-05-21 04:04:49 +000068 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
69 {
70 listnode_delete (ifc->ifp->connected, ifc);
71 connected_free (ifc);
72 }
paulca162182005-09-12 16:58:52 +000073}
74
75static void
76connected_announce (struct interface *ifp, struct connected *ifc)
77{
78 if (!ifc)
79 return;
80
81 listnode_add (ifp->connected, ifc);
82
83 /* Update interface address information to protocol daemon. */
Christian Franke02b48052013-01-24 14:04:49 +000084 if (ifc->address->family == AF_INET)
85 if_subnet_add (ifp, ifc);
86
87 zebra_interface_address_add_update (ifp, ifc);
88
89 if (if_is_operative(ifp))
paulca162182005-09-12 16:58:52 +000090 {
91 if (ifc->address->family == AF_INET)
Christian Franke02b48052013-01-24 14:04:49 +000092 connected_up_ipv4 (ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000093#ifdef HAVE_IPV6
Christian Franke02b48052013-01-24 14:04:49 +000094 else
95 connected_up_ipv6 (ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000096#endif
paulca162182005-09-12 16:58:52 +000097 }
98}
99
paul718e3742002-12-13 20:15:29 +0000100/* If same interface address is already exist... */
101struct connected *
paulca162182005-09-12 16:58:52 +0000102connected_check (struct interface *ifp, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000103{
104 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000105 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000106
paul1eb8ef22005-04-07 07:30:20 +0000107 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
108 if (prefix_same (ifc->address, p))
109 return ifc;
paul718e3742002-12-13 20:15:29 +0000110
paul718e3742002-12-13 20:15:29 +0000111 return NULL;
112}
113
Christian Franke02b48052013-01-24 14:04:49 +0000114/* Check if two ifc's describe the same address in the same state */
Paul Jakma74ecdc92006-06-15 18:10:47 +0000115static int
116connected_same (struct connected *ifc1, struct connected *ifc2)
117{
118 if (ifc1->ifp != ifc2->ifp)
119 return 0;
120
121 if (ifc1->destination)
122 if (!ifc2->destination)
123 return 0;
124 if (ifc2->destination)
125 if (!ifc1->destination)
126 return 0;
127
128 if (ifc1->destination && ifc2->destination)
129 if (!prefix_same (ifc1->destination, ifc2->destination))
130 return 0;
131
132 if (ifc1->flags != ifc2->flags)
133 return 0;
Christian Franke02b48052013-01-24 14:04:49 +0000134
135 if (ifc1->conf != ifc2->conf)
136 return 0;
Paul Jakma74ecdc92006-06-15 18:10:47 +0000137
138 return 1;
139}
140
Christian Franked7f5dad2013-01-24 14:04:46 +0000141/* Handle changes to addresses and send the neccesary announcements
142 * to clients. */
143static void
144connected_update(struct interface *ifp, struct connected *ifc)
Paul Jakma74ecdc92006-06-15 18:10:47 +0000145{
146 struct connected *current;
147
148 /* Check same connected route. */
149 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
150 {
151 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
152 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
153
154 /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
155 * back an address we have already added.
156 */
Christian Franke02b48052013-01-24 14:04:49 +0000157 if (connected_same (current, ifc))
Paul Jakma74ecdc92006-06-15 18:10:47 +0000158 {
159 /* nothing to do */
160 connected_free (ifc);
Christian Franked7f5dad2013-01-24 14:04:46 +0000161 return;
Paul Jakma74ecdc92006-06-15 18:10:47 +0000162 }
Christian Franked7f5dad2013-01-24 14:04:46 +0000163
164 /* Clear the configured flag on the old ifc, so it will be freed by
165 * connected withdraw. */
Paul Jakma74ecdc92006-06-15 18:10:47 +0000166 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
167 connected_withdraw (current); /* implicit withdraw - freebsd does this */
168 }
Christian Franked7f5dad2013-01-24 14:04:46 +0000169
Christian Franke02b48052013-01-24 14:04:49 +0000170 /* If the connected is new or has changed, announce it, if it is usable */
171 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
172 connected_announce(ifp, ifc);
Paul Jakma74ecdc92006-06-15 18:10:47 +0000173}
174
paul718e3742002-12-13 20:15:29 +0000175/* Called from if_up(). */
176void
177connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
178{
179 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +0000180
181 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
182 return;
183
Andrew J. Schorre4529632006-12-12 19:18:21 +0000184 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000185
186 /* Apply mask to the network. */
187 apply_mask_ipv4 (&p);
188
189 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
190 address. */
191 if (prefix_ipv4_any (&p))
192 return;
193
Paul Jakma7514fb72007-05-02 16:05:35 +0000194 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
G.Balajicddf3912011-11-26 21:59:32 +0400195 RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000196
G.Balaji42cb6b62012-04-02 23:31:29 +0530197 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
198 RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
199
paul718e3742002-12-13 20:15:29 +0000200 rib_update ();
201}
202
203/* Add connected IPv4 route to the interface. */
204void
205connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
pauld06b2a62005-10-11 03:53:54 +0000206 u_char prefixlen, struct in_addr *broad,
207 const char *label)
paul718e3742002-12-13 20:15:29 +0000208{
209 struct prefix_ipv4 *p;
210 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +0000211
212 /* Make connected structure. */
213 ifc = connected_new ();
214 ifc->ifp = ifp;
215 ifc->flags = flags;
Christian Frankef7f740f2013-01-24 14:04:48 +0000216 /* If we get a notification from the kernel,
217 * we can safely assume the address is known to the kernel */
218 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
paul718e3742002-12-13 20:15:29 +0000219
220 /* Allocate new connected address. */
221 p = prefix_ipv4_new ();
222 p->family = AF_INET;
223 p->prefix = *addr;
224 p->prefixlen = prefixlen;
225 ifc->address = (struct prefix *) p;
paulca162182005-09-12 16:58:52 +0000226
Andrew J. Schorre4529632006-12-12 19:18:21 +0000227 /* If there is broadcast or peer address. */
paul718e3742002-12-13 20:15:29 +0000228 if (broad)
229 {
230 p = prefix_ipv4_new ();
231 p->family = AF_INET;
232 p->prefix = *broad;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000233 p->prefixlen = prefixlen;
paul718e3742002-12-13 20:15:29 +0000234 ifc->destination = (struct prefix *) p;
hasso3fb9cd62004-10-19 19:44:43 +0000235
236 /* validate the destination address */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000237 if (CONNECTED_PEER(ifc))
hasso3fb9cd62004-10-19 19:44:43 +0000238 {
239 if (IPV4_ADDR_SAME(addr,broad))
Andrew J. Schorre4529632006-12-12 19:18:21 +0000240 zlog_warn("warning: interface %s has same local and peer "
hasso3fb9cd62004-10-19 19:44:43 +0000241 "address %s, routing protocols may malfunction",
242 ifp->name,inet_ntoa(*addr));
hasso3fb9cd62004-10-19 19:44:43 +0000243 }
244 else
245 {
246 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
247 {
248 char buf[2][INET_ADDRSTRLEN];
249 struct in_addr bcalc;
250 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
251 zlog_warn("warning: interface %s broadcast addr %s/%d != "
252 "calculated %s, routing protocols may malfunction",
253 ifp->name,
254 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
255 prefixlen,
256 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
257 }
258 }
259
paul718e3742002-12-13 20:15:29 +0000260 }
hasso3fb9cd62004-10-19 19:44:43 +0000261 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000262 {
263 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
264 {
265 zlog_warn("warning: %s called for interface %s "
266 "with peer flag set, but no peer address supplied",
267 __func__, ifp->name);
268 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
269 }
270
271 /* no broadcast or destination address was supplied */
272 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
273 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
274 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
275 }
paul718e3742002-12-13 20:15:29 +0000276
277 /* Label of this address. */
278 if (label)
paul0752ef02005-11-03 12:35:21 +0000279 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +0000280
Christian Franke02b48052013-01-24 14:04:49 +0000281 /* For all that I know an IPv4 address is always ready when we receive
282 * the notification. So it should be safe to set the REAL flag here. */
283 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
284
Christian Franked7f5dad2013-01-24 14:04:46 +0000285 connected_update(ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000286}
287
288void
289connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
290{
291 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +0000292
293 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
294 return;
295
Andrew J. Schorre4529632006-12-12 19:18:21 +0000296 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000297
298 /* Apply mask to the network. */
299 apply_mask_ipv4 (&p);
300
301 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
302 address. */
303 if (prefix_ipv4_any (&p))
304 return;
305
Denis Ovsienko6ce80bd2007-11-12 14:55:01 +0000306 /* Same logic as for connected_up_ipv4(): push the changes into the head. */
G.Balajicddf3912011-11-26 21:59:32 +0400307 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000308
G.Balaji42cb6b62012-04-02 23:31:29 +0530309 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST);
310
paul718e3742002-12-13 20:15:29 +0000311 rib_update ();
312}
313
314/* Delete connected IPv4 route to the interface. */
315void
316connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
paul0752ef02005-11-03 12:35:21 +0000317 u_char prefixlen, struct in_addr *broad)
paul718e3742002-12-13 20:15:29 +0000318{
319 struct prefix_ipv4 p;
320 struct connected *ifc;
321
322 memset (&p, 0, sizeof (struct prefix_ipv4));
323 p.family = AF_INET;
324 p.prefix = *addr;
325 p.prefixlen = prefixlen;
326
paulca162182005-09-12 16:58:52 +0000327 ifc = connected_check (ifp, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000328 if (! ifc)
329 return;
paulca162182005-09-12 16:58:52 +0000330
331 connected_withdraw (ifc);
Stephen Hemminger90d2ab02009-04-29 21:54:59 -0700332
333 rib_update();
paul718e3742002-12-13 20:15:29 +0000334}
335
336#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +0000337void
338connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
339{
340 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +0000341
342 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
343 return;
344
Andrew J. Schorre4529632006-12-12 19:18:21 +0000345 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000346
347 /* Apply mask to the network. */
348 apply_mask_ipv6 (&p);
349
hasso726f9b22003-05-25 21:04:54 +0000350#if ! defined (MUSICA) && ! defined (LINUX)
351 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000352 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
353 return;
hasso726f9b22003-05-25 21:04:54 +0000354#endif
paul718e3742002-12-13 20:15:29 +0000355
Mathieu Goessensd13c3b42009-06-23 15:59:45 +0100356 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN,
G.Balajif768f362011-11-26 22:10:39 +0400357 ifp->metric, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000358
359 rib_update ();
360}
361
362/* Add connected IPv6 route to the interface. */
363void
Andrew J. Schorre4529632006-12-12 19:18:21 +0000364connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
paul89368d92005-11-26 09:14:07 +0000365 u_char prefixlen, struct in6_addr *broad,
366 const char *label)
paul718e3742002-12-13 20:15:29 +0000367{
368 struct prefix_ipv6 *p;
369 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +0000370
371 /* Make connected structure. */
372 ifc = connected_new ();
373 ifc->ifp = ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000374 ifc->flags = flags;
Christian Frankef7f740f2013-01-24 14:04:48 +0000375 /* If we get a notification from the kernel,
376 * we can safely assume the address is known to the kernel */
377 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
paul718e3742002-12-13 20:15:29 +0000378
379 /* Allocate new connected address. */
380 p = prefix_ipv6_new ();
381 p->family = AF_INET6;
382 IPV6_ADDR_COPY (&p->prefix, addr);
383 p->prefixlen = prefixlen;
384 ifc->address = (struct prefix *) p;
385
Andrew J. Schorre4529632006-12-12 19:18:21 +0000386 /* If there is broadcast or peer address. */
paul718e3742002-12-13 20:15:29 +0000387 if (broad)
388 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000389 if (IN6_IS_ADDR_UNSPECIFIED(broad))
390 zlog_warn("warning: %s called for interface %s with unspecified "
391 "destination address; ignoring!", __func__, ifp->name);
392 else
393 {
394 p = prefix_ipv6_new ();
395 p->family = AF_INET6;
396 IPV6_ADDR_COPY (&p->prefix, broad);
397 p->prefixlen = prefixlen;
398 ifc->destination = (struct prefix *) p;
399 }
400 }
401 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
402 {
403 zlog_warn("warning: %s called for interface %s "
404 "with peer flag set, but no peer address supplied",
405 __func__, ifp->name);
406 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
paul718e3742002-12-13 20:15:29 +0000407 }
408
paul0752ef02005-11-03 12:35:21 +0000409 /* Label of this address. */
410 if (label)
411 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
Christian Franked7f5dad2013-01-24 14:04:46 +0000412
Christian Franke02b48052013-01-24 14:04:49 +0000413 /* On Linux, we only get here when DAD is complete, therefore we can set
414 * ZEBRA_IFC_REAL.
415 *
416 * On BSD, there currently doesn't seem to be a way to check for completion of
417 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
418 * might still be running.
419 */
420 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
Christian Franked7f5dad2013-01-24 14:04:46 +0000421 connected_update(ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000422}
423
424void
425connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
426{
427 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +0000428
429 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
430 return;
431
Andrew J. Schorre4529632006-12-12 19:18:21 +0000432 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000433
434 apply_mask_ipv6 (&p);
435
436 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
437 return;
438
G.Balajif768f362011-11-26 22:10:39 +0400439 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000440
441 rib_update ();
442}
443
444void
445connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
hassofce954f2004-10-07 20:29:24 +0000446 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000447{
448 struct prefix_ipv6 p;
449 struct connected *ifc;
450
451 memset (&p, 0, sizeof (struct prefix_ipv6));
452 p.family = AF_INET6;
453 memcpy (&p.prefix, address, sizeof (struct in6_addr));
454 p.prefixlen = prefixlen;
455
paulca162182005-09-12 16:58:52 +0000456 ifc = connected_check (ifp, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000457 if (! ifc)
458 return;
459
paulca162182005-09-12 16:58:52 +0000460 connected_withdraw (ifc);
Stephen Hemminger90d2ab02009-04-29 21:54:59 -0700461
462 rib_update();
paul718e3742002-12-13 20:15:29 +0000463}
464#endif /* HAVE_IPV6 */