[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:
Andrew J. Schorr 2006-12-12 19:18:21 +00:00
parent 43cd33a44e
commit e4529636b7
25 changed files with 338 additions and 393 deletions

View File

@ -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> 2006-12-07 Paul Jakma <paul.jakma@sun.com>
* bgp_fsm.c: Bug #302 fix, diagnosis, suggestions and testing * bgp_fsm.c: Bug #302 fix, diagnosis, suggestions and testing

View File

@ -543,7 +543,6 @@ bgp_connected_add (struct connected *ifc)
{ {
struct prefix p; struct prefix p;
struct prefix *addr; struct prefix *addr;
struct prefix *dest;
struct interface *ifp; struct interface *ifp;
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_connected_ref *bc; struct bgp_connected_ref *bc;
@ -557,19 +556,10 @@ bgp_connected_add (struct connected *ifc)
return; return;
addr = ifc->address; addr = ifc->address;
dest = ifc->destination;
if (addr->family == AF_INET) if (addr->family == AF_INET)
{ {
memset (&p, 0, sizeof (struct prefix)); PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
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;
apply_mask_ipv4 ((struct prefix_ipv4 *) &p); apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
if (prefix_ipv4_any ((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 #ifdef HAVE_IPV6
if (addr->family == AF_INET6) else if (addr->family == AF_INET6)
{ {
memset (&p, 0, sizeof (struct prefix)); PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
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;
apply_mask_ipv6 ((struct prefix_ipv6 *) &p); apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@ -631,7 +613,6 @@ bgp_connected_delete (struct connected *ifc)
{ {
struct prefix p; struct prefix p;
struct prefix *addr; struct prefix *addr;
struct prefix *dest;
struct interface *ifp; struct interface *ifp;
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_connected_ref *bc; struct bgp_connected_ref *bc;
@ -642,19 +623,10 @@ bgp_connected_delete (struct connected *ifc)
return; return;
addr = ifc->address; addr = ifc->address;
dest = ifc->destination;
if (addr->family == AF_INET) if (addr->family == AF_INET)
{ {
memset (&p, 0, sizeof (struct prefix)); PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
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;
apply_mask_ipv4 ((struct prefix_ipv4 *) &p); apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
if (prefix_ipv4_any ((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 #ifdef HAVE_IPV6
else if (addr->family == AF_INET6) else if (addr->family == AF_INET6)
{ {
memset (&p, 0, sizeof (struct prefix)); PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
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;
apply_mask_ipv6 ((struct prefix_ipv6 *) &p); apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6)) if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))

View File

@ -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> 2006-10-14 Paul Jakma <paul.jakma@sun.com>
* if.c: (general) Handle upgrades from SUNWzebra, which tried * if.c: (general) Handle upgrades from SUNWzebra, which tried

View File

@ -275,7 +275,6 @@ if_lookup_address (struct in_addr src)
int bestlen = 0; int bestlen = 0;
struct listnode *cnode; struct listnode *cnode;
struct interface *ifp; struct interface *ifp;
struct prefix *p;
struct connected *c; struct connected *c;
struct interface *match; struct interface *match;
@ -289,25 +288,12 @@ if_lookup_address (struct in_addr src)
{ {
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 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)) bestlen = c->address->prefixlen;
{ match = ifp;
/* 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;
match = ifp;
}
}
} }
} }
} }
@ -728,7 +714,6 @@ connected_lookup_address (struct interface *ifp, struct in_addr dst)
{ {
struct prefix addr; struct prefix addr;
struct listnode *cnode; struct listnode *cnode;
struct prefix *p;
struct connected *c; struct connected *c;
struct connected *match; struct connected *match;
@ -740,24 +725,10 @@ connected_lookup_address (struct interface *ifp, struct in_addr dst)
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 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) &&
if (CONNECTED_POINTOPOINT_HOST(c)) (!match || (c->address->prefixlen > match->address->prefixlen)))
{ match = 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)))
match = c;
}
}
} }
return match; return match;
} }

View File

@ -154,26 +154,38 @@ struct connected
/* Flags for connected address. */ /* Flags for connected address. */
u_char flags; u_char flags;
#define ZEBRA_IFA_SECONDARY (1 << 0) #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. */ /* Address of connected network. */
struct prefix *address; 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. */ /* Label for Linux 2.2.X and upper. */
char *label; char *label;
}; };
/* Given an IPV4 struct connected, this macro determines whether a /32 /* Does the destination field contain a peer address? */
peer address has been supplied (i.e. there is no subnet assigned) */ #define CONNECTED_PEER(C) CHECK_FLAG((C)->flags, ZEBRA_IFA_PEER)
#define CONNECTED_DEST_HOST(C) \
((C)->destination && ((C)->address->prefixlen == IPV4_MAX_PREFIXLEN))
/* Given an IPV4 struct connected, this macro determins whether it is /* Prefix to insert into the RIB */
a point-to-point link with a /32 peer address (i.e. there #define CONNECTED_PREFIX(C) \
is no dedicated subnet for the PtP link) */ (CONNECTED_PEER(C) ? (C)->destination : (C)->address)
#define CONNECTED_POINTOPOINT_HOST(C) \
(((C)->ifp->flags & IFF_POINTOPOINT) && CONNECTED_DEST_HOST(C)) /* 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. */ /* Interface hook sort. */
#define IF_NEW_HOOK 0 #define IF_NEW_HOOK 0

View File

@ -151,6 +151,9 @@ extern void prefix_ipv4_free (struct prefix_ipv4 *);
extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *); extern int str2prefix_ipv4 (const char *, struct prefix_ipv4 *);
extern void apply_mask_ipv4 (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 int prefix_ipv4_any (const struct prefix_ipv4 *);
extern void apply_classful_mask_ipv4 (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 int str2prefix_ipv6 (const char *, struct prefix_ipv6 *);
extern void apply_mask_ipv6 (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 int ip6_masklen (struct in6_addr);
extern void masklen2ip6 (int, struct in6_addr *); extern void masklen2ip6 (int, struct in6_addr *);

View File

@ -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) ? ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
NULL : &d)); NULL : &d));
if (ifc != NULL) if (ifc != NULL)
ifc->flags = ifc_flags; {
ifc->flags = ifc_flags;
if (ifc->destination)
ifc->destination->prefixlen = ifc->address->prefixlen;
}
} }
else else
{ {

View File

@ -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> 2006-12-04 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospfd.c: (ospf_network_run) Remove an offending 'break' statement. * ospfd.c: (ospf_network_run) Remove an offending 'break' statement.

View File

@ -354,28 +354,18 @@ ospf_if_is_configured (struct ospf *ospf, struct in_addr *address)
addr.family = AF_INET; addr.family = AF_INET;
addr.prefix = *address; addr.prefix = *address;
addr.prefixlen = IPV4_MAX_PREFIXLEN; addr.prefixlen = IPV4_MAX_PREFIXLEN;
for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi)) for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
if (oi->type != OSPF_IFTYPE_VIRTUALLINK) if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
{ {
if (oi->type == OSPF_IFTYPE_POINTOPOINT) if (oi->type == OSPF_IFTYPE_POINTOPOINT)
{ {
if (CONNECTED_DEST_HOST(oi->connected)) /* special leniency: match if addr is anywhere on peer subnet */
{ if (prefix_match(CONNECTED_PREFIX(oi->connected),
/* match only destination addr, since local addr is most likely (struct prefix *)&addr))
* not unique (borrowed from another interface) */ return oi;
if (IPV4_ADDR_SAME (address,
&oi->connected->destination->u.prefix4))
return oi;
}
else
{
/* special leniency: match if addr is anywhere on PtP subnet */
if (prefix_match(oi->address,(struct prefix *)&addr))
return oi;
}
} }
else else
{ {
if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4)) if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
return oi; return oi;
@ -432,22 +422,15 @@ ospf_if_lookup_by_prefix (struct ospf *ospf, struct prefix_ipv4 *p)
{ {
struct listnode *node; struct listnode *node;
struct ospf_interface *oi; struct ospf_interface *oi;
struct prefix ptmp;
/* Check each Interface. */ /* Check each Interface. */
for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi)) for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
{ {
if (oi->type != OSPF_IFTYPE_VIRTUALLINK) if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
{ {
if ((oi->type == OSPF_IFTYPE_POINTOPOINT) && struct prefix ptmp;
CONNECTED_DEST_HOST(oi->connected))
{ prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
prefix_copy (&ptmp, oi->connected->destination);
ptmp.prefixlen = IPV4_MAX_BITLEN;
}
else
prefix_copy (&ptmp, oi->address);
apply_mask (&ptmp); apply_mask (&ptmp);
if (prefix_same (&ptmp, (struct prefix *) p)) if (prefix_same (&ptmp, (struct prefix *) p))
return oi; return oi;
@ -477,22 +460,14 @@ ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src)
if (if_is_loopback (oi->ifp)) if (if_is_loopback (oi->ifp))
continue; continue;
if ((oi->type == OSPF_IFTYPE_POINTOPOINT) && if (prefix_match (CONNECTED_PREFIX(oi->connected),
CONNECTED_DEST_HOST(oi->connected)) (struct prefix *) &addr))
{ {
if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src)) if ( (match == NULL) ||
return oi; (match->address->prefixlen < oi->address->prefixlen)
} )
else match = oi;
{
if (prefix_match (oi->address, (struct prefix *) &addr))
{
if ( (match == NULL) ||
(match->address->prefixlen < oi->address->prefixlen)
)
match = oi;
}
} }
} }

View File

@ -543,7 +543,7 @@ link_info_set (struct stream *s, struct in_addr id,
return 1; return 1;
} }
/* Describe Point-to-Point link. */ /* Describe Point-to-Point link (Section 12.4.1.1). */
static int static int
lsa_link_ptop_set (struct stream *s, struct ospf_interface *oi) 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); LSA_LINK_TYPE_POINTOPOINT, 0, cost);
} }
if (CONNECTED_DEST_HOST(oi->connected)) /* Regardless of the state of the neighboring router, we must
{ add a Type 3 link (stub network).
/* Option 1: N.B. Options 1 & 2 share basically the same logic. */
link_type = LSA_LINK_TYPE_STUB; masklen2ip (oi->address->prefixlen, &mask);
link_id = nbr->address.u.prefix4; id.s_addr = CONNECTED_PREFIX(oi->connected)->u.prefix4.s_addr & mask.s_addr;
link_data.s_addr = 0xffffffff; links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
link_cost = o->output_cost; */ oi->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 */
masklen2ip (oi->address->prefixlen, &mask);
id.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
links += link_info_set (s, id, mask, LSA_LINK_TYPE_STUB, 0,
oi->output_cost);
}
return links; return links;
} }

View File

@ -1439,10 +1439,7 @@ ospf_snmp_if_update (struct interface *ifp)
/* Lookup first IPv4 address entry. */ /* Lookup first IPv4 address entry. */
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
{ {
if (CONNECTED_POINTOPOINT_HOST(ifc)) p = CONNECTED_ID(ifc);
p = ifc->destination;
else
p = ifc->address;
if (p->family == AF_INET) if (p->family == AF_INET)
{ {
@ -1492,19 +1489,13 @@ ospf_snmp_if_update (struct interface *ifp)
int int
ospf_snmp_is_if_have_addr (struct interface *ifp) ospf_snmp_is_if_have_addr (struct interface *ifp)
{ {
struct prefix *p;
struct listnode *nn; struct listnode *nn;
struct connected *ifc; struct connected *ifc;
/* Is this interface having any connected IPv4 address ? */ /* Is this interface having any connected IPv4 address ? */
for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc)) for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, ifc))
{ {
if (if_is_pointopoint (ifp)) if (CONNECTED_PREFIX(ifc)->family == AF_INET)
p = ifc->destination;
else
p = ifc->address;
if (p->family == AF_INET)
return 1; return 1;
} }

View File

@ -2865,8 +2865,8 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf,
struct in_addr *dest; struct in_addr *dest;
const char *dstr; const char *dstr;
if ((ifp->flags & IFF_POINTOPOINT) if (CONNECTED_PEER(oi->connected)
|| oi->type == OSPF_IFTYPE_VIRTUALLINK) || oi->type == OSPF_IFTYPE_VIRTUALLINK)
dstr = "Peer"; dstr = "Peer";
else else
dstr = "Broadcast"; dstr = "Broadcast";

View File

@ -795,6 +795,23 @@ ospf_network_unset (struct ospf *ospf, struct prefix_ipv4 *p,
int int
ospf_network_match_iface(struct connected *co, struct prefix *net) 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: /* Behaviour to match both Cisco where:
* iface address lies within network specified -> ospf * iface address lies within network specified -> ospf
* and zebra 0.9[2ish-3]: * 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 * exactly; this is not a test for falling within the prefix. This
* test is solely for compatibility with zebra. * 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))) IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
return 1; return 1;
@ -826,6 +843,8 @@ ospf_network_match_iface(struct connected *co, struct prefix *net)
return 1; return 1;
return 0; /* no match */ return 0; /* no match */
#endif /* COMPATIBILITY_MODE */
} }
void 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)) if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
continue; continue;
if (CONNECTED_POINTOPOINT_HOST(co)) addr = CONNECTED_ID(co);
addr = co->destination;
else
addr = co->address;
if (p->family == co->address->family if (p->family == co->address->family
&& ! ospf_if_is_configured (ospf, &(addr->u.prefix4)) && ! ospf_if_is_configured (ospf, &(addr->u.prefix4))

View File

@ -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> 2006-09-11 Paul Jakma <paul.jakma@sun.com>
* ripd.c: (rip_read) remove gratuitous use of mid-function * ripd.c: (rip_read) remove gratuitous use of mid-function

View File

@ -141,16 +141,10 @@ void
rip_interface_multicast_set (int sock, struct connected *connected) rip_interface_multicast_set (int sock, struct connected *connected)
{ {
struct in_addr addr; struct in_addr addr;
struct prefix_ipv4 *p;
assert (connected != NULL); assert (connected != NULL);
if (if_is_pointopoint(connected->ifp) && CONNECTED_DEST_HOST(connected)) addr = CONNECTED_ID(connected)->u.prefix4;
p = (struct prefix_ipv4 *) connected->destination;
else
p = (struct prefix_ipv4 *) connected->address;
addr = p->prefix;
if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0,
connected->ifp->ifindex) < 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)); memset (&to, 0, sizeof (struct sockaddr_in));
to.sin_port = htons (RIP_PORT_DEFAULT); to.sin_port = htons (RIP_PORT_DEFAULT);
if (connected->destination) 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; to.sin_addr = connected->destination->u.prefix4;
else else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN)
/* calculate the appropriate broadcast address */ /* calculate the appropriate broadcast address */
to.sin_addr.s_addr = to.sin_addr.s_addr =
ipv4_broadcast_addr(connected->address->u.prefix4.s_addr, ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
connected->address->prefixlen); connected->address->prefixlen);
else
/* do not know where to send the packet */
continue;
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr)); zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr));

