]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/connected.c
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
33 #include "zebra/zserv.h"
34 #include "zebra/redistribute.h"
35 #include "zebra/interface.h"
37 /* If same interface address is already exist... */
39 connected_check_ipv4 (struct interface
*ifp
, struct prefix
*p
)
41 struct connected
*ifc
;
42 struct listnode
*node
;
44 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
45 if (prefix_same (ifc
->address
, p
))
51 /* Called from if_up(). */
53 connected_up_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
56 struct prefix_ipv4
*addr
;
57 struct prefix_ipv4
*dest
;
59 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
62 addr
= (struct prefix_ipv4
*) ifc
->address
;
63 dest
= (struct prefix_ipv4
*) ifc
->destination
;
65 memset (&p
, 0, sizeof (struct prefix_ipv4
));
67 p
.prefixlen
= addr
->prefixlen
;
69 /* Point-to-point check. */
70 if (CONNECTED_POINTOPOINT_HOST(ifc
))
71 p
.prefix
= dest
->prefix
;
73 p
.prefix
= addr
->prefix
;
75 /* Apply mask to the network. */
78 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
80 if (prefix_ipv4_any (&p
))
83 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0, 0, 0);
88 /* Add connected IPv4 route to the interface. */
90 connected_add_ipv4 (struct interface
*ifp
, int flags
, struct in_addr
*addr
,
91 int prefixlen
, struct in_addr
*broad
, char *label
)
93 struct prefix_ipv4
*p
;
94 struct connected
*ifc
;
95 struct connected
*current
;
97 /* Make connected structure. */
98 ifc
= connected_new ();
102 /* Allocate new connected address. */
103 p
= prefix_ipv4_new ();
106 p
->prefixlen
= prefixlen
;
107 ifc
->address
= (struct prefix
*) p
;
109 /* If there is broadcast or pointopoint address. */
112 p
= prefix_ipv4_new ();
115 ifc
->destination
= (struct prefix
*) p
;
117 /* validate the destination address */
118 if (ifp
->flags
& IFF_POINTOPOINT
)
120 if (IPV4_ADDR_SAME(addr
,broad
))
121 zlog_warn("warning: PtP interface %s has same local and peer "
122 "address %s, routing protocols may malfunction",
123 ifp
->name
,inet_ntoa(*addr
));
124 else if ((prefixlen
!= IPV4_MAX_PREFIXLEN
) &&
125 (ipv4_network_addr(addr
->s_addr
,prefixlen
) !=
126 ipv4_network_addr(broad
->s_addr
,prefixlen
)))
128 char buf
[2][INET_ADDRSTRLEN
];
129 zlog_warn("warning: PtP interface %s network mismatch: local "
130 "%s/%d vs. peer %s, routing protocols may malfunction",
132 inet_ntop (AF_INET
, addr
, buf
[0], sizeof(buf
[0])),
134 inet_ntop (AF_INET
, broad
, buf
[1], sizeof(buf
[1])));
139 if (broad
->s_addr
!= ipv4_broadcast_addr(addr
->s_addr
,prefixlen
))
141 char buf
[2][INET_ADDRSTRLEN
];
142 struct in_addr bcalc
;
143 bcalc
.s_addr
= ipv4_broadcast_addr(addr
->s_addr
,prefixlen
);
144 zlog_warn("warning: interface %s broadcast addr %s/%d != "
145 "calculated %s, routing protocols may malfunction",
147 inet_ntop (AF_INET
, broad
, buf
[0], sizeof(buf
[0])),
149 inet_ntop (AF_INET
, &bcalc
, buf
[1], sizeof(buf
[1])));
155 /* no broadcast or destination address was supplied */
156 if ((prefixlen
== IPV4_MAX_PREFIXLEN
) && if_is_pointopoint(ifp
))
157 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
158 "peer address",ifp
->name
,inet_ntoa(*addr
),prefixlen
);
160 /* Label of this address. */
162 ifc
->label
= strdup (label
);
164 /* Check same connected route. */
165 current
= connected_check_ipv4 (ifp
, (struct prefix
*) ifc
->address
);
168 connected_free (ifc
);
173 listnode_add (ifp
->connected
, ifc
);
176 /* Update interface address information to protocol daemon. */
177 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
179 if_subnet_add (ifp
, ifc
);
181 SET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
183 zebra_interface_address_add_update (ifp
, ifc
);
186 connected_up_ipv4 (ifp
, ifc
);
191 connected_down_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
193 struct prefix_ipv4 p
;
194 struct prefix_ipv4
*addr
;
195 struct prefix_ipv4
*dest
;
197 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
200 addr
= (struct prefix_ipv4
*)ifc
->address
;
201 dest
= (struct prefix_ipv4
*)ifc
->destination
;
203 memset (&p
, 0, sizeof (struct prefix_ipv4
));
205 p
.prefixlen
= addr
->prefixlen
;
207 /* Point-to-point check. */
208 if (CONNECTED_POINTOPOINT_HOST(ifc
))
209 p
.prefix
= dest
->prefix
;
211 p
.prefix
= addr
->prefix
;
213 /* Apply mask to the network. */
214 apply_mask_ipv4 (&p
);
216 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
218 if (prefix_ipv4_any (&p
))
221 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0);
226 /* Delete connected IPv4 route to the interface. */
228 connected_delete_ipv4 (struct interface
*ifp
, int flags
, struct in_addr
*addr
,
229 int prefixlen
, struct in_addr
*broad
, char *label
)
231 struct prefix_ipv4 p
;
232 struct connected
*ifc
;
234 memset (&p
, 0, sizeof (struct prefix_ipv4
));
237 p
.prefixlen
= prefixlen
;
239 ifc
= connected_check_ipv4 (ifp
, (struct prefix
*) &p
);
243 /* Update interface address information to protocol daemon. */
244 if (CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
246 zebra_interface_address_delete_update (ifp
, ifc
);
248 if_subnet_delete (ifp
, ifc
);
250 connected_down_ipv4 (ifp
, ifc
);
252 UNSET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
255 listnode_delete (ifp
->connected
, ifc
);
256 connected_free (ifc
);
260 /* If same interface address is already exist... */
262 connected_check_ipv6 (struct interface
*ifp
, struct prefix
*p
)
264 struct connected
*ifc
;
265 struct listnode
*node
;
267 for (ALL_LIST_ELEMENTS_RO (ifp
->connected
, node
, ifc
))
268 if (prefix_same (ifc
->address
, p
))
275 connected_up_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
277 struct prefix_ipv6 p
;
278 struct prefix_ipv6
*addr
;
279 struct prefix_ipv6
*dest
;
281 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
284 addr
= (struct prefix_ipv6
*) ifc
->address
;
285 dest
= (struct prefix_ipv6
*) ifc
->destination
;
287 memset (&p
, 0, sizeof (struct prefix_ipv6
));
289 p
.prefixlen
= addr
->prefixlen
;
291 if (if_is_pointopoint (ifp
) && dest
)
293 if (IN6_IS_ADDR_UNSPECIFIED (&dest
->prefix
))
294 p
.prefix
= addr
->prefix
;
296 p
.prefix
= dest
->prefix
;
299 p
.prefix
= addr
->prefix
;
301 /* Apply mask to the network. */
302 apply_mask_ipv6 (&p
);
304 #if ! defined (MUSICA) && ! defined (LINUX)
305 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
306 if (IN6_IS_ADDR_UNSPECIFIED (&p
.prefix
))
310 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0);
315 /* Add connected IPv6 route to the interface. */
317 connected_add_ipv6 (struct interface
*ifp
, struct in6_addr
*addr
,
318 u_char prefixlen
, struct in6_addr
*broad
)
320 struct prefix_ipv6
*p
;
321 struct connected
*ifc
;
322 struct connected
*current
;
324 /* Make connected structure. */
325 ifc
= connected_new ();
328 /* Allocate new connected address. */
329 p
= prefix_ipv6_new ();
330 p
->family
= AF_INET6
;
331 IPV6_ADDR_COPY (&p
->prefix
, addr
);
332 p
->prefixlen
= prefixlen
;
333 ifc
->address
= (struct prefix
*) p
;
335 /* If there is broadcast or pointopoint address. */
338 p
= prefix_ipv6_new ();
339 p
->family
= AF_INET6
;
340 IPV6_ADDR_COPY (&p
->prefix
, broad
);
341 ifc
->destination
= (struct prefix
*) p
;
344 current
= connected_check_ipv6 (ifp
, (struct prefix
*) ifc
->address
);
347 connected_free (ifc
);
352 listnode_add (ifp
->connected
, ifc
);
355 /* Update interface address information to protocol daemon. */
356 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
358 SET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
360 zebra_interface_address_add_update (ifp
, ifc
);
363 connected_up_ipv6 (ifp
, ifc
);
368 connected_down_ipv6 (struct interface
*ifp
, struct connected
*ifc
)
370 struct prefix_ipv6 p
;
371 struct prefix_ipv6
*addr
;
372 struct prefix_ipv6
*dest
;
374 if (! CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
377 addr
= (struct prefix_ipv6
*) ifc
->address
;
378 dest
= (struct prefix_ipv6
*) ifc
->destination
;
380 memset (&p
, 0, sizeof (struct prefix_ipv6
));
382 p
.prefixlen
= addr
->prefixlen
;
384 if (if_is_pointopoint (ifp
) && dest
)
386 if (IN6_IS_ADDR_UNSPECIFIED (&dest
->prefix
))
387 p
.prefix
= addr
->prefix
;
389 p
.prefix
= dest
->prefix
;
392 p
.prefix
= addr
->prefix
;
394 apply_mask_ipv6 (&p
);
396 if (IN6_IS_ADDR_UNSPECIFIED (&p
.prefix
))
399 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT
, 0, &p
, NULL
, ifp
->ifindex
, 0);
405 connected_delete_ipv6 (struct interface
*ifp
, struct in6_addr
*address
,
406 u_char prefixlen
, struct in6_addr
*broad
)
408 struct prefix_ipv6 p
;
409 struct connected
*ifc
;
411 memset (&p
, 0, sizeof (struct prefix_ipv6
));
413 memcpy (&p
.prefix
, address
, sizeof (struct in6_addr
));
414 p
.prefixlen
= prefixlen
;
416 ifc
= connected_check_ipv6 (ifp
, (struct prefix
*) &p
);
420 /* Update interface address information to protocol daemon. */
421 if (CHECK_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
))
423 zebra_interface_address_delete_update (ifp
, ifc
);
425 connected_down_ipv6 (ifp
, ifc
);
427 UNSET_FLAG (ifc
->conf
, ZEBRA_IFC_REAL
);
430 listnode_delete (ifp
->connected
, ifc
);
431 connected_free (ifc
);
433 #endif /* HAVE_IPV6 */