]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Multihop BGP was completely broken, because listening socket has always
authorOndrej Zajicek <santiago@crfreenet.org>
Sat, 1 Nov 2008 15:58:40 +0000 (16:58 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Sat, 1 Nov 2008 15:58:40 +0000 (16:58 +0100)
ttl 1.

lib/socket.h
proto/bgp/bgp.c
sysdep/unix/io.c

index 4aa521dbd51b06bdc1ebb1caee471352d871a1de..5fe91931344bcba4c6ab15ceb8e149430df4dfdd 100644 (file)
@@ -48,6 +48,7 @@ int sk_send(sock *, unsigned len);    /* Send data, <0=err, >0=ok, 0=sleep */
 int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
 void sk_reallocate(sock *);            /* Free and allocate tbuf & rbuf */
 void sk_dump_all(void);
+int sk_set_ttl(sock *s, int ttl);      /* Set TTL for given socket */
 int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); /* Add or remove security associations for given passive socket */
 
 static inline int
index a34545bb3607421e1ac764a7bb4e46f912c993b5..29d2e09fc6a4c1a97c796d01e8ef28840b4c7d7d 100644 (file)
@@ -298,11 +298,7 @@ static void
 bgp_setup_sk(struct bgp_proto *p, struct bgp_conn *conn, sock *s)
 {
   s->data = conn;
-  s->ttl = p->cf->multihop ? : 1;
-  s->rbsize = BGP_RX_BUFFER_SIZE;
-  s->tbsize = BGP_TX_BUFFER_SIZE;
   s->err_hook = bgp_sock_err;
-  s->tos = IP_PREC_INTERNET_CONTROL;
   conn->sk = s;
 }
 
@@ -330,11 +326,15 @@ bgp_connect(struct bgp_proto *p)  /* Enter Connect state and start establishing c
     s->saddr = p->local_addr;
   s->daddr = p->cf->remote_ip;
   s->dport = BGP_PORT;
+  s->ttl = p->cf->multihop ? : 1;
+  s->rbsize = BGP_RX_BUFFER_SIZE;
+  s->tbsize = BGP_TX_BUFFER_SIZE;
+  s->tos = IP_PREC_INTERNET_CONTROL;
+  s->password = p->cf->password;
+  s->tx_hook = bgp_connected;
   BGP_TRACE(D_EVENTS, "Connecting to %I from local address %I", s->daddr, s->saddr);
   bgp_setup_conn(p, conn);
   bgp_setup_sk(p, conn, s);
-  s->tx_hook = bgp_connected;
-  s->password = p->cf->password;
   conn->state = BS_CONNECT;
   if (sk_open(s))
     {
@@ -399,6 +399,7 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
                  }
                bgp_setup_conn(p, &p->incoming_conn);
                bgp_setup_sk(p, &p->incoming_conn, sk);
+               sk_set_ttl(sk, p->cf->multihop ? : 1);
                bgp_send_open(&p->incoming_conn);
                return 0;
              }
@@ -420,7 +421,6 @@ bgp_setup_listen_sk(void)
       s->type = SK_TCP_PASSIVE;
       s->sport = BGP_PORT;
       s->tos = IP_PREC_INTERNET_CONTROL;
-      s->ttl = 1;
       s->rbsize = BGP_RX_BUFFER_SIZE;
       s->tbsize = BGP_TX_BUFFER_SIZE;
       s->rx_hook = bgp_incoming_connection;
index 8cec2cddd310f87fdcf77b849a543ea523655417..e67ed80fa0bac347a8837cb0b68502e2b8dce4eb 100644 (file)
@@ -610,6 +610,25 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
 
 #endif
 
+static char *
+sk_set_ttl_int(sock *s)
+{
+  int one = 1;
+#ifdef IPV6
+  if (s->type != SK_UDP_MC && s->type != SK_IP_MC &&
+      setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
+    return "IPV6_UNICAST_HOPS";
+#else
+  if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
+    return "IP_TTL";
+#ifdef CONFIG_UNIX_DONTROUTE
+  if (s->ttl == 1 && setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
+    return "SO_DONTROUTE";
+#endif 
+#endif
+  return NULL;
+}
+
 #define ERR(x) do { err = x; goto bad; } while(0)
 #define WARN(x) log(L_WARN "sk_setup: %s: %m", x)
 
@@ -617,32 +636,50 @@ static char *
 sk_setup(sock *s)
 {
   int fd = s->fd;
-  int one = 1;
   char *err;
 
   if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
     ERR("fcntl(O_NONBLOCK)");
   if (s->type == SK_UNIX)
     return NULL;
-#ifdef IPV6
-  if (s->ttl >= 0 && s->type != SK_UDP_MC && s->type != SK_IP_MC &&
-      setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
-    ERR("IPV6_UNICAST_HOPS");
-#else
+#ifndef IPV6
   if ((s->tos >= 0) && setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
     WARN("IP_TOS");
-  if (s->ttl >= 0 && setsockopt(fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
-    ERR("IP_TTL");
-#ifdef CONFIG_UNIX_DONTROUTE
-  if (s->ttl == 1 && setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
-    ERR("SO_DONTROUTE");
-#endif 
 #endif
-  err = NULL;
+  
+  if (s->ttl >= 0)
+    err = sk_set_ttl_int(s);
+  else
+    err = NULL;
+
 bad:
   return err;
 }
 
+/**
+ * sk_set_ttl - set TTL for given socket.
+ * @s: socket
+ * @ttl: TTL value
+ *
+ * Set TTL for already opened connections when TTL was not set before.
+ * Useful for accepted connections when different ones should have 
+ * different TTL.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
+
+int
+sk_set_ttl(sock *s, int ttl)
+{
+  char *err;
+
+  s->ttl = ttl;
+  if (err = sk_set_ttl_int(s))
+    log(L_ERR "sk_set_ttl: %s: %m", err);
+
+  return (err ? -1 : 0);
+}
+
 
 /* FIXME: check portability  */