Erich Hoover : ws2_32: Permit broadcast packets on interface-bound sockets for systems with IP_UNICAST_IF and SO_ATTACH_FILTER .

Alexandre Julliard julliard at winehq.org
Tue Oct 2 14:09:39 CDT 2012


Module: wine
Branch: master
Commit: 57019615b51378187b9a09be55e262dc664cfc4f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=57019615b51378187b9a09be55e262dc664cfc4f

Author: Erich Hoover <ehoover at mines.edu>
Date:   Wed Sep 26 16:38:29 2012 -0600

ws2_32: Permit broadcast packets on interface-bound sockets for systems with IP_UNICAST_IF and SO_ATTACH_FILTER.

---

 configure            |    1 +
 configure.ac         |    1 +
 dlls/ws2_32/socket.c |   38 ++++++++++++++++++++++++++++++++++++++
 include/config.h.in  |    3 +++
 4 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index 54675b4..2be377a 100755
--- a/configure
+++ b/configure
@@ -5848,6 +5848,7 @@ for ac_header in \
 	link.h \
 	linux/cdrom.h \
 	linux/compiler.h \
+	linux/filter.h \
 	linux/hdreg.h \
 	linux/input.h \
 	linux/ioctl.h \
diff --git a/configure.ac b/configure.ac
index 79b1175..eb57696 100644
--- a/configure.ac
+++ b/configure.ac
@@ -443,6 +443,7 @@ AC_CHECK_HEADERS(\
 	link.h \
 	linux/cdrom.h \
 	linux/compiler.h \
+	linux/filter.h \
 	linux/hdreg.h \
 	linux/input.h \
 	linux/ioctl.h \
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index d645872..8efa1e6 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -92,6 +92,9 @@
 #ifdef HAVE_NET_IF_H
 # include <net/if.h>
 #endif
+#ifdef HAVE_LINUX_FILTER_H
+# include <linux/filter.h>
+#endif
 
 #ifdef HAVE_NETIPX_IPX_H
 # include <netipx/ipx.h>
@@ -167,6 +170,27 @@
 WINE_DEFAULT_DEBUG_CHANNEL(winsock);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
+#if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
+# define LINUX_BOUND_IF
+struct interface_filter {
+    struct sock_filter iface_memaddr;
+    struct sock_filter iface_rule;
+    struct sock_filter return_keep;
+    struct sock_filter return_dump;
+};
+# define FILTER_JUMP_DUMP(here)  (u_char)(offsetof(struct interface_filter, return_dump) \
+                                 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
+                                 /sizeof(struct sock_filter)
+# define FILTER_JUMP_KEEP(here)  (u_char)(offsetof(struct interface_filter, return_keep) \
+                                 -offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
+                                 /sizeof(struct sock_filter)
+static struct interface_filter generic_interface_filter = {
+    BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_AD_OFF+SKF_AD_IFINDEX),
+    BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(iface_rule), FILTER_JUMP_DUMP(iface_rule)),
+    BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* keep packet */
+    BPF_STMT(BPF_RET+BPF_K, 0)          /* dump packet */
+};
+#endif /* LINUX_BOUND_IF */
 
 /*
  * The actual definition of WSASendTo, wrapped in a different function name
@@ -2148,6 +2172,20 @@ static BOOL interface_bind( SOCKET s, int fd, struct sockaddr *addr )
             if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &adapter->Index, sizeof(adapter->Index)) != 0)
                 goto cleanup;
             ret = TRUE;
+#elif defined(LINUX_BOUND_IF)
+            in_addr_t ifindex = (in_addr_t) htonl(adapter->Index);
+            struct interface_filter specific_interface_filter;
+            struct sock_fprog filter_prog;
+
+            if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)) != 0)
+                goto cleanup; /* Failed to suggest egress interface */
+            memcpy(&specific_interface_filter, &generic_interface_filter, sizeof(generic_interface_filter));
+            specific_interface_filter.iface_rule.k = adapter->Index;
+            filter_prog.len = sizeof(generic_interface_filter)/sizeof(struct sock_filter);
+            filter_prog.filter = (struct sock_filter *) &specific_interface_filter;
+            if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) != 0)
+                goto cleanup; /* Failed to specify incoming packet filter */
+            ret = TRUE;
 #else
             FIXME("Broadcast packets on interface-bound sockets are not currently supported on this platform, "
                   "receiving broadcast packets will not work on socket %04lx.\n", s);
diff --git a/include/config.h.in b/include/config.h.in
index c1f29bc..67f4fe4 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -392,6 +392,9 @@
 /* Define to 1 if you have the <linux/compiler.h> header file. */
 #undef HAVE_LINUX_COMPILER_H
 
+/* Define to 1 if you have the <linux/filter.h> header file. */
+#undef HAVE_LINUX_FILTER_H
+
 /* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
 #undef HAVE_LINUX_GETHOSTBYNAME_R_6
 




More information about the wine-cvs mailing list