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