2 * Address linked list routine.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 * This file is part of GNU Zebra.
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
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.
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
34 #include "zebra/zserv.h"
35 #include "zebra/redistribute.h"
36 #include "zebra/interface.h"
37 #include "zebra/connected.h"
38 extern struct zebra_t zebrad;
40 /* communicate the withdrawal of a connected address */
42 connected_withdraw (struct connected *ifc)
47 /* Update interface address information to protocol daemon. */
48 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
50 zebra_interface_address_delete_update (ifc->ifp, ifc);
52 if (ifc->address->family == AF_INET)
53 if_subnet_delete (ifc->ifp, ifc);
55 if (ifc->address->family == AF_INET)
56 connected_down_ipv4 (ifc->ifp, ifc);
59 connected_down_ipv6 (ifc->ifp, ifc);
62 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
65 /* The address is not in the kernel anymore, so clear the flag */
66 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
68 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
70 listnode_delete (ifc->ifp->connected, ifc);
76 connected_announce (struct interface *ifp, struct connected *ifc)
81 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET)
83 if (ifc->address->prefixlen == 32)
84 SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
86 UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
89 listnode_add (ifp->connected, ifc);
91 /* Update interface address information to protocol daemon. */
92 if (ifc->address->family == AF_INET)
93 if_subnet_add (ifp, ifc);
95 zebra_interface_address_add_update (ifp, ifc);
97 if (if_is_operative(ifp))
99 if (ifc->address->family == AF_INET)
100 connected_up_ipv4 (ifp, ifc);
103 connected_up_ipv6 (ifp, ifc);
108 /* If same interface address is already exist... */
110 connected_check (struct interface *ifp, struct prefix *p)
112 struct connected *ifc;
113 struct listnode *node;
115 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
116 if (prefix_same (ifc->address, p))
122 /* Check if two ifc's describe the same address in the same state */
124 connected_same (struct connected *ifc1, struct connected *ifc2)
126 if (ifc1->ifp != ifc2->ifp)
129 if (ifc1->destination)
130 if (!ifc2->destination)
132 if (ifc2->destination)
133 if (!ifc1->destination)
136 if (ifc1->destination && ifc2->destination)
137 if (!prefix_same (ifc1->destination, ifc2->destination))
140 if (ifc1->flags != ifc2->flags)
143 if (ifc1->conf != ifc2->conf)
149 /* Handle changes to addresses and send the neccesary announcements
152 connected_update(struct interface *ifp, struct connected *ifc)
154 struct connected *current;
156 /* Check same connected route. */
157 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
159 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
160 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
162 /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
163 * back an address we have already added.
165 if (connected_same (current, ifc))
168 connected_free (ifc);
172 /* Clear the configured flag on the old ifc, so it will be freed by
173 * connected withdraw. */
174 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
175 connected_withdraw (current); /* implicit withdraw - freebsd does this */
178 /* If the connected is new or has changed, announce it, if it is usable */
179 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
180 connected_announce(ifp, ifc);
183 /* Called from if_up(). */
185 connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
187 struct prefix_ipv4 p;
189 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
192 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
194 /* Apply mask to the network. */
195 apply_mask_ipv4 (&p);
197 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
199 if (prefix_ipv4_any (&p))
202 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
203 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
205 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
206 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST);
208 rib_update (ifp->vrf_id);
211 /* Add connected IPv4 route to the interface. */
213 connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
214 u_char prefixlen, struct in_addr *broad,
217 struct prefix_ipv4 *p;
218 struct connected *ifc;
220 /* Make connected structure. */
221 ifc = connected_new ();
224 /* If we get a notification from the kernel,
225 * we can safely assume the address is known to the kernel */
226 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
228 /* Allocate new connected address. */
229 p = prefix_ipv4_new ();
232 p->prefixlen = prefixlen;
233 ifc->address = (struct prefix *) p;
235 /* If there is broadcast or peer address. */
238 p = prefix_ipv4_new ();
241 p->prefixlen = prefixlen;
242 ifc->destination = (struct prefix *) p;
244 /* validate the destination address */
245 if (CONNECTED_PEER(ifc))
247 if (IPV4_ADDR_SAME(addr,broad))
248 zlog_warn("warning: interface %s has same local and peer "
249 "address %s, routing protocols may malfunction",
250 ifp->name,inet_ntoa(*addr));
254 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
256 char buf[2][INET_ADDRSTRLEN];
257 struct in_addr bcalc;
258 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
259 zlog_warn("warning: interface %s broadcast addr %s/%d != "
260 "calculated %s, routing protocols may malfunction",
262 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
264 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
271 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
273 zlog_warn("warning: %s called for interface %s "
274 "with peer flag set, but no peer address supplied",
275 __func__, ifp->name);
276 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
279 /* no broadcast or destination address was supplied */
280 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
281 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
282 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
285 /* Label of this address. */
287 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
289 /* For all that I know an IPv4 address is always ready when we receive
290 * the notification. So it should be safe to set the REAL flag here. */
291 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
293 connected_update(ifp, ifc);
297 connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
299 struct prefix_ipv4 p;
301 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
304 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
306 /* Apply mask to the network. */
307 apply_mask_ipv4 (&p);
309 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
311 if (prefix_ipv4_any (&p))
314 /* Same logic as for connected_up_ipv4(): push the changes into the head. */
315 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
318 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
321 rib_update (ifp->vrf_id);
324 /* Delete connected IPv4 route to the interface. */
326 connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
327 u_char prefixlen, struct in_addr *broad)
329 struct prefix_ipv4 p;
330 struct connected *ifc;
332 memset (&p, 0, sizeof (struct prefix_ipv4));
335 p.prefixlen = prefixlen;
337 ifc = connected_check (ifp, (struct prefix *) &p);
341 connected_withdraw (ifc);
343 rib_update (ifp->vrf_id);
348 connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
350 struct prefix_ipv6 p;
352 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
355 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
357 /* Apply mask to the network. */
358 apply_mask_ipv6 (&p);
361 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
362 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
366 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
367 RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
369 rib_update (ifp->vrf_id);
372 /* Add connected IPv6 route to the interface. */
374 connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
375 u_char prefixlen, struct in6_addr *broad,
378 struct prefix_ipv6 *p;
379 struct connected *ifc;
381 /* Make connected structure. */
382 ifc = connected_new ();
385 /* If we get a notification from the kernel,
386 * we can safely assume the address is known to the kernel */
387 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
389 /* Allocate new connected address. */
390 p = prefix_ipv6_new ();
391 p->family = AF_INET6;
392 IPV6_ADDR_COPY (&p->prefix, addr);
393 p->prefixlen = prefixlen;
394 ifc->address = (struct prefix *) p;
396 /* If there is broadcast or peer address. */
399 if (IN6_IS_ADDR_UNSPECIFIED(broad))
400 zlog_warn("warning: %s called for interface %s with unspecified "
401 "destination address; ignoring!", __func__, ifp->name);
404 p = prefix_ipv6_new ();
405 p->family = AF_INET6;
406 IPV6_ADDR_COPY (&p->prefix, broad);
407 p->prefixlen = prefixlen;
408 ifc->destination = (struct prefix *) p;
411 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
413 zlog_warn("warning: %s called for interface %s "
414 "with peer flag set, but no peer address supplied",
415 __func__, ifp->name);
416 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
419 /* Label of this address. */
421 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
423 /* On Linux, we only get here when DAD is complete, therefore we can set
426 * On BSD, there currently doesn't seem to be a way to check for completion of
427 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
428 * might still be running.
430 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
431 connected_update(ifp, ifc);
435 connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
437 struct prefix_ipv6 p;
439 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
442 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
444 apply_mask_ipv6 (&p);
446 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
449 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
452 rib_update (ifp->vrf_id);
456 connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
457 u_char prefixlen, struct in6_addr *broad)
459 struct prefix_ipv6 p;
460 struct connected *ifc;
462 memset (&p, 0, sizeof (struct prefix_ipv6));
464 memcpy (&p.prefix, address, sizeof (struct in6_addr));
465 p.prefixlen = prefixlen;
467 ifc = connected_check (ifp, (struct prefix *) &p);
471 connected_withdraw (ifc);
473 rib_update (ifp->vrf_id);
475 #endif /* HAVE_IPV6 */