View File

@ -2449,19 +2449,22 @@ rip_update_interface (struct connected *ifc, u_char version, int route_type)
/* Destination address and port setting. */ /* Destination address and port setting. */
memset (&to, 0, sizeof (struct sockaddr_in)); memset (&to, 0, sizeof (struct sockaddr_in));
if (ifc->destination) 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; to.sin_addr = ifc->destination->u.prefix4;
else else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
/* calculate the appropriate broadcast address */ /* calculate the appropriate broadcast address */
to.sin_addr.s_addr = to.sin_addr.s_addr =
ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr, ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
ifc->address->prefixlen); ifc->address->prefixlen);
else
/* do not know where to send the packet */
return;
to.sin_port = htons (RIP_PORT_DEFAULT); to.sin_port = htons (RIP_PORT_DEFAULT);
if (IS_RIP_DEBUG_EVENT) if (IS_RIP_DEBUG_EVENT)
zlog_debug ("%s announce to %s on %s", zlog_debug("%s announce to %s on %s",
if_is_pointopoint (ifc->ifp) ? "unicast" : "broadcast", CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
inet_ntoa (to.sin_addr), ifc->ifp->name); inet_ntoa (to.sin_addr), ifc->ifp->name);
rip_output_process (ifc, &to, route_type, version); rip_output_process (ifc, &to, route_type, version);
} }

