]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: support TTL-security with iBGP
authorPradosh Mohapatra <pmohapat@cumulusnetworks.com>
Thu, 12 Sep 2013 03:37:07 +0000 (03:37 +0000)
committerDavid Lamparter <equinox@opensourcerouting.org>
Mon, 19 May 2014 21:25:46 +0000 (23:25 +0200)
Traditionally, ttl-security feature has been associated with EBGP
sessions as those identify directly connected external peers. The
GTSM RFC (rfc 5082) does not make any restrictions on type of
peering. In fact, it is beneficial to support ttl-security for both
EBGP and IBGP sessions. Specifically, in data centers, there are
directly connected IBGP peerings that will benefit from the protection
ttl-security provides.

Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
[DL: function refactoring split out into previous 2 patches.  changes:
     - bgp_set_socket_ttl(): ret type int -> void
     - is_ebgp_multihop_configured(): stripped peer == NULL check
     - comments/whitespace]
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
bgpd/bgp_network.c
bgpd/bgp_vty.c
bgpd/bgpd.c
doc/bgpd.texi

index 93bb1d9b5bb3c8741745834bba396cb8c4c937eb..6c7cf54c09b6288f5422346c2918b387b1bdcb88 100644 (file)
@@ -148,11 +148,44 @@ bgp_update_sock_send_buffer_size (int fd)
 static void
 bgp_set_socket_ttl (struct peer *peer, int bgp_sock)
 {
-  if (peer->sort == BGP_PEER_EBGP) {
-    sockopt_ttl (peer->su.sa.sa_family, bgp_sock, peer->ttl);
-    if (peer->gtsm_hops)
-      sockopt_minttl (peer->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer->gtsm_hops);
-  }
+  char buf[INET_ADDRSTRLEN];
+  int ret;
+
+  /* In case of peer is EBGP, we should set TTL for this connection.  */
+  if (!peer->gtsm_hops && (peer_sort (peer) == BGP_PEER_EBGP))
+    {
+      ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, peer->ttl);
+      if (ret)
+       {
+         zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
+                   __func__,
+                   inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
+                   errno);
+       }
+    }
+  else if (peer->gtsm_hops)
+    {
+      /* On Linux, setting minttl without setting ttl seems to mess with the
+        outgoing ttl. Therefore setting both.
+      */
+      ret = sockopt_ttl (peer->su.sa.sa_family, bgp_sock, MAXTTL);
+      if (ret)
+       {
+         zlog_err ("%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
+                   __func__,
+                   inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
+                   errno);
+       }
+      ret = sockopt_minttl (peer->su.sa.sa_family, bgp_sock,
+                           MAXTTL + 1 - peer->gtsm_hops);
+      if (ret)
+       {
+         zlog_err ("%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
+                   __func__,
+                   inet_ntop (AF_INET, &peer->remote_id, buf, sizeof(buf)),
+                   errno);
+       }
+    }
 }
 
 /* Accept bgp connection. */
index bfa1f20442480f918f984ee7496c418ec313d42b..b4d765afaa827f3eb40963080ff97e6313b0f84f 100644 (file)
@@ -7857,6 +7857,12 @@ bgp_show_peer (struct vty *vty, struct peer *p)
        vty_out (vty, "  External BGP neighbor may be up to %d hops away.%s",
                 p->ttl, VTY_NEWLINE);
     }
+  else
+    {
+      if (p->gtsm_hops > 0)
+       vty_out (vty, "  Internal BGP neighbor may be up to %d hops away.%s",
+                p->gtsm_hops, VTY_NEWLINE);
+    }
 
   /* Local address. */
   if (p->su_local)
index afd0dbd219f359db33c733367903191aeee34a86..88d13ed8c1513d579f7cbbc8a2137ddba6a91247 100644 (file)
@@ -4419,21 +4419,21 @@ static int is_ebgp_multihop_configured (struct peer *peer)
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
       group = peer->group;
-      if (group->conf->ttl != 1)
+      if ((peer_sort(peer) != BGP_PEER_IBGP) &&
+         (group->conf->ttl != 1))
        return 1;
 
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
        {
-         if (peer1->sort == BGP_PEER_IBGP)
-           continue;
-
-         if (peer1->ttl != 1)
+         if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
+             (peer1->ttl != 1))
            return 1;
        }
     }
   else
     {
-      if (peer->ttl != 1)
+      if ((peer_sort(peer) != BGP_PEER_IBGP) &&
+         (peer->ttl != 1))
        return 1;
     }
   return 0;
@@ -4449,9 +4449,6 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
 
   zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
 
-  if (peer->sort == BGP_PEER_IBGP)
-    return BGP_ERR_NO_IBGP_WITH_TTLHACK;
-
   /* We cannot configure ttl-security hops when ebgp-multihop is already
      set.  For non peer-groups, the check is simple.  For peer-groups, it's
      slightly messy, because we need to check both the peer-group structure
@@ -4466,6 +4463,7 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
        return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
 
       /* specify MAXTTL on outgoing packets */
+      /* Routine handles iBGP peers correctly */
       ret = peer_ebgp_multihop_set (peer, MAXTTL);
       if (ret != 0)
        return ret;
@@ -4475,7 +4473,7 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
 
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
-      if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
+      if (peer->fd >= 0)
        sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
     }
   else
@@ -4483,9 +4481,6 @@ peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
       group = peer->group;
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
        {
-         if (peer->sort == BGP_PEER_IBGP)
-           continue;
-
          peer->gtsm_hops = group->conf->gtsm_hops;
 
          /* Change setting of existing peer
@@ -4520,9 +4515,6 @@ peer_ttl_security_hops_unset (struct peer *peer)
 
   zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
 
-  if (peer->sort == BGP_PEER_IBGP)
-      return 0;
-
   /* if a peer-group member, then reset to peer-group default rather than 0 */
   if (peer_group_active (peer))
     peer->gtsm_hops = peer->group->conf->gtsm_hops;
@@ -4532,7 +4524,7 @@ peer_ttl_security_hops_unset (struct peer *peer)
   opeer = peer;
   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
-      if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
+      if (peer->fd >= 0)
        sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
     }
   else
@@ -4540,9 +4532,6 @@ peer_ttl_security_hops_unset (struct peer *peer)
       group = peer->group;
       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
        {
-         if (peer->sort == BGP_PEER_IBGP)
-           continue;
-
          peer->gtsm_hops = 0;
          
          if (peer->fd >= 0)
@@ -4865,7 +4854,7 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
                   VTY_NEWLINE);
 
      /* ttl-security hops */
-      if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
+      if (peer->gtsm_hops != 0)
         if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
           vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
                    peer->gtsm_hops, VTY_NEWLINE);
index 24028d6f9dc242b8af55cbda420947c3e6d9d68e..cb9789bdb2b5f19693fd0c5d637f5042b5290e55 100644 (file)
@@ -366,6 +366,14 @@ Note that replace-as can only be specified if no-prepend is.
 This command is only allowed for eBGP peers.
 @end deffn
 
+@deffn {BGP} {neighbor @var{peer} ttl-security hops @var{number}} {}
+@deffnx {BGP} {no neighbor @var{peer} ttl-security hops @var{number}} {}
+This command enforces Generalized TTL Security Mechanism (GTSM), as
+specified in RFC 5082. With this command, only neighbors that are the
+specified number of hops away will be allowed to become neighbors. This
+command is mututally exclusive with @command{ebgp-multihop}.
+@end deffn
+
 @node Peer filtering
 @subsection Peer filtering