Re: Allow bgpd to filter on the nexthop attribute

2012-11-10 Thread Claudio Jeker
On Sat, Nov 10, 2012 at 03:38:15PM +0100, Claudio Jeker wrote:
 In some cases it helps to be able to restrict nexthops from pathes
 received. E.g. at IXP where only routes originating from the neighbor
 should be accepted.
 
 This diff implements this for bgpd.

Updated diff that fixes a missing break. Found by Florian.

-- 
:wq Claudio

Index: bgpd.conf.5
===
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
retrieving revision 1.121
diff -u -p -r1.121 bgpd.conf.5
--- bgpd.conf.5 24 Aug 2012 17:04:06 -  1.121
+++ bgpd.conf.5 28 Oct 2012 13:38:06 -
@@ -1175,6 +1175,17 @@ is repeated more than
 .Ar len
 times.
 .Pp
+.It Ic nexthop Ar address
+This rule applies only to
+.Em UPDATES
+where the nexthop is equal to
+.Ar address.
+The
+.Ar address
+can be set to
+.Em neighbor
+in which case the nexthop is compared against the address of the neighbor.
+.Pp
 .It Xo
 .Ic prefix
 .Ar address Ns Li / Ns Ar len
Index: bgpd.h
===
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.273
diff -u -p -r1.273 bgpd.h
--- bgpd.h  18 Sep 2012 10:10:00 -  1.273
+++ bgpd.h  28 Oct 2012 13:00:03 -
@@ -749,6 +749,13 @@ struct filter_prefix {
u_int8_tlen;
 };
 
