From ed40466af80c9d0b88436c637a1d54b28a669b1c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 12 Jun 2015 07:59:11 -0700 Subject: [PATCH] bgpd-set-somark.patch BGP: Set SO_MARK on connecting sockets to ensure lookup in right routing table In the presence of a function such as management VRF/MRF, bgpd needs to be able to specify that it intends to run in the dataplane and not the front panel. To ensure this, we add a mark in the connecting socket so that the kernel does the routing lookup in the right table. This assumes that an appropriate ip rule has been configured (outside the scope of this package). While we've forced the mark to be 254 for now, it maybe required to make it configurable at a later time. --- bgpd/bgp_network.c | 5 +++++ lib/sockunion.c | 19 +++++++++++++++++++ lib/sockunion.h | 3 +++ 3 files changed, 27 insertions(+) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 68934655f0..c65119489c 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -440,6 +440,8 @@ bgp_update_source (struct peer *peer) sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source); } +#define DATAPLANE_MARK 254 /* main table ID */ + /* BGP try to connect to the peer. */ int bgp_connect (struct peer *peer) @@ -466,6 +468,9 @@ bgp_connect (struct peer *peer) sockopt_reuseaddr (peer->fd); sockopt_reuseport (peer->fd); + if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0) + zlog_warn("Unable to set mark on FD for peer %s, err=%s", peer->host, + safe_strerror(errno)); #ifdef IPTOS_PREC_INTERNETCONTROL if (bgpd_privs.change (ZPRIVS_RAISE)) diff --git a/lib/sockunion.c b/lib/sockunion.c index efd41362c6..59c5ba5dd0 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -496,6 +496,25 @@ sockopt_cork (int sock, int onoff) #endif } +int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *cap) +{ +#ifdef SO_MARK + int ret; + + if ( cap->change (ZPRIVS_RAISE) ) + zlog_err ("routing_socket: Can't raise privileges"); + + ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)); + + if ( cap->change (ZPRIVS_LOWER) ) + zlog_err ("routing_socket: Can't lower privileges"); + + return ret; +#else + return 0; +#endif +} + int sockopt_minttl (int family, int sock, int minttl) { diff --git a/lib/sockunion.h b/lib/sockunion.h index 8f0a9be37c..78356e4cb7 100644 --- a/lib/sockunion.h +++ b/lib/sockunion.h @@ -23,6 +23,8 @@ #ifndef _ZEBRA_SOCKUNION_H #define _ZEBRA_SOCKUNION_H +#include "privs.h" + #if 0 union sockunion { struct sockinet { @@ -99,6 +101,7 @@ extern int sockunion_bind (int sock, union sockunion *, extern int sockopt_ttl (int family, int sock, int ttl); extern int sockopt_minttl (int family, int sock, int minttl); extern int sockopt_cork (int sock, int onoff); +extern int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *); extern int sockunion_socket (union sockunion *su); extern const char *inet_sutop (union sockunion *su, char *str); extern enum connect_result sockunion_connect (int fd, union sockunion *su, -- 2.39.5