]> git.proxmox.com Git - mirror_frr.git/blame - zebra/connected.c
Merge pull request #3506 from opensourcerouting/6.0-init-fixes
[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 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "linklist.h"
26#include "if.h"
27#include "table.h"
28#include "rib.h"
29#include "table.h"
30#include "log.h"
0752ef0b 31#include "memory.h"
4a1ab8e4 32#include "zebra_memory.h"
718e3744 33
82f97584 34#include "vty.h"
b84c7253 35#include "zebra/debug.h"
718e3744 36#include "zebra/zserv.h"
37#include "zebra/redistribute.h"
eef1fe11 38#include "zebra/interface.h"
a1ac18c4 39#include "zebra/connected.h"
b6120505 40#include "zebra/rtadv.h"
40c7bdb0 41#include "zebra/zebra_mpls.h"
939fba27 42#include "zebra/debug.h"
6b0655a2 43
02b4805f 44/* communicate the withdrawal of a connected address */
d62a17ae 45static void connected_withdraw(struct connected *ifc)
ca16218d 46{
d62a17ae 47 if (!ifc)
48 return;
ca16218d 49
d62a17ae 50 /* Update interface address information to protocol daemon. */
51 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
52 zebra_interface_address_delete_update(ifc->ifp, ifc);
ca16218d 53
d62a17ae 54 if (ifc->address->family == AF_INET)
55 if_subnet_delete(ifc->ifp, ifc);
9db047fc 56
11461c63 57 connected_down(ifc->ifp, ifc);
ca16218d 58
d62a17ae 59 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
60 }
ca16218d 61
d62a17ae 62 /* The address is not in the kernel anymore, so clear the flag */
63 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
f7f740fe 64
d62a17ae 65 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
66 listnode_delete(ifc->ifp->connected, ifc);
67 connected_free(ifc);
68 }
ca16218d 69}
70
d62a17ae 71static void connected_announce(struct interface *ifp, struct connected *ifc)
ca16218d 72{
d62a17ae 73 if (!ifc)
74 return;
75
b0fa6f6a
CS
76 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET &&
77 !IS_ZEBRA_IF_VRF(ifp)) {
d62a17ae 78 if (ifc->address->prefixlen == 32)
79 SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
80 else
81 UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
82 }
83
84 listnode_add(ifp->connected, ifc);
85
86 /* Update interface address information to protocol daemon. */
87 if (ifc->address->family == AF_INET)
88 if_subnet_add(ifp, ifc);
89
90 zebra_interface_address_add_update(ifp, ifc);
91
92 if (if_is_operative(ifp)) {
ae87977c 93 connected_up(ifp, ifc);
d62a17ae 94 }
ca16218d 95}
6b0655a2 96
718e3744 97/* If same interface address is already exist... */
abffde07
DL
98struct connected *connected_check(struct interface *ifp,
99 union prefixconstptr pu)
718e3744 100{
abffde07 101 const struct prefix *p = pu.p;
d62a17ae 102 struct connected *ifc;
103 struct listnode *node;
718e3744 104
d62a17ae 105 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
106 if (prefix_same(ifc->address, p))
107 return ifc;
718e3744 108
d62a17ae 109 return NULL;
718e3744 110}
111
abffde07
DL
112/* same, but with peer address */
113struct connected *connected_check_ptp(struct interface *ifp,
114 union prefixconstptr pu,
115 union prefixconstptr du)
116{
117 const struct prefix *p = pu.p;
118 const struct prefix *d = du.p;
119 struct connected *ifc;
120 struct listnode *node;
121
122 /* ignore broadcast addresses */
123 if (p->prefixlen != IPV4_MAX_PREFIXLEN)
124 d = NULL;
125
126 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
127 if (!prefix_same(ifc->address, p))
128 continue;
129 if (!CONNECTED_PEER(ifc) && !d)
130 return ifc;
131 if (CONNECTED_PEER(ifc) && d
132 && prefix_same(ifc->destination, d))
133 return ifc;
134 }
135
136 return NULL;
137}
138
02b4805f 139/* Check if two ifc's describe the same address in the same state */
d62a17ae 140static int connected_same(struct connected *ifc1, struct connected *ifc2)
74ecdc9e 141{
d62a17ae 142 if (ifc1->ifp != ifc2->ifp)
143 return 0;
144
145 if (ifc1->destination)
146 if (!ifc2->destination)
147 return 0;
148 if (ifc2->destination)
149 if (!ifc1->destination)
150 return 0;
151
152 if (ifc1->destination && ifc2->destination)
153 if (!prefix_same(ifc1->destination, ifc2->destination))
154 return 0;
155
156 if (ifc1->flags != ifc2->flags)
157 return 0;
158
159 if (ifc1->conf != ifc2->conf)
160 return 0;
161
162 return 1;
74ecdc9e
PJ
163}
164
d7f5dad6
CF
165/* Handle changes to addresses and send the neccesary announcements
166 * to clients. */
d62a17ae 167static void connected_update(struct interface *ifp, struct connected *ifc)
74ecdc9e 168{
d62a17ae 169 struct connected *current;
170
171 /* Check same connected route. */
abffde07
DL
172 current = connected_check_ptp(ifp, ifc->address, ifc->destination);
173 if (current) {
d62a17ae 174 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
175 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
176
177 /* Avoid spurious withdraws, this might be just the kernel
178 * 'reflecting'
179 * back an address we have already added.
180 */
181 if (connected_same(current, ifc)) {
182 /* nothing to do */
183 connected_free(ifc);
184 return;
185 }
186
187 /* Clear the configured flag on the old ifc, so it will be freed
188 * by
189 * connected withdraw. */
190 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
191 connected_withdraw(
192 current); /* implicit withdraw - freebsd does this */
193 }
194
195 /* If the connected is new or has changed, announce it, if it is usable
196 */
197 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
198 connected_announce(ifp, ifc);
74ecdc9e
PJ
199}
200
718e3744 201/* Called from if_up(). */
ae87977c 202void connected_up(struct interface *ifp, struct connected *ifc)
718e3744 203{
ae87977c 204 afi_t afi;
d62a17ae 205 struct prefix p;
fd36be7e 206 struct nexthop nh = {
4a7371e9
DS
207 .type = NEXTHOP_TYPE_IFINDEX,
208 .ifindex = ifp->ifindex,
209 .vrf_id = ifp->vrf_id,
fd36be7e 210 };
d62a17ae 211
212 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
213 return;
214
ae87977c 215 PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
d62a17ae 216
217 /* Apply mask to the network. */
218 apply_mask(&p);
219
ae87977c
DS
220 afi = family2afi(p.family);
221
222 switch (afi) {
223 case AFI_IP:
224 /*
225 * In case of connected address is 0.0.0.0/0 we treat it tunnel
226 * address.
227 */
228 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
229 return;
230 break;
231 case AFI_IP6:
232#ifndef LINUX
233 /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
234 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
235 return;
236#endif
237 break;
238 default:
239 zlog_warn("Received unknown AFI: %s", afi2str(afi));
d62a17ae 240 return;
ae87977c
DS
241 break;
242 }
d62a17ae 243
4a7371e9
DS
244 rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
245 NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
d62a17ae 246
4a7371e9
DS
247 rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
248 NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
d62a17ae 249
ae87977c
DS
250 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
251 char buf[PREFIX_STRLEN];
252
996c9314
LB
253 zlog_debug(
254 "%u: IF %s address %s add/up, scheduling RIB processing",
255 ifp->vrf_id, ifp->name,
256 prefix2str(&p, buf, sizeof(buf)));
ae87977c 257 }
d62a17ae 258 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
259
260 /* Schedule LSP forwarding entries for processing, if appropriate. */
261 if (ifp->vrf_id == VRF_DEFAULT) {
ae87977c
DS
262 if (IS_ZEBRA_DEBUG_MPLS) {
263 char buf[PREFIX_STRLEN];
264
996c9314
LB
265 zlog_debug(
266 "%u: IF %s IP %s address add/up, scheduling MPLS processing",
267 ifp->vrf_id, ifp->name,
268 prefix2str(&p, buf, sizeof(buf)));
ae87977c 269 }
d62a17ae 270 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
271 }
718e3744 272}
273
274/* Add connected IPv4 route to the interface. */
d62a17ae 275void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
d7c0a89a 276 uint8_t prefixlen, struct in_addr *broad,
d62a17ae 277 const char *label)
718e3744 278{
d62a17ae 279 struct prefix_ipv4 *p;
280 struct connected *ifc;
281
282 if (ipv4_martian(addr))
283 return;
284
285 /* Make connected structure. */
286 ifc = connected_new();
287 ifc->ifp = ifp;
288 ifc->flags = flags;
289 /* If we get a notification from the kernel,
290 * we can safely assume the address is known to the kernel */
291 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
292
293 /* Allocate new connected address. */
294 p = prefix_ipv4_new();
295 p->family = AF_INET;
296 p->prefix = *addr;
abffde07
DL
297 p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
298 : prefixlen;
d62a17ae 299 ifc->address = (struct prefix *)p;
300
301 /* If there is broadcast or peer address. */
302 if (broad) {
303 p = prefix_ipv4_new();
304 p->family = AF_INET;
305 p->prefix = *broad;
306 p->prefixlen = prefixlen;
307 ifc->destination = (struct prefix *)p;
308
309 /* validate the destination address */
310 if (CONNECTED_PEER(ifc)) {
311 if (IPV4_ADDR_SAME(addr, broad))
312 zlog_warn(
313 "warning: interface %s has same local and peer "
314 "address %s, routing protocols may malfunction",
315 ifp->name, inet_ntoa(*addr));
316 } else {
317 if (broad->s_addr
318 != ipv4_broadcast_addr(addr->s_addr, prefixlen)) {
319 char buf[2][INET_ADDRSTRLEN];
320 struct in_addr bcalc;
321 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,
322 prefixlen);
323 zlog_warn(
324 "warning: interface %s broadcast addr %s/%d != "
325 "calculated %s, routing protocols may malfunction",
326 ifp->name,
327 inet_ntop(AF_INET, broad, buf[0],
328 sizeof(buf[0])),
329 prefixlen,
330 inet_ntop(AF_INET, &bcalc, buf[1],
331 sizeof(buf[1])));
332 }
333 }
334
335 } else {
336 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
337 zlog_warn(
338 "warning: %s called for interface %s "
339 "with peer flag set, but no peer address supplied",
340 __func__, ifp->name);
341 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
342 }
343
344 /* no broadcast or destination address was supplied */
345 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
346 zlog_warn(
347 "warning: PtP interface %s with addr %s/%d needs a "
348 "peer address",
349 ifp->name, inet_ntoa(*addr), prefixlen);
e4529636
AS
350 }
351
d62a17ae 352 /* Label of this address. */
353 if (label)
354 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 355
d62a17ae 356 /* For all that I know an IPv4 address is always ready when we receive
357 * the notification. So it should be safe to set the REAL flag here. */
358 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
718e3744 359
d62a17ae 360 connected_update(ifp, ifc);
718e3744 361}
362
11461c63 363void connected_down(struct interface *ifp, struct connected *ifc)
718e3744 364{
11461c63 365 afi_t afi;
d62a17ae 366 struct prefix p;
fd36be7e 367 struct nexthop nh = {
4a7371e9
DS
368 .type = NEXTHOP_TYPE_IFINDEX,
369 .ifindex = ifp->ifindex,
370 .vrf_id = ifp->vrf_id,
fd36be7e 371 };
718e3744 372
d62a17ae 373 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
374 return;
718e3744 375
11461c63 376 PREFIX_COPY(&p, CONNECTED_PREFIX(ifc));
718e3744 377
d62a17ae 378 /* Apply mask to the network. */
379 apply_mask(&p);
718e3744 380
11461c63
DS
381 afi = family2afi(p.family);
382
383 switch (afi) {
384 case AFI_IP:
385 /*
386 * In case of connected address is 0.0.0.0/0 we treat it tunnel
387 * address.
388 */
389 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
390 return;
391 break;
392 case AFI_IP6:
393 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
394 return;
395 break;
396 default:
397 zlog_info("Unknown AFI: %s", afi2str(afi));
398 break;
399 }
718e3744 400
11461c63
DS
401 /*
402 * Same logic as for connected_up(): push the changes into the
403 * head.
404 */
405 rib_delete(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
40ecd8e4 406 &p, NULL, &nh, 0, 0, 0, false);
718e3744 407
996c9314 408 rib_delete(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
40ecd8e4 409 &p, NULL, &nh, 0, 0, 0, false);
42cb6b66 410
11461c63
DS
411 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
412 char buf[PREFIX_STRLEN];
413
996c9314
LB
414 zlog_debug(
415 "%u: IF %s IP %s address down, scheduling RIB processing",
416 ifp->vrf_id, ifp->name,
417 prefix2str(&p, buf, sizeof(buf)));
11461c63 418 }
b84c7253 419
d62a17ae 420 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
40c7bdb0 421
d62a17ae 422 /* Schedule LSP forwarding entries for processing, if appropriate. */
423 if (ifp->vrf_id == VRF_DEFAULT) {
11461c63
DS
424 if (IS_ZEBRA_DEBUG_MPLS) {
425 char buf[PREFIX_STRLEN];
426
996c9314
LB
427 zlog_debug(
428 "%u: IF %s IP %s address down, scheduling MPLS processing",
429 ifp->vrf_id, ifp->name,
430 prefix2str(&p, buf, sizeof(buf)));
11461c63 431 }
d62a17ae 432 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
433 }
718e3744 434}
435
dc7cd304
DS
436static void connected_delete_helper(struct connected *ifc, struct prefix *p)
437{
438 struct interface *ifp;
439
440 if (!ifc)
441 return;
442 ifp = ifc->ifp;
443
444 connected_withdraw(ifc);
445
446 if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
447 char buf[PREFIX_STRLEN];
448
996c9314
LB
449 zlog_debug(
450 "%u: IF %s IP %s address del, scheduling RIB processing",
451 ifp->vrf_id, ifp->name,
452 prefix2str(p, buf, sizeof(buf)));
dc7cd304
DS
453 }
454 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
455
456 /* Schedule LSP forwarding entries for processing, if appropriate. */
457 if (ifp->vrf_id == VRF_DEFAULT) {
458 if (IS_ZEBRA_DEBUG_MPLS) {
459 char buf[PREFIX_STRLEN];
460
996c9314
LB
461 zlog_debug(
462 "%u: IF %s IP %s address delete, scheduling MPLS processing",
463 ifp->vrf_id, ifp->name,
464 prefix2str(p, buf, sizeof(buf)));
dc7cd304
DS
465 }
466 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
467 }
468}
469
718e3744 470/* Delete connected IPv4 route to the interface. */
d62a17ae 471void connected_delete_ipv4(struct interface *ifp, int flags,
d7c0a89a 472 struct in_addr *addr, uint8_t prefixlen,
d62a17ae 473 struct in_addr *broad)
718e3744 474{
dc7cd304 475 struct prefix p, d;
d62a17ae 476 struct connected *ifc;
477
dc7cd304 478 memset(&p, 0, sizeof(struct prefix));
d62a17ae 479 p.family = AF_INET;
dc7cd304 480 p.u.prefix4 = *addr;
abffde07
DL
481 p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
482 : prefixlen;
483
484 if (broad) {
dc7cd304 485 memset(&d, 0, sizeof(struct prefix));
abffde07 486 d.family = AF_INET;
dc7cd304 487 d.u.prefix4 = *broad;
abffde07 488 d.prefixlen = prefixlen;
dc7cd304 489 ifc = connected_check_ptp(ifp, &p, &d);
abffde07 490 } else
dc7cd304 491 ifc = connected_check_ptp(ifp, &p, NULL);
d62a17ae 492
dc7cd304 493 connected_delete_helper(ifc, &p);
718e3744 494}
495
718e3744 496/* Add connected IPv6 route to the interface. */
d62a17ae 497void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
60c0687a
DS
498 struct in6_addr *broad, uint8_t prefixlen,
499 const char *label)
718e3744 500{
d62a17ae 501 struct prefix_ipv6 *p;
502 struct connected *ifc;
503
504 if (ipv6_martian(addr))
505 return;
506
507 /* Make connected structure. */
508 ifc = connected_new();
509 ifc->ifp = ifp;
510 ifc->flags = flags;
511 /* If we get a notification from the kernel,
512 * we can safely assume the address is known to the kernel */
513 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
514
515 /* Allocate new connected address. */
516 p = prefix_ipv6_new();
517 p->family = AF_INET6;
518 IPV6_ADDR_COPY(&p->prefix, addr);
519 p->prefixlen = prefixlen;
520 ifc->address = (struct prefix *)p;
521
f52d0a1a 522 if (broad) {
60c0687a
DS
523 p = prefix_ipv6_new();
524 p->family = AF_INET6;
525 IPV6_ADDR_COPY(&p->prefix, broad);
526 p->prefixlen = prefixlen;
527 ifc->destination = (struct prefix *)p;
f52d0a1a
DS
528 } else {
529 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
530 zlog_warn("warning: %s called for interface %s with peer flag set, but no peer address supplied",
531 __func__, ifp->name);
532 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
533 }
60c0687a
DS
534 }
535
d62a17ae 536 /* Label of this address. */
537 if (label)
538 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
539
540 /* On Linux, we only get here when DAD is complete, therefore we can set
541 * ZEBRA_IFC_REAL.
542 *
543 * On BSD, there currently doesn't seem to be a way to check for
544 * completion of
545 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL,
546 * although DAD
547 * might still be running.
548 */
549 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
550 connected_update(ifp, ifc);
718e3744 551}
552
d62a17ae 553void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
60c0687a 554 struct in6_addr *broad, uint8_t prefixlen)
718e3744 555{
60c0687a 556 struct prefix p, d;
d62a17ae 557 struct connected *ifc;
558
dc7cd304 559 memset(&p, 0, sizeof(struct prefix));
d62a17ae 560 p.family = AF_INET6;
dc7cd304 561 memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
d62a17ae 562 p.prefixlen = prefixlen;
563
60c0687a
DS
564 if (broad) {
565 memset(&d, 0, sizeof(struct prefix));
566 d.family = AF_INET6;
a85297a7 567 IPV6_ADDR_COPY(&d.u.prefix6, broad);
60c0687a
DS
568 d.prefixlen = prefixlen;
569 ifc = connected_check_ptp(ifp, &p, &d);
570 } else
571 ifc = connected_check_ptp(ifp, &p, NULL);
d62a17ae 572
dc7cd304 573 connected_delete_helper(ifc, &p);
718e3744 574}
d44ca835 575
d62a17ae 576int connected_is_unnumbered(struct interface *ifp)
d44ca835 577{
d62a17ae 578 struct connected *connected;
579 struct listnode *node;
580
581 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
582 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
583 && connected->address->family == AF_INET)
584 return CHECK_FLAG(connected->flags,
585 ZEBRA_IFA_UNNUMBERED);
586 }
587 return 0;
d44ca835 588}