OpenOSPFD patch (2)

Hi all,

Here is a patch to add two new functions to OpenOSPF6d.

The first function is the new keyword fib-routing-priority. This keyword allows to choose a custom routing priority. this function is useful when you use ospf6d with BGPd or ripd, to decrease ospf6d routes priority to use routes obtained from another protocol (bgpd for example).

The second function is the new chain fib-ignore-update nexthop . This new feature allows to prevent insertion of a specific route into the kernel routing table. This function is useful when you have two border routers with BGP + OSPF and a redistribute default on OSPF. OSPF is prior than BGP by default, and will cause a routing loop for outgoing packets. With this function you can refuse to insert a route obtained from your first/second border router and then, break the routing loop.

Comments are welcome, thanks !

--- OpenBSD-ORIG/usr.sbin/ospf6d/kroute.c    2013-02-16 04:03:41.000000000 +0100
+++ OpenBSD/usr.sbin/ospf6d/kroute.c    2013-07-10 18:25:33.809401325 +0200
@@ -1,6 +1,7 @@
-/*  $OpenBSD: kroute.c,v 1.41 2013/01/14 14:39:38 florian Exp $ */
+/*  $OpenBSD: kroute.c,v 1.42 2013/07/10 14:39:38 florian 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>
  *
@@ -928,12 +929,15 @@
     if (kr_state.fib_sync == 0)
         return (0);

+    if (kr_filter_do(kroute) != 0)
+        return (0);
+
     /* initialize header */
     bzero(&hdr, sizeof(hdr));
     hdr.rtm_version = RTM_VERSION;
     hdr.rtm_type = action;
     hdr.rtm_flags = RTF_UP;
-    hdr.rtm_priority = RTP_OSPF;
+    hdr.rtm_priority = get_fibrtprio();
     if (action == RTM_CHANGE)
         hdr.rtm_fmask = RTF_REJECT|RTF_BLACKHOLE;
     hdr.rtm_seq = kr_state.rtseq++;    /* overflow doesn't matter */
@@ -1496,3 +1500,28 @@
     }
     return (0);
 }
+
+struct kroute_filter *
+kr_filter_new(struct in6_addr nexthop, struct in6_addr prefix,
+    u_int8_t prefixlen)
+{
+    struct kroute_filter         *kroute_filter;
+    
+    if ((kroute_filter = calloc(1, sizeof(*kroute_filter))) == NULL)
+        err(1, "kr_filter_new: calloc");
+    
+    kroute_filter->prefix = prefix;
+    kroute_filter->nexthop = nexthop;
+    kroute_filter->prefixlen = prefixlen;
+
+    return (kroute_filter);    
+}
+
+void
+kr_filter_del(struct kroute_filter *kroute_filter)
+{
+    LIST_REMOVE(kroute_filter, entry);
+    
+    free(kroute_filter);
+}
+
diff: OpenBSD-ORIG/usr.sbin/ospf6d/obj: Aucun fichier ou dossier de ce type
diff: OpenBSD/usr.sbin/ospf6d/obj: Aucun fichier ou dossier de ce type
diff -u OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.c OpenBSD/usr.sbin/ospf6d/ospf6d.c
--- OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.c    2011-11-15 05:17:45.000000000 +0100
+++ OpenBSD/usr.sbin/ospf6d/ospf6d.c    2013-07-10 17:51:18.920541838 +0200
@@ -1,6 +1,7 @@
-/*  $OpenBSD: ospf6d.c,v 1.22 2011/08/20 19:02:28 sthen Exp $ */
+/*  $OpenBSD: ospf6d.c,v 1.23 2013/07/10 19:02:28 sthen Exp $ */

 /*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2004, 2007 Esben Norby <norby@openbsd.org>
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -632,12 +633,16 @@
     struct area        *a, *xa, *na;
     struct iface        *iface;
     struct redistribute    *r;
+    struct kroute_filter *rf, *nrf;

     /* change of rtr_id needs a restart */
     conf->flags = xconf->flags;
     conf->spf_delay = xconf->spf_delay;
     conf->spf_hold_time = xconf->spf_hold_time;
     conf->redistribute = xconf->redistribute;
+    
+    /* change of fib routing priority needs a restart */
+    conf->routing_priority = xconf->routing_priority;

     if (ospfd_process == PROC_MAIN) {
         /* main process does neither use areas nor interfaces */
@@ -649,6 +654,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;
     }

