]> git.proxmox.com Git - mirror_frr.git/blame - zebra/connected.c
Zebra: Schedule RIB processing based on trigger event
[mirror_frr.git] / zebra / connected.c
CommitLineData
718e3744 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"
0752ef0b 32#include "memory.h"
718e3744 33
b84c7253 34#include "zebra/debug.h"
718e3744 35#include "zebra/zserv.h"
36#include "zebra/redistribute.h"
eef1fe11 37#include "zebra/interface.h"
a1ac18c4 38#include "zebra/connected.h"
b6120505 39#include "zebra/rtadv.h"
6ce80bdb 40extern struct zebra_t zebrad;
6b0655a2 41
02b4805f 42/* communicate the withdrawal of a connected address */
ca16218d 43static void
44connected_withdraw (struct connected *ifc)
45{
46 if (! ifc)
47 return;
48
49 /* Update interface address information to protocol daemon. */
50 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
51 {
52 zebra_interface_address_delete_update (ifc->ifp, ifc);
53
9db047fc
CF
54 if (ifc->address->family == AF_INET)
55 if_subnet_delete (ifc->ifp, ifc);
56
ca16218d 57 if (ifc->address->family == AF_INET)
58 connected_down_ipv4 (ifc->ifp, ifc);
aa2e32be 59#ifdef HAVE_IPV6
ca16218d 60 else
61 connected_down_ipv6 (ifc->ifp, ifc);
aa2e32be 62#endif
ca16218d 63
64 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
65 }
66
f7f740fe
CF
67 /* The address is not in the kernel anymore, so clear the flag */
68 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
69
9c37851e
AS
70 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
71 {
72 listnode_delete (ifc->ifp->connected, ifc);
73 connected_free (ifc);
74 }
b6120505
DW
75
76 /* Enable RA suppression if there are no IPv6 addresses on this interface */
77 if (! ipv6_address_configured(ifc->ifp))
78 ipv6_nd_suppress_ra_set (ifc->ifp, RA_SUPPRESS);
ca16218d 79}
80
81static void
82connected_announce (struct interface *ifp, struct connected *ifc)
83{
84 if (!ifc)
85 return;
525c1839 86
70d43d7c 87 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET)
525c1839 88 {
70d43d7c 89 if (ifc->address->prefixlen == 32)
4e3afb14 90 SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
4e3afb14 91 else
4e3afb14 92 UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
525c1839
DS
93 }
94
ca16218d 95 listnode_add (ifp->connected, ifc);
96
97 /* Update interface address information to protocol daemon. */
02b4805f
CF
98 if (ifc->address->family == AF_INET)
99 if_subnet_add (ifp, ifc);
ca16218d 100
b6120505
DW
101 else if (ifc->address->family == AF_INET6)
102 ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
103
02b4805f 104 zebra_interface_address_add_update (ifp, ifc);
ca16218d 105
02b4805f
CF
106 if (if_is_operative(ifp))
107 {
108 if (ifc->address->family == AF_INET)
109 connected_up_ipv4 (ifp, ifc);
aa2e32be 110#ifdef HAVE_IPV6
02b4805f
CF
111 else
112 connected_up_ipv6 (ifp, ifc);
aa2e32be 113#endif
ca16218d 114 }
115}
6b0655a2 116
718e3744 117/* If same interface address is already exist... */
118struct connected *
ca16218d 119connected_check (struct interface *ifp, struct prefix *p)
718e3744 120{
121 struct connected *ifc;
52dc7ee6 122 struct listnode *node;
718e3744 123
1eb8ef25 124 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
125 if (prefix_same (ifc->address, p))
126 return ifc;
718e3744 127
718e3744 128 return NULL;
129}
130
02b4805f 131/* Check if two ifc's describe the same address in the same state */
74ecdc9e
PJ
132static int
133connected_same (struct connected *ifc1, struct connected *ifc2)
134{
135 if (ifc1->ifp != ifc2->ifp)
136 return 0;
137
138 if (ifc1->destination)
139 if (!ifc2->destination)
140 return 0;
141 if (ifc2->destination)
142 if (!ifc1->destination)
143 return 0;
144
145 if (ifc1->destination && ifc2->destination)
146 if (!prefix_same (ifc1->destination, ifc2->destination))
147 return 0;
148
149 if (ifc1->flags != ifc2->flags)
150 return 0;
02b4805f
CF
151
152 if (ifc1->conf != ifc2->conf)
153 return 0;
74ecdc9e
PJ
154
155 return 1;
156}
157
d7f5dad6
CF
158/* Handle changes to addresses and send the neccesary announcements
159 * to clients. */
160static void
161connected_update(struct interface *ifp, struct connected *ifc)
74ecdc9e
PJ
162{
163 struct connected *current;
164
165 /* Check same connected route. */
166 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
167 {
168 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
169 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
170
171 /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
172 * back an address we have already added.
173 */
02b4805f 174 if (connected_same (current, ifc))
74ecdc9e
PJ
175 {
176 /* nothing to do */
177 connected_free (ifc);
d7f5dad6 178 return;
74ecdc9e 179 }
d7f5dad6
CF
180
181 /* Clear the configured flag on the old ifc, so it will be freed by
182 * connected withdraw. */
74ecdc9e
PJ
183 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
184 connected_withdraw (current); /* implicit withdraw - freebsd does this */
185 }
d7f5dad6 186
02b4805f
CF
187 /* If the connected is new or has changed, announce it, if it is usable */
188 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
189 connected_announce(ifp, ifc);
74ecdc9e
PJ
190}
191
718e3744 192/* Called from if_up(). */
193void
194connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
195{
196 struct prefix_ipv4 p;
718e3744 197
198 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
199 return;
200
e4529636 201 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 202
203 /* Apply mask to the network. */
204 apply_mask_ipv4 (&p);
205
206 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
207 address. */
208 if (prefix_ipv4_any (&p))
209 return;
210
7c8ff89e 211 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
78104b9b 212 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
718e3744 213
7c8ff89e 214 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, NULL, ifp->ifindex,
78104b9b 215 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
42cb6b66 216
41ec9222 217 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 218 zlog_debug ("%u: IF %s IPv4 address add/up, scheduling RIB processing",
219 ifp->vrf_id, ifp->name);
220 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 221}
222
223/* Add connected IPv4 route to the interface. */
224void
225connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
d06b2a64 226 u_char prefixlen, struct in_addr *broad,
227 const char *label)
718e3744 228{
229 struct prefix_ipv4 *p;
230 struct connected *ifc;
718e3744 231
d914d5ff
DS
232 if (ipv4_martian(addr))
233 return;
234
718e3744 235 /* Make connected structure. */
236 ifc = connected_new ();
237 ifc->ifp = ifp;
238 ifc->flags = flags;
f7f740fe
CF
239 /* If we get a notification from the kernel,
240 * we can safely assume the address is known to the kernel */
241 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
718e3744 242
243 /* Allocate new connected address. */
244 p = prefix_ipv4_new ();
245 p->family = AF_INET;
246 p->prefix = *addr;
247 p->prefixlen = prefixlen;
248 ifc->address = (struct prefix *) p;
ca16218d 249
e4529636 250 /* If there is broadcast or peer address. */
718e3744 251 if (broad)
252 {
253 p = prefix_ipv4_new ();
254 p->family = AF_INET;
255 p->prefix = *broad;
e4529636 256 p->prefixlen = prefixlen;
718e3744 257 ifc->destination = (struct prefix *) p;
3fb9cd6e 258
259 /* validate the destination address */
e4529636 260 if (CONNECTED_PEER(ifc))
3fb9cd6e 261 {
262 if (IPV4_ADDR_SAME(addr,broad))
e4529636 263 zlog_warn("warning: interface %s has same local and peer "
3fb9cd6e 264 "address %s, routing protocols may malfunction",
265 ifp->name,inet_ntoa(*addr));
3fb9cd6e 266 }
267 else
268 {
269 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
270 {
271 char buf[2][INET_ADDRSTRLEN];
272 struct in_addr bcalc;
273 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
274 zlog_warn("warning: interface %s broadcast addr %s/%d != "
275 "calculated %s, routing protocols may malfunction",
276 ifp->name,
277 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
278 prefixlen,
279 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
280 }
281 }
282
718e3744 283 }
3fb9cd6e 284 else
e4529636
AS
285 {
286 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
287 {
288 zlog_warn("warning: %s called for interface %s "
289 "with peer flag set, but no peer address supplied",
290 __func__, ifp->name);
291 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
292 }
293
294 /* no broadcast or destination address was supplied */
295 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
296 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
297 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
298 }
718e3744 299
300 /* Label of this address. */
301 if (label)
0752ef0b 302 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
718e3744 303
02b4805f
CF
304 /* For all that I know an IPv4 address is always ready when we receive
305 * the notification. So it should be safe to set the REAL flag here. */
306 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
307
d7f5dad6 308 connected_update(ifp, ifc);
718e3744 309}
310
311void
312connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
313{
314 struct prefix_ipv4 p;
718e3744 315
316 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
317 return;
318
e4529636 319 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 320
321 /* Apply mask to the network. */
322 apply_mask_ipv4 (&p);
323
324 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
325 address. */
326 if (prefix_ipv4_any (&p))
327 return;
328
6ce80bdb 329 /* Same logic as for connected_up_ipv4(): push the changes into the head. */
78104b9b
FL
330 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0,
331 SAFI_UNICAST);
718e3744 332
78104b9b
FL
333 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, 0,
334 SAFI_MULTICAST);
42cb6b66 335
41ec9222 336 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 337 zlog_debug ("%u: IF %s IPv4 address down, scheduling RIB processing",
338 ifp->vrf_id, ifp->name);
b84c7253 339
1c848137 340 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 341}
342
343/* Delete connected IPv4 route to the interface. */
344void
345connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
0752ef0b 346 u_char prefixlen, struct in_addr *broad)
718e3744 347{
348 struct prefix_ipv4 p;
349 struct connected *ifc;
350
351 memset (&p, 0, sizeof (struct prefix_ipv4));
352 p.family = AF_INET;
353 p.prefix = *addr;
354 p.prefixlen = prefixlen;
355
ca16218d 356 ifc = connected_check (ifp, (struct prefix *) &p);
718e3744 357 if (! ifc)
358 return;
525c1839 359
ca16218d 360 connected_withdraw (ifc);
90d2ab0f 361
41ec9222 362 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 363 zlog_debug ("%u: IF %s IPv4 address del, scheduling RIB processing",
364 ifp->vrf_id, ifp->name);
b84c7253 365
1c848137 366 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 367}
368
369#ifdef HAVE_IPV6
718e3744 370void
371connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
372{
373 struct prefix_ipv6 p;
718e3744 374
375 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
376 return;
377
e4529636 378 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 379
380 /* Apply mask to the network. */
381 apply_mask_ipv6 (&p);
382
726f9b2b 383#if ! defined (MUSICA) && ! defined (LINUX)
384 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
718e3744 385 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
386 return;
726f9b2b 387#endif
718e3744 388
78104b9b
FL
389 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
390 RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
718e3744 391
41ec9222 392 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 393 zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
394 ifp->vrf_id, ifp->name);
b84c7253 395
1c848137 396 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 397}
398
399/* Add connected IPv6 route to the interface. */
400void
e4529636 401connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
89368d9f 402 u_char prefixlen, struct in6_addr *broad,
403 const char *label)
718e3744 404{
405 struct prefix_ipv6 *p;
406 struct connected *ifc;
718e3744 407
d914d5ff
DS
408 if (ipv6_martian(addr))
409 return;
410
718e3744 411 /* Make connected structure. */
412 ifc = connected_new ();
413 ifc->ifp = ifp;
e4529636 414 ifc->flags = flags;
f7f740fe
CF
415 /* If we get a notification from the kernel,
416 * we can safely assume the address is known to the kernel */
417 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
718e3744 418
419 /* Allocate new connected address. */
420 p = prefix_ipv6_new ();
421 p->family = AF_INET6;
422 IPV6_ADDR_COPY (&p->prefix, addr);
423 p->prefixlen = prefixlen;
424 ifc->address = (struct prefix *) p;
425
e4529636 426 /* If there is broadcast or peer address. */
718e3744 427 if (broad)
428 {
e4529636
AS
429 if (IN6_IS_ADDR_UNSPECIFIED(broad))
430 zlog_warn("warning: %s called for interface %s with unspecified "
431 "destination address; ignoring!", __func__, ifp->name);
432 else
433 {
434 p = prefix_ipv6_new ();
435 p->family = AF_INET6;
436 IPV6_ADDR_COPY (&p->prefix, broad);
437 p->prefixlen = prefixlen;
438 ifc->destination = (struct prefix *) p;
439 }
440 }
441 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
442 {
443 zlog_warn("warning: %s called for interface %s "
444 "with peer flag set, but no peer address supplied",
445 __func__, ifp->name);
446 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
718e3744 447 }
448
0752ef0b 449 /* Label of this address. */
450 if (label)
451 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
d7f5dad6 452
02b4805f
CF
453 /* On Linux, we only get here when DAD is complete, therefore we can set
454 * ZEBRA_IFC_REAL.
455 *
456 * On BSD, there currently doesn't seem to be a way to check for completion of
457 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
458 * might still be running.
459 */
460 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
d7f5dad6 461 connected_update(ifp, ifc);
718e3744 462}
463
464void
465connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
466{
467 struct prefix_ipv6 p;
718e3744 468
469 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
470 return;
471
e4529636 472 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 473
474 apply_mask_ipv6 (&p);
475
476 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
477 return;
478
78104b9b
FL
479 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, 0, &p, NULL, ifp->ifindex,
480 ifp->vrf_id, 0, SAFI_UNICAST);
718e3744 481
41ec9222 482 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 483 zlog_debug ("%u: IF %s IPv6 address down, scheduling RIB processing",
484 ifp->vrf_id, ifp->name);
b84c7253 485
1c848137 486 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 487}
488
489void
490connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
fce954f8 491 u_char prefixlen, struct in6_addr *broad)
718e3744 492{
493 struct prefix_ipv6 p;
494 struct connected *ifc;
495
496 memset (&p, 0, sizeof (struct prefix_ipv6));
497 p.family = AF_INET6;
498 memcpy (&p.prefix, address, sizeof (struct in6_addr));
499 p.prefixlen = prefixlen;
500
ca16218d 501 ifc = connected_check (ifp, (struct prefix *) &p);
718e3744 502 if (! ifc)
503 return;
504
ca16218d 505 connected_withdraw (ifc);
90d2ab0f 506
41ec9222 507 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
1c848137 508 zlog_debug ("%u: IF %s IPv6 address del, scheduling RIB processing",
509 ifp->vrf_id, ifp->name);
b84c7253 510
1c848137 511 rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
718e3744 512}
513#endif /* HAVE_IPV6 */
d44ca835
DS
514
515int
516connected_is_unnumbered (struct interface *ifp)
517{
518 struct connected *connected;
519 struct listnode *node;
520
521 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
522 {
523 if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) &&
524 connected->address->family == AF_INET)
525 return CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED);
526 }
527 return 0;
528}