Hi, This patch adds support for IP multicast sockets to winsock. I stole liberally from a patch from the summer of 2001 from Marcus, so thanks to him for that: http://www.winehq.com/hypermail/wine-patches/2001/07/0009.html ChangeLog: - Map winsock sockopts to the POSIX equivalents for IP multicast - Remap winsock1 constant values to winsock2 using a forwarder function - Change a FIXME to a TRACE, it appeared to be simply reporting progress thanks -mike -- Mike Hearn <m.hearn@signal.qinetiq.com> QinetiQ - Malvern Technology Center
--- dlls/wsock32/socket.c 2002-08-17 01:43:18.000000000 +0100 +++ ../wine/dlls/wsock32/socket.c 2003-04-01 12:17:42.000000000 +0100 @@ -40,6 +40,9 @@ #define recv linux_recv /* */ +#define setsockopt linux_setsockopt +#define getsockopt linux_getsockopt + #include "config.h" #include <errno.h> @@ -85,9 +88,53 @@ extern int WINAPI ioctlsocket(SOCKET,long,u_long*); /* */ +/* for the get/setsockopt forwarders */ +#undef setsockopt +#undef getsockopt +extern int WINAPI setsockopt(SOCKET s, INT level, INT optname ,char* optval, INT optlen); +extern int WINAPI getsockopt(SOCKET s, INT level, INT optname ,char* optval, INT* optlen); WINE_DEFAULT_DEBUG_CHANNEL(winsock); +/* internal remapper function for the IP_ constants */ +INT _remap_optname(INT level, INT optname) { + TRACE("level=%d, optname=%d\n", level, optname); + if (level == WS_IPPROTO_IP) { + switch (optname) { /***** from value *****/ + case 2: return 9; /* IP_MULTICAST_IF */ + case 3: return 10; /* IP_MULTICAST_TTL */ + case 4: return 11; /* IP_MULTICAST_LOOP */ + case 5: return 12; /* IP_ADD_MEMBERSHIP */ + case 6: return 13; /* IP_DROP_MEMBERSHIP */ + case 7: return 4; /* IP_TTL */ + case 8: return 3; /* IP_TOS */ + case 9: return 14; /* IP_DONTFRAGMENT */ + default: FIXME("Unknown optname %d, can't remap!\n", optname); return optname; + } + } else { + /* don't need to do anything */ + return optname; + } +} + +/*********************************************************************** + * setsockopt (WSOCK32.21) + * + * We have these forwarders because, for reasons unknown to us mere mortals, + * the values of the IP_ constants changed between winsock.h and winsock2.h. + * So, we need to remap them here. + */ +INT WINAPI WS1_setsockopt(SOCKET s, INT level, INT optname, char *optval, INT optlen) +{ + return setsockopt(s, level, _remap_optname(level, optname), optval, optlen); +} + +/*********************************************************************** + * getsockopt (WSOCK32.7) + */ +INT WINAPI WS1_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen) { + return getsockopt(s, level, _remap_optname(level, optname), optval, optlen); +} /*********************************************************************** * WsControl (WSOCK32.1001) --- dlls/wsock32/wsock32.spec 2003-03-17 00:17:00.000000000 +0000 +++ ../wine/dlls/wsock32/wsock32.spec 2003-04-01 12:13:49.000000000 +0100 @@ -4,7 +4,7 @@ 4 stdcall connect(long ptr long) ws2_32.connect 5 stdcall getpeername(long ptr ptr) ws2_32.getpeername 6 stdcall getsockname(long ptr ptr) ws2_32.getsockname - 7 stdcall getsockopt(long long long ptr ptr) ws2_32.getsockopt + 7 stdcall getsockopt(long long long ptr ptr) WS1_getsockopt 8 stdcall htonl(long) ws2_32.htonl 9 stdcall htons(long) ws2_32.htons 10 stdcall inet_addr(str) ws2_32.inet_addr @@ -18,7 +18,7 @@ 18 stdcall select(long ptr ptr ptr ptr) ws2_32.select 19 stdcall send(long ptr long long) ws2_32.send 20 stdcall sendto(long ptr long long ptr long) ws2_32.sendto - 21 stdcall setsockopt(long long long ptr long) ws2_32.setsockopt + 21 stdcall setsockopt(long long long ptr long) WS1_setsockopt 22 stdcall shutdown(long long) ws2_32.shutdown 23 stdcall socket(long long long) ws2_32.socket 51 stdcall gethostbyaddr(ptr long long) ws2_32.gethostbyaddr --- dlls/winsock/socket.c 2003-03-17 04:42:11.000000000 +0000 +++ ../wine/dlls/winsock/socket.c 2003-04-01 13:41:16.000000000 +0100 @@ -278,6 +278,16 @@ 0 }; +static int _ws_ip_ops[] = { + WS_IP_MULTICAST_IF, WS_IP_MULTICAST_TTL, WS_IP_MULTICAST_LOOP, WS_IP_ADD_MEMBERSHIP, WS_IP_DROP_MEMBERSHIP, + WS_IP_DROP_MEMBERSHIP, WS_IP_OPTIONS, WS_IP_HDRINCL, WS_IP_TOS, WS_IP_TTL, 0 +}; + +static int _px_ip_ops[] = { + IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, + IP_DROP_MEMBERSHIP, IP_OPTIONS, IP_HDRINCL, IP_TOS, IP_TTL, 0 +}; + static DWORD opentype_tls_index = -1; /* TLS index for SO_OPENTYPE flag */ inline static DWORD NtStatusToWSAError ( const DWORD status ) @@ -482,6 +492,18 @@ } FIXME("Unknown IPPROTO_TCP optname 0x%x\n", *optname); break; + case WS_IPPROTO_IP: + *level = IPPROTO_IP; + for(i=0; _ws_ip_ops[i]; i++) { + if (_ws_ip_ops[i] == *optname ) break; + } + if( _ws_ip_ops[i] ) { + *optname = _px_ip_ops[i]; + return 1; + } + FIXME("Unknown IPPROTO_IP optname 0x%x\n", *optname); + break; + default: FIXME("Unimplemented or unknown socket level\n"); } return 0; } @@ -1488,7 +1511,7 @@ int on = 1; /* The game GrandPrixLegends binds more than one time, but does * not do a SO_REUSEADDR - Stevens says this is ok */ - FIXME( "Setting WS_SO_REUSEADDR on socket before we binding it\n"); + TRACE( "Setting WS_SO_REUSEADDR on socket before we bind it\n"); WS_setsockopt( s, WS_SOL_SOCKET, WS_SO_REUSEADDR, (char*)&on, sizeof(on) ); if (bind(fd, uaddr, uaddrlen) < 0) @@ -2724,6 +2748,7 @@ level = SOL_SOCKET; }else{ if (!convert_sockopt(&level, &optname)) { + ERR("Invalid level (%d) or optname (%d)\n", level, optname); SetLastError(WSAENOPROTOOPT); close(fd); return SOCKET_ERROR; @@ -2791,6 +2816,7 @@ close(fd); return 0; } + TRACE("Setting socket error, %d\n", wsaErrno()); SetLastError(wsaErrno()); close(fd); } --- include/winsock.h 2003-03-17 21:22:34.000000000 +0000 +++ ../wine/include/winsock.h 2003-03-28 17:04:47.000000000 +0000 @@ -653,6 +653,56 @@ #define WS_TCP_NODELAY 1 #endif +/* IPPROTO_IP options */ +#if !defined(__WINE_WINSOCK2__) /* WinSock2 has different values for the IP_ constants */ +# ifndef USE_WS_PREFIX +# define IP_OPTIONS 1 +# define IP_MULTICAST_IF 2 +# define IP_MULTICAST_TTL 3 +# define IP_MULTICAST_LOOP 4 +# define IP_ADD_MEMBERSHIP 5 +# define IP_DROP_MEMBERSHIP 6 +# define IP_TTL 7 +# define IP_TOS 8 +# define IP_DONTFRAGMENT 9 +# else +# define WS_IP_OPTIONS 1 +# define WS_IP_MULTICAST_IF 2 +# define WS_IP_MULTICAST_TTL 3 +# define WS_IP_MULTICAST_LOOP 4 +# define WS_IP_ADD_MEMBERSHIP 5 +# define WS_IP_DROP_MEMBERSHIP 6 +# define WS_IP_TTL 7 +# define WS_IP_TOS 8 +# define WS_IP_DONTFRAGMENT 9 +# endif +#else /* start the winsock2 section */ +# ifndef USE_WS_PREFIX +# define IP_OPTIONS 1 +# define IP_HDRINCL 2 +# define IP_TOS 3 +# define IP_TTL 4 +# define IP_MULTICAST_IF 9 +# define IP_MULTICAST_TTL 10 +# define IP_MULTICAST_LOOP 11 +# define IP_ADD_MEMBERSHIP 12 +# define IP_DROP_MEMBERSHIP 13 +# define IP_DONTFRAGMENT 14 +# else +# define WS_IP_OPTIONS 1 +# define WS_IP_HDRINCL 2 +# define WS_IP_TOS 3 +# define WS_IP_TTL 4 +# define WS_IP_MULTICAST_IF 9 +# define WS_IP_MULTICAST_TTL 10 +# define WS_IP_MULTICAST_LOOP 11 +# define WS_IP_ADD_MEMBERSHIP 12 +# define WS_IP_DROP_MEMBERSHIP 13 +# define WS_IP_DONTFRAGMENT 14 +# endif +#endif + + /* * Socket I/O flags (supported by spec 1.1) */