Suite à des travaux d’installation d’une liaison inter-site avec de nouveaux routeurs de bordure BGP+OSPF sous OpenBSD, je me suis rendu compte d’une limitation technique d’OpenOSPF.
En effet, mes routeurs devant distribuer les routes via GRE+OSPF, ils redistribuaient la route par défaut (obligatoire pour les routeurs internes), la route était redistribuée sur le tunnel GRE et provoquait une boucle de routage coupant le WAN.
La second limitation technique était celle de BGP et OSPF. OSPF étant prioritaire, si on redonde des routeurs de bordure, la route par défaut provoque une boucle de routage entre les routeurs de bordure.
OpenOSPF ne disposant pas de dispositif de filtrage, et devant en avoir un rapidement j’ai donc décidé de patcher le logiciel afin d’intégrer un dispositif de filtrage permettant de garder la cohérence de l’algorithme SPF tout en empêchant le système d’intégrer la route.
Je vous partage ce petit patch de 147 lignes permettant d’intégrer la fonctionnalité sur OpenOSPF (version d’OpenBSD 5.3), sous licence BSD.
--- /root/ospfd/ospfd.c 2011-11-15 05:17:46.000000000 +0100
+++ /usr/src/usr.sbin/ospfd/ospfd.c 2013-05-31 22:38:22.202030731 +0200
@@ -1,6 +1,7 @@
-/* $OpenBSD: ospfd.c,v 1.78 2011/08/20 11:16:09 sthen Exp $ */
+/* $OpenBSD: ospfd.c,v 1.79 2013/05/31 22:35:17 sthen Exp $ */
/*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -680,6 +681,7 @@
struct area *a, *xa, *na;
struct iface *iface;
struct redistribute *r;
+ struct kroute_filter *rf, *nrf;
int rchange = 0;
/* change of rtr_id needs a restart */
@@ -701,6 +703,14 @@
SIMPLEQ_REMOVE_HEAD(&xconf->redist_list, entry);
SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
}
+ for (rf = LIST_FIRST(&conf->kroute_filter_list); rf != NULL; rf =
nrf) {
+ nrf = LIST_NEXT(rf, entry);
+ kr_filter_del(rf);
+ }
+ for (rf = LIST_FIRST(&xconf->kroute_filter_list); rf != NULL; rf =
nrf) {
+ nrf = LIST_NEXT(rf, entry);
+ LIST_INSERT_HEAD(&conf->kroute_filter_list, rf, entry);
+ }
goto done;
}
@@ -891,3 +901,26 @@
return (i);
return (NULL);
}
+
+int
+kr_filter_do(struct kroute *kr)
+{
+ struct kroute_filter *i;
+
+ LIST_FOREACH(i, &ospfd_conf->kroute_filter_list, entry) {
+ /*
+ * TODO: filter all routes for one nexthop
+ */
+ if (i->prefix.s_addr == kr->prefix.s_addr &&
+ i->prefixlen == kr->prefixlen &&
+ (i->nexthop.s_addr == kr->nexthop.s_addr ||
+ i->nexthop.s_addr == INADDR_ANY)) {
+ log_info("ospfd_filternexthop: filtering route %s/%u",
+ inet_ntoa(i->prefix), i->prefixlen);
+ log_info("ospfd_filternexthop: nexthop is %s",
+ inet_ntoa(i->nexthop));
+ return (1);
+ }
+ }
+ return (0);
+}
--- /root/ospfd/ospfd.h 2013-02-16 04:03:42.000000000 +0100
+++ /usr/src/usr.sbin/ospfd/ospfd.h 2013-05-31 22:38:44.768029188 +0200
@@ -1,6 +1,7 @@
-/* $OpenBSD: ospfd.h,v 1.91 2013/01/17 10:07:56 markus Exp $ */
+/* $OpenBSD: ospfd.h,v 1.92 2013/05/31 22:38:56 markus Exp $ */
/*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
*
@@ -387,6 +388,7 @@
u_int8_t border;
u_int8_t redistribute;
u_int rdomain;
+ LIST_HEAD(, kroute_filter) kroute_filter_list;
char *csock;
};
@@ -526,6 +528,14 @@
int level;
};
+/* kernel route filtering */
+struct kroute_filter {
+ LIST_ENTRY(kroute_filter) entry;
+ struct in_addr prefix;
+ struct in_addr nexthop;
+ u_int8_t prefixlen;
+};
+
/* area.c */
struct area *area_new(void);
int area_del(struct area *);
@@ -564,6 +574,9 @@
void kr_ifinfo(char *, pid_t);
struct kif *kif_findname(char *, struct in_addr, struct kif_addr **);
void kr_reload(void);
+struct kroute_filter *kr_filter_new(struct in_addr, struct in_addr,
u_int8_t);
+void kr_filter_del(struct kroute_filter *);
+struct kroute_filter *kr_filter_find(struct ospfd_conf *, struct
in_addr, struct in_addr, u_int8_t);
u_int8_t mask2prefixlen(in_addr_t);
in_addr_t prefixlen2mask(u_int8_t);
@@ -592,6 +605,7 @@
void imsg_event_add(struct imsgev *);
int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
pid_t, int, void *, u_int16_t);
+int kr_filter_do(struct kroute *);
/* printconf.c */
void print_config(struct ospfd_conf *);
--- /root/ospfd/parse.y 2010-12-20 19:09:24.000000000 +0100
+++ /usr/src/usr.sbin/ospfd/parse.y 2013-05-31 22:39:09.098027524 +0200
@@ -1,6 +1,7 @@
-/* $OpenBSD: parse.y,v 1.73 2010/12/13 13:43:37 bluhm Exp $ */
+/* $OpenBSD: parse.y,v 1.74 2013/05/31 22:12:08 bluhm Exp $ */
/*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
* Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -116,12 +117,14 @@
%}
-%token AREA INTERFACE ROUTERID FIBUPDATE REDISTRIBUTE RTLABEL RDOMAIN
-%token RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG
+%token AREA INTERFACE ROUTERID FIBUPDATE
+%token REDISTRIBUTE RTLABEL RDOMAIN RFC1583COMPAT STUB ROUTER SPFDELAY
+%token SPFHOLDTIME EXTTAG
%token AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
%token METRIC PASSIVE
%token HELLOINTERVAL FASTHELLOINTERVAL TRANSMITDELAY
%token RETRANSMITINTERVAL ROUTERDEADTIME ROUTERPRIORITY
+%token KROUTEIGNOREINSERT PREFIXLEN NEXTHOP
%token SET TYPE
%token YES NO
%token MSEC MINIMAL
@@ -435,7 +438,32 @@
}
;
-defaults : METRIC NUMBER {
+defaults : KROUTEIGNOREINSERT STRING PREFIXLEN NUMBER NEXTHOP STRING {
+ struct kroute_filter* kroute_filter;
+ struct in_addr prefix;
+ struct in_addr nexthop;
+ u_int8_t prefixlen;
+
+ if (!inet_aton($2, &prefix)) {
+ yyerror("bad network: %llu/%llu", $2, $4);
+ free($2);
+ YYERROR;
+ }
+
+ if (!inet_aton($6, &nexthop)) {
+ yyerror("bad network: %llu/%llu", $2, $4);
+ free($2);
+ YYERROR;
+ }
+
+ prefixlen = $4;
+
+ kroute_filter = kr_filter_new(nexthop,prefix,prefixlen);
+ LIST_INSERT_HEAD(&conf->kroute_filter_list, kroute_filter, entry);
+
+ free($2);
+ }
+ | METRIC NUMBER {
if ($2 < MIN_METRIC || $2 > MAX_METRIC) {
yyerror("metric out of range (%d-%d)",
MIN_METRIC, MAX_METRIC);
@@ -508,7 +536,6 @@
| MINIMAL {
$ = FAST_RTR_DEAD_TIME;
}
-
optnl : '\n' optnl
|
;
@@ -726,11 +753,14 @@
{"hello-interval", HELLOINTERVAL},
{"include", INCLUDE},
{"interface", INTERFACE},
+ {"kroute-ignore-insert", KROUTEIGNOREINSERT},
{"metric", METRIC},
{"minimal", MINIMAL},
{"msec", MSEC},
+ {"nexthop", NEXTHOP},
{"no", NO},
{"passive", PASSIVE},
+ {"prefixlen", PREFIXLEN},
{"rdomain", RDOMAIN},
{"redistribute", REDISTRIBUTE},
{"retransmit-interval", RETRANSMITINTERVAL},
@@ -1101,6 +1131,7 @@
LIST_INIT(&conf->area_list);
LIST_INIT(&conf->cand_list);
SIMPLEQ_INIT(&conf->redist_list);
+ LIST_INIT(&conf->kroute_filter_list);
yyparse();
errors = file->errors;
--- /root/ospfd/printconf.c 2010-02-20 19:02:25.000000000 +0100
+++ /usr/src/usr.sbin/ospfd/printconf.c 2013-05-31 22:39:27.174026288
+0200
@@ -1,4 +1,4 @@
-/* $OpenBSD: printconf.c,v 1.15 2010/02/16 08:39:05 dlg Exp $ */
+/* $OpenBSD: printconf.c,v 1.16 2013/05/31 21:59:48 dlg Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -32,6 +32,7 @@
const char *print_no(u_int16_t);
void print_redistribute(struct redist_list *);
void print_rtlabel(struct ospfd_conf *);
+void print_kroute_filter(struct ospfd_conf *);
void print_iface(struct iface *);
void
@@ -54,6 +55,7 @@
print_redistribute(&conf->redist_list);
print_rtlabel(conf);
+ print_kroute_filter(conf);
printf("spf-delay msec %u\n", conf->spf_delay);
printf("spf-holdtime msec %u\n", conf->spf_hold_time);
@@ -109,6 +111,19 @@
}
void
+print_kroute_filter(struct ospfd_conf *conf)
+{
+ struct kroute_filter *kroute_filter;
+
+ LIST_FOREACH(kroute_filter, &conf->kroute_filter_list, entry) {
+ printf("kroute-ignore-insert %s prefixlen %u",
+ inet_ntoa(kroute_filter->prefix),kroute_filter->prefixlen);
+ printf(" nexthop %s\n",
+ inet_ntoa(kroute_filter->nexthop));
+ }
+}
+
+void
print_iface(struct iface *iface)
{
struct auth_md *md;