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