View File

@ -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> 2006-12-08 Piotr Chytla <pch@packetconsulting.pl>
* zebra_rib.c: (static_install_ipv{4,6}) Case where existing * zebra_rib.c: (static_install_ipv{4,6}) Case where existing

View File

@ -173,24 +173,11 @@ void
connected_up_ipv4 (struct interface *ifp, struct connected *ifc) connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
{ {
struct prefix_ipv4 p; struct prefix_ipv4 p;
struct prefix_ipv4 *addr;
struct prefix_ipv4 *dest;
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
return; return;
addr = (struct prefix_ipv4 *) ifc->address; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
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;
/* Apply mask to the network. */ /* Apply mask to the network. */
apply_mask_ipv4 (&p); apply_mask_ipv4 (&p);
@ -227,33 +214,22 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
p->prefixlen = prefixlen; p->prefixlen = prefixlen;
ifc->address = (struct prefix *) p; ifc->address = (struct prefix *) p;
/* If there is broadcast or pointopoint address. */ /* If there is broadcast or peer address. */
if (broad) if (broad)
{ {
p = prefix_ipv4_new (); p = prefix_ipv4_new ();
p->family = AF_INET; p->family = AF_INET;
p->prefix = *broad; p->prefix = *broad;
p->prefixlen = prefixlen;
ifc->destination = (struct prefix *) p; ifc->destination = (struct prefix *) p;
/* validate the destination address */ /* validate the destination address */
if (ifp->flags & IFF_POINTOPOINT) if (CONNECTED_PEER(ifc))
{ {
if (IPV4_ADDR_SAME(addr,broad)) 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", "address %s, routing protocols may malfunction",
ifp->name,inet_ntoa(*addr)); 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 else
{ {
@ -273,10 +249,20 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
} }
else else
/* no broadcast or destination address was supplied */ {
if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp)) if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
zlog_warn("warning: PtP interface %s with addr %s/%d needs a " {
"peer address",ifp->name,inet_ntoa(*addr),prefixlen); 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. */ /* Label of this address. */
if (label) if (label)
@ -293,24 +279,11 @@ void
connected_down_ipv4 (struct interface *ifp, struct connected *ifc) connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
{ {
struct prefix_ipv4 p; struct prefix_ipv4 p;
struct prefix_ipv4 *addr;
struct prefix_ipv4 *dest;
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
return; return;
addr = (struct prefix_ipv4 *)ifc->address; PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
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;
/* Apply mask to the network. */ /* Apply mask to the network. */
apply_mask_ipv4 (&p); apply_mask_ipv4 (&p);
@ -350,28 +323,11 @@ void
connected_up_ipv6 (struct interface *ifp, struct connected *ifc) connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
{ {
struct prefix_ipv6 p; struct prefix_ipv6 p;
struct prefix_ipv6 *addr;
struct prefix_ipv6 *dest;
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
return; return;
addr = (struct prefix_ipv6 *) ifc->address; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
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;
/* Apply mask to the network. */ /* Apply mask to the network. */
apply_mask_ipv6 (&p); apply_mask_ipv6 (&p);
@ -390,7 +346,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
/* Add connected IPv6 route to the interface. */ /* Add connected IPv6 route to the interface. */
void 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, u_char prefixlen, struct in6_addr *broad,
const char *label) const char *label)
{ {
@ -400,6 +356,7 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
/* Make connected structure. */ /* Make connected structure. */
ifc = connected_new (); ifc = connected_new ();
ifc->ifp = ifp; ifc->ifp = ifp;
ifc->flags = flags;
/* Allocate new connected address. */ /* Allocate new connected address. */
p = prefix_ipv6_new (); p = prefix_ipv6_new ();
@ -408,13 +365,27 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
p->prefixlen = prefixlen; p->prefixlen = prefixlen;
ifc->address = (struct prefix *) p; ifc->address = (struct prefix *) p;
/* If there is broadcast or pointopoint address. */ /* If there is broadcast or peer address. */
if (broad) if (broad)
{ {
p = prefix_ipv6_new (); if (IN6_IS_ADDR_UNSPECIFIED(broad))
p->family = AF_INET6; zlog_warn("warning: %s called for interface %s with unspecified "
IPV6_ADDR_COPY (&p->prefix, broad); "destination address; ignoring!", __func__, ifp->name);
ifc->destination = (struct prefix *) p; 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. */ /* Label of this address. */
@ -431,28 +402,11 @@ void
connected_down_ipv6 (struct interface *ifp, struct connected *ifc) connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
{ {
struct prefix_ipv6 p; struct prefix_ipv6 p;
struct prefix_ipv6 *addr;
struct prefix_ipv6 *dest;
if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
return; return;
addr = (struct prefix_ipv6 *) ifc->address; PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
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;
apply_mask_ipv6 (&p); apply_mask_ipv6 (&p);

View File

@ -40,7 +40,7 @@ extern void connected_down_ipv4 (struct interface *, struct connected *);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
extern void 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, u_char prefixlen, struct in6_addr *broad,
const char *label); const char *label);
extern void extern void

View File

@ -249,6 +249,7 @@ if_getaddrs (void)
struct sockaddr_in *mask; struct sockaddr_in *mask;
struct sockaddr_in *dest; struct sockaddr_in *dest;
struct in_addr *dest_pnt; struct in_addr *dest_pnt;
int flags = 0;
addr = (struct sockaddr_in *) ifap->ifa_addr; addr = (struct sockaddr_in *) ifap->ifa_addr;
mask = (struct sockaddr_in *) ifap->ifa_netmask; mask = (struct sockaddr_in *) ifap->ifa_netmask;
@ -256,19 +257,25 @@ if_getaddrs (void)
dest_pnt = NULL; 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 = (struct sockaddr_in *) ifap->ifa_dstaddr;
dest_pnt = &dest->sin_addr; dest_pnt = &dest->sin_addr;
flags = ZEBRA_IFA_PEER;
} }
else if (ifap->ifa_broadaddr &&
if (ifap->ifa_flags & IFF_BROADCAST) !IPV4_ADDR_SAME(&addr->sin_addr,
&((struct sockaddr_in *)
ifap->ifa_broadaddr)->sin_addr))
{ {
dest = (struct sockaddr_in *) ifap->ifa_broadaddr; dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
dest_pnt = &dest->sin_addr; 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); prefixlen, dest_pnt, NULL);
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
@ -278,6 +285,7 @@ if_getaddrs (void)
struct sockaddr_in6 *mask; struct sockaddr_in6 *mask;
struct sockaddr_in6 *dest; struct sockaddr_in6 *dest;
struct in6_addr *dest_pnt; struct in6_addr *dest_pnt;
int flags = 0;
addr = (struct sockaddr_in6 *) ifap->ifa_addr; addr = (struct sockaddr_in6 *) ifap->ifa_addr;
mask = (struct sockaddr_in6 *) ifap->ifa_netmask; mask = (struct sockaddr_in6 *) ifap->ifa_netmask;
@ -285,22 +293,22 @@ if_getaddrs (void)
dest_pnt = NULL; dest_pnt = NULL;
if (ifap->ifa_flags & IFF_POINTOPOINT) if (ifap->ifa_dstaddr &&
!IPV6_ADDR_SAME(&addr->sin6_addr,
&((struct sockaddr_in6 *)
ifap->ifa_dstaddr)->sin6_addr))
{ {
if (ifap->ifa_dstaddr) dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
{ dest_pnt = &dest->sin6_addr;
dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr; flags = ZEBRA_IFA_PEER;
dest_pnt = &dest->sin6_addr;
}
} }
else if (ifap->ifa_broadaddr &&
if (ifap->ifa_flags & IFF_BROADCAST) !IPV6_ADDR_SAME(&addr->sin6_addr,
&((struct sockaddr_in6 *)
ifap->ifa_broadaddr)->sin6_addr))
{ {
if (ifap->ifa_broadaddr) dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
{ dest_pnt = &dest->sin6_addr;
dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
dest_pnt = &dest->sin6_addr;
}
} }
#if defined(KAME) #if defined(KAME)
@ -312,7 +320,7 @@ if_getaddrs (void)
} }
#endif #endif
connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, connected_add_ipv6 (ifp, flags, &addr->sin6_addr, prefixlen,
dest_pnt, NULL); dest_pnt, NULL);
} }
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */
@ -335,6 +343,7 @@ if_get_addr (struct interface *ifp)
struct sockaddr_in dest; struct sockaddr_in dest;
struct in_addr *dest_pnt; struct in_addr *dest_pnt;
u_char prefixlen; u_char prefixlen;
int flags = 0;
/* Interface's name and address family. */ /* Interface's name and address family. */
strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ); 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. */ /* Point to point or borad cast address pointer init. */
dest_pnt = NULL; 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));
}
else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_dstaddr.sin_addr))
{ {
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;
}
memcpy (&dest, &ifreq.ifr_dstaddr, sizeof (struct sockaddr_in)); memcpy (&dest, &ifreq.ifr_dstaddr, sizeof (struct sockaddr_in));
dest_pnt = &dest.sin_addr; dest_pnt = &dest.sin_addr;
flags = ZEBRA_IFA_PEER;
} }
if (ifp->flags & IFF_BROADCAST) if (!dest_pnt)
{ {
ret = if_ioctl (SIOCGIFBRDADDR, (caddr_t) &ifreq); ret = if_ioctl (SIOCGIFBRDADDR, (caddr_t) &ifreq);
if (ret < 0) if (ret < 0)
{ {
if (errno != EADDRNOTAVAIL) if (errno != EADDRNOTAVAIL)
{ zlog_warn ("SIOCGIFBRDADDR fail: %s", safe_strerror (errno));
zlog_warn ("SIOCGIFBRDADDR fail: %s", safe_strerror (errno));
return ret;
}
return 0;
} }
memcpy (&dest, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in)); else if (!IPV4_ADDR_SAME(&addr.sin_addr, &ifreq.ifr_broadaddr.sin_addr))
dest_pnt = &dest.sin_addr; {
memcpy (&dest, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
dest_pnt = &dest.sin_addr;
}
} }
/* Set address to the interface. */ /* 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; return 0;
} }

View File

@ -258,6 +258,7 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
char *dest_pnt = NULL; char *dest_pnt = NULL;
u_char prefixlen = 0; u_char prefixlen = 0;
afi_t af; afi_t af;
int flags = 0;
/* Interface's name and address family. /* Interface's name and address family.
* We need to use the logical interface name / label, if we've been * 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. */ /* Point to point or broad cast address pointer init. */
dest_pnt = NULL; 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)); memcpy (&dest, &lifreq.lifr_dstaddr, ADDRLEN (addr));
if (af == AF_INET) if (af == AF_INET)
dest_pnt = (char *) &(SIN (&dest)->sin_addr); dest_pnt = (char *) &(SIN (&dest)->sin_addr);
else else
dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr); dest_pnt = (char *) &(SIN6 (&dest)->sin6_addr);
flags = ZEBRA_IFA_PEER;
} }
if (af == AF_INET) 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)); memcpy (&mask, &lifreq.lifr_addr, ADDRLEN (addr));
prefixlen = ip_masklen (SIN (&mask)->sin_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)); memcpy (&dest, &lifreq.lifr_broadaddr, sizeof (struct sockaddr_in));
dest_pnt = (char *) &SIN (&dest)->sin_addr; 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. */ /* Set address to the interface. */
if (af == AF_INET) 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); (struct in_addr *) dest_pnt, label);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (af == AF_INET6) 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); (struct in6_addr *) dest_pnt, label);
#endif /* HAVE_IPV6 */ #endif /* HAVE_IPV6 */

