Many changes in (mainly) kernel syncers.
- BSD kernel syncer is now self-conscious and can learn alien routes - important bugfix in BSD kernel syncer (crash after protocol restart) - many minor changes and bugfixes in kernel syncers and neighbor cache - direct protocol does not generate host and link local routes - min_scope check is removed, all routes have SCOPE_UNIVERSE by default - also fixes some remaining compiler warnings
This commit is contained in:
parent
e81b440f68
commit
ff2857b03d
19 changed files with 279 additions and 298 deletions
|
@ -824,7 +824,14 @@ defined by using the <cf>defined( <m>attribute</m> )</cf> operator.
|
||||||
Network the route is talking about. Read-only. (See the chapter about routing tables.)
|
Network the route is talking about. Read-only. (See the chapter about routing tables.)
|
||||||
|
|
||||||
<tag><m/enum/ scope</tag>
|
<tag><m/enum/ scope</tag>
|
||||||
Address scope of the network (<cf/SCOPE_HOST/ for addresses local to this host, <cf/SCOPE_LINK/ for those specific for a physical link, <cf/SCOPE_SITE/ and <cf/SCOPE_ORGANIZATION/ for private addresses, <cf/SCOPE_UNIVERSE/ for globally visible addresses).
|
The scope of the route. Possible values: <cf/SCOPE_HOST/ for
|
||||||
|
routes local to this host, <cf/SCOPE_LINK/ for those specific
|
||||||
|
for a physical link, <cf/SCOPE_SITE/ and
|
||||||
|
<cf/SCOPE_ORGANIZATION/ for private routes and
|
||||||
|
<cf/SCOPE_UNIVERSE/ for globally visible routes. This
|
||||||
|
attribute is not interpreted by BIRD and can be used to mark
|
||||||
|
routes in filters. The default value for new routes is
|
||||||
|
<cf/SCOPE_UNIVERSE/.
|
||||||
|
|
||||||
<tag><m/int/ preference</tag>
|
<tag><m/int/ preference</tag>
|
||||||
Preference of the route. Valid values are 0-65535. (See the chapter about routing tables.)
|
Preference of the route. Valid values are 0-65535. (See the chapter about routing tables.)
|
||||||
|
@ -842,7 +849,11 @@ defined by using the <cf>defined( <m>attribute</m> )</cf> operator.
|
||||||
what protocol has told me about this route. Possible values: <cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, <cf/RTS_STATIC_DEVICE/, <cf/RTS_REDIRECT/, <cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT/, <cf/RTS_BGP/, <cf/RTS_PIPE/.
|
what protocol has told me about this route. Possible values: <cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, <cf/RTS_STATIC_DEVICE/, <cf/RTS_REDIRECT/, <cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT/, <cf/RTS_BGP/, <cf/RTS_PIPE/.
|
||||||
|
|
||||||
<tag><m/enum/ cast</tag>
|
<tag><m/enum/ cast</tag>
|
||||||
Route type (<cf/RTC_UNICAST/ for normal routes, <cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ for broadcast, multicast and anycast routes). Read-only.
|
|
||||||
|
Route type (Currently <cf/RTC_UNICAST/ for normal routes,
|
||||||
|
<cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ will
|
||||||
|
be used in the future for broadcast, multicast and anycast
|
||||||
|
routes). Read-only.
|
||||||
|
|
||||||
<tag><m/enum/ dest</tag>
|
<tag><m/enum/ dest</tag>
|
||||||
Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_NETWORK/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
|
Type of destination the packets should be sent to (<cf/RTD_ROUTER/ for forwarding to a neighboring router, <cf/RTD_NETWORK/ for routing to a directly-connected network, <cf/RTD_BLACKHOLE/ for packets to be silently discarded, <cf/RTD_UNREACHABLE/, <cf/RTD_PROHIBIT/ for packets that should be returned with ICMP host unreachable / ICMP administratively prohibited messages). Read-only.
|
||||||
|
|
4
lib/ip.h
4
lib/ip.h
|
@ -50,6 +50,10 @@ struct prefix {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
|
#define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
|
||||||
|
#define ipa_zero(x) (!ipa_nonzero(x))
|
||||||
|
|
||||||
|
static inline int ipa_classify_net(ip_addr a)
|
||||||
|
{ return ipa_zero(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Conversions between internal and string representation
|
* Conversions between internal and string representation
|
||||||
|
|
|
@ -97,6 +97,7 @@ typedef struct neighbor {
|
||||||
} neighbor;
|
} neighbor;
|
||||||
|
|
||||||
#define NEF_STICKY 1
|
#define NEF_STICKY 1
|
||||||
|
#define NEF_ONLINK 2
|
||||||
|
|
||||||
neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
|
neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags);
|
||||||
neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags);
|
neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags);
|
||||||
|
|
|
@ -112,12 +112,12 @@ neighbor *
|
||||||
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
||||||
{
|
{
|
||||||
neighbor *n;
|
neighbor *n;
|
||||||
int class, scope = SCOPE_HOST;
|
int class, scope = -1; ;
|
||||||
unsigned int h = neigh_hash(p, a);
|
unsigned int h = neigh_hash(p, a);
|
||||||
struct iface *i;
|
struct iface *i;
|
||||||
|
|
||||||
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
||||||
if (n->proto == p && ipa_equal(*a, n->addr))
|
if (n->proto == p && ipa_equal(*a, n->addr) && (!ifa || (ifa == n->iface)))
|
||||||
return n;
|
return n;
|
||||||
|
|
||||||
class = ipa_classify(*a);
|
class = ipa_classify(*a);
|
||||||
|
@ -129,7 +129,12 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
||||||
return NULL; /* Bad scope or a somecast */
|
return NULL; /* Bad scope or a somecast */
|
||||||
|
|
||||||
if (ifa)
|
if (ifa)
|
||||||
|
{
|
||||||
scope = if_connected(a, ifa);
|
scope = if_connected(a, ifa);
|
||||||
|
|
||||||
|
if ((scope < 0) && (flags & NEF_ONLINK))
|
||||||
|
scope = class & IADDR_SCOPE_MASK;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
WALK_LIST(i, iface_list)
|
WALK_LIST(i, iface_list)
|
||||||
if ((scope = if_connected(a, i)) >= 0)
|
if ((scope = if_connected(a, i)) >= 0)
|
||||||
|
@ -138,22 +143,28 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ifa && !(flags & NEF_STICKY))
|
/* scope < 0 means i don't know neighbor */
|
||||||
|
/* scope >= 0 implies ifa != NULL */
|
||||||
|
|
||||||
|
if ((scope < 0) && !(flags & NEF_STICKY))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
n = sl_alloc(neigh_slab);
|
n = sl_alloc(neigh_slab);
|
||||||
n->addr = *a;
|
n->addr = *a;
|
||||||
n->iface = ifa;
|
if (scope >= 0)
|
||||||
if (ifa)
|
|
||||||
{
|
{
|
||||||
add_tail(&neigh_hash_table[h], &n->n);
|
add_tail(&neigh_hash_table[h], &n->n);
|
||||||
add_tail(&ifa->neighbors, &n->if_n);
|
add_tail(&ifa->neighbors, &n->if_n);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* sticky flag does not work for link-local neighbors;
|
||||||
|
fortunately, we don't use this combination */
|
||||||
add_tail(&sticky_neigh_list, &n->n);
|
add_tail(&sticky_neigh_list, &n->n);
|
||||||
|
ifa = NULL;
|
||||||
scope = 0;
|
scope = 0;
|
||||||
}
|
}
|
||||||
|
n->iface = ifa;
|
||||||
n->proto = p;
|
n->proto = p;
|
||||||
n->data = NULL;
|
n->data = NULL;
|
||||||
n->aux = 0;
|
n->aux = 0;
|
||||||
|
|
|
@ -113,7 +113,6 @@ proto_new(struct proto_config *c, unsigned size)
|
||||||
p->table = c->table->table;
|
p->table = c->table->table;
|
||||||
p->in_filter = c->in_filter;
|
p->in_filter = c->in_filter;
|
||||||
p->out_filter = c->out_filter;
|
p->out_filter = c->out_filter;
|
||||||
p->min_scope = SCOPE_SITE;
|
|
||||||
p->hash_key = random_u32();
|
p->hash_key = random_u32();
|
||||||
c->proto = p;
|
c->proto = p;
|
||||||
return p;
|
return p;
|
||||||
|
|
|
@ -130,7 +130,6 @@ struct proto {
|
||||||
u32 debug; /* Debugging flags */
|
u32 debug; /* Debugging flags */
|
||||||
u32 mrtdump; /* MRTDump flags */
|
u32 mrtdump; /* MRTDump flags */
|
||||||
unsigned preference; /* Default route preference */
|
unsigned preference; /* Default route preference */
|
||||||
int min_scope; /* Minimal route scope accepted */
|
|
||||||
unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
|
unsigned accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */
|
||||||
unsigned disabled; /* Manually disabled */
|
unsigned disabled; /* Manually disabled */
|
||||||
unsigned proto_state; /* Protocol state machine (see below) */
|
unsigned proto_state; /* Protocol state machine (see below) */
|
||||||
|
|
|
@ -33,6 +33,10 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
|
||||||
!iface_patt_find(&P->iface_list, ad->iface))
|
!iface_patt_find(&P->iface_list, ad->iface))
|
||||||
/* Empty list is automagically treated as "*" */
|
/* Empty list is automagically treated as "*" */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ad->scope <= SCOPE_LINK)
|
||||||
|
return;
|
||||||
|
|
||||||
if (c & IF_CHANGE_DOWN)
|
if (c & IF_CHANGE_DOWN)
|
||||||
{
|
{
|
||||||
net *n;
|
net *n;
|
||||||
|
@ -56,7 +60,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
|
||||||
bzero(&A, sizeof(A));
|
bzero(&A, sizeof(A));
|
||||||
A.proto = p;
|
A.proto = p;
|
||||||
A.source = RTS_DEVICE;
|
A.source = RTS_DEVICE;
|
||||||
A.scope = ad->scope;
|
A.scope = SCOPE_UNIVERSE;
|
||||||
A.cast = RTC_UNICAST;
|
A.cast = RTC_UNICAST;
|
||||||
A.dest = RTD_DEVICE;
|
A.dest = RTD_DEVICE;
|
||||||
A.iface = ad->iface;
|
A.iface = ad->iface;
|
||||||
|
@ -76,7 +80,6 @@ dev_init(struct proto_config *c)
|
||||||
struct proto *p = proto_new(c, sizeof(struct proto));
|
struct proto *p = proto_new(c, sizeof(struct proto));
|
||||||
|
|
||||||
p->ifa_notify = dev_ifa_notify;
|
p->ifa_notify = dev_ifa_notify;
|
||||||
p->min_scope = SCOPE_HOST;
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ rte_trace_out(unsigned int flag, struct proto *p, rte *e, char *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int class, int refeed)
|
do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
|
||||||
{
|
{
|
||||||
struct proto *p = a->proto;
|
struct proto *p = a->proto;
|
||||||
struct filter *filter = p->out_filter;
|
struct filter *filter = p->out_filter;
|
||||||
|
@ -183,13 +183,7 @@ do_rte_announce(struct announce_hook *a, int type UNUSED, net *net, rte *new, rt
|
||||||
stats->exp_updates_received++;
|
stats->exp_updates_received++;
|
||||||
|
|
||||||
char *drop_reason = NULL;
|
char *drop_reason = NULL;
|
||||||
if ((class & IADDR_SCOPE_MASK) < p->min_scope)
|
if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
|
||||||
{
|
|
||||||
stats->exp_updates_rejected++;
|
|
||||||
drop_reason = "out of scope";
|
|
||||||
fast_exit_hack = 1;
|
|
||||||
}
|
|
||||||
else if ((ok = p->import_control ? p->import_control(p, &new, &tmpa, rte_update_pool) : 0) < 0)
|
|
||||||
{
|
{
|
||||||
stats->exp_updates_rejected++;
|
stats->exp_updates_rejected++;
|
||||||
drop_reason = "rejected by protocol";
|
drop_reason = "rejected by protocol";
|
||||||
|
@ -332,7 +326,6 @@ static void
|
||||||
rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
|
rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *tmpa)
|
||||||
{
|
{
|
||||||
struct announce_hook *a;
|
struct announce_hook *a;
|
||||||
int class = ipa_classify(net->n.prefix);
|
|
||||||
|
|
||||||
if (type == RA_OPTIMAL)
|
if (type == RA_OPTIMAL)
|
||||||
{
|
{
|
||||||
|
@ -346,7 +339,7 @@ rte_announce(rtable *tab, unsigned type, net *net, rte *new, rte *old, ea_list *
|
||||||
{
|
{
|
||||||
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
ASSERT(a->proto->core_state == FS_HAPPY || a->proto->core_state == FS_FEEDING);
|
||||||
if (a->proto->accept_ra_types == type)
|
if (a->proto->accept_ra_types == type)
|
||||||
do_rte_announce(a, type, net, new, old, tmpa, class, 0);
|
do_rte_announce(a, type, net, new, old, tmpa, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,33 +355,15 @@ rte_validate(rte *e)
|
||||||
n->n.prefix, n->n.pxlen, e->sender->name);
|
n->n.prefix, n->n.pxlen, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (n->n.pxlen)
|
|
||||||
|
c = ipa_classify_net(n->n.prefix);
|
||||||
|
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
{
|
{
|
||||||
c = ipa_classify(n->n.prefix);
|
|
||||||
if (c < 0 || !(c & IADDR_HOST))
|
|
||||||
{
|
|
||||||
if (!ipa_nonzero(n->n.prefix))
|
|
||||||
{
|
|
||||||
/* Various default routes */
|
|
||||||
#ifdef IPV6
|
|
||||||
if (n->n.pxlen == 96)
|
|
||||||
#else
|
|
||||||
if (n->n.pxlen <= 1)
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
log(L_WARN "Ignoring bogus route %I/%d received via %s",
|
log(L_WARN "Ignoring bogus route %I/%d received via %s",
|
||||||
n->n.prefix, n->n.pxlen, e->sender->name);
|
n->n.prefix, n->n.pxlen, e->sender->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ((c & IADDR_SCOPE_MASK) < e->sender->min_scope)
|
|
||||||
{
|
|
||||||
log(L_WARN "Ignoring %s scope route %I/%d received from %I via %s",
|
|
||||||
ip_scope_text(c & IADDR_SCOPE_MASK),
|
|
||||||
n->n.prefix, n->n.pxlen, e->attrs->from, e->sender->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,7 +993,7 @@ do_feed_baby(struct proto *p, int type, struct announce_hook *h, net *n, rte *e)
|
||||||
|
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
tmpa = q->make_tmp_attrs ? q->make_tmp_attrs(e, rte_update_pool) : NULL;
|
||||||
do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, ipa_classify(n->n.prefix), p->refeeding);
|
do_rte_announce(h, type, n, e, p->refeeding ? e : NULL, tmpa, p->refeeding);
|
||||||
rte_update_unlock();
|
rte_update_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,11 +1165,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
if (p2 && p2 != p0) ok = 0;
|
if (p2 && p2 != p0) ok = 0;
|
||||||
if (ok && d->export_mode)
|
if (ok && d->export_mode)
|
||||||
{
|
{
|
||||||
int class = ipa_classify(n->n.prefix);
|
|
||||||
int ic;
|
int ic;
|
||||||
if ((class & IADDR_SCOPE_MASK) < p1->min_scope)
|
if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
|
||||||
ok = 0;
|
|
||||||
else if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
|
|
||||||
ok = 0;
|
ok = 0;
|
||||||
else if (!ic && d->export_mode > 1)
|
else if (!ic && d->export_mode > 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -914,7 +914,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
|
||||||
rta *a = NULL;
|
rta *a = NULL;
|
||||||
ip_addr prefix;
|
ip_addr prefix;
|
||||||
net *n;
|
net *n;
|
||||||
rte e;
|
|
||||||
int err = 0, pxlen;
|
int err = 0, pxlen;
|
||||||
|
|
||||||
p->mp_reach_len = 0;
|
p->mp_reach_len = 0;
|
||||||
|
@ -936,8 +935,6 @@ bgp_do_rx_update(struct bgp_conn *conn,
|
||||||
|
|
||||||
DO_NLRI(mp_reach)
|
DO_NLRI(mp_reach)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Create fake NEXT_HOP attribute */
|
/* Create fake NEXT_HOP attribute */
|
||||||
if (len < 1 || (*x != 16 && *x != 32) || len < *x + 2)
|
if (len < 1 || (*x != 16 && *x != 32) || len < *x + 2)
|
||||||
goto bad;
|
goto bad;
|
||||||
|
|
|
@ -1234,7 +1234,6 @@ show_lsa_sum_rt(struct top_hash_entry *he)
|
||||||
static inline void
|
static inline void
|
||||||
show_lsa_external(struct top_hash_entry *he)
|
show_lsa_external(struct top_hash_entry *he)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
|
||||||
struct ospf_lsa_ext *ext = he->lsa_body;
|
struct ospf_lsa_ext *ext = he->lsa_body;
|
||||||
char str_via[STD_ADDRESS_P_LENGTH + 8] = "";
|
char str_via[STD_ADDRESS_P_LENGTH + 8] = "";
|
||||||
char str_tag[16] = "";
|
char str_tag[16] = "";
|
||||||
|
@ -1245,7 +1244,7 @@ show_lsa_external(struct top_hash_entry *he)
|
||||||
rt_metric = ext->metric & METRIC_MASK;
|
rt_metric = ext->metric & METRIC_MASK;
|
||||||
ebit = ext->metric & LSA_EXT_EBIT;
|
ebit = ext->metric & LSA_EXT_EBIT;
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
ip = ipa_and(ipa_from_u32(lsa->id), ext->netmask);
|
ip = ipa_and(ipa_from_u32(he->lsa.id), ext->netmask);
|
||||||
pxlen = ipa_mklen(ext->netmask);
|
pxlen = ipa_mklen(ext->netmask);
|
||||||
rt_fwaddr = ext->fwaddr;
|
rt_fwaddr = ext->fwaddr;
|
||||||
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
|
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
|
||||||
|
@ -1282,10 +1281,7 @@ show_lsa_external(struct top_hash_entry *he)
|
||||||
static inline void
|
static inline void
|
||||||
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
|
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
|
||||||
struct ospf_lsa_prefix *px = he->lsa_body;
|
struct ospf_lsa_prefix *px = he->lsa_body;
|
||||||
struct ospf_lsa_ext *ext = he->lsa_body;
|
|
||||||
char *msg;
|
|
||||||
ip_addr pxa;
|
ip_addr pxa;
|
||||||
int pxlen;
|
int pxlen;
|
||||||
u8 pxopts;
|
u8 pxopts;
|
||||||
|
@ -1504,8 +1500,10 @@ ospf_sh_lsadb(struct proto *p)
|
||||||
break;
|
break;
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
case LSA_SCOPE_LINK:
|
case LSA_SCOPE_LINK:
|
||||||
|
{
|
||||||
struct iface *ifa = if_find_by_index(hea[i]->domain);
|
struct iface *ifa = if_find_by_index(hea[i]->domain);
|
||||||
cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
|
cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ static void
|
||||||
process_prefixes(struct ospf_area *oa)
|
process_prefixes(struct ospf_area *oa)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct proto *p = &po->proto;
|
// struct proto *p = &po->proto;
|
||||||
struct top_hash_entry *en, *src;
|
struct top_hash_entry *en, *src;
|
||||||
struct ospf_lsa_prefix *px;
|
struct ospf_lsa_prefix *px;
|
||||||
ip_addr pxa;
|
ip_addr pxa;
|
||||||
|
@ -228,7 +228,6 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
|
||||||
{
|
{
|
||||||
// struct proto *p = &oa->po->proto;
|
// struct proto *p = &oa->po->proto;
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
orta nf;
|
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
struct ospf_lsa_rt *rt = en->lsa_body;
|
struct ospf_lsa_rt *rt = en->lsa_body;
|
||||||
|
@ -249,6 +248,7 @@ ospf_rt_spfa_rtlinks(struct ospf_area *oa, struct top_hash_entry *act, struct to
|
||||||
*/
|
*/
|
||||||
DBG("\n");
|
DBG("\n");
|
||||||
|
|
||||||
|
orta nf;
|
||||||
nf.type = RTS_OSPF;
|
nf.type = RTS_OSPF;
|
||||||
nf.options = 0;
|
nf.options = 0;
|
||||||
nf.metric1 = act->dist + rtl->metric;
|
nf.metric1 = act->dist + rtl->metric;
|
||||||
|
@ -571,7 +571,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
|
||||||
type = ORT_NET;
|
type = ORT_NET;
|
||||||
re = (ort *) fib_find(&po->rtf, &ip, pxlen);
|
re = (ort *) fib_find(&po->rtf, &ip, pxlen);
|
||||||
}
|
}
|
||||||
else if (en->lsa.type == LSA_T_SUM_RT)
|
else // en->lsa.type == LSA_T_SUM_RT
|
||||||
{
|
{
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
struct ospf_lsa_sum *ls = en->lsa_body;
|
struct ospf_lsa_sum *ls = en->lsa_body;
|
||||||
|
|
|
@ -33,39 +33,8 @@
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
|
|
||||||
#ifdef IPV6
|
|
||||||
#define HOST_MASK 128
|
|
||||||
#else
|
|
||||||
#define HOST_MASK 32
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int rt_sock = 0;
|
int rt_sock = 0;
|
||||||
|
|
||||||
#define CHECK_FAMILY(sa) \
|
|
||||||
((((struct sockaddr *)sa)->sa_family) == BIRD_AF)
|
|
||||||
|
|
||||||
static struct iface *
|
|
||||||
krt_temp_iface_index(struct krt_proto *p, unsigned index)
|
|
||||||
{
|
|
||||||
struct iface *i, *j;
|
|
||||||
|
|
||||||
WALK_LIST(i, p->scan.temp_ifs)
|
|
||||||
if (i->index == index)
|
|
||||||
return i;
|
|
||||||
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
|
||||||
if (j = if_find_by_index(index))
|
|
||||||
{
|
|
||||||
strcpy(i->name, j->name);
|
|
||||||
i->addr = j->addr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
strcpy(i->name, "?");
|
|
||||||
i->index = index;
|
|
||||||
add_tail(&p->scan.temp_ifs, &i->n);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
krt_capable(rte *e)
|
krt_capable(rte *e)
|
||||||
{
|
{
|
||||||
|
@ -83,7 +52,7 @@ krt_capable(rte *e)
|
||||||
|| a->dest == RTD_UNREACHABLE
|
|| a->dest == RTD_UNREACHABLE
|
||||||
#endif
|
#endif
|
||||||
#ifdef RTF_BLACKHOLE
|
#ifdef RTF_BLACKHOLE
|
||||||
|| a->dest == RTD_BLACKHOLE /* FIXME Prohibited? */
|
|| a->dest == RTD_BLACKHOLE
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -96,6 +65,13 @@ krt_capable(rte *e)
|
||||||
l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
|
l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
|
||||||
memmove(body, &(u), l); body += l;}
|
memmove(body, &(u), l); body += l;}
|
||||||
|
|
||||||
|
#define GETADDR(p, F) \
|
||||||
|
bzero(p, sizeof(*p));\
|
||||||
|
if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
|
||||||
|
unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
|
||||||
|
memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
|
||||||
|
body += l;}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_sock_send(int cmd, rte *e)
|
krt_sock_send(int cmd, rte *e)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +84,7 @@ krt_sock_send(int cmd, rte *e)
|
||||||
char *body = (char *)msg.buf;
|
char *body = (char *)msg.buf;
|
||||||
sockaddr gate, mask, dst;
|
sockaddr gate, mask, dst;
|
||||||
|
|
||||||
DBG("krt-sock: send %I/%d via %I", net->n.prefix, net->n.pxlen, a->gw);
|
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
|
||||||
|
|
||||||
fill_in_sockaddr(&dst, net->n.prefix, 0);
|
fill_in_sockaddr(&dst, net->n.prefix, 0);
|
||||||
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
|
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
|
||||||
|
@ -119,9 +95,9 @@ krt_sock_send(int cmd, rte *e)
|
||||||
msg.rtm.rtm_type = cmd;
|
msg.rtm.rtm_type = cmd;
|
||||||
msg.rtm.rtm_seq = msg_seq++;
|
msg.rtm.rtm_seq = msg_seq++;
|
||||||
msg.rtm.rtm_addrs = RTA_DST;
|
msg.rtm.rtm_addrs = RTA_DST;
|
||||||
msg.rtm.rtm_flags = RTF_UP;
|
msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
|
||||||
|
|
||||||
if (net->n.pxlen == HOST_MASK)
|
if (net->n.pxlen == MAX_PREFIX_LENGTH)
|
||||||
{
|
{
|
||||||
msg.rtm.rtm_flags |= RTF_HOST;
|
msg.rtm.rtm_flags |= RTF_HOST;
|
||||||
}
|
}
|
||||||
|
@ -200,12 +176,12 @@ krt_sock_send(int cmd, rte *e)
|
||||||
msg.rtm.rtm_msglen = l;
|
msg.rtm.rtm_msglen = l;
|
||||||
|
|
||||||
if ((l = write(rt_sock, (char *)&msg, l)) < 0) {
|
if ((l = write(rt_sock, (char *)&msg, l)) < 0) {
|
||||||
log(L_ERR "KIF: error writting route to socket (%I/%d)", net->n.prefix, net->n.pxlen);
|
log(L_ERR "KIF: Error sending route %I/%d to kernel", net->n.prefix, net->n.pxlen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_set_notify(struct krt_proto *p UNUSED, net *net UNUSED, rte *new, rte *old)
|
krt_set_notify(struct krt_proto *p UNUSED, net *net, rte *new, rte *old)
|
||||||
{
|
{
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
|
@ -258,68 +234,87 @@ krt_set_start(struct krt_proto *x, int first UNUSED)
|
||||||
bug("krt-sock: sk_open failed");
|
bug("krt-sock: sk_open failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
{
|
{
|
||||||
sockaddr gate, mask, dst;
|
|
||||||
rta a;
|
rta a;
|
||||||
rte *e;
|
rte *e;
|
||||||
net *net;
|
net *net;
|
||||||
|
sockaddr dst, gate, mask;
|
||||||
ip_addr idst, igate, imask;
|
ip_addr idst, igate, imask;
|
||||||
void *body = (char *)msg->buf;
|
void *body = (char *)msg->buf;
|
||||||
int new = (msg->rtm.rtm_type == RTM_ADD);
|
int new = (msg->rtm.rtm_type == RTM_ADD);
|
||||||
int src;
|
int src;
|
||||||
|
char *errmsg = "KRT: Invalid route received";
|
||||||
int flags = msg->rtm.rtm_flags;
|
int flags = msg->rtm.rtm_flags;
|
||||||
int addrs = msg->rtm.rtm_addrs;
|
int addrs = msg->rtm.rtm_addrs;
|
||||||
int masklen = -1;
|
|
||||||
|
|
||||||
if (!(flags & RTF_UP))
|
if (!(flags & RTF_UP) && scan)
|
||||||
{
|
SKIP("not up in scan\n");
|
||||||
DBG("Down.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & RTF_HOST)
|
if (!(flags & RTF_DONE) && !scan)
|
||||||
masklen = HOST_MASK;
|
SKIP("not done in async\n");
|
||||||
|
|
||||||
if(!CHECK_FAMILY(body)) return;
|
if (flags & RTF_LLINFO)
|
||||||
|
SKIP("link-local\n");
|
||||||
|
|
||||||
if(msg->rtm.rtm_flags & RTF_LLINFO) return; /* ARPs etc. */
|
GETADDR(&dst, RTA_DST);
|
||||||
|
GETADDR(&gate, RTA_GATEWAY);
|
||||||
#define GETADDR(p, F) \
|
GETADDR(&mask, RTA_NETMASK);
|
||||||
bzero(p, sizeof(*p));\
|
|
||||||
if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
|
|
||||||
unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
|
|
||||||
memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
|
|
||||||
body += l;}
|
|
||||||
|
|
||||||
GETADDR (&dst, RTA_DST);
|
|
||||||
GETADDR (&gate, RTA_GATEWAY);
|
|
||||||
GETADDR (&mask, RTA_NETMASK);
|
|
||||||
|
|
||||||
idst = IPA_NONE;
|
|
||||||
igate = IPA_NONE;
|
|
||||||
imask = IPA_NONE;
|
|
||||||
|
|
||||||
|
if (sa_family_check(&dst))
|
||||||
get_sockaddr(&dst, &idst, NULL, 0);
|
get_sockaddr(&dst, &idst, NULL, 0);
|
||||||
if(CHECK_FAMILY(&gate)) get_sockaddr(&gate, &igate, NULL, 0);
|
else
|
||||||
|
SKIP("invalid DST");
|
||||||
|
|
||||||
|
/* We will check later whether we have valid gateway addr */
|
||||||
|
if (sa_family_check(&gate))
|
||||||
|
get_sockaddr(&gate, &igate, NULL, 0);
|
||||||
|
else
|
||||||
|
igate = IPA_NONE;
|
||||||
|
|
||||||
|
/* We do not test family for RTA_NETMASK, because BSD sends us
|
||||||
|
some strange values, but interpreting them as IPv4/IPv6 works */
|
||||||
get_sockaddr(&mask, &imask, NULL, 0);
|
get_sockaddr(&mask, &imask, NULL, 0);
|
||||||
|
|
||||||
if (masklen < 0) masklen = ipa_mklen(imask);
|
int c = ipa_classify_net(idst);
|
||||||
|
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
|
SKIP("strange class/scope\n");
|
||||||
|
|
||||||
|
int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_mklen(imask);
|
||||||
|
if (pxlen < 0)
|
||||||
|
{ log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
|
||||||
|
|
||||||
|
if ((flags & RTF_GATEWAY) && ipa_zero(igate))
|
||||||
|
{ log(L_ERR "%s (%I/%d) - missing gateway", errmsg, idst, pxlen); return; }
|
||||||
|
|
||||||
|
u32 self_mask = RTF_PROTO1;
|
||||||
|
u32 alien_mask = RTF_STATIC | RTF_PROTO1;
|
||||||
|
|
||||||
|
#ifdef RTF_PROTO2
|
||||||
|
alien_mask |= RTF_PROTO2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RTF_PROTO3
|
||||||
|
alien_mask |= RTF_PROTO3;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
|
if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
|
||||||
|
src = KRT_SRC_REDIRECT;
|
||||||
|
else if (flags & self_mask)
|
||||||
{
|
{
|
||||||
log(L_WARN "krt: Ignoring redirect to %I/%d via %I", idst, masklen, igate);
|
if (!scan)
|
||||||
return;
|
SKIP("echo\n");
|
||||||
|
src = KRT_SRC_BIRD;
|
||||||
}
|
}
|
||||||
|
else if (flags & alien_mask)
|
||||||
|
src = KRT_SRC_ALIEN;
|
||||||
|
else
|
||||||
|
src = KRT_SRC_KERNEL;
|
||||||
|
|
||||||
if (masklen < 0)
|
net = net_get(p->p.table, idst, pxlen);
|
||||||
{
|
|
||||||
log(L_WARN "krt: Got invalid route from kernel!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
net = net_get(p->p.table, idst, masklen);
|
|
||||||
|
|
||||||
bzero(&a, sizeof(a));
|
bzero(&a, sizeof(a));
|
||||||
|
|
||||||
|
@ -333,56 +328,56 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
a.iface = NULL;
|
a.iface = NULL;
|
||||||
a.eattrs = NULL;
|
a.eattrs = NULL;
|
||||||
|
|
||||||
a.dest = RTD_NONE;
|
/* reject/blackhole routes have also set RTF_GATEWAY,
|
||||||
|
we wil check them first. */
|
||||||
if (flags & RTF_GATEWAY)
|
|
||||||
{
|
|
||||||
neighbor *ng = neigh_find(&p->p, &igate, 0);
|
|
||||||
if (ng && ng->scope)
|
|
||||||
a.iface = ng->iface;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.dest = RTD_ROUTER;
|
|
||||||
a.gw = igate;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a.dest = RTD_DEVICE;
|
|
||||||
a.gw = IPA_NONE;
|
|
||||||
a.iface = krt_temp_iface_index(p, msg->rtm.rtm_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef RTF_REJECT
|
#ifdef RTF_REJECT
|
||||||
if(flags & RTF_REJECT) {
|
if(flags & RTF_REJECT) {
|
||||||
a.dest = RTD_UNREACHABLE;
|
a.dest = RTD_UNREACHABLE;
|
||||||
a.gw = IPA_NONE;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RTF_BLACKHOLE
|
#ifdef RTF_BLACKHOLE
|
||||||
if(flags & RTF_BLACKHOLE) {
|
if(flags & RTF_BLACKHOLE) {
|
||||||
a.dest = RTD_BLACKHOLE;
|
a.dest = RTD_BLACKHOLE;
|
||||||
a.gw = IPA_NONE;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (a.dest == RTD_NONE)
|
a.iface = if_find_by_index(msg->rtm.rtm_index);
|
||||||
|
if (!a.iface)
|
||||||
{
|
{
|
||||||
log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
|
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
|
||||||
|
net->n.prefix, net->n.pxlen, msg->rtm.rtm_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
src = KRT_SRC_UNKNOWN; /* FIXME */
|
if (flags & RTF_GATEWAY)
|
||||||
|
{
|
||||||
|
neighbor *ng;
|
||||||
|
a.dest = RTD_ROUTER;
|
||||||
|
a.gw = igate;
|
||||||
|
|
||||||
|
ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
|
||||||
|
if (!ng || (ng->scope == SCOPE_HOST))
|
||||||
|
{
|
||||||
|
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
|
||||||
|
net->n.prefix, net->n.pxlen, a.gw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
a.dest = RTD_DEVICE;
|
||||||
|
|
||||||
|
done:
|
||||||
e = rte_get_temp(&a);
|
e = rte_get_temp(&a);
|
||||||
e->net = net;
|
e->net = net;
|
||||||
e->u.krt.src = src;
|
e->u.krt.src = src;
|
||||||
//e->u.krt.proto = i->rtm_protocol;
|
|
||||||
//e->u.krt.type = i->rtm_type;
|
/* These are probably too Linux-specific */
|
||||||
|
e->u.krt.proto = 0;
|
||||||
|
e->u.krt.type = 0;
|
||||||
e->u.krt.metric = 0;
|
e->u.krt.metric = 0;
|
||||||
|
|
||||||
if (scan)
|
if (scan)
|
||||||
|
@ -471,6 +466,10 @@ krt_read_addr(struct ks_msg *msg)
|
||||||
int scope, masklen = -1;
|
int scope, masklen = -1;
|
||||||
int new = (ifam->ifam_type == RTM_NEWADDR);
|
int new = (ifam->ifam_type == RTM_NEWADDR);
|
||||||
|
|
||||||
|
/* Strange messages with zero (invalid) ifindex appear on OpenBSD */
|
||||||
|
if (ifam->ifam_index == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if(!(iface = if_find_by_index(ifam->ifam_index)))
|
if(!(iface = if_find_by_index(ifam->ifam_index)))
|
||||||
{
|
{
|
||||||
log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
|
log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
|
||||||
|
@ -486,7 +485,9 @@ krt_read_addr(struct ks_msg *msg)
|
||||||
GETADDR (&null, RTA_AUTHOR);
|
GETADDR (&null, RTA_AUTHOR);
|
||||||
GETADDR (&brd, RTA_BRD);
|
GETADDR (&brd, RTA_BRD);
|
||||||
|
|
||||||
if(!CHECK_FAMILY(&addr)) return; /* Some other family address */
|
/* Some other family address */
|
||||||
|
if (!sa_family_check(&addr))
|
||||||
|
return;
|
||||||
|
|
||||||
get_sockaddr(&addr, &iaddr, NULL, 0);
|
get_sockaddr(&addr, &iaddr, NULL, 0);
|
||||||
get_sockaddr(&mask, &imask, NULL, 0);
|
get_sockaddr(&mask, &imask, NULL, 0);
|
||||||
|
@ -593,27 +594,27 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
||||||
mib[4] = cmd;
|
mib[4] = cmd;
|
||||||
mib[5] = 0;
|
mib[5] = 0;
|
||||||
|
|
||||||
if( sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
|
if (sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
die("RT scan...");
|
die("RT scan...");
|
||||||
}
|
}
|
||||||
|
|
||||||
obl = *bl;
|
obl = *bl;
|
||||||
|
|
||||||
while(needed > *bl) *bl *= 2;
|
while (needed > *bl) *bl *= 2;
|
||||||
while(needed < (*bl/2)) *bl /= 2;
|
while (needed < (*bl/2)) *bl /= 2;
|
||||||
|
|
||||||
if( (obl!=*bl) || !*buf)
|
if ((obl!=*bl) || !*buf)
|
||||||
{
|
{
|
||||||
if(*buf) mb_free(*buf);
|
if (*buf) mb_free(*buf);
|
||||||
if( (*buf = mb_alloc(pool, *bl)) == NULL ) die("RT scan buf alloc");
|
if ((*buf = mb_alloc(pool, *bl)) == NULL) die("RT scan buf alloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
on = needed;
|
on = needed;
|
||||||
|
|
||||||
if( sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
|
if (sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
|
||||||
{
|
{
|
||||||
if(on != needed) return; /* The buffer size changed since last sysctl */
|
if (on != needed) return; /* The buffer size changed since last sysctl */
|
||||||
die("RT scan 2");
|
die("RT scan 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,22 +625,23 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte *krt_buffer = NULL;
|
||||||
|
static byte *kif_buffer = NULL;
|
||||||
|
static size_t krt_buflen = 32768;
|
||||||
|
static size_t kif_buflen = 4096;
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_fire(struct krt_proto *p)
|
krt_scan_fire(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
static byte *buf = NULL;
|
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
|
||||||
static size_t bl = 32768;
|
|
||||||
krt_sysctl_scan((struct proto *)p , p->krt_pool, &buf, &bl, NET_RT_DUMP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_if_scan(struct kif_proto *p)
|
krt_if_scan(struct kif_proto *p)
|
||||||
{
|
{
|
||||||
static byte *buf = NULL;
|
|
||||||
static size_t bl = 4096;
|
|
||||||
struct proto *P = (struct proto *)p;
|
struct proto *P = (struct proto *)p;
|
||||||
if_start_update();
|
if_start_update();
|
||||||
krt_sysctl_scan(P, P->pool, &buf, &bl, NET_RT_IFLIST);
|
krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST);
|
||||||
if_end_update();
|
if_end_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,6 +654,8 @@ krt_set_construct(struct krt_config *c UNUSED)
|
||||||
void
|
void
|
||||||
krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
krt_set_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
||||||
{
|
{
|
||||||
|
mb_free(krt_buffer);
|
||||||
|
krt_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -672,5 +676,7 @@ krt_if_start(struct kif_proto *p UNUSED)
|
||||||
void
|
void
|
||||||
krt_if_shutdown(struct kif_proto *p UNUSED)
|
krt_if_shutdown(struct kif_proto *p UNUSED)
|
||||||
{
|
{
|
||||||
|
mb_free(kif_buffer);
|
||||||
|
kif_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#define IPV6
|
#define IPV6
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
#define CONFIG_AUTO_ROUTES
|
||||||
#undef CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
#undef CONFIG_MULTIPLE_TABLES
|
||||||
|
|
||||||
#undef CONFIG_UNIX_IFACE
|
#undef CONFIG_UNIX_IFACE
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CONFIG_AUTO_ROUTES
|
#define CONFIG_AUTO_ROUTES
|
||||||
#undef CONFIG_SELF_CONSCIOUS
|
#define CONFIG_SELF_CONSCIOUS
|
||||||
#undef CONFIG_MULTIPLE_TABLES
|
#undef CONFIG_MULTIPLE_TABLES
|
||||||
|
|
||||||
#undef CONFIG_UNIX_IFACE
|
#undef CONFIG_UNIX_IFACE
|
||||||
|
|
|
@ -52,7 +52,6 @@ struct nl_sock
|
||||||
static struct nl_sock nl_scan = {.fd = -1}; /* Netlink socket for synchronous scan */
|
static struct nl_sock nl_scan = {.fd = -1}; /* Netlink socket for synchronous scan */
|
||||||
static struct nl_sock nl_req = {.fd = -1}; /* Netlink socket for requests */
|
static struct nl_sock nl_req = {.fd = -1}; /* Netlink socket for requests */
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nl_open_sock(struct nl_sock *nl)
|
nl_open_sock(struct nl_sock *nl)
|
||||||
{
|
{
|
||||||
|
@ -555,23 +554,7 @@ krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
|
||||||
nl_send_route(p, new, 1);
|
nl_send_route(p, new, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct iface *
|
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
|
||||||
krt_temp_iface(struct krt_proto *p, unsigned index)
|
|
||||||
{
|
|
||||||
struct iface *i, *j;
|
|
||||||
|
|
||||||
WALK_LIST(i, p->scan.temp_ifs)
|
|
||||||
if (i->index == index)
|
|
||||||
return i;
|
|
||||||
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
|
||||||
if (j = if_find_by_index(index))
|
|
||||||
strcpy(i->name, j->name);
|
|
||||||
else
|
|
||||||
strcpy(i->name, "?");
|
|
||||||
i->index = index;
|
|
||||||
add_tail(&p->scan.temp_ifs, &i->n);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nl_parse_route(struct nlmsghdr *h, int scan)
|
nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
|
@ -599,31 +582,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
#endif
|
#endif
|
||||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
|
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
|
||||||
{
|
{
|
||||||
log(L_ERR "nl_parse_route: Malformed message received");
|
log(L_ERR "KRT: Malformed message received");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = nl_table_map[i->rtm_table]; /* Do we know this table? */
|
|
||||||
if (!p)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef IPV6
|
|
||||||
if (a[RTA_IIF])
|
|
||||||
{
|
|
||||||
DBG("KRT: Ignoring route with IIF set\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (i->rtm_tos != 0) /* We don't support TOS */
|
|
||||||
{
|
|
||||||
DBG("KRT: Ignoring route with TOS %02x\n", i->rtm_tos);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (scan && !new)
|
|
||||||
{
|
|
||||||
DBG("KRT: Ignoring route deletion\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,33 +593,57 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dst = IPA_NONE;
|
dst = IPA_NONE;
|
||||||
|
|
||||||
if (a[RTA_OIF])
|
if (a[RTA_OIF])
|
||||||
memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
|
memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
|
||||||
else
|
else
|
||||||
oif = ~0;
|
oif = ~0;
|
||||||
|
|
||||||
DBG("Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
|
DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
|
||||||
|
|
||||||
|
p = nl_table_map[i->rtm_table]; /* Do we know this table? */
|
||||||
|
if (!p)
|
||||||
|
SKIP("unknown table %d", i->rtm_table);
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
if (a[RTA_IIF])
|
||||||
|
SKIP("IIF set\n");
|
||||||
|
#else
|
||||||
|
if (i->rtm_tos != 0) /* We don't support TOS */
|
||||||
|
SKIP("TOS %02x\n", i->rtm_tos);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (scan && !new)
|
||||||
|
SKIP("RTM_DELROUTE in scan\n");
|
||||||
|
|
||||||
|
int c = ipa_classify_net(dst);
|
||||||
|
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
|
SKIP("strange class/scope\n");
|
||||||
|
|
||||||
|
// ignore rtm_scope, it is not a real scope
|
||||||
|
// if (i->rtm_scope != RT_SCOPE_UNIVERSE)
|
||||||
|
// SKIP("scope %u\n", i->rtm_scope);
|
||||||
|
|
||||||
switch (i->rtm_protocol)
|
switch (i->rtm_protocol)
|
||||||
{
|
{
|
||||||
|
case RTPROT_UNSPEC:
|
||||||
|
SKIP("proto unspec\n");
|
||||||
|
|
||||||
case RTPROT_REDIRECT:
|
case RTPROT_REDIRECT:
|
||||||
src = KRT_SRC_REDIRECT;
|
src = KRT_SRC_REDIRECT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RTPROT_KERNEL:
|
case RTPROT_KERNEL:
|
||||||
DBG("Route originated in kernel, ignoring\n");
|
src = KRT_SRC_KERNEL;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case RTPROT_BIRD:
|
case RTPROT_BIRD:
|
||||||
#ifdef IPV6
|
|
||||||
case RTPROT_BOOT:
|
|
||||||
/* Current Linux kernels don't remember rtm_protocol for IPv6 routes and supply RTPROT_BOOT instead */
|
|
||||||
#endif
|
|
||||||
if (!scan)
|
if (!scan)
|
||||||
{
|
SKIP("echo\n");
|
||||||
DBG("Echo of our own route, ignoring\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
src = KRT_SRC_BIRD;
|
src = KRT_SRC_BIRD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RTPROT_BOOT:
|
||||||
default:
|
default:
|
||||||
src = KRT_SRC_ALIEN;
|
src = KRT_SRC_ALIEN;
|
||||||
}
|
}
|
||||||
|
@ -679,52 +662,48 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
switch (i->rtm_type)
|
switch (i->rtm_type)
|
||||||
{
|
{
|
||||||
case RTN_UNICAST:
|
case RTN_UNICAST:
|
||||||
if (oif == ~0U)
|
ra.iface = if_find_by_index(oif);
|
||||||
|
if (!ra.iface)
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Mysterious route with no OIF (%I/%d)", net->n.prefix, net->n.pxlen);
|
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
|
||||||
|
net->n.prefix, net->n.pxlen, oif);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a[RTA_GATEWAY])
|
if (a[RTA_GATEWAY])
|
||||||
{
|
{
|
||||||
struct iface *ifa = if_find_by_index(oif);
|
|
||||||
neighbor *ng;
|
neighbor *ng;
|
||||||
ra.dest = RTD_ROUTER;
|
ra.dest = RTD_ROUTER;
|
||||||
memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
|
memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
|
||||||
ipa_ntoh(ra.gw);
|
ipa_ntoh(ra.gw);
|
||||||
|
|
||||||
if (i->rtm_flags & RTNH_F_ONLINK)
|
ng = neigh_find2(&p->p, &ra.gw, ra.iface,
|
||||||
|
(i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
|
||||||
|
if (!ng || (ng->scope == SCOPE_HOST))
|
||||||
{
|
{
|
||||||
/* route with 'onlink' attribute */
|
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
|
||||||
ra.iface = if_find_by_index(oif);
|
net->n.prefix, net->n.pxlen, ra.gw);
|
||||||
if (ra.iface == NULL)
|
|
||||||
{
|
|
||||||
log(L_WARN "Kernel told us to use unknown interface %u for %I/%d",
|
|
||||||
oif, net->n.prefix, net->n.pxlen);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ng = neigh_find2(&p->p, &ra.gw, ifa, 0);
|
|
||||||
if (ng && ng->scope)
|
|
||||||
{
|
|
||||||
if (ng->iface != ifa)
|
|
||||||
log(L_WARN "KRT: Route with unexpected iface for %I/%d", net->n.prefix, net->n.pxlen);
|
|
||||||
ra.iface = ng->iface;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ra.dest = RTD_DEVICE;
|
ra.dest = RTD_DEVICE;
|
||||||
ra.iface = krt_temp_iface(p, oif);
|
|
||||||
|
/*
|
||||||
|
* In Linux IPv6, 'native' device routes have proto
|
||||||
|
* RTPROT_BOOT and not RTPROT_KERNEL (which they have in
|
||||||
|
* IPv4 and which is expected). We cannot distinguish
|
||||||
|
* 'native' and user defined device routes, so we ignore all
|
||||||
|
* such device routes and for consistency, we have the same
|
||||||
|
* behavior in IPv4. Anyway, users should use RTPROT_STATIC
|
||||||
|
* for their 'alien' routes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (i->rtm_protocol == RTPROT_BOOT)
|
||||||
|
src = KRT_SRC_KERNEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case RTN_BLACKHOLE:
|
case RTN_BLACKHOLE:
|
||||||
ra.dest = RTD_BLACKHOLE;
|
ra.dest = RTD_BLACKHOLE;
|
||||||
|
@ -737,13 +716,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
break;
|
break;
|
||||||
/* FIXME: What about RTN_THROW? */
|
/* FIXME: What about RTN_THROW? */
|
||||||
default:
|
default:
|
||||||
DBG("KRT: Ignoring route with type=%d\n", i->rtm_type);
|
SKIP("type %d\n", i->rtm_type);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i->rtm_scope != RT_SCOPE_UNIVERSE)
|
|
||||||
{
|
|
||||||
DBG("KRT: Ignoring route with scope=%d\n", i->rtm_scope);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -663,7 +663,6 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
|
||||||
static char *
|
static char *
|
||||||
sk_set_ttl_int(sock *s)
|
sk_set_ttl_int(sock *s)
|
||||||
{
|
{
|
||||||
int one = 1;
|
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
||||||
return "IPV6_UNICAST_HOPS";
|
return "IPV6_UNICAST_HOPS";
|
||||||
|
@ -671,6 +670,7 @@ sk_set_ttl_int(sock *s)
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
||||||
return "IP_TTL";
|
return "IP_TTL";
|
||||||
#ifdef CONFIG_UNIX_DONTROUTE
|
#ifdef CONFIG_UNIX_DONTROUTE
|
||||||
|
int one = 1;
|
||||||
if (s->ttl == 1 && setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
if (s->ttl == 1 && setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
||||||
return "SO_DONTROUTE";
|
return "SO_DONTROUTE";
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -558,32 +558,30 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||||
rte *old;
|
rte *old;
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
int verdict;
|
int verdict;
|
||||||
#ifdef KRT_ALLOW_LEARN
|
|
||||||
int src = e->u.krt.src;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_AUTO_ROUTES
|
#ifdef KRT_ALLOW_LEARN
|
||||||
if (e->attrs->dest == RTD_DEVICE)
|
switch (e->u.krt.src)
|
||||||
{
|
{
|
||||||
/* It's a device route. Probably a kernel-generated one. */
|
case KRT_SRC_KERNEL:
|
||||||
verdict = KRF_IGNORE;
|
verdict = KRF_IGNORE;
|
||||||
goto sentenced;
|
goto sentenced;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef KRT_ALLOW_LEARN
|
case KRT_SRC_REDIRECT:
|
||||||
if (src == KRT_SRC_ALIEN)
|
verdict = KRF_DELETE;
|
||||||
{
|
goto sentenced;
|
||||||
|
|
||||||
|
case KRT_SRC_ALIEN:
|
||||||
if (KRT_CF->learn)
|
if (KRT_CF->learn)
|
||||||
krt_learn_scan(p, e);
|
krt_learn_scan(p, e);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
krt_trace_in_rl(&rl_alien_ignored, p, e, "alien route, ignored");
|
krt_trace_in_rl(&rl_alien_ignored, p, e, "[alien] ignored");
|
||||||
rte_free(e);
|
rte_free(e);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
|
||||||
|
|
||||||
if (net->n.flags & KRF_VERDICT_MASK)
|
if (net->n.flags & KRF_VERDICT_MASK)
|
||||||
{
|
{
|
||||||
|
@ -605,7 +603,7 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||||
else
|
else
|
||||||
verdict = KRF_DELETE;
|
verdict = KRF_DELETE;
|
||||||
|
|
||||||
sentenced:
|
sentenced:
|
||||||
krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]);
|
krt_trace_in(p, e, ((char *[]) { "?", "seen", "will be updated", "will be removed", "ignored" }) [verdict]);
|
||||||
net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict;
|
net->n.flags = (net->n.flags & ~KRF_VERDICT_MASK) | verdict;
|
||||||
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
||||||
|
@ -680,19 +678,24 @@ krt_prune(struct krt_proto *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_got_route_async(struct krt_proto *p, rte *e, int new UNUSED)
|
krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
||||||
{
|
{
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
int src = e->u.krt.src;
|
|
||||||
|
|
||||||
switch (src)
|
switch (e->u.krt.src)
|
||||||
{
|
{
|
||||||
case KRT_SRC_BIRD:
|
case KRT_SRC_BIRD:
|
||||||
ASSERT(0); /* Should be filtered by the back end */
|
ASSERT(0); /* Should be filtered by the back end */
|
||||||
|
|
||||||
case KRT_SRC_REDIRECT:
|
case KRT_SRC_REDIRECT:
|
||||||
DBG("It's a redirect, kill him! Kill! Kill!\n");
|
if (new)
|
||||||
|
{
|
||||||
|
krt_trace_in(p, e, "[redirect] deleting");
|
||||||
krt_set_notify(p, net, NULL, e);
|
krt_set_notify(p, net, NULL, e);
|
||||||
|
}
|
||||||
|
/* If !new, it is probably echo of our deletion */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
case KRT_SRC_ALIEN:
|
case KRT_SRC_ALIEN:
|
||||||
if (KRT_CF->learn)
|
if (KRT_CF->learn)
|
||||||
|
@ -878,7 +881,6 @@ krt_init(struct proto_config *c)
|
||||||
|
|
||||||
p->p.accept_ra_types = RA_OPTIMAL;
|
p->p.accept_ra_types = RA_OPTIMAL;
|
||||||
p->p.rt_notify = krt_notify;
|
p->p.rt_notify = krt_notify;
|
||||||
p->p.min_scope = SCOPE_HOST;
|
|
||||||
return &p->p;
|
return &p->p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
|
||||||
#define KRT_SRC_BIRD 0 /* Our route (not passed in async mode) */
|
#define KRT_SRC_BIRD 0 /* Our route (not passed in async mode) */
|
||||||
#define KRT_SRC_REDIRECT 1 /* Redirect route, delete it */
|
#define KRT_SRC_REDIRECT 1 /* Redirect route, delete it */
|
||||||
#define KRT_SRC_ALIEN 2 /* Route installed by someone else */
|
#define KRT_SRC_ALIEN 2 /* Route installed by someone else */
|
||||||
|
#define KRT_SRC_KERNEL 3 /* Kernel routes, are ignored by krt syncer */
|
||||||
|
|
||||||
extern struct protocol proto_unix_iface;
|
extern struct protocol proto_unix_iface;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#ifndef _BIRD_UNIX_H_
|
#ifndef _BIRD_UNIX_H_
|
||||||
#define _BIRD_UNIX_H_
|
#define _BIRD_UNIX_H_
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
struct pool;
|
struct pool;
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
|
@ -29,10 +31,12 @@ volatile int async_shutdown_flag;
|
||||||
#define BIRD_PF PF_INET6
|
#define BIRD_PF PF_INET6
|
||||||
#define BIRD_AF AF_INET6
|
#define BIRD_AF AF_INET6
|
||||||
typedef struct sockaddr_in6 sockaddr;
|
typedef struct sockaddr_in6 sockaddr;
|
||||||
|
static inline int sa_family_check(sockaddr *sa) { return sa->sin6_family == AF_INET6; }
|
||||||
#else
|
#else
|
||||||
#define BIRD_PF PF_INET
|
#define BIRD_PF PF_INET
|
||||||
#define BIRD_AF AF_INET
|
#define BIRD_AF AF_INET
|
||||||
typedef struct sockaddr_in sockaddr;
|
typedef struct sockaddr_in sockaddr;
|
||||||
|
static inline int sa_family_check(sockaddr *sa) { return sa->sin_family == AF_INET; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SUN_LEN
|
#ifndef SUN_LEN
|
||||||
|
|
Loading…
Reference in a new issue