]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
BGP: Add support for BGP hostname capability
authorVincent Bernat <vincent@bernat.ch>
Wed, 10 Feb 2021 15:53:57 +0000 (16:53 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 10 Feb 2021 15:53:57 +0000 (16:53 +0100)
This is an implementation of draft-walton-bgp-hostname-capability-02.
It is implemented since quite some time for FRR and in datacenter, this
gives a nice output to avoid using IP addresses.

It is disabled by default. The hostname is retrieved from uname(2) and
can be overriden with "hostname" option. The domain name is never set
nor displayed.

Minor changes by committer.

conf/conf.c
conf/conf.h
doc/bird.sgml
nest/cmds.c
nest/config.Y
proto/bgp/bgp.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c
sysdep/unix/main.c
sysdep/unix/unix.h

index 6f64b5416c59029b43ee1d10beafd919b897140e..58abcde13dd42f6c05902c3736374a9b338cbcf6 100644 (file)
@@ -55,6 +55,7 @@
 #include "lib/timer.h"
 #include "conf/conf.h"
 #include "filter/filter.h"
+#include "sysdep/unix/unix.h"
 
 
 static jmp_buf conf_jmpbuf;
@@ -217,6 +218,14 @@ config_del_obstacle(struct config *c)
 static int
 global_commit(struct config *new, struct config *old)
 {
+  if (!new->hostname)
+    {
+      new->hostname = get_hostname(new->mem);
+
+      if (!new->hostname)
+        log(L_WARN "Cannot determine hostname");
+    }
+
   if (!old)
     return 0;
 
index 3e47c918546974a20fd80c49e20063bf94e4918a..860d267aa7b9f2cd5a635ac33c6bc44bd93b24d4 100644 (file)
@@ -40,6 +40,7 @@ struct config {
   struct timeformat tf_log;            /* Time format for the logfile */
   struct timeformat tf_base;           /* Time format for other purposes */
   u32 gr_wait;                         /* Graceful restart wait timeout (sec) */
+  const char *hostname;                        /* Hostname */
 
   int cli_debug;                       /* Tracing of CLI connections and commands */
   int latency_debug;                   /* I/O loop tracks duration of each event */
index 28b0e400b46440d0a57198c72e70905045543ab0..5d1df5bc9f9145f68b67d0e6ac85eab0bea2af8c 100644 (file)
@@ -585,6 +585,9 @@ include "tablename.conf";;
        See <ref id="proto-iface" name="interface"> section for detailed
        description of interface patterns with extended clauses.
 
+       <tag><label id="opt-hostname">hostname "<m/name/"</tag>
+       Set hostname. Default: node name as returned by `uname -n'.
+
        <tag><label id="opt-graceful-restart">graceful restart wait <m/number/</tag>
        During graceful restart recovery, BIRD waits for convergence of routing
        protocols. This option allows to specify a timeout for the recovery to
@@ -2536,6 +2539,9 @@ using the following configuration parameters:
        This option is relevant to IPv4 mode with enabled capability
        advertisement only. Default: on.
 
+       <tag><label id="bgp-advertise-hostname">advertise hostname <m/switch/</tag>
+       Advertise hostname capability along with the hostname. Default: off.
+
        <tag><label id="bgp-disable-after-error">disable after error <m/switch/</tag>
        When an error is encountered (either locally or by the other side),
        disable the instance automatically and wait for an administrator to fix
index da4015cfba0d85d5ce3a21b85cff15e205a4d68a..18f39eb56c10de0b9cad38410ea78368aede9c3e 100644 (file)
@@ -27,6 +27,7 @@ cmd_show_status(void)
   cli_msg(-1000, "BIRD " BIRD_VERSION);
   tm_format_time(tim, &config->tf_base, current_time());
   cli_msg(-1011, "Router ID is %R", config->router_id);
+  cli_msg(-1011, "Hostname is %s", config->hostname);
   cli_msg(-1011, "Current server time is %s", tim);
   tm_format_time(tim, &config->tf_base, boot_time);
   cli_msg(-1011, "Last reboot on %s", tim);
index 0bb8ca51dba00d105e2bee6b53b8bb873a962b03..39bf61490001c02799b621a4d59f694c42a6885c 100644 (file)
@@ -87,7 +87,7 @@ proto_postconfig(void)
 
 CF_DECLS
 
-CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
+CF_KEYWORDS(ROUTER, ID, HOSTNAME, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
 CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, DEFAULT, TABLE, STATES, ROUTES, FILTERS)
 CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, SADR, MPLS)
 CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
@@ -151,6 +151,10 @@ idval:
    }
  ;
 
+conf: hostname_override ;
+
+hostname_override: HOSTNAME text ';' { new_config->hostname = $2; } ;
+
 conf: gr_opts ;
 
 gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
index 302d026c01036970d403f40462cc0f3b756b8ae9..c54afe0651d4b21744d276794be2575140d2aff0 100644 (file)
  * RFC 8654 - Extended Message Support for BGP
  * draft-ietf-idr-ext-opt-param-07
  * draft-uttaro-idr-bgp-persistence-04
+ * draft-walton-bgp-hostname-capability-02
  */
 
 #undef LOCAL_DEBUG
@@ -2415,6 +2416,9 @@ bgp_show_capabilities(struct bgp_proto *p UNUSED, struct bgp_caps *caps)
     bgp_show_afis(-1006, "        AF supported:", afl1, afn1);
     bgp_show_afis(-1006, "        AF preserved:", afl2, afn2);
   }
+
+  if (caps->hostname)
+    cli_msg(-1006, "      Hostname: %s", caps->hostname);
 }
 
 static void
index dd7dc28fd03d125ead9965f7939c62aa5644fd43..cca4b4482dc04627e097f82dfbd9200ad3e9ff7b 100644 (file)
@@ -98,6 +98,7 @@ struct bgp_config {
   int enable_refresh;                  /* Enable local support for route refresh [RFC 2918] */
   int enable_as4;                      /* Enable local support for 4B AS numbers [RFC 6793] */
   int enable_extended_messages;                /* Enable local support for extended messages [draft] */
+  int enable_hostname;                 /* Enable local support for hostname [draft] */
   u32 rr_cluster_id;                   /* Route reflector cluster ID, if different from local ID */
   int rr_client;                       /* Whether neighbor is RR client of me */
   int rs_client;                       /* Whether neighbor is RS client of me */
@@ -228,6 +229,8 @@ struct bgp_caps {
   u8 any_ext_next_hop;                 /* Bitwise OR of per-AF ext_next_hop */
   u8 any_add_path;                     /* Bitwise OR of per-AF add_path */
 
+  const char *hostname;                        /* Hostname, RFC draft */
+
   u16 af_count;                                /* Number of af_data items */
   u16 length;                          /* Length of capabilities in OPEN msg */
 
index 18c3560dfc9b9ca49bdd2cbb8a75f0e7020d0e7e..2dfbdca9bc92f5d63114bd8762c1a1ef540bfe59 100644 (file)
@@ -62,6 +62,7 @@ bgp_proto_start: proto_start BGP {
      BGP_CFG->error_delay_time_max = 300;
      BGP_CFG->enable_refresh = 1;
      BGP_CFG->enable_as4 = 1;
+     BGP_CFG->enable_hostname = 0;
      BGP_CFG->capabilities = 2;
      BGP_CFG->interpret_communities = 1;
      BGP_CFG->allow_as_sets = 1;
@@ -173,6 +174,7 @@ bgp_proto:
  | bgp_proto ENABLE ROUTE REFRESH bool ';' { BGP_CFG->enable_refresh = $5; }
  | bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
  | bgp_proto ENABLE EXTENDED MESSAGES bool ';' { BGP_CFG->enable_extended_messages = $5; }
+ | bgp_proto ADVERTISE HOSTNAME bool ';' { BGP_CFG->enable_hostname = $4; }
  | bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
  | bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
  | bgp_proto SETKEY bool ';' { BGP_CFG->setkey = $3; }
index 78fdd1e006a396321f8b775b7a91e367d269b01f..b16ee2425f0bcd46d2d97386938b7d104d4933e4 100644 (file)
@@ -252,6 +252,14 @@ bgp_prepare_capabilities(struct bgp_conn *conn)
   if (p->cf->llgr_mode)
     caps->llgr_aware = 1;
 
+  if (p->cf->enable_hostname && config->hostname)
+  {
+    size_t length = strlen(config->hostname);
+    char *hostname = mb_allocz(p->p.pool, length+1);
+    memcpy(hostname, config->hostname, length+1);
+    caps->hostname = hostname;
+  }
+
   /* Allocate and fill per-AF fields */
   WALK_LIST(c, p->p.channels)
   {
@@ -412,6 +420,24 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
     data[-1] = buf - data;
   }
 
+  if (caps->hostname)
+  {
+    *buf++ = 73;                /* Capability 73: Hostname */
+    *buf++ = 0;                        /* Capability data length */
+    data = buf;
+
+    /* Hostname */
+    size_t length = strlen(caps->hostname);
+    *buf++ = length;
+    memcpy(buf, caps->hostname, length);
+    buf += length;
+
+    /* Domain, not implemented */
+    *buf++ = 0;
+
+    data[-1] = buf - data;
+  }
+
   caps->length = buf - buf_head;
 
   return buf;
@@ -573,6 +599,21 @@ bgp_read_capabilities(struct bgp_conn *conn, byte *pos, int len)
       }
       break;
 
+    case 73: /* Hostname, RFC draft */
+      if ((cl < 2) || (cl < 2 + pos[2]))
+        goto err;
+
+      int length = pos[2];
+      char *hostname = mb_allocz(p->p.pool, length+1);
+      memcpy(hostname, pos + 3, length);
+      hostname[length] = 0;
+
+      for (i = 0; i < length; i++)
+        if (hostname[i] < ' ')
+          hostname[i] = ' ';
+
+      caps->hostname = hostname;
+
       /* We can safely ignore all other capabilities */
     }
 
index 2c7e3ceff6321568c37795c12e994f94973466c9..67e766553bce26f0e8f8a994d16e6a0b42b18975 100644 (file)
@@ -20,6 +20,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
 #include <libgen.h>
 
 #include "nest/bird.h"
@@ -88,6 +89,21 @@ drop_gid(gid_t gid)
     die("setgroups: %m");
 }
 
+/*
+ *     Hostname
+ */
+
+char *
+get_hostname(linpool *lp)
+{
+  struct utsname uts = {};
+
+  if (uname(&uts) < 0)
+      return NULL;
+
+  return lp_strdup(lp, uts.nodename);
+}
+
 /*
  *     Reading the Configuration
  */
index 0f2973f0e485b950335b319abd982ef59659fc5a..ad85d1ea5fd6dd4849acda381e32202e04525894 100644 (file)
@@ -24,6 +24,7 @@ extern int parse_and_exit;
 void async_config(void);
 void async_dump(void);
 void async_shutdown(void);
+char *get_hostname(linpool *lp);
 void cmd_check_config(const char *name);
 void cmd_reconfig(const char *name, int type, uint timeout);
 void cmd_reconfig_confirm(void);