-/* $OpenBSD: eigrpd.c,v 1.2 2015/10/10 05:12:33 renato Exp $ */
+/* $OpenBSD: eigrpd.c,v 1.3 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
conf->rdomain= xconf->rdomain;
conf->fib_priority_internal = xconf->fib_priority_internal;
conf->fib_priority_external = xconf->fib_priority_external;
+ conf->fib_priority_summary = xconf->fib_priority_summary;
/* merge instances */
TAILQ_FOREACH_SAFE(eigrp, &conf->instances, entry, etmp) {
-/* $OpenBSD: eigrpd.h,v 1.4 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: eigrpd.h,v 1.5 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
#define IF_STA_DOWN 0x01
#define IF_STA_ACTIVE 0x02
+struct summary_addr {
+ TAILQ_ENTRY(summary_addr) entry;
+ union eigrpd_addr prefix;
+ uint8_t prefixlen;
+};
+
struct eigrp_iface {
RB_ENTRY(eigrp_iface) id_tree;
TAILQ_ENTRY(eigrp_iface) e_entry;
struct nbr *self;
struct rinfo_head update_list; /* multicast updates */
struct rinfo_head query_list; /* multicast queries */
+ TAILQ_HEAD(, summary_addr) summary_list;
};
#define INADDRSZ 4
unsigned int rdomain;
uint8_t fib_priority_internal;
uint8_t fib_priority_external;
+ uint8_t fib_priority_summary;
TAILQ_HEAD(, iface) iface_list;
TAILQ_HEAD(, eigrp) instances;
char *csock;
const union eigrpd_addr *, int);
int eigrp_addrcmp(int, union eigrpd_addr *, union eigrpd_addr *);
int eigrp_addrisset(int, union eigrpd_addr *);
+int eigrp_prefixcmp(int, const union eigrpd_addr *,
+ const union eigrpd_addr *, uint8_t);
void embedscope(struct sockaddr_in6 *);
void recoverscope(struct sockaddr_in6 *);
void addscope(struct sockaddr_in6 *, uint32_t);
-/* $OpenBSD: eigrpe.c,v 1.5 2015/10/10 05:12:33 renato Exp $ */
+/* $OpenBSD: eigrpe.c,v 1.6 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
TAILQ_INIT(&nei->nbr_list);
TAILQ_INIT(&nei->update_list);
TAILQ_INIT(&nei->query_list);
+ TAILQ_INIT(&nei->summary_list);
TAILQ_INSERT_TAIL(&niface->ei_list, nei, i_entry);
TAILQ_INSERT_TAIL(&neigrp->ei_list, nei, e_entry);
if (RB_INSERT(iface_id_head, &ifaces_by_id, nei) !=
-/* $OpenBSD: interface.c,v 1.7 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: interface.c,v 1.8 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
TAILQ_INIT(&ei->nbr_list);
TAILQ_INIT(&ei->update_list);
TAILQ_INIT(&ei->query_list);
+ TAILQ_INIT(&ei->summary_list);
TAILQ_INSERT_TAIL(&iface->ei_list, ei, i_entry);
TAILQ_INSERT_TAIL(&eigrp->ei_list, ei, e_entry);
if (RB_INSERT(iface_id_head, &ifaces_by_id, ei) != NULL)
void
eigrp_if_del(struct eigrp_iface *ei)
{
+ struct summary_addr *summary;
+
RB_REMOVE(iface_id_head, &ifaces_by_id, ei);
TAILQ_REMOVE(&ei->eigrp->ei_list, ei, e_entry);
TAILQ_REMOVE(&ei->iface->ei_list, ei, i_entry);
+ while ((summary = TAILQ_FIRST(&ei->summary_list)) != NULL) {
+ TAILQ_REMOVE(&ei->summary_list, summary, entry);
+ free(summary);
+ }
message_list_clr(&ei->query_list);
message_list_clr(&ei->update_list);
-/* $OpenBSD: kroute.c,v 1.2 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: kroute.c,v 1.3 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
}
if (kr.priority == eigrpd_conf->fib_priority_internal ||
- kr.priority == eigrpd_conf->fib_priority_external) {
+ kr.priority == eigrpd_conf->fib_priority_external ||
+ kr.priority == eigrpd_conf->fib_priority_summary) {
log_warnx("alien EIGRP route %s/%d", log_addr(kr.af, &kr.prefix),
kr.prefixlen);
return (send_rtmsg(kr_state.fd, RTM_DELETE, &kr));
-/* $OpenBSD: parse.y,v 1.3 2015/10/19 14:15:59 jsg Exp $ */
+/* $OpenBSD: parse.y,v 1.4 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
%token ROUTERID AS FIBUPDATE RDOMAIN REDISTRIBUTE METRIC DFLTMETRIC
%token MAXHOPS MAXPATHS VARIANCE FIBPRIORITY_INT FIBPRIORITY_EXT
+%token FIBPRIORITY_SUMM SUMMARY_ADDR
%token AF IPV4 IPV6 HELLOINTERVAL HOLDTIME KVALUES ACTIVETIMEOUT
%token INTERFACE PASSIVE DELAY BANDWIDTH SPLITHORIZON
%token YES NO
}
conf->fib_priority_external = $2;
}
+ | FIBPRIORITY_SUMM NUMBER {
+ if ($2 <= RTP_NONE || $2 > RTP_MAX) {
+ yyerror("invalid fib-priority");
+ YYERROR;
+ }
+ conf->fib_priority_summary = $2;
+ }
| defaults
;
;
interfaceoptsl : PASSIVE { ei->passive = 1; }
+ | SUMMARY_ADDR STRING {
+ struct summary_addr *s;
+
+ if ((s = calloc(1, sizeof(*s))) == NULL)
+ fatal(NULL);
+ if (host($2, &s->prefix, &s->prefixlen) < 0) {
+ yyerror("invalid summary-address");
+ free($2);
+ free(s);
+ YYERROR;
+ }
+
+ free($2);
+ TAILQ_INSERT_TAIL(&ei->summary_list, s, entry);
+ }
| iface_defaults
;
{"delay", DELAY},
{"fib-priority-external", FIBPRIORITY_EXT},
{"fib-priority-internal", FIBPRIORITY_INT},
+ {"fib-priority-summary", FIBPRIORITY_SUMM},
{"fib-update", FIBUPDATE},
{"hello-interval", HELLOINTERVAL},
{"holdtime", HOLDTIME},
{"redistribute", REDISTRIBUTE},
{"router-id", ROUTERID},
{"split-horizon", SPLITHORIZON},
+ {"summary-address", SUMMARY_ADDR},
{"variance", VARIANCE},
{"yes", YES}
};
conf->rdomain = 0;
conf->fib_priority_internal = RTP_EIGRP;
conf->fib_priority_external = RTP_EIGRP;
+ conf->fib_priority_summary = RTP_EIGRP;
memset(&globaldefs, 0, sizeof(globaldefs));
defs = &globaldefs;
-/* $OpenBSD: printconf.c,v 1.2 2015/10/04 22:54:38 renato Exp $ */
+/* $OpenBSD: printconf.c,v 1.3 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
printf("rdomain %u\n", conf->rdomain);
printf("fib-priority-internal %u\n", conf->fib_priority_internal);
printf("fib-priority-external %u\n", conf->fib_priority_external);
+ printf("fib-priority-summary %u\n", conf->fib_priority_summary);
}
const char *
void
print_iface(struct eigrp_iface *ei)
{
+ struct summary_addr *summary;
+
printf("\t\tinterface %s {\n", ei->iface->name);
printf("\t\t\thello-interval %u\n", ei->hello_interval);
printf("\t\t\tholdtime %u\n", ei->hello_holdtime);
printf("\t\t\tsplit-horizon %s\n", (ei->splithorizon) ? "yes" : "no");
if (ei->passive)
printf("\t\t\tpassive\n");
+ TAILQ_FOREACH(summary, &ei->summary_list, entry)
+ printf("\t\t\tsummary-address %s/%u\n", log_addr(ei->eigrp->af,
+ &summary->prefix), summary->prefixlen);
printf("\t\t}\n");
}
-/* $OpenBSD: rde.c,v 1.5 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: rde.c,v 1.6 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
TAILQ_INIT(&nei->nbr_list);
TAILQ_INIT(&nei->update_list);
TAILQ_INIT(&nei->query_list);
+ TAILQ_INIT(&nei->summary_list);
TAILQ_INSERT_TAIL(&niface->ei_list, nei, i_entry);
TAILQ_INSERT_TAIL(&neigrp->ei_list, nei, e_entry);
if (RB_INSERT(iface_id_head, &ifaces_by_id, nei) !=
}
}
+void
+rt_summary_set(struct eigrp *eigrp, struct summary_addr *summary,
+ struct classic_metric *metric)
+{
+ struct rinfo ri;
+
+ memset(&ri, 0, sizeof(ri));
+ ri.af = eigrp->af;
+ ri.type = EIGRP_ROUTE_INTERNAL;
+ memcpy(&ri.prefix, &summary->prefix, sizeof(ri.prefix));
+ ri.prefixlen = summary->prefixlen;
+ memcpy(&ri.metric, metric, sizeof(ri.metric));
+
+ rde_check_update(eigrp->rnbr_summary, &ri);
+}
+
/* send all known routing information to new neighbor */
void
rt_snap(struct rde_nbr *nbr)
struct rinfo ri;
RB_FOREACH(rn, rt_tree, &eigrp->topology)
- if (rn->state == DUAL_STA_PASSIVE) {
+ if (rn->state == DUAL_STA_PASSIVE &&
+ !rde_summary_check(nbr->ei, &rn->prefix, rn->prefixlen)) {
rinfo_fill_successor(rn, &ri);
rde_imsg_compose_eigrpe(IMSG_SEND_UPDATE,
nbr->peerid, 0, &ri, sizeof(ri));
-/* $OpenBSD: rde.h,v 1.3 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: rde.h,v 1.4 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
void rde_send_change_kroute(struct rt_node *, struct eigrp_route *);
void rde_send_delete_kroute(struct rt_node *, struct eigrp_route *);
void rt_redist_set(struct kroute *, int);
+void rt_summary_set(struct eigrp *, struct summary_addr *,
+ struct classic_metric *);
void rt_snap(struct rde_nbr *);
struct ctl_rt *rt_to_ctl(struct rt_node *, struct eigrp_route *);
void rt_dump(struct ctl_show_topology_req *, pid_t);
struct eigrp_route *);
struct eigrp_route *rt_get_successor_fc(struct rt_node *);
+struct summary_addr *rde_summary_check(struct eigrp_iface *,
+ union eigrpd_addr *, uint8_t);
void rde_send_update(struct eigrp_iface *, struct rinfo *);
void rde_send_update_all(struct rt_node *, struct rinfo *);
void rde_send_query(struct eigrp_iface *, struct rinfo *,
-/* $OpenBSD: rde_dual.c,v 1.6 2015/10/21 03:48:09 renato Exp $ */
+/* $OpenBSD: rde_dual.c,v 1.7 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
void
rt_set_successor(struct rt_node *rn, struct eigrp_route *successor)
{
+ struct eigrp *eigrp = rn->eigrp;
+ struct eigrp_iface *ei;
+ struct summary_addr *summary;
+
if (successor == NULL) {
rn->successor.nbr = NULL;
rn->successor.type = 0;
sizeof(rn->successor.metric));
memset(&rn->successor.emetric, 0,
sizeof(rn->successor.emetric));
- return;
+ } else {
+ rn->successor.nbr = successor->nbr;
+ rn->successor.type = successor->type;
+ rn->successor.fdistance = successor->distance;
+ rn->successor.rdistance = successor->rdistance;
+ memcpy(&rn->successor.metric, &successor->metric,
+ sizeof(rn->successor.metric));
+ memcpy(&rn->successor.emetric, &successor->emetric,
+ sizeof(rn->successor.emetric));
}
- rn->successor.nbr = successor->nbr;
- rn->successor.type = successor->type;
- rn->successor.fdistance = successor->distance;
- rn->successor.rdistance = successor->rdistance;
- memcpy(&rn->successor.metric, &successor->metric,
- sizeof(rn->successor.metric));
- memcpy(&rn->successor.emetric, &successor->emetric,
- sizeof(rn->successor.emetric));
+ TAILQ_FOREACH(ei, &eigrp->ei_list, e_entry) {
+ summary = rde_summary_check(ei, &rn->prefix, rn->prefixlen);
+ if (summary)
+ rt_summary_set(eigrp, summary, &rn->successor.metric);
+ }
}
struct eigrp_route *
return (successor);
}
+struct summary_addr *
+rde_summary_check(struct eigrp_iface *ei, union eigrpd_addr *prefix,
+ uint8_t prefixlen)
+{
+ struct summary_addr *summary;
+
+ TAILQ_FOREACH(summary, &ei->summary_list, entry) {
+ /* do not filter the summary itself */
+ if (summary->prefixlen == prefixlen &&
+ !eigrp_addrcmp(ei->eigrp->af, prefix, &summary->prefix))
+ return (NULL);
+
+ if (summary->prefixlen <= prefixlen &&
+ !eigrp_prefixcmp(ei->eigrp->af, prefix, &summary->prefix,
+ summary->prefixlen))
+ return (summary);
+ }
+
+ return (NULL);
+}
+
void
rde_send_update(struct eigrp_iface *ei, struct rinfo *ri)
{
- if (ri->metric.hop_count >= ei->eigrp->maximum_hops)
+ if (ri->metric.hop_count >= ei->eigrp->maximum_hops ||
+ rde_summary_check(ei, &ri->prefix, ri->prefixlen))
ri->metric.delay = EIGRP_INFINITE_METRIC;
rde_imsg_compose_eigrpe(IMSG_SEND_MUPDATE, ei->ifaceid, 0,
{
int type;
- if (ri->metric.hop_count >= nbr->eigrp->maximum_hops)
+ if (ri->metric.hop_count >= nbr->eigrp->maximum_hops ||
+ rde_summary_check(nbr->ei, &ri->prefix, ri->prefixlen))
ri->metric.delay = EIGRP_INFINITE_METRIC;
if (!siareply)
-/* $OpenBSD: util.c,v 1.2 2015/10/04 23:00:10 renato Exp $ */
+/* $OpenBSD: util.c,v 1.3 2015/10/21 03:52:12 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
return (0);
}
+int
+eigrp_prefixcmp(int af, const union eigrpd_addr *a, const union eigrpd_addr *b,
+ uint8_t prefixlen)
+{
+ in_addr_t mask, aa, ba;
+ int i;
+ uint8_t m;
+
+ switch (af) {
+ case AF_INET:
+ if (prefixlen == 0)
+ return (0);
+ if (prefixlen > 32)
+ fatalx("eigrp_prefixcmp: bad IPv4 prefixlen");
+ mask = htonl(prefixlen2mask(prefixlen));
+ aa = htonl(a->v4.s_addr) & mask;
+ ba = htonl(b->v4.s_addr) & mask;
+ return (aa - ba);
+ case AF_INET6:
+ if (prefixlen == 0)
+ return (0);
+ if (prefixlen > 128)
+ fatalx("eigrp_prefixcmp: bad IPv6 prefixlen");
+ for (i = 0; i < prefixlen / 8; i++)
+ if (a->v6.s6_addr[i] != b->v6.s6_addr[i])
+ return (a->v6.s6_addr[i] - b->v6.s6_addr[i]);
+ i = prefixlen % 8;
+ if (i) {
+ m = 0xff00 >> i;
+ if ((a->v6.s6_addr[prefixlen / 8] & m) !=
+ (b->v6.s6_addr[prefixlen / 8] & m))
+ return ((a->v6.s6_addr[prefixlen / 8] & m) -
+ (b->v6.s6_addr[prefixlen / 8] & m));
+ }
+ return (0);
+ default:
+ fatalx("eigrp_prefixcmp: unknown af");
+ }
+ return (-1);
+}
+
#define IN6_IS_SCOPE_EMBED(a) \
((IN6_IS_ADDR_LINKLOCAL(a)) || \
(IN6_IS_ADDR_MC_LINKLOCAL(a)) || \