@@ -799,3 +812,31 @@
             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 (memcmp(&i->prefix,&kr->prefix, sizeof(&i->prefix)) == 0 &&
+            i->prefixlen == kr->prefixlen &&
+            memcmp(&i->nexthop, &kr->nexthop, sizeof(&i->nexthop)) == 0) {
+                log_info("kr_filter_do: filtering route %s/%u for nexthop %s",
+                    log_in6addr(&i->prefix), i->prefixlen,
+                    log_in6addr(&i->nexthop));
+                    
+                return (1);
+        }
+    }
+    return (0);
+}
+
+u_int8_t
+get_fibrtprio(void)
+{
+    return (ospfd_conf->routing_priority);
+}
diff -u OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.conf.5 OpenBSD/usr.sbin/ospf6d/ospf6d.conf.5
--- OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.conf.5    2012-06-19 20:05:26.000000000 +0200
+++ OpenBSD/usr.sbin/ospf6d/ospf6d.conf.5    2013-07-10 18:24:03.088407528 +0200
@@ -102,6 +102,32 @@
 option to ensure that no traffic tries to transit via this router.
 .Pp
 .It Xo
+.Ic fib-routing-priority Ar 9-62
+.Xc
+Setting the routing priority permit to ajust the kernel route choice
+when multiple protocols are used (for example a BGP plus OSPF router).
+The routing priority is contained between
+.Ic RTP_STATIC
+(8) and
+.Ic RTP_MAX
+(63)
+.Ic Warning!
+Be sure the ospf6d priority
+.Ic isn't same as
+another used protocol on this machine (except ospfd daemon).
+.Pp
+.It Xo
+.Ic fib-ignore-route Ar prefix
+.Ic nexthop Ar hop
+.Xc
+Block some kernel route insertions based on an discovered
+.Ar prefix
+and it's
+.Ar nexthop .
+This function permit to break some routing loops
+caused by mutiple protocol use.
+.Pp
+.It Xo
 .Op Ic no
 .Ic redistribute
 .Sm off
diff -u OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.h OpenBSD/usr.sbin/ospf6d/ospf6d.h
--- OpenBSD-ORIG/usr.sbin/ospf6d/ospf6d.h    2013-02-16 04:03:41.000000000 +0100
+++ OpenBSD/usr.sbin/ospf6d/ospf6d.h    2013-07-10 17:59:07.577509792 +0200
@@ -1,6 +1,7 @@
 /*  $OpenBSD: ospf6d.h,v 1.26 2013/01/14 14:39:38 florian Exp $ */

 /*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
  * Copyright (c) 2004, 2007 Esben Norby <norby@openbsd.org>
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
  *
@@ -375,6 +376,8 @@
     int            flags;
     u_int8_t        border;
     u_int8_t        redistribute;
+    LIST_HEAD(, kroute_filter)    kroute_filter_list;
+    u_int8_t        routing_priority;
 };

 /* kroute */
@@ -494,6 +497,14 @@
     int             level;
 };

+/* kernel route filtering */
+struct kroute_filter {
+    LIST_ENTRY(kroute_filter)    entry;
+    struct in6_addr         prefix;
+    struct in6_addr         nexthop;
+    u_int8_t         prefixlen;
+};
+
 /* area.c */
 struct area    *area_new(void);
 int         area_del(struct area *);
@@ -537,6 +548,9 @@
 void         kr_show_route(struct imsg *);
 void         kr_reload(void);

+struct kroute_filter *kr_filter_new(struct in6_addr, struct in6_addr, u_int8_t);
+void kr_filter_del(struct kroute_filter *);
+
 void         embedscope(struct sockaddr_in6 *);
 void         recoverscope(struct sockaddr_in6 *);
 void         addscope(struct sockaddr_in6 *, u_int32_t);
@@ -570,6 +584,8 @@
 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 *);
+u_int8_t get_fibrtprio(void);

 /* printconf.c */
 void    print_config(struct ospfd_conf *);
