bgpd: support TTL-security with iBGP

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>
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 93bb1d9..6c7cf54 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -148,11 +148,44 @@
 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. */