View File

@ -240,7 +240,7 @@ ifaddr_proc_ipv6 ()
str2in6_addr (addr, &p.prefix); str2in6_addr (addr, &p.prefix);
p.prefixlen = plen; 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); fclose (fp);
return 0; return 0;

View File

@ -564,10 +564,6 @@ static void
connected_dump_vty (struct vty *vty, struct connected *connected) connected_dump_vty (struct vty *vty, struct connected *connected)
{ {
struct prefix *p; struct prefix *p;
struct interface *ifp;
/* Set interface pointer. */
ifp = connected->ifp;
/* Print interface address. */ /* Print interface address. */
p = connected->address; p = connected->address;
@ -576,21 +572,10 @@ connected_dump_vty (struct vty *vty, struct connected *connected)
vty_out (vty, "/%d", p->prefixlen); vty_out (vty, "/%d", p->prefixlen);
/* If there is destination address, print it. */ /* If there is destination address, print it. */
p = connected->destination; if (connected->destination)
if (p)
{ {
if (p->family == AF_INET) vty_out (vty, (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
if (ifp->flags & IFF_BROADCAST) prefix_vty_out (vty, connected->destination);
{
vty_out (vty, " broadcast ");
prefix_vty_out (vty, p);
}
if (ifp->flags & IFF_POINTOPOINT)
{
vty_out (vty, " pointopoint ");
prefix_vty_out (vty, p);
}
} }
if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY)) if (CHECK_FLAG (connected->flags, ZEBRA_IFA_SECONDARY))

View File

@ -609,7 +609,7 @@ ifam_read (struct ifa_msghdr *ifam)
SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0); SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
if (ifam->ifam_type == RTM_NEWADDR) if (ifam->ifam_type == RTM_NEWADDR)
connected_add_ipv6 (ifp, connected_add_ipv6 (ifp, 0,
&addr.sin6.sin6_addr, &addr.sin6.sin6_addr,
ip6_masklen (mask.sin6.sin6_addr), ip6_masklen (mask.sin6.sin6_addr),
&brd.sin6.sin6_addr, &brd.sin6.sin6_addr,

View File

@ -577,8 +577,8 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
struct rtattr *tb[IFA_MAX + 1]; struct rtattr *tb[IFA_MAX + 1];
struct interface *ifp; struct interface *ifp;
void *addr = NULL; void *addr;
void *broad = NULL; void *broad;
u_char flags = 0; u_char flags = 0;
char *label = NULL; 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) if (tb[IFA_ADDRESS] == NULL)
tb[IFA_ADDRESS] = tb[IFA_LOCAL]; tb[IFA_ADDRESS] = tb[IFA_LOCAL];
if (ifp->flags & IFF_POINTOPOINT) /* local interface address */
addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : 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))
{ {
if (tb[IFA_LOCAL]) broad = RTA_DATA(tb[IFA_ADDRESS]);
{ SET_FLAG (flags, ZEBRA_IFA_PEER);
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 else
{ /* seeking a broadcast address */
if (tb[IFA_ADDRESS]) broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);
addr = RTA_DATA (tb[IFA_ADDRESS]);
else
addr = NULL;
if (tb[IFA_BROADCAST])
broad = RTA_DATA(tb[IFA_BROADCAST]);
else
broad = NULL;
}
/* addr is primary key, SOL if we don't have one */ /* addr is primary key, SOL if we don't have one */
if (addr == NULL) if (addr == NULL)
@ -707,7 +695,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
if (ifa->ifa_family == AF_INET6) if (ifa->ifa_family == AF_INET6)
{ {
if (h->nlmsg_type == RTM_NEWADDR) 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 *) addr, ifa->ifa_prefixlen,
(struct in6_addr *) broad, label); (struct in6_addr *) broad, label);
else else
@ -1849,7 +1837,7 @@ netlink_address (int cmd, int family, struct interface *ifp,
if (family == AF_INET && cmd == RTM_NEWADDR) if (family == AF_INET && cmd == RTM_NEWADDR)
{ {
if (if_is_broadcast (ifp) && ifc->destination) if (!CONNECTED_PEER(ifc) && ifc->destination)
{ {
p = ifc->destination; p = ifc->destination;
addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,