version 1.1.1.1, 2012/02/21 17:26:11
|
version 1.1.1.4, 2016/11/02 10:09:10
|
Line 36
|
Line 36
|
#include "zebra/interface.h" |
#include "zebra/interface.h" |
#include "zebra/connected.h" |
#include "zebra/connected.h" |
extern struct zebra_t zebrad; |
extern struct zebra_t zebrad; |
| |
/* withdraw a connected address */ | /* communicate the withdrawal of a connected address */ |
static void |
static void |
connected_withdraw (struct connected *ifc) |
connected_withdraw (struct connected *ifc) |
{ |
{ |
Line 49 connected_withdraw (struct connected *ifc)
|
Line 49 connected_withdraw (struct connected *ifc)
|
{ |
{ |
zebra_interface_address_delete_update (ifc->ifp, ifc); |
zebra_interface_address_delete_update (ifc->ifp, ifc); |
|
|
if_subnet_delete (ifc->ifp, ifc); |
|
|
|
if (ifc->address->family == AF_INET) |
if (ifc->address->family == AF_INET) |
|
if_subnet_delete (ifc->ifp, ifc); |
|
|
|
if (ifc->address->family == AF_INET) |
connected_down_ipv4 (ifc->ifp, ifc); |
connected_down_ipv4 (ifc->ifp, ifc); |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
else |
else |
Line 61 connected_withdraw (struct connected *ifc)
|
Line 62 connected_withdraw (struct connected *ifc)
|
UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); |
UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); |
} |
} |
|
|
|
/* The address is not in the kernel anymore, so clear the flag */ |
|
UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); |
|
|
if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) |
if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) |
{ |
{ |
listnode_delete (ifc->ifp->connected, ifc); |
listnode_delete (ifc->ifp->connected, ifc); |
Line 77 connected_announce (struct interface *ifp, struct conn
|
Line 81 connected_announce (struct interface *ifp, struct conn
|
listnode_add (ifp->connected, ifc); |
listnode_add (ifp->connected, ifc); |
|
|
/* Update interface address information to protocol daemon. */ |
/* Update interface address information to protocol daemon. */ |
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) | if (ifc->address->family == AF_INET) |
{ | if_subnet_add (ifp, ifc); |
if (ifc->address->family == AF_INET) | |
if_subnet_add (ifp, ifc); | |
|
|
SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); | zebra_interface_address_add_update (ifp, ifc); |
|
|
zebra_interface_address_add_update (ifp, ifc); | if (if_is_operative(ifp)) |
| { |
if (if_is_operative(ifp)) | if (ifc->address->family == AF_INET) |
{ | connected_up_ipv4 (ifp, ifc); |
if (ifc->address->family == AF_INET) | |
connected_up_ipv4 (ifp, ifc); | |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
else | else |
connected_up_ipv6 (ifp, ifc); | connected_up_ipv6 (ifp, ifc); |
#endif |
#endif |
} |
|
} |
} |
} |
} |
| |
/* If same interface address is already exist... */ |
/* If same interface address is already exist... */ |
struct connected * |
struct connected * |
connected_check (struct interface *ifp, struct prefix *p) |
connected_check (struct interface *ifp, struct prefix *p) |
Line 112 connected_check (struct interface *ifp, struct prefix
|
Line 111 connected_check (struct interface *ifp, struct prefix
|
return NULL; |
return NULL; |
} |
} |
|
|
/* Check if two ifc's describe the same address */ | /* Check if two ifc's describe the same address in the same state */ |
static int |
static int |
connected_same (struct connected *ifc1, struct connected *ifc2) |
connected_same (struct connected *ifc1, struct connected *ifc2) |
{ |
{ |
Line 132 connected_same (struct connected *ifc1, struct connect
|
Line 131 connected_same (struct connected *ifc1, struct connect
|
|
|
if (ifc1->flags != ifc2->flags) |
if (ifc1->flags != ifc2->flags) |
return 0; |
return 0; |
|
|
|
if (ifc1->conf != ifc2->conf) |
|
return 0; |
|
|
return 1; |
return 1; |
} |
} |
|
|
/* Handle implicit withdrawals of addresses, where a system ADDs an address | /* Handle changes to addresses and send the neccesary announcements |
* to an interface which already has the same address configured. | * to clients. */ |
* | static void |
* Returns the struct connected which must be announced to clients, | connected_update(struct interface *ifp, struct connected *ifc) |
* or NULL if nothing to do. | |
*/ | |
static struct connected * | |
connected_implicit_withdraw (struct interface *ifp, struct connected *ifc) | |
{ |
{ |
struct connected *current; |
struct connected *current; |
|
|
Line 156 connected_implicit_withdraw (struct interface *ifp, st
|
Line 154 connected_implicit_withdraw (struct interface *ifp, st
|
/* Avoid spurious withdraws, this might be just the kernel 'reflecting' |
/* Avoid spurious withdraws, this might be just the kernel 'reflecting' |
* back an address we have already added. |
* back an address we have already added. |
*/ |
*/ |
if (connected_same (current, ifc) && CHECK_FLAG(current->conf, ZEBRA_IFC_REAL)) | if (connected_same (current, ifc)) |
{ |
{ |
/* nothing to do */ |
/* nothing to do */ |
connected_free (ifc); |
connected_free (ifc); |
return NULL; | return; |
} |
} |
| |
| /* Clear the configured flag on the old ifc, so it will be freed by |
| * connected withdraw. */ |
UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); |
UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED); |
connected_withdraw (current); /* implicit withdraw - freebsd does this */ |
connected_withdraw (current); /* implicit withdraw - freebsd does this */ |
} |
} |
return ifc; | |
| /* If the connected is new or has changed, announce it, if it is usable */ |
| if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) |
| connected_announce(ifp, ifc); |
} |
} |
|
|
/* Called from if_up(). */ |
/* Called from if_up(). */ |
Line 189 connected_up_ipv4 (struct interface *ifp, struct conne
|
Line 192 connected_up_ipv4 (struct interface *ifp, struct conne
|
return; |
return; |
|
|
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, |
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, |
RT_TABLE_MAIN, ifp->metric, 0); | ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); |
|
|
rib_update (); | rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, |
| ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST); |
| |
| rib_update (ifp->vrf_id); |
} |
} |
|
|
/* Add connected IPv4 route to the interface. */ |
/* Add connected IPv4 route to the interface. */ |
Line 207 connected_add_ipv4 (struct interface *ifp, int flags,
|
Line 213 connected_add_ipv4 (struct interface *ifp, int flags,
|
ifc = connected_new (); |
ifc = connected_new (); |
ifc->ifp = ifp; |
ifc->ifp = ifp; |
ifc->flags = flags; |
ifc->flags = flags; |
|
/* If we get a notification from the kernel, |
|
* we can safely assume the address is known to the kernel */ |
|
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); |
|
|
/* Allocate new connected address. */ |
/* Allocate new connected address. */ |
p = prefix_ipv4_new (); |
p = prefix_ipv4_new (); |
Line 269 connected_add_ipv4 (struct interface *ifp, int flags,
|
Line 278 connected_add_ipv4 (struct interface *ifp, int flags,
|
if (label) |
if (label) |
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); |
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); |
|
|
/* nothing to do? */ | /* For all that I know an IPv4 address is always ready when we receive |
if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) | * the notification. So it should be safe to set the REAL flag here. */ |
return; | SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); |
| |
connected_announce (ifp, ifc); | connected_update(ifp, ifc); |
} |
} |
|
|
void |
void |
Line 295 connected_down_ipv4 (struct interface *ifp, struct con
|
Line 304 connected_down_ipv4 (struct interface *ifp, struct con
|
return; |
return; |
|
|
/* Same logic as for connected_up_ipv4(): push the changes into the head. */ |
/* Same logic as for connected_up_ipv4(): push the changes into the head. */ |
rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); | rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, |
| SAFI_UNICAST); |
|
|
rib_update (); | rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, |
| SAFI_MULTICAST); |
| |
| rib_update (ifp->vrf_id); |
} |
} |
|
|
/* Delete connected IPv4 route to the interface. */ |
/* Delete connected IPv4 route to the interface. */ |
Line 319 connected_delete_ipv4 (struct interface *ifp, int flag
|
Line 332 connected_delete_ipv4 (struct interface *ifp, int flag
|
|
|
connected_withdraw (ifc); |
connected_withdraw (ifc); |
|
|
rib_update(); | rib_update (ifp->vrf_id); |
} |
} |
|
|
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
Line 336 connected_up_ipv6 (struct interface *ifp, struct conne
|
Line 349 connected_up_ipv6 (struct interface *ifp, struct conne
|
/* Apply mask to the network. */ |
/* Apply mask to the network. */ |
apply_mask_ipv6 (&p); |
apply_mask_ipv6 (&p); |
|
|
#if ! defined (MUSICA) && ! defined (LINUX) | #ifndef LINUX |
/* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ |
/* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */ |
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) |
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) |
return; |
return; |
#endif |
#endif |
|
|
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, | rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, |
ifp->metric, 0); | RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST); |
|
|
rib_update (); | rib_update (ifp->vrf_id); |
} |
} |
|
|
/* Add connected IPv6 route to the interface. */ |
/* Add connected IPv6 route to the interface. */ |
Line 361 connected_add_ipv6 (struct interface *ifp, int flags,
|
Line 374 connected_add_ipv6 (struct interface *ifp, int flags,
|
ifc = connected_new (); |
ifc = connected_new (); |
ifc->ifp = ifp; |
ifc->ifp = ifp; |
ifc->flags = flags; |
ifc->flags = flags; |
|
/* If we get a notification from the kernel, |
|
* we can safely assume the address is known to the kernel */ |
|
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); |
|
|
/* Allocate new connected address. */ |
/* Allocate new connected address. */ |
p = prefix_ipv6_new (); |
p = prefix_ipv6_new (); |
Line 395 connected_add_ipv6 (struct interface *ifp, int flags,
|
Line 411 connected_add_ipv6 (struct interface *ifp, int flags,
|
/* Label of this address. */ |
/* Label of this address. */ |
if (label) |
if (label) |
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); |
ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); |
| |
if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) | /* On Linux, we only get here when DAD is complete, therefore we can set |
return; | * ZEBRA_IFC_REAL. |
| * |
connected_announce (ifp, ifc); | * On BSD, there currently doesn't seem to be a way to check for completion of |
| * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD |
| * might still be running. |
| */ |
| SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); |
| connected_update(ifp, ifc); |
} |
} |
|
|
void |
void |
Line 417 connected_down_ipv6 (struct interface *ifp, struct con
|
Line 438 connected_down_ipv6 (struct interface *ifp, struct con
|
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) |
if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) |
return; |
return; |
|
|
rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); | rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id, |
| SAFI_UNICAST); |
|
|
rib_update (); | rib_update (ifp->vrf_id); |
} |
} |
|
|
void |
void |
Line 440 connected_delete_ipv6 (struct interface *ifp, struct i
|
Line 462 connected_delete_ipv6 (struct interface *ifp, struct i
|
|
|
connected_withdraw (ifc); |
connected_withdraw (ifc); |
|
|
rib_update(); | rib_update (ifp->vrf_id); |
} |
} |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |