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