summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-04-02 16:11:46 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2010-04-02 16:11:46 +0200
commite7b09e4ab99fc850480480bbb577ffa36a6c5cd7 (patch)
tree878afa02cdb11fc78664ea8ce5ac542e897d91d2
parent97ab4c34986139b2419c563a3de7ddfe41727d07 (diff)
downloadbird-e7b09e4ab99fc850480480bbb577ffa36a6c5cd7.tar
bird-e7b09e4ab99fc850480480bbb577ffa36a6c5cd7.zip
Use SO_BINDTODEVICE also in Linux/IPv6.
-rw-r--r--proto/ospf/iface.c10
-rw-r--r--sysdep/bsd/sysio.h8
-rw-r--r--sysdep/linux/sysio.h15
-rw-r--r--sysdep/unix/io.c3
4 files changed, 24 insertions, 12 deletions
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 0416355..6931619 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -66,17 +66,7 @@ ospf_sk_open(struct ospf_iface *ifa)
sk = sk_new(p->pool);
sk->type = SK_IP;
sk->dport = OSPF_PROTO;
-
-#ifdef OSPFv2
- /*
- * In Linux IPv4, binding a raw socket to an IP address of an iface causes
- * that the socket does not receive multicast packets, as they have
- * different (multicast) destination IP address.
- */
sk->saddr = IPA_NONE;
-#else /* OSPFv3 */
- sk->saddr = ifa->addr->ip; /* link-local addr */
-#endif
sk->tos = IP_PREC_INTERNET_CONTROL;
sk->rx_hook = ospf_rx_hook;
diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h
index 87c78fb..ff821a7 100644
--- a/sysdep/bsd/sysio.h
+++ b/sysdep/bsd/sysio.h
@@ -22,6 +22,14 @@ get_inaddr(ip_addr *a, struct in6_addr *ia)
ipa_ntoh(*a);
}
+static inline char *
+sysio_bind_to_iface(sock *s)
+{
+ /* Unfortunately not available */
+ return NULL;
+}
+
+
#else
#include <net/if.h>
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index 1cfbcc4..795d0b3 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -6,6 +6,8 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
+#include <net/if.h>
+
#ifdef IPV6
#ifndef IPV6_UNICAST_HOPS
@@ -28,9 +30,18 @@ get_inaddr(ip_addr *a, struct in6_addr *ia)
ipa_ntoh(*a);
}
-#else
+static inline char *
+sysio_bind_to_iface(sock *s)
+{
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, s->iface->name);
+ if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
+ return "SO_BINDTODEVICE";
-#include <net/if.h>
+ return NULL;
+}
+
+#else
static inline void
set_inaddr(struct in_addr *ia, ip_addr a)
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index abfa5c2..a0dbb41 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -876,6 +876,9 @@ sk_setup_multicast(sock *s)
if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
ERR("IPV6_MULTICAST_IF");
+ if (err = sysio_bind_to_iface(s))
+ goto bad;
+
return 0;
bad: