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