]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Better support for link-local addresses in IO code.
authorOndrej Zajicek <santiago@crfreenet.org>
Sun, 8 Jan 2012 14:27:04 +0000 (15:27 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Sun, 8 Jan 2012 14:27:04 +0000 (15:27 +0100)
lib/socket.h
sysdep/unix/io.c
sysdep/unix/unix.h

index 9b9452c65123fd985ec85ff6ff2c011f33671c9c..b0c3eda2c20f0b37ae091fc602478a8184f5f2b3 100644 (file)
@@ -58,7 +58,7 @@ int sk_set_ttl(sock *s, int ttl);     /* Set transmit TTL for given socket */
 int sk_set_min_ttl(sock *s, int ttl);  /* Set minimal accepted TTL for given socket */
 
 /* Add or remove security associations for given passive socket */
-int sk_set_md5_auth(sock *s, ip_addr a, char *passwd);
+int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
 int sk_rx_ready(sock *s);
 
 /* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
index 815989f88c772d7b37e4381dca1c320a0c0b84de..d72161f1179a45079d122c22af1763460a00dbe4 100644 (file)
@@ -609,10 +609,10 @@ sk_insert(sock *s)
 
 #ifdef IPV6
 
-void
-fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
+static void
+fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port)
 {
-  memset (sa, 0, sizeof (struct sockaddr_in6));
+  memset(sa, 0, sizeof (struct sockaddr_in6));
   sa->sin6_family = AF_INET6;
   sa->sin6_port = htons(port);
   sa->sin6_flowinfo = 0;
@@ -620,16 +620,13 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
   sa->sin6_len = sizeof(struct sockaddr_in6);
 #endif
   set_inaddr(&sa->sin6_addr, a);
-}
 
-static inline void
-fill_in_sockifa(sockaddr *sa, struct iface *ifa)
-{
-  sa->sin6_scope_id = ifa ? ifa->index : 0;
+  if (ifa && ipa_has_link_scope(a))
+    sa->sin6_scope_id = ifa->index;
 }
 
-void
-get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
+static void
+get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
 {
   if (check && sa->sin6_family != AF_INET6)
     bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family);
@@ -637,12 +634,15 @@ get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
     *port = ntohs(sa->sin6_port);
   memcpy(a, &sa->sin6_addr, sizeof(*a));
   ipa_ntoh(*a);
+
+  if (ifa && ipa_has_link_scope(*a))
+    *ifa = if_find_by_index(sa->sin6_scope_id);
 }
 
 #else
 
-void
-fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
+static void
+fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port)
 {
   memset (sa, 0, sizeof (struct sockaddr_in));
   sa->sin_family = AF_INET;
@@ -653,13 +653,8 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
   set_inaddr(&sa->sin_addr, a);
 }
 
-static inline void
-fill_in_sockifa(sockaddr *sa UNUSED, struct iface *ifa UNUSED)
-{
-}
-
-void
-get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
+static void
+get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
 {
   if (check && sa->sin_family != AF_INET)
     bug("get_sockaddr called for wrong address family (%d)", sa->sin_family);
@@ -855,6 +850,7 @@ sk_set_min_ttl(sock *s, int ttl)
  * sk_set_md5_auth - add / remove MD5 security association for given socket.
  * @s: socket
  * @a: IP address of the other side
+ * @ifa: Interface for link-local IP address
  * @passwd: password used for MD5 authentication
  *
  * In TCP MD5 handling code in kernel, there is a set of pairs
@@ -870,10 +866,10 @@ sk_set_min_ttl(sock *s, int ttl)
  */
 
 int
-sk_set_md5_auth(sock *s, ip_addr a, char *passwd)
+sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
 {
   sockaddr sa;
-  fill_in_sockaddr(&sa, a, 0);
+  fill_in_sockaddr(&sa, a, ifa, 0);
   return sk_set_md5_auth_int(s, &sa, passwd);
 }
 
@@ -1049,7 +1045,7 @@ sk_tcp_connected(sock *s)
   sockaddr lsa;
   int lsa_len = sizeof(lsa);
   if (getsockname(s->fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
-    get_sockaddr(&lsa, &s->saddr, &s->sport, 1);
+    get_sockaddr(&lsa, &s->saddr, &s->iface, &s->sport, 1);
 
   s->type = SK_TCP;
   sk_alloc_bufs(s);
@@ -1075,9 +1071,9 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
          sockaddr lsa;
          int lsa_len = sizeof(lsa);
          if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
-           get_sockaddr(&lsa, &t->saddr, &t->sport, 1);
+           get_sockaddr(&lsa, &t->saddr, &t->iface, &t->sport, 1);
 
-         get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1);
+         get_sockaddr((sockaddr *) sa, &t->daddr, &t->iface, &t->dport, 1);
        }
       sk_insert(t);
       if (err = sk_setup(t))
@@ -1156,12 +1152,11 @@ sk_open(sock *s)
          if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
            ERR("SO_REUSEADDR");
        }
-      fill_in_sockaddr(&sa, s->saddr, port);
-      fill_in_sockifa(&sa, s->iface);
+      fill_in_sockaddr(&sa, s->saddr, s->iface, port);
       if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
        ERR("bind");
     }
-  fill_in_sockaddr(&sa, s->daddr, s->dport);
+  fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
 
   if (s->password)
     {
@@ -1284,8 +1279,7 @@ sk_maybe_write(sock *s)
          return 1;
 
        sockaddr sa;
-       fill_in_sockaddr(&sa, s->daddr, s->dport);
-       fill_in_sockifa(&sa, s->iface);
+       fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
 
        struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
        // byte cmsg_buf[CMSG_TX_SPACE];
@@ -1463,7 +1457,7 @@ sk_read(sock *s)
            return 0;
          }
        s->rpos = s->rbuf + e;
-       get_sockaddr(&sa, &s->faddr, &s->fport, 1);
+       get_sockaddr(&sa, &s->faddr, NULL, &s->fport, 1);
        sysio_process_rx_cmsgs(s, &msg);
 
        s->rx_hook(s, e);
@@ -1480,7 +1474,7 @@ sk_write(sock *s)
     case SK_TCP_ACTIVE:
       {
        sockaddr sa;
-       fill_in_sockaddr(&sa, s->daddr, s->dport);
+       fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
        if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0 || errno == EISCONN)
          sk_tcp_connected(s);
        else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
index 76825aaddb696e1bbed2afc9d79fbfb8a2b65a95..ff31af29696704329a62aa578839770d6e05ed95 100644 (file)
@@ -48,8 +48,8 @@ struct birdsock;
 
 void io_init(void);
 void io_loop(void);
-void fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port);
-void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port, int check);
+// void fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port);
+// void get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check);
 void sk_open_unix(struct birdsock *s, char *name);
 void *tracked_fopen(struct pool *, char *name, char *mode);
 void test_old_bird(char *path);