mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 08:50:26 +00:00
[PtP over ethernet] New peer flag allows much more addressing flexibility
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating whether a peer address has been configured. Comment now shows the new interpretation of the destination addr: if ZEBRA_IFA_PEER is set, then it must contain the destination address, otherwise it may contain the broadcast address or be NULL. (CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete macros that were specific to IPv4 and not fully general. (CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag. (CONNECTED_PREFIX) New macro giving the prefix to insert into the RIB: if CONNECTED_PEER, then use the destination (peer) address, else use the address field. (CONNECTED_ID) New macro to come up with an identifying address for the struct connected. * if.c: (if_lookup_address, connected_lookup_address) Streamline logic with new CONNECTED_PREFIX macro. * prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros for better performance than the general prefix_copy function. * zclient.c: (zebra_interface_address_read) For non-null destination addresses, set prefixlen to equal the address prefixlen. This is needed to get the new CONNECTED_PREFIX macro to work properly. * connected.c: (connected_up_ipv4, connected_down_ipv4, connected_up_ipv6, connected_down_ipv6) Simplify logic using the new CONNECTED_PREFIX macro. (connected_add_ipv4) Set prefixlen in destination addresses (required by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead of testing for IFF_POINTOPOINT. Delete invalid warning message. Warn about cases where the ZEBRA_IFA_PEER is set but no destination address has been supplied (and turn off the flag). (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning. Set prefixlen in destination address so CONNECTED_PREFIX will work. * connected.h: (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. * interface.c: (connected_dump_vty) Use CONNECTED_PEER macro to decide whether the destination address is a peer or broadcast address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT). * if_ioctl.c: (if_getaddrs) Instead of setting a peer address only when the IFF_POINTOPOINT is set, we now accept a peer address whenever it is available and not the same as the local address. Otherwise (no peer address assigned), we check for a broadcast address (regardless of the IFF_BROADCAST flag). And must now pass a flags value of ZEBRA_IFA_PEER to connected_add_ipv4 when a peer address is assigned. The same new logic is used with the IPv6 code as well (and we pass the new flags argument to connected_add_ipv6). (if_get_addr) Do not bother to check IFF_POINTOPOINT: just issue the SIOCGIFDSTADDR ioctl and see if we get back a peer address not matching the local address (and set the ZEBRA_IFA_PEER in that case). If there's no peer address, try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set. * if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl without bothering to check the IFF_POINTOPOINT flag. And if no peer address was found, just try the SIOCGLIFBRDADDR ioctl without checking the IFF_BROADCAST flag. Call connected_add_ipv4 and connected_add_ipv6 with appropriate flags. * if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to connected_add_ipv6. * kernel_socket.c: (ifam_read) Must pass new flags argument to connected_add_ipv6. * rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2 to determine local and possible peer address (so there's no longer a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately. Pass new flags argument to connected_add_ipv6. (netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast to determine whether the connected destination address is a broadcast address. * bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete) Simplify logic by using new CONNECTED_PREFIX macro. * ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix, ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX macro. * ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX macro, both options collapse into the same code. * ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new CONNECTED_ID macro. (ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX macro. * ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro instead of testing the IFF_POINTOPOINT flag. * ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro instead of testing with if_is_pointopoint. And add commented-out code to implement alternative (in my opinion) more elegant behavior that has no special-case treatment for PtP addresses. (ospf_network_run) Use new CONNECTED_ID macro to simplify logic. * rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID macro to simplify logic. (rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does not give a useful result if prefixlen is 32 (we require a peer address in such cases). * ripd.c: (rip_update_interface) Fix same bug as above.
This commit is contained in:
parent
43cd33a44e
commit
e4529636b7
@ -1,3 +1,8 @@
|
||||
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete)
|
||||
Simplify logic by using new CONNECTED_PREFIX macro.
|
||||
|
||||
2006-12-07 Paul Jakma <paul.jakma@sun.com>
|
||||
|
||||
* bgp_fsm.c: Bug #302 fix, diagnosis, suggestions and testing
|
||||
|
@ -543,7 +543,6 @@ bgp_connected_add (struct connected *ifc)
|
||||
{
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct prefix *dest;
|
||||
struct interface *ifp;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
@ -557,19 +556,10 @@ bgp_connected_add (struct connected *ifc)
|
||||
return;
|
||||
|
||||
addr = ifc->address;
|
||||
dest = ifc->destination;
|
||||
|
||||
if (addr->family == AF_INET)
|
||||
{
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (CONNECTED_POINTOPOINT_HOST(ifc))
|
||||
p.u.prefix4 = dest->u.prefix4;
|
||||
else
|
||||
p.u.prefix4 = addr->u.prefix4;
|
||||
|
||||
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
||||
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
||||
|
||||
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
||||
@ -590,17 +580,9 @@ bgp_connected_add (struct connected *ifc)
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (addr->family == AF_INET6)
|
||||
else if (addr->family == AF_INET6)
|
||||
{
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (if_is_pointopoint (ifp) && dest)
|
||||
p.u.prefix6 = dest->u.prefix6;
|
||||
else
|
||||
p.u.prefix6 = addr->u.prefix6;
|
||||
|
||||
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
||||
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
||||
@ -631,7 +613,6 @@ bgp_connected_delete (struct connected *ifc)
|
||||
{
|
||||
struct prefix p;
|
||||
struct prefix *addr;
|
||||
struct prefix *dest;
|
||||
struct interface *ifp;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
@ -642,19 +623,10 @@ bgp_connected_delete (struct connected *ifc)
|
||||
return;
|
||||
|
||||
addr = ifc->address;
|
||||
dest = ifc->destination;
|
||||
|
||||
if (addr->family == AF_INET)
|
||||
{
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (CONNECTED_POINTOPOINT_HOST(ifc))
|
||||
p.u.prefix4 = dest->u.prefix4;
|
||||
else
|
||||
p.u.prefix4 = addr->u.prefix4;
|
||||
|
||||
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
||||
apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
|
||||
|
||||
if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
|
||||
@ -677,15 +649,7 @@ bgp_connected_delete (struct connected *ifc)
|
||||
#ifdef HAVE_IPV6
|
||||
else if (addr->family == AF_INET6)
|
||||
{
|
||||
memset (&p, 0, sizeof (struct prefix));
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (if_is_pointopoint (ifp) && dest)
|
||||
p.u.prefix6 = dest->u.prefix6;
|
||||
else
|
||||
p.u.prefix6 = addr->u.prefix6;
|
||||
|
||||
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
||||
apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
|
||||
|
@ -1,3 +1,26 @@
|
||||
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating
|
||||
whether a peer address has been configured. Comment now shows
|
||||
the new interpretation of the destination addr: if ZEBRA_IFA_PEER
|
||||
is set, then it must contain the destination address, otherwise
|
||||
it may contain the broadcast address or be NULL.
|
||||
(CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete
|
||||
macros that were specific to IPv4 and not fully general.
|
||||
(CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag.
|
||||
(CONNECTED_PREFIX) New macro giving the prefix to insert into
|
||||
the RIB: if CONNECTED_PEER, then use the destination (peer) address,
|
||||
else use the address field.
|
||||
(CONNECTED_ID) New macro to come up with an identifying address
|
||||
for the struct connected.
|
||||
* if.c: (if_lookup_address, connected_lookup_address) Streamline
|
||||
logic with new CONNECTED_PREFIX macro.
|
||||
* prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros
|
||||
for better performance than the general prefix_copy function.
|
||||
* zclient.c: (zebra_interface_address_read) For non-null destination
|
||||
addresses, set prefixlen to equal the address prefixlen. This
|
||||
is needed to get the new CONNECTED_PREFIX macro to work properly.
|
||||
|
||||
2006-10-14 Paul Jakma <paul.jakma@sun.com>
|
||||
|
||||
* if.c: (general) Handle upgrades from SUNWzebra, which tried
|
||||
|
43
lib/if.c
43
lib/if.c
@ -275,7 +275,6 @@ if_lookup_address (struct in_addr src)
|
||||
int bestlen = 0;
|
||||
struct listnode *cnode;
|
||||
struct interface *ifp;
|
||||
struct prefix *p;
|
||||
struct connected *c;
|
||||
struct interface *match;
|
||||
|
||||
@ -289,28 +288,15 @@ if_lookup_address (struct in_addr src)
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
|
||||
{
|
||||
if (c->address && (c->address->family == AF_INET))
|
||||
if (c->address && (c->address->family == AF_INET) &&
|
||||
prefix_match(CONNECTED_PREFIX(c), &addr) &&
|
||||
(c->address->prefixlen > bestlen))
|
||||
{
|
||||
if (CONNECTED_POINTOPOINT_HOST(c))
|
||||
{
|
||||
/* PTP links are conventionally identified
|
||||
by the address of the far end - MAG */
|
||||
if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &src))
|
||||
return ifp;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c->address;
|
||||
|
||||
if (prefix_match (p, &addr) && p->prefixlen > bestlen)
|
||||
{
|
||||
bestlen = p->prefixlen;
|
||||
bestlen = c->address->prefixlen;
|
||||
match = ifp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
@ -728,7 +714,6 @@ connected_lookup_address (struct interface *ifp, struct in_addr dst)
|
||||
{
|
||||
struct prefix addr;
|
||||
struct listnode *cnode;
|
||||
struct prefix *p;
|
||||
struct connected *c;
|
||||
struct connected *match;
|
||||
|
||||
@ -740,25 +725,11 @@ connected_lookup_address (struct interface *ifp, struct in_addr dst)
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
|
||||
{
|
||||
if (c->address && (c->address->family == AF_INET))
|
||||
{
|
||||
if (CONNECTED_POINTOPOINT_HOST(c))
|
||||
{
|
||||
/* PTP links are conventionally identified
|
||||
by the address of the far end - MAG */
|
||||
if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &dst))
|
||||
return c;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c->address;
|
||||
|
||||
if (prefix_match (p, &addr) &&
|
||||
(!match || (p->prefixlen > match->address->prefixlen)))
|
||||
if (c->address && (c->address->family == AF_INET) &&
|
||||
prefix_match(CONNECTED_PREFIX(c), &addr) &&
|
||||
(!match || (c->address->prefixlen > match->address->prefixlen)))
|
||||
match = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
|
32
lib/if.h
32
lib/if.h
@ -155,25 +155,37 @@ struct connected
|
||||
/* Flags for connected address. */
|
||||
u_char flags;
|
||||
#define ZEBRA_IFA_SECONDARY (1 << 0)
|
||||
#define ZEBRA_IFA_PEER (1 << 1)
|
||||
/* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
|
||||
a peer address has been configured. If this flag is set,
|
||||
the destination field must contain the peer address.
|
||||
Otherwise, if this flag is not set, the destination address
|
||||
will either contain a broadcast address or be NULL.
|
||||
*/
|
||||
|
||||
/* Address of connected network. */
|
||||
struct prefix *address;
|
||||
struct prefix *destination; /* broadcast or peer address; may be NULL */
|
||||
|
||||
/* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is set.
|
||||
Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */
|
||||
struct prefix *destination;
|
||||
|
||||
/* Label for Linux 2.2.X and upper. */
|
||||
char *label;
|
||||
};
|
||||
|
||||
/* Given an IPV4 struct connected, this macro determines whether a /32
|
||||
peer address has been supplied (i.e. there is no subnet assigned) */
|
||||
#define CONNECTED_DEST_HOST(C) \
|
||||
((C)->destination && ((C)->address->prefixlen == IPV4_MAX_PREFIXLEN))
|
||||
/* Does the destination field contain a peer address? */
|
||||
#define CONNECTED_PEER(C) CHECK_FLAG((C)->flags, ZEBRA_IFA_PEER)
|
||||
|
||||
/* Given an IPV4 struct connected, this macro determins whether it is
|
||||
a point-to-point link with a /32 peer address (i.e. there
|
||||
is no dedicated subnet for the PtP link) */
|
||||
#define CONNECTED_POINTOPOINT_HOST(C) \
|
||||
(((C)->ifp->flags & IFF_POINTOPOINT) && CONNECTED_DEST_HOST(C))
|
||||
/* Prefix to insert into the RIB */
|
||||
#define CONNECTED_PREFIX(C) \
|
||||
(CONNECTED_PEER(C) ? (C)->destination : (C)->address)
|
||||
|
||||
/* Identifying address. We guess that if there's a peer address, but the
|
||||
local address is in the same prefix, then the local address may be unique. */
|
||||
#define CONNECTED_ID(C) \
|
||||
((CONNECTED_PEER(C) && !prefix_match((C)->destination, (C)->address)) ?\
|
||||
(C)->destination : (C)->address)
|
||||
|
||||
/* Interface hook sort. */
|
||||
#define IF_NEW_HOOK 0
|
||||
|
@ -151,6 +151,9 @@ extern void prefix_ipv4_free (struct prefix_ipv4 *);
|
||||
extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *);
|
||||
extern void apply_mask_ipv4 (struct prefix_ipv4 *);
|
||||
|
||||
#define PREFIX_COPY_IPV4(DST, SRC) \
|
||||
*((struct prefix_ipv4 *)(DST)) = *((const struct prefix_ipv4 *)(SRC));
|
||||
|
||||
extern int prefix_ipv4_any (const struct prefix_ipv4 *);
|
||||
extern void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
|
||||
|
||||
@ -172,6 +175,9 @@ extern void prefix_ipv6_free (struct prefix_ipv6 *);
|
||||
extern int str2prefix_ipv6 (const char *, struct prefix_ipv6 *);
|
||||
extern void apply_mask_ipv6 (struct prefix_ipv6 *);
|
||||
|
||||
#define PREFIX_COPY_IPV6(DST, SRC) \
|
||||
*((struct prefix_ipv6 *)(DST)) = *((const struct prefix_ipv6 *)(SRC));
|
||||
|
||||
extern int ip6_masklen (struct in6_addr);
|
||||
extern void masklen2ip6 (int, struct in6_addr *);
|
||||
|
||||
|
@ -780,7 +780,11 @@ zebra_interface_address_read (int type, struct stream *s)
|
||||
ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
|
||||
NULL : &d));
|
||||
if (ifc != NULL)
|
||||
{
|
||||
ifc->flags = ifc_flags;
|
||||
if (ifc->destination)
|
||||
ifc->destination->prefixlen = ifc->address->prefixlen;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,3 +1,22 @@
|
||||
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix,
|
||||
ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX
|
||||
macro.
|
||||
* ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX
|
||||
macro, both options collapse into the same code.
|
||||
* ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new
|
||||
CONNECTED_ID macro.
|
||||
(ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX
|
||||
macro.
|
||||
* ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro
|
||||
instead of testing the IFF_POINTOPOINT flag.
|
||||
* ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro
|
||||
instead of testing with if_is_pointopoint. And add commented-out
|
||||
code to implement alternative (in my opinion) more elegant behavior
|
||||
that has no special-case treatment for PtP addresses.
|
||||
(ospf_network_run) Use new CONNECTED_ID macro to simplify logic.
|
||||
|
||||
2006-12-04 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* ospfd.c: (ospf_network_run) Remove an offending 'break' statement.
|
||||
|
@ -360,21 +360,11 @@ ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
|
||||
{
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
||||
{
|
||||
if (CONNECTED_DEST_HOST(oi->connected))
|
||||
{
|
||||
/* match only destination addr, since local addr is most likely
|
||||
* not unique (borrowed from another interface) */
|
||||
if (IPV4_ADDR_SAME (address,
|
||||
&oi->connected->destination->u.prefix4))
|
||||
/* special leniency: match if addr is anywhere on peer subnet */
|
||||
if (prefix_match(CONNECTED_PREFIX(oi->connected),
|
||||
(struct prefix *)&addr))
|
||||
return oi;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* special leniency: match if addr is anywhere on PtP subnet */
|
||||
if (prefix_match(oi->address,(struct prefix *)&addr))
|
||||
return oi;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
|
||||
@ -432,22 +422,15 @@ ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf_interface *oi;
|
||||
struct prefix ptmp;
|
||||
|
||||
/* Check each Interface. */
|
||||
for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
|
||||
{
|
||||
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
||||
{
|
||||
if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
|
||||
CONNECTED_DEST_HOST(oi->connected))
|
||||
{
|
||||
prefix_copy (&ptmp, oi->connected->destination);
|
||||
ptmp.prefixlen = IPV4_MAX_BITLEN;
|
||||
}
|
||||
else
|
||||
prefix_copy (&ptmp, oi->address);
|
||||
struct prefix ptmp;
|
||||
|
||||
prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
|
||||
apply_mask (&ptmp);
|
||||
if (prefix_same (&ptmp, (struct prefix *) p))
|
||||
return oi;
|
||||
@ -478,15 +461,8 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src)
|
||||
if (if_is_loopback (oi->ifp))
|
||||
continue;
|
||||
|
||||
if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
|
||||
CONNECTED_DEST_HOST(oi->connected))
|
||||
{
|
||||
if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
|
||||
return oi;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prefix_match (oi->address, (struct prefix *) &addr))
|
||||
if (prefix_match (CONNECTED_PREFIX(oi->connected),
|
||||
(struct prefix *) &addr))
|
||||
{
|
||||
if ( (match == NULL) ||
|
||||
(match->address->prefixlen < oi->address->prefixlen)
|
||||
@ -494,7 +470,6 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src)
|
||||
match = oi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
@ -543,7 +543,7 @@ link_info_set (struct stream *s, struct in_addr id,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Describe Point-to-Point link. */
|
||||
/* Describe Point-to-Point link (Section 12.4.1.1). */
|
||||
static int
|
||||
lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
|
||||
{
|
||||
@ -564,28 +564,13 @@ lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi)
|
||||
LSA_LINK_TYPE_POINTOPOINT, 0, cost);
|
||||
}
|
||||
|
||||
if (CONNECTED_DEST_HOST(oi->connected))
|
||||
{
|
||||
/* Option 1:
|
||||
link_type = LSA_LINK_TYPE_STUB;
|
||||
link_id = nbr->address.u.prefix4;
|
||||
link_data.s_addr = 0xffffffff;
|
||||
link_cost = o->output_cost; */
|
||||
|
||||
id.s_addr = oi->connected->destination->u.prefix4.s_addr;
|
||||
mask.s_addr = 0xffffffff;
|
||||
links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
oi->output_cost);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Option 2: We need to include link to a stub
|
||||
network regardless of the state of the neighbor */
|
||||
/* Regardless of the state of the neighboring router, we must
|
||||
add a Type 3 link (stub network).
|
||||
N.B. Options 1 & 2 share basically the same logic. */
|
||||
masklen2ip (oi->address->prefixlen, &mask);
|
||||
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
|
||||
id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
|
||||
links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
|
||||
oi->output_cost);
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
|
@ -1439,10 +1439,7 @@ ospf_snmp_if_update (struct interface *ifp)
|
||||
/* Lookup first IPv4 address entry. */
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
|
||||
{
|
||||
if (CONNECTED_POINTOPOINT_HOST(ifc))
|
||||
p = ifc->destination;
|
||||
else
|
||||
p = ifc->address;
|
||||
p = CONNECTED_ID(ifc);
|
||||
|
||||
if (p->family == AF_INET)
|
||||
{
|
||||
@ -1492,19 +1489,13 @@ ospf_snmp_if_update (struct interface *ifp)
|
||||
int
|
||||
ospf_snmp_is_if_have_addr (struct interface *ifp)
|
||||
{
|
||||
struct prefix *p;
|
||||
struct listnode *nn;
|
||||
struct connected *ifc;
|
||||
|
||||
/* Is this interface having any connected IPv4 address ? */
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
|
||||
{
|
||||
if (if_is_pointopoint (ifp))
|
||||
p = ifc->destination;
|
||||
else
|
||||
p = ifc->address;
|
||||
|
||||
if (p->family == AF_INET)
|
||||
if (CONNECTED_PREFIX(ifc)->family == AF_INET)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2865,7 +2865,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
|
||||
struct in_addr *dest;
|
||||
const char *dstr;
|
||||
|
||||
if ((ifp->flags & IFF_POINTOPOINT)
|
||||
if (CONNECTED_PEER(oi->connected)
|
||||
|| oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||
dstr = "Peer";
|
||||
else
|
||||
|
@ -795,6 +795,23 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
|
||||
int
|
||||
ospf_network_match_iface(struct connected *co, struct prefix *net)
|
||||
{
|
||||
#define COMPATIBILITY_MODE
|
||||
/* The old code used to have a special case for PtP interfaces:
|
||||
|
||||
if (if_is_pointopoint (co->ifp) && co->destination &&
|
||||
IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
|
||||
return 1;
|
||||
|
||||
The new approach is much more general. If a peer address is supplied,
|
||||
then we are routing to that prefix, so that's the address to compare
|
||||
against (not the local address, which may not be unique).
|
||||
*/
|
||||
#ifndef COMPATIBILITY_MODE
|
||||
/* new approach: more elegant and conceptually clean */
|
||||
return prefix_match(net, CONNECTED_PREFIX(co));
|
||||
#else /* COMPATIBILITY_MODE */
|
||||
/* match old (strange?) behavior */
|
||||
|
||||
/* Behaviour to match both Cisco where:
|
||||
* iface address lies within network specified -> ospf
|
||||
* and zebra 0.9[2ish-3]:
|
||||
@ -806,7 +823,7 @@ ospf_network_match_iface(struct connected *co, struct prefix *net)
|
||||
* exactly; this is not a test for falling within the prefix. This
|
||||
* test is solely for compatibility with zebra.
|
||||
*/
|
||||
if (if_is_pointopoint (co->ifp) && co->destination &&
|
||||
if (CONNECTED_PEER(co) &&
|
||||
IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
|
||||
return 1;
|
||||
|
||||
@ -826,6 +843,8 @@ ospf_network_match_iface(struct connected *co, struct prefix *net)
|
||||
return 1;
|
||||
|
||||
return 0; /* no match */
|
||||
|
||||
#endif /* COMPATIBILITY_MODE */
|
||||
}
|
||||
|
||||
void
|
||||
@ -856,10 +875,7 @@ ospf_network_run (struct ospf *ospf, struct prefix *p, struct ospf_area *area)
|
||||
if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
|
||||
continue;
|
||||
|
||||
if (CONNECTED_POINTOPOINT_HOST(co))
|
||||
addr = co->destination;
|
||||
else
|
||||
addr = co->address;
|
||||
addr = CONNECTED_ID(co);
|
||||
|
||||
if (p->family == co->address->family
|
||||
&& ! ospf_if_is_configured (ospf, &(addr->u.prefix4))
|
||||
|
@ -1,3 +1,12 @@
|
||||
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID
|
||||
macro to simplify logic.
|
||||
(rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does
|
||||
not give a useful result if prefixlen is 32 (we require a peer
|
||||
address in such cases).
|
||||
* ripd.c: (rip_update_interface) Fix same bug as above.
|
||||
|
||||
2006-09-11 Paul Jakma <paul.jakma@sun.com>
|
||||
|
||||
* ripd.c: (rip_read) remove gratuitous use of mid-function
|
||||
|
@ -141,16 +141,10 @@ void
|
||||
rip_interface_multicast_set (int sock, struct connected *connected)
|
||||
{
|
||||
struct in_addr addr;
|
||||
struct prefix_ipv4 *p;
|
||||
|
||||
assert (connected != NULL);
|
||||
|
||||
if (if_is_pointopoint(connected->ifp) && CONNECTED_DEST_HOST(connected))
|
||||
p = (struct prefix_ipv4 *) connected->destination;
|
||||
else
|
||||
p = (struct prefix_ipv4 *) connected->address;
|
||||
|
||||
addr = p->prefix;
|
||||
addr = CONNECTED_ID(connected)->u.prefix4;
|
||||
|
||||
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0,
|
||||
connected->ifp->ifindex) < 0)
|
||||
@ -197,13 +191,16 @@ rip_request_interface_send (struct interface *ifp, u_char version)
|
||||
memset (&to, 0, sizeof (struct sockaddr_in));
|
||||
to.sin_port = htons (RIP_PORT_DEFAULT);
|
||||
if (connected->destination)
|
||||
/* use specified broadcast or point-to-point destination addr */
|
||||
/* use specified broadcast or peer destination addr */
|
||||
to.sin_addr = connected->destination->u.prefix4;
|
||||
else
|
||||
else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN)
|
||||
/* calculate the appropriate broadcast address */
|
||||
to.sin_addr.s_addr =
|
||||
ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
|
||||
connected->address->prefixlen);
|
||||
else
|
||||
/* do not know where to send the packet */
|
||||
continue;
|
||||
|
||||
if (IS_RIP_DEBUG_EVENT)
|
||||
zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr));
|
||||
|
11
ripd/ripd.c
11
ripd/ripd.c
@ -2449,18 +2449,21 @@ rip_update_interface (struct connected *ifc, u_char version, int route_type)
|
||||
/* Destination address and port setting. */
|
||||
memset (&to, 0, sizeof (struct sockaddr_in));
|
||||
if (ifc->destination)
|
||||
/* use specified broadcast or point-to-point destination addr */
|
||||
/* use specified broadcast or peer destination addr */
|
||||
to.sin_addr = ifc->destination->u.prefix4;
|
||||
else
|
||||
else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
|
||||
/* calculate the appropriate broadcast address */
|
||||
to.sin_addr.s_addr =
|
||||
ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
|
||||
ifc->address->prefixlen);
|
||||
else
|
||||
/* do not know where to send the packet */
|
||||
return;
|
||||
to.sin_port = htons (RIP_PORT_DEFAULT);
|
||||
|
||||
if (IS_RIP_DEBUG_EVENT)
|
||||
zlog_debug ("%s announce to %s on %s",
|
||||
if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast",
|
||||
zlog_debug("%s announce to %s on %s",
|
||||
CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
|
||||
inet_ntoa (to.sin_addr), ifc->ifp->name);
|
||||
|
||||
rip_output_process (ifc, &to, route_type, version);
|
||||
|
@ -1,3 +1,53 @@
|
||||
2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
|
||||
|
||||
* connected.c: (connected_up_ipv4, connected_down_ipv4,
|
||||
connected_up_ipv6, connected_down_ipv6) Simplify logic using the
|
||||
new CONNECTED_PREFIX macro.
|
||||
(connected_add_ipv4) Set prefixlen in destination addresses (required
|
||||
by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead
|
||||
of testing for IFF_POINTOPOINT. Delete invalid warning message.
|
||||
Warn about cases where the ZEBRA_IFA_PEER is set but no
|
||||
destination address has been supplied (and turn off the flag).
|
||||
(connected_add_ipv6) Add new flags argument so callers may set
|
||||
the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies
|
||||
IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning.
|
||||
Set prefixlen in destination address so CONNECTED_PREFIX will work.
|
||||
* connected.h: (connected_add_ipv6) Add new flags argument so
|
||||
callers may set the ZEBRA_IFA_PEER flag.
|
||||
* interface.c: (connected_dump_vty) Use CONNECTED_PEER macro
|
||||
to decide whether the destination address is a peer or broadcast
|
||||
address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT).
|
||||
* if_ioctl.c: (if_getaddrs) Instead of setting a peer address
|
||||
only when the IFF_POINTOPOINT is set, we now accept a peer
|
||||
address whenever it is available and not the same as the local
|
||||
address. Otherwise (no peer address assigned), we check
|
||||
for a broadcast address (regardless of the IFF_BROADCAST flag).
|
||||
And must now pass a flags value of ZEBRA_IFA_PEER to
|
||||
connected_add_ipv4 when a peer address is assigned.
|
||||
The same new logic is used with the IPv6 code as well (and we
|
||||
pass the new flags argument to connected_add_ipv6).
|
||||
(if_get_addr) Do not bother to check IFF_POINTOPOINT: just
|
||||
issue the SIOCGIFDSTADDR ioctl and see if we get back
|
||||
a peer address not matching the local address (and set
|
||||
the ZEBRA_IFA_PEER in that case). If there's no peer address,
|
||||
try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set.
|
||||
* if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl
|
||||
without bothering to check the IFF_POINTOPOINT flag. And if
|
||||
no peer address was found, just try the SIOCGLIFBRDADDR ioctl
|
||||
without checking the IFF_BROADCAST flag. Call connected_add_ipv4
|
||||
and connected_add_ipv6 with appropriate flags.
|
||||
* if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to
|
||||
connected_add_ipv6.
|
||||
* kernel_socket.c: (ifam_read) Must pass new flags argument to
|
||||
connected_add_ipv6.
|
||||
* rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2
|
||||
to determine local and possible peer address (so there's no longer
|
||||
a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately.
|
||||
Pass new flags argument to connected_add_ipv6.
|
||||
(netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast
|
||||
to determine whether the connected destination address is a
|
||||
broadcast address.
|
||||
|
||||
2006-12-08 Piotr Chytla <pch@packetconsulting.pl>
|
||||
|
||||
* zebra_rib.c: (static_install_ipv{4,6}) Case where existing
|
||||
|
@ -173,24 +173,11 @@ void
|
||||
connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix_ipv4 *addr;
|
||||
struct prefix_ipv4 *dest;
|
||||
|
||||
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
|
||||
return;
|
||||
|
||||
addr = (struct prefix_ipv4 *) ifc->address;
|
||||
dest = (struct prefix_ipv4 *) ifc->destination;
|
||||
|
||||
memset (&p, 0, sizeof (struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
/* Point-to-point check. */
|
||||
if (CONNECTED_POINTOPOINT_HOST(ifc))
|
||||
p.prefix = dest->prefix;
|
||||
else
|
||||
p.prefix = addr->prefix;
|
||||
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
||||
|
||||
/* Apply mask to the network. */
|
||||
apply_mask_ipv4 (&p);
|
||||
@ -227,33 +214,22 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
|
||||
p->prefixlen = prefixlen;
|
||||
ifc->address = (struct prefix *) p;
|
||||
|
||||
/* If there is broadcast or pointopoint address. */
|
||||
/* If there is broadcast or peer address. */
|
||||
if (broad)
|
||||
{
|
||||
p = prefix_ipv4_new ();
|
||||
p->family = AF_INET;
|
||||
p->prefix = *broad;
|
||||
p->prefixlen = prefixlen;
|
||||
ifc->destination = (struct prefix *) p;
|
||||
|
||||
/* validate the destination address */
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
if (CONNECTED_PEER(ifc))
|
||||
{
|
||||
if (IPV4_ADDR_SAME(addr,broad))
|
||||
zlog_warn("warning: PtP interface %s has same local and peer "
|
||||
zlog_warn("warning: interface %s has same local and peer "
|
||||
"address %s, routing protocols may malfunction",
|
||||
ifp->name,inet_ntoa(*addr));
|
||||
else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
|
||||
(ipv4_network_addr(addr->s_addr,prefixlen) !=
|
||||
ipv4_network_addr(broad->s_addr,prefixlen)))
|
||||
{
|
||||
char buf[2][INET_ADDRSTRLEN];
|
||||
zlog_warn("warning: PtP interface %s network mismatch: local "
|
||||
"%s/%d vs. peer %s, routing protocols may malfunction",
|
||||
ifp->name,
|
||||
inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
|
||||
prefixlen,
|
||||
inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -273,10 +249,20 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
|
||||
{
|
||||
zlog_warn("warning: %s called for interface %s "
|
||||
"with peer flag set, but no peer address supplied",
|
||||
__func__, ifp->name);
|
||||
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
|
||||
}
|
||||
|
||||
/* no broadcast or destination address was supplied */
|
||||
if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
|
||||
zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
|
||||
"peer address",ifp->name,inet_ntoa(*addr),prefixlen);
|
||||
}
|
||||
|
||||
/* Label of this address. */
|
||||
if (label)
|
||||
@ -293,24 +279,11 @@ void
|
||||
connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
|
||||
{
|
||||
struct prefix_ipv4 p;
|
||||
struct prefix_ipv4 *addr;
|
||||
struct prefix_ipv4 *dest;
|
||||
|
||||
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
|
||||
return;
|
||||
|
||||
addr = (struct prefix_ipv4 *)ifc->address;
|
||||
dest = (struct prefix_ipv4 *)ifc->destination;
|
||||
|
||||
memset (&p, 0, sizeof (struct prefix_ipv4));
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
/* Point-to-point check. */
|
||||
if (CONNECTED_POINTOPOINT_HOST(ifc))
|
||||
p.prefix = dest->prefix;
|
||||
else
|
||||
p.prefix = addr->prefix;
|
||||
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
||||
|
||||
/* Apply mask to the network. */
|
||||
apply_mask_ipv4 (&p);
|
||||
@ -350,28 +323,11 @@ void
|
||||
connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
|
||||
{
|
||||
struct prefix_ipv6 p;
|
||||
struct prefix_ipv6 *addr;
|
||||
struct prefix_ipv6 *dest;
|
||||
|
||||
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
|
||||
return;
|
||||
|
||||
addr = (struct prefix_ipv6 *) ifc->address;
|
||||
dest = (struct prefix_ipv6 *) ifc->destination;
|
||||
|
||||
memset (&p, 0, sizeof (struct prefix_ipv6));
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (if_is_pointopoint (ifp) && dest)
|
||||
{
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
|
||||
p.prefix = addr->prefix;
|
||||
else
|
||||
p.prefix = dest->prefix;
|
||||
}
|
||||
else
|
||||
p.prefix = addr->prefix;
|
||||
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
||||
|
||||
/* Apply mask to the network. */
|
||||
apply_mask_ipv6 (&p);
|
||||
@ -390,7 +346,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
|
||||
|
||||
/* Add connected IPv6 route to the interface. */
|
||||
void
|
||||
connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
|
||||
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
|
||||
u_char prefixlen, struct in6_addr *broad,
|
||||
const char *label)
|
||||
{
|
||||
@ -400,6 +356,7 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
|
||||
/* Make connected structure. */
|
||||
ifc = connected_new ();
|
||||
ifc->ifp = ifp;
|
||||
ifc->flags = flags;
|
||||
|
||||
/* Allocate new connected address. */
|
||||
p = prefix_ipv6_new ();
|
||||
@ -408,14 +365,28 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
|
||||
p->prefixlen = prefixlen;
|
||||
ifc->address = (struct prefix *) p;
|
||||
|
||||
/* If there is broadcast or pointopoint address. */
|
||||
/* If there is broadcast or peer address. */
|
||||
if (broad)
|
||||
{
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(broad))
|
||||
zlog_warn("warning: %s called for interface %s with unspecified "
|
||||
"destination address; ignoring!", __func__, ifp->name);
|
||||
else
|
||||
{
|
||||
p = prefix_ipv6_new ();
|
||||
p->family = AF_INET6;
|
||||
IPV6_ADDR_COPY (&p->prefix, broad);
|
||||
p->prefixlen = prefixlen;
|
||||
ifc->destination = (struct prefix *) p;
|
||||
}
|
||||
}
|
||||
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
|
||||
{
|
||||
zlog_warn("warning: %s called for interface %s "
|
||||
"with peer flag set, but no peer address supplied",
|
||||
__func__, ifp->name);
|
||||
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
|
||||
}
|
||||
|
||||
/* Label of this address. */
|
||||
if (label)
|
||||
@ -431,28 +402,11 @@ void
|
||||
connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
|
||||
{
|
||||
struct prefix_ipv6 p;
|
||||
struct prefix_ipv6 *addr;
|
||||
struct prefix_ipv6 *dest;
|
||||
|
||||
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
|
||||
return;
|
||||
|
||||
addr = (struct prefix_ipv6 *) ifc->address;
|
||||
dest = (struct prefix_ipv6 *) ifc->destination;
|
||||
|
||||
memset (&p, 0, sizeof (struct prefix_ipv6));
|
||||
p.family = AF_INET6;
|
||||
p.prefixlen = addr->prefixlen;
|
||||
|
||||
if (if_is_pointopoint (ifp) && dest)
|
||||
{
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix))
|
||||
p.prefix = addr->prefix;
|
||||
else
|
||||
p.prefix = dest->prefix;
|
||||
}
|
||||
else
|
||||
p.prefix = addr->prefix;
|
||||
PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
|
||||
|
||||
apply_mask_ipv6 (&p);
|
||||
|
||||
|
@ -40,7 +40,7 @@ extern void connected_down_ipv4 (struct interface *, struct connected *);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
extern void
|
||||
connected_add_ipv6 (struct interface *ifp, struct in6_addr *address,
|
||||
connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address,
|
||||
u_char prefixlen, struct in6_addr *broad,
|
||||
const char *label);
|
||||
extern void
|
||||
|
@ -249,6 +249,7 @@ if_getaddrs (void)
|
||||
struct sockaddr_in *mask;
|
||||
struct sockaddr_in *dest;
|
||||
struct in_addr *dest_pnt;
|
||||
int flags = 0;
|
||||
|
||||
addr = (struct sockaddr_in *) ifap->ifa_addr;
|
||||
mask = (struct sockaddr_in *) ifap->ifa_netmask;
|
||||
@ -256,19 +257,25 @@ if_getaddrs (void)
|
||||
|
||||
dest_pnt = NULL;
|
||||
|
||||
if (ifap->ifa_flags & IFF_POINTOPOINT)
|
||||
if (ifap->ifa_dstaddr &&
|
||||
!IPV4_ADDR_SAME(&addr->sin_addr,
|
||||
&((struct sockaddr_in *)
|
||||
ifap->ifa_dstaddr)->sin_addr))
|
||||
{
|
||||
dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
|
||||
dest_pnt = &dest->sin_addr;
|
||||
flags = ZEBRA_IFA_PEER;
|
||||
}
|
||||
|
||||
if (ifap->ifa_flags & IFF_BROADCAST)
|
||||
else if (ifap->ifa_broadaddr &&
|
||||
!IPV4_ADDR_SAME(&addr->sin_addr,
|
||||
&((struct sockaddr_in *)
|
||||
ifap->ifa_broadaddr)->sin_addr))
|
||||
{
|
||||
dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
|
||||
dest_pnt = &dest->sin_addr;
|
||||
}
|
||||
|
||||
connected_add_ipv4 (ifp, 0, &addr->sin_addr,
|
||||
connected_add_ipv4 (ifp, flags, &addr->sin_addr,
|
||||
prefixlen, dest_pnt, NULL);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
@ -278,6 +285,7 @@ if_getaddrs (void)
|
||||
struct sockaddr_in6 *mask;
|
||||
struct sockaddr_in6 *dest;
|
||||
struct in6_addr *dest_pnt;
|
||||
int flags = 0;
|
||||
|
||||
addr = (struct sockaddr_in6 *) ifap->ifa_addr;
|
||||
mask = (struct sockaddr_in6 *) ifap->ifa_netmask;
|
||||
@ -285,23 +293,23 @@ if_getaddrs (void)
|
||||
|
||||
dest_pnt = NULL;
|
||||
|
||||
if (ifap->ifa_flags & IFF_POINTOPOINT)
|
||||
{
|
||||
if (ifap->ifa_dstaddr)
|
||||
if (ifap->ifa_dstaddr &&
|
||||
!IPV6_ADDR_SAME(&addr->sin6_addr,
|
||||
&((struct sockaddr_in6 *)
|
||||
ifap->ifa_dstaddr)->sin6_addr))
|
||||
{
|
||||
dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
|
||||
dest_pnt = &dest->sin6_addr;
|
||||
flags = ZEBRA_IFA_PEER;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifap->ifa_flags & IFF_BROADCAST)
|
||||
{
|
||||
if (ifap->ifa_broadaddr)
|
||||
else if (ifap->ifa_broadaddr &&
|
||||
!IPV6_ADDR_SAME(&addr->sin6_addr,
|
||||
&((struct sockaddr_in6 *)
|
||||
ifap->ifa_broadaddr)->sin6_addr))
|
||||
{
|
||||
dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
|
||||
dest_pnt = &dest->sin6_addr;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(KAME)
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr))
|
||||
@ -312,7 +320,7 @@ if_getaddrs (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen,
|
||||
connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen,
|
||||
dest_pnt, NULL);
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
@ -335,6 +343,7 @@ if_get_addr (struct interface *ifp)
|
||||
struct sockaddr_in dest;
|
||||
struct in_addr *dest_pnt;
|
||||
u_char prefixlen;
|
||||
int flags = 0;
|
||||
|
||||
/* Interface's name and address family. */
|
||||
strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
|
||||
@ -374,40 +383,36 @@ if_get_addr (struct interface *ifp)
|
||||
/* Point to point or borad cast address pointer init. */
|
||||
dest_pnt = NULL;
|
||||
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
{
|
||||
ret = if_ioctl (SIOCGIFDSTADDR, (caddr_t) &ifreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
{
|
||||
zlog_warn ("SIOCGIFDSTADDR fail: %s", safe_strerror (errno));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_dstaddr.sin_addr))
|
||||
{
|
||||
memcpy (&dest, &ifreq.ifr_dstaddr, sizeof (struct sockaddr_in));
|
||||
dest_pnt = &dest.sin_addr;
|
||||
flags = ZEBRA_IFA_PEER;
|
||||
}
|
||||
if (ifp->flags & IFF_BROADCAST)
|
||||
if (!dest_pnt)
|
||||
{
|
||||
ret = if_ioctl (SIOCGIFBRDADDR, (caddr_t) &ifreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
{
|
||||
zlog_warn ("SIOCGIFBRDADDR fail: %s", safe_strerror (errno));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_broadaddr.sin_addr))
|
||||
{
|
||||
memcpy (&dest, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
|
||||
dest_pnt = &dest.sin_addr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set address to the interface. */
|
||||
connected_add_ipv4 (ifp, 0, &addr.sin_addr, prefixlen, dest_pnt, NULL);
|
||||
connected_add_ipv4 (ifp, flags, &addr.sin_addr, prefixlen, dest_pnt, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -258,6 +258,7 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
|
||||
char *dest_pnt = NULL;
|
||||
u_char prefixlen = 0;
|
||||
afi_t af;
|
||||
int flags = 0;
|
||||
|
||||
/* Interface's name and address family.
|
||||
* We need to use the logical interface name / label, if we've been
|
||||
@ -272,21 +273,14 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
|
||||
/* Point to point or broad cast address pointer init. */
|
||||
dest_pnt = NULL;
|
||||
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
if (AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq) >= 0)
|
||||
{
|
||||
ret = AF_IOCTL (af, SIOCGLIFDSTADDR, (caddr_t) & lifreq);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
zlog_warn ("SIOCGLIFDSTADDR (%s) fail: %s",
|
||||
ifp->name, safe_strerror (errno));
|
||||
return ret;
|
||||
}
|
||||
memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr));
|
||||
if (af == AF_INET)
|
||||
dest_pnt = (char *) &(SIN (&dest)->sin_addr);
|
||||
else
|
||||
dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr);
|
||||
flags = ZEBRA_IFA_PEER;
|
||||
}
|
||||
|
||||
if (af == AF_INET)
|
||||
@ -306,19 +300,8 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
|
||||
memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr));
|
||||
|
||||
prefixlen = ip_masklen (SIN (&mask)->sin_addr);
|
||||
if (ifp->flags & IFF_BROADCAST)
|
||||
if (!dest_pnt && (if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq) >= 0))
|
||||
{
|
||||
ret = if_ioctl (SIOCGLIFBRDADDR, (caddr_t) & lifreq);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (errno != EADDRNOTAVAIL)
|
||||
{
|
||||
zlog_warn ("SIOCGLIFBRDADDR (%s) fail: %s",
|
||||
ifp->name, safe_strerror (errno));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in));
|
||||
dest_pnt = (char *) &SIN (&dest)->sin_addr;
|
||||
}
|
||||
@ -348,11 +331,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
|
||||
|
||||
/* Set address to the interface. */
|
||||
if (af == AF_INET)
|
||||
connected_add_ipv4 (ifp, 0, &SIN (addr)->sin_addr, prefixlen,
|
||||
connected_add_ipv4 (ifp, flags, &SIN (addr)->sin_addr, prefixlen,
|
||||
(struct in_addr *) dest_pnt, label);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (af == AF_INET6)
|
||||
connected_add_ipv6 (ifp, &SIN6 (addr)->sin6_addr, prefixlen,
|
||||
connected_add_ipv6 (ifp, flags, &SIN6 (addr)->sin6_addr, prefixlen,
|
||||
(struct in6_addr *) dest_pnt, label);
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
|
@ -240,7 +240,7 @@ ifaddr_proc_ipv6 ()
|
||||
str2in6_addr (addr, &p.prefix);
|
||||
p.prefixlen = plen;
|
||||
|
||||
connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL, ifname);
|
||||
connected_add_ipv6 (ifp, 0, &p.prefix, p.prefixlen, NULL, ifname);
|
||||
}
|
||||
fclose (fp);
|
||||
return 0;
|
||||
|
@ -564,10 +564,6 @@ static void
|
||||
connected_dump_vty (struct vty *vty, struct connected *connected)
|
||||
{
|
||||
struct prefix *p;
|
||||
struct interface *ifp;
|
||||
|
||||
/* Set interface pointer. */
|
||||
ifp = connected->ifp;
|
||||
|
||||
/* Print interface address. */
|
||||
p = connected->address;
|
||||
@ -576,21 +572,10 @@ connected_dump_vty (struct vty *vty, struct connected *connected)
|
||||
vty_out (vty, "/%d", p->prefixlen);
|
||||
|
||||
/* If there is destination address, print it. */
|
||||
p = connected->destination;
|
||||
if (p)
|
||||
if (connected->destination)
|
||||
{
|
||||
if (p->family == AF_INET)
|
||||
if (ifp->flags & IFF_BROADCAST)
|
||||
{
|
||||
vty_out (vty, " broadcast ");
|
||||
prefix_vty_out (vty, p);
|
||||
}
|
||||
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
{
|
||||
vty_out (vty, " pointopoint ");
|
||||
prefix_vty_out (vty, p);
|
||||
}
|
||||
vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
|
||||
prefix_vty_out (vty, connected->destination);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))
|
||||
|
@ -609,7 +609,7 @@ ifam_read (struct ifa_msghdr *ifam)
|
||||
SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
|
||||
|
||||
if (ifam->ifam_type == RTM_NEWADDR)
|
||||
connected_add_ipv6 (ifp,
|
||||
connected_add_ipv6 (ifp, 0,
|
||||
&addr.sin6.sin6_addr,
|
||||
ip6_masklen (mask.sin6.sin6_addr),
|
||||
&brd.sin6.sin6_addr,
|
||||
|
@ -577,8 +577,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
struct ifaddrmsg *ifa;
|
||||
struct rtattr *tb[IFA_MAX + 1];
|
||||
struct interface *ifp;
|
||||
void *addr = NULL;
|
||||
void *broad = NULL;
|
||||
void *addr;
|
||||
void *broad;
|
||||
u_char flags = 0;
|
||||
char *label = NULL;
|
||||
|
||||
@ -637,41 +637,29 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
}
|
||||
}
|
||||
|
||||
/* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
|
||||
if (tb[IFA_LOCAL] == NULL)
|
||||
tb[IFA_LOCAL] = tb[IFA_ADDRESS];
|
||||
if (tb[IFA_ADDRESS] == NULL)
|
||||
tb[IFA_ADDRESS] = tb[IFA_LOCAL];
|
||||
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
{
|
||||
if (tb[IFA_LOCAL])
|
||||
{
|
||||
addr = RTA_DATA (tb[IFA_LOCAL]);
|
||||
if (tb[IFA_ADDRESS] &&
|
||||
memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4))
|
||||
/* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */
|
||||
broad = RTA_DATA (tb[IFA_ADDRESS]);
|
||||
else
|
||||
broad = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tb[IFA_ADDRESS])
|
||||
addr = RTA_DATA (tb[IFA_ADDRESS]);
|
||||
else
|
||||
addr = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tb[IFA_ADDRESS])
|
||||
addr = RTA_DATA (tb[IFA_ADDRESS]);
|
||||
else
|
||||
addr = NULL;
|
||||
/* local interface address */
|
||||
addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);
|
||||
|
||||
if (tb[IFA_BROADCAST])
|
||||
broad = RTA_DATA(tb[IFA_BROADCAST]);
|
||||
else
|
||||
broad = NULL;
|
||||
/* is there a peer address? */
|
||||
/* N.B. I do not understand why the memcmp compares 4 bytes regardless
|
||||
of address family, but this is exactly how it appears in
|
||||
print_addrinfo. I wonder if it should be RTA_PAYLOAD(tb[IFA_ADDRESS])
|
||||
instead of 4... */
|
||||
if (tb[IFA_ADDRESS] &&
|
||||
memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), 4))
|
||||
{
|
||||
broad = RTA_DATA(tb[IFA_ADDRESS]);
|
||||
SET_FLAG (flags, ZEBRA_IFA_PEER);
|
||||
}
|
||||
else
|
||||
/* seeking a broadcast address */
|
||||
broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
|
||||
|
||||
/* addr is primary key, SOL if we don't have one */
|
||||
if (addr == NULL)
|
||||
@ -707,7 +695,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
|
||||
if (ifa->ifa_family == AF_INET6)
|
||||
{
|
||||
if (h->nlmsg_type == RTM_NEWADDR)
|
||||
connected_add_ipv6 (ifp,
|
||||
connected_add_ipv6 (ifp, flags,
|
||||
(struct in6_addr *) addr, ifa->ifa_prefixlen,
|
||||
(struct in6_addr *) broad, label);
|
||||
else
|
||||
@ -1849,7 +1837,7 @@ netlink_address (int cmd, int family, struct interface *ifp,
|
||||
|
||||
if (family == AF_INET && cmd == RTM_NEWADDR)
|
||||
{
|
||||
if (if_is_broadcast (ifp) && ifc->destination)
|
||||
if (!CONNECTED_PEER(ifc) && ifc->destination)
|
||||
{
|
||||
p = ifc->destination;
|
||||
addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
|
||||
|
Loading…
Reference in New Issue
Block a user