debug("\t%I, net %I/%-2d bc %I -> %I%s%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite,
(a->flags & IF_UP) ? "" : " DOWN",
(a->flags & IA_PRIMARY) ? "" : " SEC",
- (a->flags & IA_UNNUMBERED) ? " UNNUM" : "");
+ (a->flags & IA_PEER) ? "PEER" : "");
}
/**
ipa_equal(b->brd, a->brd) &&
ipa_equal(b->opposite, a->opposite) &&
b->scope == a->scope &&
- !((b->flags ^ a->flags) & IA_UNNUMBERED))
+ !((b->flags ^ a->flags) & IA_PEER))
{
b->flags |= IF_UPDATED;
return b;
if ((i->flags & IF_ADMIN_UP) &&
!(i->flags & (IF_IGNORE | IF_SHUTDOWN)) &&
i->addr &&
- !(i->addr->flags & IA_UNNUMBERED) &&
+ !(i->addr->flags & IA_PEER) &&
(!j || ipa_to_u32(i->addr->ip) < ipa_to_u32(j->addr->ip)))
j = i;
if (!j)
if (ipa_in_net(a->ip, p->prefix, p->pxlen))
return pos;
- if ((a->flags & IA_UNNUMBERED) &&
+ if ((a->flags & IA_PEER) &&
ipa_in_net(a->opposite, p->prefix, p->pxlen))
return pos;
static void
if_show_addr(struct ifa *a)
{
- byte broad[STD_ADDRESS_P_LENGTH + 16];
byte opp[STD_ADDRESS_P_LENGTH + 16];
- if (ipa_nonzero(a->brd))
- bsprintf(broad, ", broadcast %I", a->brd);
- else
- broad[0] = 0;
if (ipa_nonzero(a->opposite))
bsprintf(opp, ", opposite %I", a->opposite);
else
opp[0] = 0;
- cli_msg(-1003, "\t%I/%d (%s%s%s, scope %s%s)",
+ cli_msg(-1003, "\t%I/%d (%s%s, scope %s)",
a->ip, a->pxlen,
(a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "Unselected",
- broad, opp,
- ip_scope_text(a->scope),
- (a->flags & IA_UNNUMBERED) ? ", unnumbered" : "");
+ opp, ip_scope_text(a->scope));
}
void
#define IA_PRIMARY 0x10000 /* This address is primary */
#define IA_SECONDARY 0x20000 /* This address has been reported as secondary by the kernel */
-#define IA_UNNUMBERED 0x40000 /* This address belongs to an unnumbered device */
+#define IA_PEER 0x40000 /* A peer/ptp address */
+#define IA_HOST 0x80000 /* A host/loopback address */
#define IA_FLAGS 0xff0000
+/*
+ * There are three kinds of addresses in BIRD:
+ * - Standard (prefix-based) addresses, these may define ifa.opposite (for /30 or /31).
+ * - Peer/ptp addresses, without common prefix for ifa.ip and ifa.opposite.
+ * ifa.opposite is defined and ifa.prefix/pxlen == ifa.opposite/32 (for simplicity).
+ * - Host addresses, with ifa.prefix/pxlen == ifa.ip/32 (or /128).
+ * May be considered a special case of standard addresses.
+ *
+ * Peer addresses (AFAIK) do not exist in IPv6. Linux alos supports generalized peer
+ * address (with pxlen < 32 and ifa.ip outside prefix), we do not support that.
+ */
+
+
#define IF_JUST_CREATED 0x10000000 /* Send creation event as soon as possible */
#define IF_TMP_DOWN 0x20000000 /* Temporary shutdown due to interface reconfiguration */
#define IF_UPDATED 0x40000000 /* Touched in last scan */
struct iface *if_find_by_name(char *);
void ifa_recalc_all_primary_addresses(void);
-static inline int
-ifa_match_addr(struct ifa *ifa, ip_addr addr)
-{
- if (ifa->flags & IA_UNNUMBERED)
- return ipa_equal(addr, ifa->opposite);
- else
- return ipa_in_net(addr, ifa->prefix, ifa->pxlen);
-}
-
/* The Neighbor Cache */
typedef struct neighbor {
{
if (ipa_equal(*a, b->ip))
return SCOPE_HOST;
- if (b->flags & IA_UNNUMBERED)
+ if (b->flags & IA_PEER)
{
if (ipa_equal(*a, b->opposite))
return b->scope;
if (! addr)
return 0;
+ /* a host/loopback address */
+ if (addr->flags & IA_HOST)
+ return 1;
+
/*
* We cannot properly support multiple OSPF ifaces on real iface
* with multiple prefixes, therefore we force OSPF ifaces with
return 1;
#endif
- /* a loopback/dummy address */
- if ((addr->pxlen == MAX_PREFIX_LENGTH) && ipa_zero(addr->opposite))
- return 1;
-
return ip->stub;
}
int old_type = ifa->type;
#ifdef OSPFv2
- if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_UNNUMBERED))
+ if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
ifa->type = OSPF_IT_PTP;
- if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_UNNUMBERED))
+ if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
ifa->type = OSPF_IT_PTMP;
#endif
else
{
#ifdef OSPFv2
- if (ifa->addr->flags & IA_UNNUMBERED)
+ if (ifa->addr->flags & IA_PEER)
cli_msg(-1015, "Interface %s (peer %I)", ifa->iface->name, ifa->addr->opposite);
else
cli_msg(-1015, "Interface %s (%I/%d)", ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen);
struct proto_ospf *po = ifa->oa->po;
// struct proto *p = &po->proto;
- int src_local = ifa_match_addr(ifa->addr, sk->faddr);
+ int src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
int dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
int dst_mcast = ipa_equal(sk->laddr, AllSPFRouters) || ipa_equal(sk->laddr, AllDRouters);
if (!oa->ac)
return 0;
+ /* Does not work for IA_PEER addresses, but it is not called on these */
struct ospf_stubnet_config *sn;
WALK_LIST(sn, oa->ac->stubnet_list)
{
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
ln->type = LSART_PTP;
ln->id = neigh->rid;
- ln->data = (ifa->addr->flags & IA_UNNUMBERED) ?
+ ln->data = (ifa->addr->flags & IA_PEER) ?
ifa->iface->index : ipa_to_u32(ifa->addr->ip);
ln->metric = ifa->cost;
ln->padding = 0;
/* Now we will originate stub area if there is no primary */
if (net_lsa ||
(ifa->type == OSPF_IT_VLINK) ||
- (ifa->addr->flags & IA_UNNUMBERED) ||
+ (ifa->addr->flags & IA_PEER) ||
configured_stubnet(oa, ifa->addr))
continue;
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
- if ((ifa->state == OSPF_IS_LOOP) || (ifa->type == OSPF_IT_PTMP))
+ if ((ifa->addr->flags & IA_HOST) ||
+ (ifa->state == OSPF_IS_LOOP) ||
+ (ifa->type == OSPF_IT_PTMP))
{
/* Host stub entry */
ln->type = LSART_STUB;
WALK_LIST(a, ifa->iface->addrs)
{
if ((a->flags & IA_SECONDARY) ||
- (a->flags & IA_UNNUMBERED) ||
+ (a->flags & IA_PEER) ||
(a->scope <= SCOPE_LINK))
continue;
configured_stubnet(oa, a))
continue;
- if ((ifa->state == OSPF_IS_LOOP) || (ifa->type == OSPF_IT_PTMP))
+ if ((a->flags & IA_HOST) ||
+ (ifa->state == OSPF_IS_LOOP) ||
+ (ifa->type == OSPF_IT_PTMP))
+ {
lsa_put_prefix(po, a->ip, MAX_PREFIX_LENGTH, 0);
+ host_addr = 1;
+ }
else
lsa_put_prefix(po, a->prefix, a->pxlen, ifa->cost);
i++;
-
- if ((ifa->state == OSPF_IS_LOOP) ||
- (a->pxlen == MAX_PREFIX_LENGTH))
- host_addr = 1;
}
ifa->px_pos_end = i;
}
if (new) {
- if (new->addr->flags & IA_UNNUMBERED)
+ if (new->addr->flags & IA_PEER)
log( L_WARN "%s: rip is not defined over unnumbered links", p->name );
if (rif->multicast) {
#ifndef IPV6
{
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
+ if (masklen == BITS_PER_IP_ADDRESS)
+ ifa.flags |= IA_HOST;
+
if (masklen == (BITS_PER_IP_ADDRESS - 1))
ifa.opposite = ipa_opposite_m1(ifa.ip);
}
else /* PtP iface */
{
- ifa.flags |= IA_UNNUMBERED;
+ ifa.flags |= IA_PEER;
ifa.prefix = ifa.opposite = ifa.brd;
}
ipa_ntoh(addr);
ifa.prefix = ifa.brd = addr;
- /* It is either a peer address, or loopback/dummy address */
- if (!ipa_equal(ifa.ip, addr))
+ /* It is either a host address or a peer address */
+ if (ipa_equal(ifa.ip, addr))
+ ifa.flags |= IA_HOST;
+ else
{
- ifa.flags |= IA_UNNUMBERED;
+ ifa.flags |= IA_PEER;
ifa.opposite = addr;
}
}
if (fl & IFF_POINTOPOINT)
{
- a.flags |= IA_UNNUMBERED;
+ a.flags |= IA_PEER;
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
{ err = "SIOCGIFDSTADDR"; goto faulty; }
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1);
&& (fl & IFF_MULTICAST)
#endif
#ifndef CONFIG_UNNUM_MULTICAST
- && !(a.flags & IA_UNNUMBERED)
+ && !(a.flags & IA_PEER)
#endif
)
i.flags |= IF_MULTICAST;