char *syslog_name; /* Name used for syslog (NULL -> no syslog) */
struct rtable_config *def_tables[NET_MAX]; /* Default routing tables for each network */
struct iface_patt *router_id_from; /* Configured list of router ID iface patterns */
+ struct rtable_config *local4;
+ struct rtable_config *local6;
u32 router_id; /* Our Router ID */
unsigned proto_default_debug; /* Default protocol debug mask */
CF_KEYWORDS(BGP, PASSWORDS, DESCRIPTION, SORTED, ORDERED)
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
-CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS)
+CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS, STATISTICS, NETWORKS, ADDRESSES)
/* For r_args_channel */
CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC)
return neigh_find2(p, a, NULL, flags);
}
+struct iface * net_route_ifa(const ip_addr *a, struct iface *vrf);
+
neighbor *
neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags)
scope = class & IADDR_SCOPE_MASK;
}
else
- WALK_LIST(i, iface_list)
- if ((!p->vrf || p->vrf == i->master) &&
+ {
+ if ((i = net_route_ifa(a, p->vrf)) &&
((scope = if_connected(a, i, &addr)) >= 0))
- {
- ifa = i;
- break;
- }
+ ifa = i;
+ }
/* scope < 0 means i don't know neighbor */
/* scope >= 0 implies ifa != NULL */
p->proto = cf->protocol;
p->net_type = cf->net_type;
p->disabled = cf->disabled;
+ p->hidden = cf->hidden;
p->hash_key = random_u32();
cf->proto = p;
DBG("Protocol start\n");
- /* Start device protocol first */
+
+ /* Start direct protocols first */
+ WALK_LIST_DELSAFE(p, n, proto_list)
+ if (p->proto == &proto_device)
+ proto_rethink_goal(p);
+
+ /* Start device protocol second */
if (first_dev_proto)
proto_rethink_goal(first_dev_proto);
int cnt = 0;
WALK_LIST(p, proto_list)
- if (!patt || patmatch(patt, p->name))
+ if ((!patt || patmatch(patt, p->name)) && !p->hidden)
cmd(p, arg, cnt++);
if (!cnt)
{
p = NULL;
WALK_LIST(q, proto_list)
- if ((q->proto == pr) && (q->proto_state != PS_DOWN))
+ if ((q->proto == pr) && (q->proto_state != PS_DOWN) && !q->hidden)
{
if (p)
cf_error("There are multiple %s protocols running", pr->name);
int class; /* SYM_PROTO or SYM_TEMPLATE */
u8 net_type; /* Protocol network type (NET_*), 0 for undefined */
u8 disabled; /* Protocol enabled/disabled by default */
+ byte hidden; /* Protocol not showed in show protocols */
u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */
u32 router_id; /* Protocol specific router ID */
byte gr_recovery; /* Protocol should participate in graceful restart recovery */
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
byte down_code; /* Reason for shutdown (PDC_* codes) */
+ byte hidden; /* Protocol not showed in show protocols */
u32 hash_key; /* Random key used for hashing of neighbors */
btime last_state_change; /* Time of last state transition */
char *last_state_name_announced; /* Last state name we've announced to the user */
if (!c)
return;
+ if (cf->host_ip)
+ {
+ net = alloca(sizeof(net_addr));
+ net_fill_ip_host(net, ad->ip);
+ }
+
/* For IPv6 SADR, replace regular prefix with SADR prefix */
if (c->net_type == NET_IP6_SADR)
{
struct proto_config c;
list iface_list; /* list of struct iface_patt */
int check_link;
+ int host_ip; /* Annunce local IP instead of prefix */
struct channel_config *ip4_channel;
struct channel_config *ip6_channel;
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
+#include "nest/rt-dev.h"
#include "nest/cli.h"
#include "lib/resource.h"
#include "lib/event.h"
}
}
+static inline struct iface *
+net_route_ifa4(rtable *t, net_addr_ip4 *a, struct iface *vrf)
+{
+ while (1)
+ {
+ if (!BIT32_TEST(t->pxlens, a->pxlen))
+ goto next;
+
+ net *n = net_find(t, (net_addr *) a);
+
+ if (!n)
+ goto next;
+
+ for (rte *e = n->routes; e; e = e->next)
+ {
+ struct iface *i = e->attrs->nh.iface;
+ if (rte_is_valid(e) &&
+ (e->attrs->dest == RTD_UNICAST) &&
+ (!vrf || vrf == i->master))
+ return i;
+ }
+
+ next:
+ if (!a->pxlen)
+ return NULL;
+
+ a->pxlen--;
+ ip4_clrbit(&a->prefix, a->pxlen);
+ }
+}
+
+static inline struct iface *
+net_route_ifa6(rtable *t, net_addr_ip6 *a, struct iface *vrf)
+{
+ while (1)
+ {
+ if (!BIT32_TEST(t->pxlens, a->pxlen))
+ goto next;
+
+ net *n = net_find(t, (net_addr *) a);
+
+ if (!n)
+ goto next;
+
+ for (rte *e = n->routes; e; e = e->next)
+ {
+ struct iface *i = e->attrs->nh.iface;
+ if (rte_is_valid(e) &&
+ (e->attrs->dest == RTD_UNICAST) &&
+ (!vrf || vrf == i->master))
+ return i;
+ }
+
+ next:
+ if (!a->pxlen)
+ return NULL;
+
+ a->pxlen--;
+ ip6_clrbit(&a->prefix, a->pxlen);
+ }
+}
+
+struct iface *
+net_route_ifa(const ip_addr *a, struct iface *vrf)
+{
+ net_addr n0;
+ net_fill_ip_host(&n0, *a);
+
+ switch (n0.type)
+ {
+ case NET_IP4:
+ return net_route_ifa4(config->local4->table, (net_addr_ip4 *) &n0, vrf);
+
+ case NET_IP6:
+ return net_route_ifa6(config->local6->table, (net_addr_ip6 *) &n0, vrf);
+
+ default:
+ return NULL;
+ }
+}
+
static int
net_roa_check_ip4(rtable *tab, const net_addr_ip4 *px, u32 asn)
rt_new_table(cf_get_symbol("master4"), NET_IP4);
rt_new_table(cf_get_symbol("master6"), NET_IP6);
+
+ c->local4 = rt_new_table(cf_get_symbol("local4"), NET_IP4);
+ c->local6 = rt_new_table(cf_get_symbol("local6"), NET_IP6);
+
+
+ /* Define two direct protocols and connect them to local tables */
+
+ struct symbol *s;
+ struct rt_dev_config *dev;
+ static struct channel_config *cc;
+
+ s = cf_get_symbol("networks");
+ dev = proto_config_new(&proto_device, SYM_PROTO);
+ init_list(&dev->iface_list);
+ cf_define_symbol(s, SYM_PROTO, dev);
+ dev->c.name = s->name;
+ dev->c.hidden = 1;
+ // dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
+
+ cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
+ cc->table = c->local4;
+
+ cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
+ cc->table = c->local6;
+
+ proto_device.postconfig(&dev->c);
+
+
+ s = cf_get_symbol("addresses");
+ dev = proto_config_new(&proto_device, SYM_PROTO);
+ init_list(&dev->iface_list);
+ cf_define_symbol(s, SYM_PROTO, dev);
+ dev->c.name = s->name;
+ dev->c.hidden = 1;
+ // dev->c.debug = D_EVENTS | D_STATES | D_IFACES;
+ dev->host_ip = 1;
+
+ cc = channel_config_get(NULL, net_label[NET_IP4], NET_IP4, &dev->c);
+ cc->table = c->local4;
+
+ cc = channel_config_get(NULL, net_label[NET_IP6], NET_IP6, &dev->c);
+ cc->table = c->local6;
+
+ proto_device.postconfig(&dev->c);
}