diff -u OpenBSD-ORIG/usr.sbin/ospf6d/parse.y OpenBSD/usr.sbin/ospf6d/parse.y
--- OpenBSD-ORIG/usr.sbin/ospf6d/parse.y    2011-06-27 20:55:28.000000000 +0200
+++ OpenBSD/usr.sbin/ospf6d/parse.y    2013-07-10 17:59:23.398508710 +0200
@@ -1,6 +1,7 @@
 /*  $OpenBSD: parse.y,v 1.21 2011/06/27 03:07:26 dlg 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>
@@ -27,6 +28,7 @@
 #include <sys/stat.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <net/route.h>

 #include <ctype.h>
 #include <err.h>
@@ -118,6 +120,7 @@
 %token    METRIC PASSIVE
 %token    HELLOINTERVAL TRANSMITDELAY
 %token    RETRANSMITINTERVAL ROUTERDEADTIME ROUTERPRIORITY
+%token    FIBIGNOREROUTE NEXTHOP FIBROUTEPRIORITY
 %token    SET TYPE
 %token    YES NO
 %token    DEMOTE
@@ -330,7 +333,44 @@
         }
         ;

-defaults    : METRIC NUMBER {
+defaults    : FIBIGNOREROUTE STRING NEXTHOP STRING {
+            struct kroute_filter* kroute_filter;
+            struct in6_addr rt_prefix;
+            struct in6_addr rt_nexthop;
+            u_int8_t rt_prefixlen;
+            u_int8_t rt_nexthoplen;
+            
+            if (prefix($2,&rt_prefix,&rt_prefixlen) == 0) {
+                yyerror("bad route: %s", $2);
+                free($2);
+                YYERROR;
+            }
+            
+            if (prefix($4, &rt_nexthop,&rt_nexthoplen) == 0) {
+                yyerror("bad nexthop: %s", $4);
+                free($4);
+                YYERROR;
+            }
+            
+            kroute_filter = kr_filter_new(rt_nexthop,rt_prefix,rt_prefixlen);
+            LIST_INSERT_HEAD(&conf->kroute_filter_list, kroute_filter, entry);
+            
+            free($2);
+            free($4);
+        }
+        | FIBROUTEPRIORITY NUMBER {
+            /*
+            * OSPF routing priority neither be less or equal than static routes
+            * nor be greater or equal than RTP_MAX
+            */
+            if ($2 <= RTP_STATIC || $2 >= RTP_MAX) {
+                yyerror("fib-route-priority out of range (must be > 8 and < 63)");
+                YYERROR;
+            }
+            
+            conf->routing_priority = $2;
+        }
+        | METRIC NUMBER {
             if ($2 < MIN_METRIC || $2 > MAX_METRIC) {
                 yyerror("metric out of range (%d-%d)",
                     MIN_METRIC, MAX_METRIC);
@@ -541,11 +581,14 @@
         {"area",        AREA},
         {"demote",        DEMOTE},
         {"external-tag",    EXTTAG},
+        {"fib-ignore-route",    FIBIGNOREROUTE},
+        {"fib-routing-priority",    FIBROUTEPRIORITY},
         {"fib-update",        FIBUPDATE},
         {"hello-interval",    HELLOINTERVAL},
         {"include",        INCLUDE},
         {"interface",        INTERFACE},
         {"metric",        METRIC},
+        {"nexthop",        NEXTHOP},
         {"no",            NO},
         {"passive",        PASSIVE},
         {"redistribute",    REDISTRIBUTE},
@@ -902,6 +945,7 @@
     defs->priority = DEFAULT_PRIORITY;

     conf->spf_delay = DEFAULT_SPF_DELAY;
+    conf->routing_priority = RTP_OSPF;
     conf->spf_hold_time = DEFAULT_SPF_HOLDTIME;
     conf->spf_state = SPF_IDLE;

@@ -914,6 +958,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;
diff -u OpenBSD-ORIG/usr.sbin/ospf6d/printconf.c OpenBSD/usr.sbin/ospf6d/printconf.c
--- OpenBSD-ORIG/usr.sbin/ospf6d/printconf.c    2010-11-29 21:57:30.000000000 +0100
+++ OpenBSD/usr.sbin/ospf6d/printconf.c    2013-07-10 18:00:07.638505685 +0200
@@ -1,6 +1,7 @@
 /*  $OpenBSD: printconf.c,v 1.4 2010/08/22 21:15:25 bluhm Exp $ */

 /*
+ * Copyright (c) 2013 Loic Blot <loic.blot@unix-experience.fr>
  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -33,6 +34,7 @@
 const char *print_no(u_int16_t);
 void    print_redistribute(struct ospfd_conf *);
 void    print_rtlabel(struct ospfd_conf *);
+void    print_kroute_filter(struct ospfd_conf *);
 void    print_iface(struct iface *);

 void
@@ -50,9 +52,11 @@

     print_redistribute(conf);
     print_rtlabel(conf);
+    print_kroute_filter(conf);

     printf("spf-delay %u\n", conf->spf_delay);
     printf("spf-holdtime %u\n", conf->spf_hold_time);
+    printf("fib-routing-priority %u\n", conf->routing_priority);
 }

 const char *
@@ -105,6 +109,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/%u",
+            log_in6addr(&kroute_filter->prefix),kroute_filter->prefixlen);
+        printf(" nexthop %s\n",
+            log_in6addr(&kroute_filter->nexthop));
+    }
+}
+
+void
 print_iface(struct iface *iface)
 {
     printf("\tinterface %s {\n", iface->name);