http://bugs.winehq.org/show_bug.cgi?id=7929
------- Additional Comments From damjan.jov@gmail.com 2007-20-06 01:34 ------- An app asks to bind to A.B.C.D, and on Windows that means it sends only through that NIC, receives unicasts from only that NIC, and still receives broadcasts through that NIC. On Linux it means it also sends only through that NIC, also receives unicasts only from that NIC, but *DOESN'T* receive any broadcasts from that NIC or any other. It's not a wine-specific bug, it's a long standing bug in Java too, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4212324.
User-space filtering is unthinkably ugly - you would have to bind to 0.0.0.0 so you can receive broadcasts, but you would not only get broadcasts from other NICs but also unicasts from other NICs (on the same port), as well as sending broadcasts through other NICs you would not normally send to. It would be a terrible hack - not only would bind/connect/recv/send have to be patched, but functions like select as well (since it has to peek at incoming UDP datagrams and chuck out the ones from the wrong NIC...) and getsockname (you have to lie to the app and say you're bound to A.B.C.D) and probably numerous others. It means you need radically different treatment of TCP and UDP sockets, and the patch would not only span ws2_32 but wineserver as well.
The SO_BINDTODEVICE option needs root access - so I can think of 2 solutions where wine doesn't run as root. You could pass the socket to a helper process that runs as root and have it apply SO_BINDTODEVICE for us, and if the helper process doesn't exist or have root access, fall back to what we have now. Or, when a UDP socket binds to an address other than 0.0.0.0, call a helper process and have it bind to 0.0.0.0 and the same port, then when the helper process receives a broadcast packet, filter it, and either use a raw socket to send it to the wine app that wants broadcasts or send it from a well-known port and somehow pass wine additional data that tells ws2_32 what to put into the address field of recvfrom().