Publié le: 2010-06-10

OpenOSPFD patch (fr)

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;