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"
39 /* withdraw a connected address */
41 connected_withdraw (struct connected
*ifc
)
46 /* Update interface address information to protocol daemon. */
47 if (CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
49 zebra_interface_address_delete_update (ifc
->ifp
, ifc
);
51 if_subnet_delete (ifc
->ifp
, ifc
);
53 if (ifc
->address
->family
== AF_INET
)
54 connected_down_ipv4 (ifc
->ifp
, ifc
);
57 connected_down_ipv6 (ifc
->ifp
, ifc
);
60 UNSET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
63 if (!CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_CONFIGURED
))
65 listnode_delete (ifc
->ifp
->connected
, ifc
);
71 connected_announce (struct interface
*ifp
, struct connected
*ifc
)
76 listnode_add (ifp
->connected
, ifc
);
78 /* Update interface address information to protocol daemon. */
79 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
81 if (ifc
->address
->family
== AF_INET
)
82 if_subnet_add (ifp
, ifc
);
84 SET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
86 zebra_interface_address_add_update (ifp
, ifc
);
90 if (ifc
->address
->family
== AF_INET
)
91 connected_up_ipv4 (ifp
, ifc
);
94 connected_up_ipv6 (ifp
, ifc
);
100 /* If same interface address is already exist... */
102 connected_check (struct interface
*ifp
, struct prefix
*p
)
104 struct connected
*ifc
;
105 struct listnode
*node
;
107 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
108 if (prefix_same (ifc
->address
, p
))
114 /* Check if two ifc's describe the same address */
116 connected_same (struct connected
*ifc1
, struct connected
*ifc2
)
118 if (ifc1
->ifp
!= ifc2
->ifp
)
121 if (ifc1
->destination
)
122 if (!ifc2
->destination
)
124 if (ifc2
->destination
)
125 if (!ifc1
->destination
)
128 if (ifc1
->destination
&& ifc2
->destination
)
129 if (!prefix_same (ifc1
->destination
, ifc2
->destination
))
132 if (ifc1
->flags
!= ifc2
->flags
)
138 /* Handle implicit withdrawals of addresses, where a system ADDs an address
139 * to an interface which already has the same address configured.
141 * Returns the struct connected which must be announced to clients,
142 * or NULL if nothing to do.
144 static struct connected
*
145 connected_implicit_withdraw (struct interface
*ifp
, struct connected
*ifc
)
147 struct connected
*current
;
149 /* Check same connected route. */
150 if ((current
= connected_check (ifp
, (struct prefix
*) ifc
->address
)))
152 if (CHECK_FLAG(current
->conf
, ZEBRA_IFC_CONFIGURED
))
153 SET_FLAG(ifc
->conf
, ZEBRA_IFC_CONFIGURED
);
155 /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
156 * back an address we have already added.
158 if (connected_same (current
, ifc
) && CHECK_FLAG(current
->conf
, ZEBRA_IFC_REAL
))
161 connected_free (ifc
);
165 UNSET_FLAG(current
->conf
, ZEBRA_IFC_CONFIGURED
);
166 connected_withdraw (current
); /* implicit withdraw - freebsd does this */
171 /* Called from if_up(). */
173 connected_up_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
175 struct prefix_ipv4 p
;
177 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
180 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
182 /* Apply mask to the network. */
183 apply_mask_ipv4 (&p
);
185 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
187 if (prefix_ipv4_any (&p
))
190 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, NULL
, ifp
->ifindex
,
191 RT_TABLE_MAIN
, ifp
->metric
, 0);
196 /* Add connected IPv4 route to the interface. */
198 connected_add_ipv4 (struct interface
*ifp
, int flags
, struct in_addr
*addr
,
199 u_char prefixlen
, struct in_addr
*broad
,
202 struct prefix_ipv4
*p
;
203 struct connected
*ifc
;
205 /* Make connected structure. */
206 ifc
= connected_new ();
210 /* Allocate new connected address. */
211 p
= prefix_ipv4_new ();
214 p
->prefixlen
= prefixlen
;
215 ifc
->address
= (struct prefix
*) p
;
217 /* If there is broadcast or peer address. */
220 p
= prefix_ipv4_new ();
223 p
->prefixlen
= prefixlen
;
224 ifc
->destination
= (struct prefix
*) p
;
226 /* validate the destination address */
227 if (CONNECTED_PEER(ifc
))
229 if (IPV4_ADDR_SAME(addr
,broad
))
230 zlog_warn("warning: interface %s has same local and peer "
231 "address %s, routing protocols may malfunction",
232 ifp
->name
,inet_ntoa(*addr
));
236 if (broad
->s_addr
!= ipv4_broadcast_addr(addr
->s_addr
,prefixlen
))
238 char buf
[2][INET_ADDRSTRLEN
];
239 struct in_addr bcalc
;
240 bcalc
.s_addr
= ipv4_broadcast_addr(addr
->s_addr
,prefixlen
);
241 zlog_warn("warning: interface %s broadcast addr %s/%d != "
242 "calculated %s, routing protocols may malfunction",
244 inet_ntop (AF_INET
, broad
, buf
[0], sizeof(buf
[0])),
246 inet_ntop (AF_INET
, &bcalc
, buf
[1], sizeof(buf
[1])));
253 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_PEER
))
255 zlog_warn("warning: %s called for interface %s "
256 "with peer flag set, but no peer address supplied",
257 __func__
, ifp
->name
);
258 UNSET_FLAG(ifc
->flags
, ZEBRA_IFA_PEER
);
261 /* no broadcast or destination address was supplied */
262 if ((prefixlen
== IPV4_MAX_PREFIXLEN
) && if_is_pointopoint(ifp
))
263 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
264 "peer address",ifp
->name
,inet_ntoa(*addr
),prefixlen
);
267 /* Label of this address. */
269 ifc
->label
= XSTRDUP (MTYPE_CONNECTED_LABEL
, label
);
272 if ((ifc
= connected_implicit_withdraw (ifp
, ifc
)) == NULL
)
275 connected_announce (ifp
, ifc
);
279 connected_down_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
281 struct prefix_ipv4 p
;
283 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
286 PREFIX_COPY_IPV4(&p
, CONNECTED_PREFIX(ifc
));
288 /* Apply mask to the network. */
289 apply_mask_ipv4 (&p
);
291 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
293 if (prefix_ipv4_any (&p
))
296 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0);
301 /* Delete connected IPv4 route to the interface. */
303 connected_delete_ipv4 (struct interface
*ifp
, int flags
, struct in_addr
*addr
,
304 u_char prefixlen
, struct in_addr
*broad
)
306 struct prefix_ipv4 p
;
307 struct connected
*ifc
;
309 memset (&p
, 0, sizeof (struct prefix_ipv4
));
312 p
.prefixlen
= prefixlen
;
314 ifc
= connected_check (ifp
, (struct prefix
*) &p
);
318 connected_withdraw (ifc
);
323 connected_up_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
325 struct prefix_ipv6 p
;
327 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
330 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
332 /* Apply mask to the network. */
333 apply_mask_ipv6 (&p
);
335 #if ! defined (MUSICA) && ! defined (LINUX)
336 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
337 if (IN6_IS_ADDR_UNSPECIFIED (&p
.prefix
))
341 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0,
347 /* Add connected IPv6 route to the interface. */
349 connected_add_ipv6 (struct interface
*ifp
, int flags
, struct in6_addr
*addr
,
350 u_char prefixlen
, struct in6_addr
*broad
,
353 struct prefix_ipv6
*p
;
354 struct connected
*ifc
;
356 /* Make connected structure. */
357 ifc
= connected_new ();
361 /* Allocate new connected address. */
362 p
= prefix_ipv6_new ();
363 p
->family
= AF_INET6
;
364 IPV6_ADDR_COPY (&p
->prefix
, addr
);
365 p
->prefixlen
= prefixlen
;
366 ifc
->address
= (struct prefix
*) p
;
368 /* If there is broadcast or peer address. */
371 if (IN6_IS_ADDR_UNSPECIFIED(broad
))
372 zlog_warn("warning: %s called for interface %s with unspecified "
373 "destination address; ignoring!", __func__
, ifp
->name
);
376 p
= prefix_ipv6_new ();
377 p
->family
= AF_INET6
;
378 IPV6_ADDR_COPY (&p
->prefix
, broad
);
379 p
->prefixlen
= prefixlen
;
380 ifc
->destination
= (struct prefix
*) p
;
383 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_PEER
) && !ifc
->destination
)
385 zlog_warn("warning: %s called for interface %s "
386 "with peer flag set, but no peer address supplied",
387 __func__
, ifp
->name
);
388 UNSET_FLAG(ifc
->flags
, ZEBRA_IFA_PEER
);
391 /* Label of this address. */
393 ifc
->label
= XSTRDUP (MTYPE_CONNECTED_LABEL
, label
);
395 if ((ifc
= connected_implicit_withdraw (ifp
, ifc
)) == NULL
)
398 connected_announce (ifp
, ifc
);
402 connected_down_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
404 struct prefix_ipv6 p
;
406 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
409 PREFIX_COPY_IPV6(&p
, CONNECTED_PREFIX(ifc
));
411 apply_mask_ipv6 (&p
);
413 if (IN6_IS_ADDR_UNSPECIFIED (&p
.prefix
))
416 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0);
422 connected_delete_ipv6 (struct interface
*ifp
, struct in6_addr
*address
,
423 u_char prefixlen
, struct in6_addr
*broad
)
425 struct prefix_ipv6 p
;
426 struct connected
*ifc
;
428 memset (&p
, 0, sizeof (struct prefix_ipv6
));
430 memcpy (&p
.prefix
, address
, sizeof (struct in6_addr
));
431 p
.prefixlen
= prefixlen
;
433 ifc
= connected_check (ifp
, (struct prefix
*) &p
);
437 connected_withdraw (ifc
);
439 #endif /* HAVE_IPV6 */