+struct filter_nexthop {
+   struct bgpd_addraddr;
+   u_int8_tflags;
+#define FILTER_NEXTHOP_ADDR1
+#define FILTER_NEXTHOP_NEIGHBOR2
+};
+
 struct filter_prefixlen {
enum comp_ops   op;
u_int8_taid;
@@ -759,6 +766,7 @@ struct filter_prefixlen {
 struct filter_match {
struct filter_prefixprefix;
struct filter_prefixlen prefixlen;
+   struct filter_nexthop   nexthop;
struct filter_asas;
struct filter_aslen aslen;
struct filter_community community;
Index: parse.y
===
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.264
diff -u -p -r1.264 parse.y
--- parse.y 23 Sep 2012 09:39:17 -  1.264
+++ parse.y 28 Oct 2012 13:29:16 -
@@ -1700,6 +1700,26 @@ filter_elm   : filter_prefix_h   {
}
fmopts.aid = AID_INET6;
}
+   | NEXTHOP address   {
+   if (fmopts.m.nexthop.flags) {
+   yyerror(nexthop already specified);
+   YYERROR;
+   }
+   if (fmopts.aid  fmopts.aid != $2.aid) {
+   yyerror(nexthop address family doesn't match 
+   rule address family);
+   YYERROR;
+   }
+   fmopts.m.nexthop.addr = $2;
+   fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR;
+   }
+   | NEXTHOP NEIGHBOR  {
+   if (fmopts.m.nexthop.flags) {
+   yyerror(nexthop already specified);
+   YYERROR;
+   }
+   fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR;
+   }
;
 
 prefixlenop: unaryop NUMBER{
Index: printconf.c
===
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.88
diff -u -p -r1.88 printconf.c
--- printconf.c 23 Sep 2012 09:39:18 -  1.88
+++ printconf.c 28 Oct 2012 13:33:58 -
@@ -561,6 +561,13 @@ print_rule(struct peer *peer_l, struct f
}
}
 
+   if (r-match.nexthop.flags) {
+   if (r-match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
+   printf(nexthop neighbor );
+   else
+   printf(nexthop %s , log_addr(r-match.nexthop.addr));
+   }
+
if (r-match.as.type) {
if (r-match.as.type == AS_ALL)
printf(AS %s , log_as(r-match.as.as));
Index: rde_filter.c
===
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.67
diff -u -p -r1.67 rde_filter.c
--- rde_filter.c20 Sep 2011 21:19:06 -  1.67
+++ rde_filter.c10 Nov 2012 17:50:31 -
@@ -384,6 +384,34 @@ rde_filter_match(struct filter_rule *f, 
}
/* NOTREACHED */
}
+   if (f-match.nexthop.flags != 0) {
+   struct bgpd_addr *nexthop, *cmpaddr;
+   if (asp-nexthop == NULL)
+   /* no nexthop, skip */
+   return (0);
+   nexthop = asp-nexthop-exit_nexthop;
+   if (f-match.nexthop.flags == 

Re: Allow bgpd to filter on the nexthop attribute

2012-11-10 Thread Claudio Jeker
On Sat, Nov 10, 2012 at 06:52:17PM +0100, Claudio Jeker wrote:
 On Sat, Nov 10, 2012 at 03:38:15PM +0100, Claudio Jeker wrote:
  In some cases it helps to be able to restrict nexthops from pathes
  received. E.g. at IXP where only routes originating from the neighbor
  should be accepted.
  
  This diff implements this for bgpd.
 
 Updated diff that fixes a missing break. Found by Florian.

Another bug found by Florian Obser. This time the netxhop neighbor
feature crashed the rde because the asp passed around in the filter is not
linked and therefor asp-peer is NULL. Oups.
Since rde_filter() already carries the from peer just pass that info down.

-- 
:wq Claudio

Index: bgpd.conf.5
===
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.conf.5,v
retrieving revision 1.121
diff -u -p -r1.121 bgpd.conf.5
--- bgpd.conf.5 24 Aug 2012 17:04:06 -  1.121
+++ bgpd.conf.5 28 Oct 2012 13:38:06 -
@@ -1175,6 +1175,17 @@ is repeated more than
 .Ar len
 times.
 .Pp
+.It Ic nexthop Ar address
+This rule applies only to
+.Em UPDATES
+where the nexthop is equal to
+.Ar address.
+The
+.Ar address
+can be set to
+.Em neighbor
+in which case the nexthop is compared against the address of the neighbor.
+.Pp
 .It Xo
 .Ic prefix
 .Ar address Ns Li / Ns Ar len
Index: bgpd.h
===
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.273
diff -u -p -r1.273 bgpd.h
--- bgpd.h  18 Sep 2012 10:10:00 -  1.273
+++ bgpd.h  28 Oct 2012 13:00:03 -
@@ -749,6 +749,13 @@ struct filter_prefix {
u_int8_tlen;
 };
 
+struct filter_nexthop {
+   struct bgpd_addraddr;
+   u_int8_tflags;
+#define FILTER_NEXTHOP_ADDR1
+#define FILTER_NEXTHOP_NEIGHBOR2
+};
+
 struct filter_prefixlen {
enum comp_ops   op;
u_int8_taid;
@@ -759,6 +766,7 @@ struct filter_prefixlen {
 struct filter_match {
struct filter_prefixprefix;
struct filter_prefixlen prefixlen;
+   struct filter_nexthop   nexthop;
struct filter_asas;
struct filter_aslen aslen;
struct filter_community community;
Index: parse.y
===
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.264
diff -u -p -r1.264 parse.y
--- parse.y 23 Sep 2012 09:39:17 -  1.264
+++ parse.y 28 Oct 2012 13:29:16 -
@@ -1700,6 +1700,26 @@ filter_elm   : filter_prefix_h   {
}
fmopts.aid = AID_INET6;
}
+   | NEXTHOP address   {
+   if (fmopts.m.nexthop.flags) {
+   yyerror(nexthop already specified);
+   YYERROR;
+   }
+   if (fmopts.aid  fmopts.aid != $2.aid) {
+   yyerror(nexthop address family doesn't match 
+   rule address family);
+   YYERROR;
+   }
+   fmopts.m.nexthop.addr = $2;
+   fmopts.m.nexthop.flags = FILTER_NEXTHOP_ADDR;
+   }
+   | NEXTHOP NEIGHBOR  {
+   if (fmopts.m.nexthop.flags) {
+   yyerror(nexthop already specified);
+   YYERROR;
+   }
+   fmopts.m.nexthop.flags = FILTER_NEXTHOP_NEIGHBOR;
+   }
;
 
 prefixlenop: unaryop NUMBER{
Index: printconf.c
===
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.88
diff -u -p -r1.88 printconf.c
--- printconf.c 23 Sep 2012 09:39:18 -  1.88
+++ printconf.c 28 Oct 2012 13:33:58 -
@@ -561,6 +561,13 @@ print_rule(struct peer *peer_l, struct f
}
}
 
+   if (r-match.nexthop.flags) {
+   if (r-match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
+   printf(nexthop neighbor );
+   else
+   printf(nexthop %s , log_addr(r-match.nexthop.addr));
+   }
+
if (r-match.as.type) {
if (r-match.as.type == AS_ALL)
printf(AS %s , log_as(r-match.as.as));
Index: rde_filter.c
===
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.67
diff -u -p -r1.67 rde_filter.c
--- rde_filter.c20 Sep 2011 21:19:06 -  1.67
+++ rde_filter.c10 Nov 2012 20:56:14 -
@@ -26,7 +26,7 @@
 #include rde.h
 
 intrde_filter_match(struct filter_rule *, struct rde_aspath *,
-