From 76f6ffaf1b08fd3f30f5fe30e96e529778ba3b45 Mon Sep 17 00:00:00 2001 From: Francois Gouget <fgouget@free.fr> Date: Mon, 8 Oct 2001 20:36:03 +0000 Subject: [PATCH] Fix the SOCKADDR_IPX declaration. Centralize all sockaddr_xxx conversions in ws_sockaddr_ws2u and ws_sockaddr_u2ws. Remove ugly casts in TRACEs. --- dlls/winsock/socket.c | 698 +++++++++++++++++++++++------------------- include/winsock.h | 11 - include/wsipx.h | 14 +- 3 files changed, 400 insertions(+), 323 deletions(-) diff --git a/dlls/winsock/socket.c b/dlls/winsock/socket.c index 178697bf208..7b41bae3947 100644 --- a/dlls/winsock/socket.c +++ b/dlls/winsock/socket.c @@ -91,6 +91,7 @@ #include "wingdi.h" #include "winuser.h" #include "winsock2.h" +#include "wsipx.h" #include "wine/winsock16.h" #include "winnt.h" #include "heap.h" @@ -153,6 +154,7 @@ static FARPROC blocking_hook; int WS_dup_he(struct hostent* p_he, int flag); int WS_dup_pe(struct protoent* p_pe, int flag); int WS_dup_se(struct servent* p_se, int flag); +int WINAPI WSOCK32_getpeername(SOCKET s, ws_sockaddr *name, int *namelen); typedef void WIN_hostent; typedef void WIN_protoent; @@ -736,10 +738,13 @@ static struct ws_protoent* check_buffer_pe(int size) /* ----------------------------------- i/o APIs */ -/*********************************************************************** - * accept (WS2_32.1) - */ -static void WSOCK32_async_accept(SOCKET s, SOCKET as) +#ifdef HAVE_IPX +#define SUPPORTED_PF(pf) ((pf)==AF_INET || (pf)== AF_IPX) +#else +#define SUPPORTED_PF(pf) ((pf)==AF_INET) +#endif + +static void ws2_async_accept(SOCKET s, SOCKET as) { int q; /* queue socket for WSAAsyncSelect */ @@ -756,12 +761,130 @@ static void WSOCK32_async_accept(SOCKET s, SOCKET as) /**********************************************************************/ -SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr, - INT *addrlen32) +/* Returns the converted address if successful, NULL if it was too small to + * start with. Note that the returned pointer may be the original pointer + * if no conversion is necessary. + */ +const struct sockaddr* ws_sockaddr_ws2u(const ws_sockaddr* wsaddr, int wsaddrlen, int *uaddrlen) +{ + switch (wsaddr->sa_family) + { +#ifdef HAVE_IPX + case WS_AF_IPX: + { + struct ws_sockaddr_ipx* wsipx=(struct ws_sockaddr_ipx*)wsaddr; + struct sockaddr_ipx* uipx; + + if (wsaddrlen<sizeof(struct ws_sockaddr_ipx)) + return NULL; + + *uaddrlen=sizeof(struct sockaddr_ipx); + uipx=malloc(*uaddrlen); + uipx->sipx_family=AF_IPX; + uipx->sipx_port=wsipx->sa_socket; + /* copy sa_netnum and sa_nodenum to sipx_network and sipx_node + * in one go + */ + memcpy(&uipx->sipx_network,wsipx->sa_netnum,sizeof(uipx->sipx_network)+sizeof(uipx->sipx_node)); + uipx->sipx_type=IPX_FRAME_NONE; + uipx->sipx_zero=0; + return (const struct sockaddr*)uipx; + } +#endif + + default: + if (wsaddrlen<sizeof(ws_sockaddr)) + return NULL; + + /* No conversion needed, just return the original address */ + *uaddrlen=wsaddrlen; + return (const struct sockaddr*)wsaddr; + } + return NULL; +} + +/* allocates a Unix sockaddr structure to receive the data */ +inline struct sockaddr* ws_sockaddr_alloc(const ws_sockaddr* wsaddr, int* wsaddrlen, int* uaddrlen) { + if (*wsaddrlen==0) + *uaddrlen=0; + else + *uaddrlen=max(sizeof(struct sockaddr),*wsaddrlen); + if (wsaddr==NULL) + return NULL; + + return malloc(*uaddrlen); +} + +/* Returns 0 if successful, -1 if the buffer is too small */ +int ws_sockaddr_u2ws(const struct sockaddr* uaddr, int uaddrlen, ws_sockaddr* wsaddr, int* wsaddrlen) +{ + int res; + + switch(uaddr->sa_family) + { #ifdef HAVE_IPX - struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr; + case AF_IPX: + { + struct sockaddr_ipx* uipx=(struct sockaddr_ipx*)uaddr; + struct ws_sockaddr_ipx* wsipx=(struct ws_sockaddr_ipx*)wsaddr; + + res=-1; + switch (*wsaddrlen) /* how much can we copy? */ + { + default: + res=0; /* enough */ + wsipx->sa_socket=uipx->sipx_port; + /* fall through */ + case 13: + case 12: + memcpy(wsipx->sa_nodenum,uipx->sipx_node,sizeof(wsipx->sa_nodenum)); + /* fall through */ + case 11: + case 10: + case 9: + case 8: + case 7: + case 6: + memcpy(wsipx->sa_netnum,&uipx->sipx_network,sizeof(wsipx->sa_netnum)); + /* fall through */ + case 5: + case 4: + case 3: + case 2: + wsipx->sa_family=AF_IPX; + /* fall through */ + case 1: + case 0: + /* way too small */ + } + } + break; #endif + + default: + /* No conversion needed */ + memcpy(wsaddr,uaddr,*wsaddrlen); + res=(*wsaddrlen<uaddrlen?-1:0); + } + return res; +} + +/* to be called to free the memory allocated by ws_sockaddr_ws2u or + * ws_sockaddr_alloc + */ +inline void ws_sockaddr_free(const struct sockaddr* uaddr, const ws_sockaddr* wsaddr) +{ + if (uaddr!=NULL && uaddr!=(const struct sockaddr*)wsaddr) + free((void*)uaddr); +} + +/*********************************************************************** + * accept (WS2_32.1) + */ +SOCKET WINAPI WSOCK32_accept(SOCKET s, ws_sockaddr *addr, + int *addrlen32) +{ int fd = _get_sock_fd(s); TRACE("socket %04x\n", (UINT16)s ); @@ -790,37 +913,23 @@ SOCKET WINAPI WSOCK32_accept(SOCKET s, struct sockaddr *addr, if (as) { unsigned omask = _get_sock_mask( s ); - int fd = _get_sock_fd( as ); - if( getpeername(fd, addr, addrlen32) != -1 ) - { -#ifdef HAVE_IPX - if (addr && ((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) { - addr = (struct sockaddr *) - malloc(addrlen32 ? *addrlen32 : sizeof(*addr2)); - memcpy(addr, addr2, - addrlen32 ? *addrlen32 : sizeof(*addr2)); - addr2->sipx_family = WS_AF_IPX; - addr2->sipx_network = ((struct sockaddr_ipx *)addr)->sipx_network; - addr2->sipx_port = ((struct sockaddr_ipx *)addr)->sipx_port; - memcpy(addr2->sipx_node, - ((struct sockaddr_ipx *)addr)->sipx_node, IPX_NODE_LEN); - free(addr); - } -#endif - } else SetLastError(wsaErrno()); - close(fd); + WSOCK32_getpeername(fd, addr, addrlen32); if (omask & FD_WINE_SERVEVENT) - WSOCK32_async_accept(s, as); + ws2_async_accept(s, as); return as; } } + else + { + SetLastError(WSAENOTSOCK); + } return INVALID_SOCKET; } /*********************************************************************** * accept (WINSOCK.1) */ -SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr, +SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, ws_sockaddr* addr, INT16* addrlen16 ) { INT addrlen32 = addrlen16 ? *addrlen16 : 0; @@ -832,80 +941,73 @@ SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr, /*********************************************************************** * bind (WS2_32.2) */ -INT WINAPI WSOCK32_bind(SOCKET s, struct sockaddr *name, INT namelen) +int WINAPI WSOCK32_bind(SOCKET s, const ws_sockaddr* name, int namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; - TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen); + TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen); #if DEBUG_SOCKADDR dump_sockaddr(name); #endif + res=SOCKET_ERROR; if (fd != -1) { - /* FIXME: what family does this really map to on the Unix side? */ - if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (name && - ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX) - { - name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(name, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port; - ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network; - memcpy(((struct sockaddr_ipx *)name)->sipx_node, - name2->sipx_node, IPX_NODE_LEN); - namelen = sizeof(struct sockaddr_ipx); - } -#endif - if ( namelen >= sizeof(*name) ) - { - if ( name && (((struct ws_sockaddr_in *)name)->sin_family == AF_INET -#ifdef HAVE_IPX - || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX -#endif - )) + if (!name || !SUPPORTED_PF(name->sa_family)) { - if ( bind(fd, name, namelen) < 0 ) - { - int loc_errno = errno; - WARN("\tfailure - errno = %i\n", errno); - errno = loc_errno; - switch(errno) - { - case EBADF: SetLastError(WSAENOTSOCK); break; - case EADDRNOTAVAIL: SetLastError(WSAEINVAL); break; - default: SetLastError(wsaErrno());break; - } - } - else { -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - close(fd); - return 0; /* success */ - } - } else SetLastError(WSAEAFNOSUPPORT); - } else SetLastError(WSAEFAULT); -#ifdef HAVE_IPX - if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - close(fd); + SetLastError(WSAEAFNOSUPPORT); + } + else + { + const struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + if (bind(fd, uaddr, uaddrlen) < 0) + { + int loc_errno = errno; + WARN("\tfailure - errno = %i\n", errno); + errno = loc_errno; + switch (errno) + { + case EBADF: + SetLastError(WSAENOTSOCK); + break; + case EADDRNOTAVAIL: + SetLastError(WSAEINVAL); + break; + default: + SetLastError(wsaErrno()); + break; + } + } + else + { + res=0; /* success */ + } + ws_sockaddr_free(uaddr,name); + } + } + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * bind (WINSOCK.2) */ -INT16 WINAPI WINSOCK_bind16(SOCKET16 s, struct sockaddr *name, INT16 namelen) +INT16 WINAPI WINSOCK_bind16(SOCKET16 s, ws_sockaddr *name, INT16 namelen) { return (INT16)WSOCK32_bind( s, name, namelen ); } @@ -931,89 +1033,85 @@ INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s) /*********************************************************************** * connect (WS2_32.4) */ -INT WINAPI WSOCK32_connect(SOCKET s, struct sockaddr *name, INT namelen) +int WINAPI WSOCK32_connect(SOCKET s, const ws_sockaddr* name, int namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif - int fd = _get_sock_fd(s); + int fd = _get_sock_fd(s); - TRACE("socket %04x, ptr %8x, length %d\n", s, (int) name, namelen); + TRACE("socket %04x, ptr %p, length %d\n", s, name, namelen); #if DEBUG_SOCKADDR - dump_sockaddr(name); + dump_sockaddr(name); #endif - if (fd != -1) - { - if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)name)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (name && ((struct ws_sockaddr_ipx *)name)->sipx_family == WS_AF_IPX) - { - name = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(name, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)name)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)name)->sipx_port = name2->sipx_port; - ((struct sockaddr_ipx *)name)->sipx_network = name2->sipx_network; - memcpy(((struct sockaddr_ipx *)name)->sipx_node, - name2->sipx_node, IPX_NODE_LEN); - namelen = sizeof(struct sockaddr_ipx); - } -#endif - if (connect(fd, name, namelen) == 0) { - close(fd); - goto connect_success; - } - if (errno == EINPROGRESS) + if (fd != -1) { - /* tell wineserver that a connection is in progress */ - _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, - FD_CONNECT|FD_READ|FD_WRITE, - FD_WINE_CONNECTED|FD_WINE_LISTENING); - if (_is_blocking(s)) - { - int result; - /* block here */ - do_block(fd, 7); - _sync_sock_state(s); /* let wineserver notice connection */ - /* retrieve any error codes from it */ - result = _get_sock_error(s, FD_CONNECT_BIT); - if (result) - SetLastError(result); - else { - close(fd); - goto connect_success; - } - } - else SetLastError(WSAEWOULDBLOCK); - close(fd); + const struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_ws2u(name,namelen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + int rc; + + rc=connect(fd, uaddr, uaddrlen); + ws_sockaddr_free(uaddr,name); + if (rc == 0) + goto connect_success; + } + + if (errno == EINPROGRESS) + { + /* tell wineserver that a connection is in progress */ + _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, + FD_CONNECT|FD_READ|FD_WRITE, + FD_WINE_CONNECTED|FD_WINE_LISTENING); + if (_is_blocking(s)) + { + int result; + /* block here */ + do_block(fd, 7); + _sync_sock_state(s); /* let wineserver notice connection */ + /* retrieve any error codes from it */ + result = _get_sock_error(s, FD_CONNECT_BIT); + if (result) + SetLastError(result); + else + { + goto connect_success; + } + } + else + { + SetLastError(WSAEWOULDBLOCK); + } + } + else + { + SetLastError(wsaErrno()); + } + close(fd); } else { - SetLastError(wsaErrno()); - close(fd); + SetLastError(WSAENOTSOCK); } - } -#ifdef HAVE_IPX - if (name && ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif - return SOCKET_ERROR; + return SOCKET_ERROR; + connect_success: -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) - free(name); -#endif + close(fd); _enable_event(s, FD_CONNECT|FD_READ|FD_WRITE, - FD_WINE_CONNECTED|FD_READ|FD_WRITE, - FD_CONNECT|FD_WINE_LISTENING); - return 0; + FD_WINE_CONNECTED|FD_READ|FD_WRITE, + FD_CONNECT|FD_WINE_LISTENING); + return 0; } /*********************************************************************** * connect (WINSOCK.4) */ -INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen) +INT16 WINAPI WINSOCK_connect16(SOCKET16 s, ws_sockaddr *name, INT16 namelen) { return (INT16)WSOCK32_connect( s, name, namelen ); } @@ -1021,44 +1119,47 @@ INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen) /*********************************************************************** * getpeername (WS2_32.5) */ -INT WINAPI WSOCK32_getpeername(SOCKET s, struct sockaddr *name, - INT *namelen) +int WINAPI WSOCK32_getpeername(SOCKET s, ws_sockaddr *name, int *namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; + + TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen); - TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, *namelen); + res=SOCKET_ERROR; if (fd != -1) { - if (getpeername(fd, name, namelen) == 0) { -#ifdef HAVE_IPX - if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) { - name = (struct sockaddr *) - malloc(namelen ? *namelen : sizeof(*name2)); - memcpy(name, name2, namelen ? *namelen : sizeof(*name2)); - name2->sipx_family = WS_AF_IPX; - name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network; - name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port; - memcpy(name2->sipx_node, - ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN); - free(name); - } -#endif - close(fd); - return 0; - } - SetLastError(wsaErrno()); - close(fd); + struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen); + if (getpeername(fd, uaddr, &uaddrlen) != 0) + { + SetLastError(wsaErrno()); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0) + { + /* The buffer was too small */ + SetLastError(WSAEFAULT); + } + else + { + res=0; + } + ws_sockaddr_free(uaddr,name); + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * getpeername (WINSOCK.5) */ -INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name, +INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, ws_sockaddr *name, INT16 *namelen16) { INT namelen32 = *namelen16; @@ -1075,44 +1176,46 @@ INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name, /*********************************************************************** * getsockname (WS2_32.6) */ -INT WINAPI WSOCK32_getsockname(SOCKET s, struct sockaddr *name, - INT *namelen) +int WINAPI WSOCK32_getsockname(SOCKET s, ws_sockaddr *name, int *namelen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; -#endif int fd = _get_sock_fd(s); + int res; - TRACE("socket: %04x, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen); + TRACE("socket: %04x, ptr %p, len %8x\n", s, name, *namelen); + + res=SOCKET_ERROR; if (fd != -1) { - if (getsockname(fd, name, namelen) == 0) { -#ifdef HAVE_IPX - if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) { - name = (struct sockaddr *) - malloc(namelen ? *namelen : sizeof(*name2)); - memcpy(name, name2, namelen ? *namelen : sizeof(*name2)); - name2->sipx_family = WS_AF_IPX; - name2->sipx_network = ((struct sockaddr_ipx *)name)->sipx_network; - name2->sipx_port = ((struct sockaddr_ipx *)name)->sipx_port; - memcpy(name2->sipx_node, - ((struct sockaddr_ipx *)name)->sipx_node, IPX_NODE_LEN); - free(name); - } -#endif - close(fd); - return 0; - } - SetLastError(wsaErrno()); - close(fd); + struct sockaddr* uaddr; + int uaddrlen; + + uaddr=ws_sockaddr_alloc(name,namelen,&uaddrlen); + if (getsockname(fd, uaddr, &uaddrlen) != 0) + { + SetLastError(wsaErrno()); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,name,namelen) != 0) + { + /* The buffer was too small */ + SetLastError(WSAEFAULT); + } + else + { + res=0; + } + close(fd); } - return SOCKET_ERROR; + else + { + SetLastError(WSAENOTSOCK); + } + return res; } /*********************************************************************** * getsockname (WINSOCK.6) */ -INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, struct sockaddr *name, +INT16 WINAPI WINSOCK_getsockname16(SOCKET16 s, ws_sockaddr *name, INT16 *namelen16) { INT retVal; @@ -1684,77 +1787,70 @@ INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags) /*********************************************************************** * recvfrom (WS2_32.17) */ -INT WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *from, INT *fromlen32) +int WINAPI WSOCK32_recvfrom(SOCKET s, char *buf, INT len, int flags, + ws_sockaddr *from, int *fromlen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from; -#endif int fd = _get_sock_fd(s); + int res; TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags); #if DEBUG_SOCKADDR - if( from ) dump_sockaddr(from); - else DPRINTF("from = NULL\n"); + if (from) + dump_sockaddr(from); + else + DPRINTF("from = NULL\n"); #endif + res=SOCKET_ERROR; if (fd != -1) { - int length; + struct sockaddr* uaddr; + int uaddrlen; + int length; - if (_is_blocking(s)) - { - /* block here */ - /* FIXME: OOB and exceptfds */ - do_block(fd, 1); - } - if ((length = recvfrom(fd, buf, len, flags, from, fromlen32)) >= 0) - { - TRACE(" -> %i bytes\n", length); + if (_is_blocking(s)) + { + /* block here */ + /* FIXME: OOB and exceptfds */ + do_block(fd, 1); + } -#ifdef HAVE_IPX - if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { - from = (struct sockaddr *) - malloc(fromlen32 ? *fromlen32 : sizeof(*from2)); - memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2)); - from2->sipx_family = WS_AF_IPX; - from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network; - from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port; - memcpy(from2->sipx_node, - ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN); - free(from); - } -#endif - close(fd); - _enable_event(s, FD_READ, 0, 0); - return length; - } - SetLastError(wsaErrno()); - close(fd); + uaddr=ws_sockaddr_alloc(from,fromlen,&uaddrlen); + length=recvfrom(fd, buf, len, flags, uaddr, &uaddrlen); + if (length < 0) + { + SetLastError(wsaErrno()); + WARN(" -> ERROR\n"); + } + else if (ws_sockaddr_u2ws(uaddr,uaddrlen,from,fromlen) != 0) + { + /* The from buffer was too small, but we read the data + * anyway. Is that really bad? + */ + SetLastError(WSAEFAULT); + WARN(" -> WSAEFAULT\n"); + } + else + { + TRACE(" -> %i bytes\n", length); + _enable_event(s, FD_READ, 0, 0); + res=length; + } + close(fd); } - else SetLastError(WSAENOTSOCK); - WARN(" -> ERROR\n"); -#ifdef HAVE_IPX - if (from && ((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { - from = (struct sockaddr *) - malloc(fromlen32 ? *fromlen32 : sizeof(*from2)); - memcpy(from, from2, fromlen32 ? *fromlen32 : sizeof(*from2)); - from2->sipx_family = WS_AF_IPX; - from2->sipx_network = ((struct sockaddr_ipx *)from)->sipx_network; - from2->sipx_port = ((struct sockaddr_ipx *)from)->sipx_port; - memcpy(from2->sipx_node, - ((struct sockaddr_ipx *)from)->sipx_node, IPX_NODE_LEN); - free(from); + else + { + SetLastError(WSAENOTSOCK); + WARN(" -> WSAENOTSOCK\n"); } -#endif - return SOCKET_ERROR; + return res; } /*********************************************************************** * recvfrom (WINSOCK.17) */ INT16 WINAPI WINSOCK_recvfrom16(SOCKET16 s, char *buf, INT16 len, INT16 flags, - struct sockaddr *from, INT16 *fromlen16) + ws_sockaddr *from, INT16 *fromlen16) { INT fromlen32; INT *p = &fromlen32; @@ -1947,72 +2043,56 @@ INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags) /*********************************************************************** * sendto (WS2_32.20) */ -INT WINAPI WSOCK32_sendto(SOCKET s, char *buf, INT len, INT flags, - struct sockaddr *to, INT tolen) +int WINAPI WSOCK32_sendto(SOCKET s, const char *buf, int len, int flags, + const ws_sockaddr *to, int tolen) { -#ifdef HAVE_IPX - struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to; -#endif int fd = _get_sock_fd(s); + int res; TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags); + + res=SOCKET_ERROR; if (fd != -1) { - INT length; + const struct sockaddr* uaddr; + int uaddrlen; - if (to && ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_PUP) - ((struct ws_sockaddr_ipx *)to)->sipx_family = AF_UNSPEC; -#ifdef HAVE_IPX - else if (to && - ((struct ws_sockaddr_ipx *)to)->sipx_family == WS_AF_IPX) - { - to = (struct sockaddr *) malloc(sizeof(struct sockaddr_ipx)); - memset(to, '\0', sizeof(struct sockaddr_ipx)); - ((struct sockaddr_ipx *)to)->sipx_family = AF_IPX; - ((struct sockaddr_ipx *)to)->sipx_port = to2->sipx_port; - ((struct sockaddr_ipx *)to)->sipx_network = to2->sipx_network; - memcpy(((struct sockaddr_ipx *)to)->sipx_node, - to2->sipx_node, IPX_NODE_LEN); - tolen = sizeof(struct sockaddr_ipx); - } -#endif - if (_is_blocking(s)) - { - /* block here */ - /* FIXME: exceptfds */ - do_block(fd, 2); - } - if ((length = sendto(fd, buf, len, flags, to, tolen)) < 0 ) - { - SetLastError(wsaErrno()); - if( GetLastError() == WSAEWOULDBLOCK ) - _enable_event(s, FD_WRITE, 0, 0); - } - else { -#ifdef HAVE_IPX - if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { - free(to); - } -#endif - close(fd); - return length; - } - close(fd); + uaddr=ws_sockaddr_ws2u(to,tolen,&uaddrlen); + if (uaddr == NULL) + { + SetLastError(WSAEFAULT); + } + else + { + if (_is_blocking(s)) + { + /* block here */ + /* FIXME: exceptfds */ + do_block(fd, 2); + } + res=sendto(fd, buf, len, flags, uaddr, uaddrlen); + if (res < 0 ) + { + SetLastError(wsaErrno()); + if( GetLastError() == WSAEWOULDBLOCK ) + _enable_event(s, FD_WRITE, 0, 0); + } + ws_sockaddr_free(uaddr,to); + } + close(fd); } - else SetLastError(WSAENOTSOCK); -#ifdef HAVE_IPX - if (to && ((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { - free(to); + else + { + SetLastError(WSAENOTSOCK); } -#endif - return SOCKET_ERROR; + return res; } /*********************************************************************** * sendto (WINSOCK.20) */ INT16 WINAPI WINSOCK_sendto16(SOCKET16 s, char *buf, INT16 len, INT16 flags, - struct sockaddr *to, INT16 tolen) + ws_sockaddr *to, INT16 tolen) { return (INT16)WSOCK32_sendto( s, buf, len, flags, to, tolen ); } diff --git a/include/winsock.h b/include/winsock.h index b1afc4fbaa6..124154d87b1 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -441,17 +441,6 @@ INT WINAPI WSARecvEx(SOCKET s, char *buf, INT len, INT *flags); #define WS_AF_MAX 27 -#include "pshpack1.h" - -struct ws_sockaddr_ipx -{ - SHORT sipx_family; - UINT sipx_network; - CHAR sipx_node[6]; - WORD sipx_port; -}; - -#include "poppack.h" #ifdef __cplusplus } diff --git a/include/wsipx.h b/include/wsipx.h index d40839ac66e..7ed21c09fb3 100644 --- a/include/wsipx.h +++ b/include/wsipx.h @@ -1,13 +1,21 @@ /* WCIPX.H */ -#ifndef _WINE_WCIPX_ -#define _WINE_WCIPX_ +#ifndef _WINE_WSIPX_ +#define _WINE_WSIPX_ #ifdef __cplusplus extern "C" { #endif /* defined(__cplusplus) */ +typedef struct ws_sockaddr_ipx +{ + short sa_family; + char sa_netnum[4]; + char sa_nodenum[6]; + unsigned short sa_socket; +} SOCKADDR_IPX, *PSOCKADDR_IPX, *LPSOCKADDR_IPX; + /* * constants */ @@ -20,4 +28,4 @@ extern "C" { } /* extern "C" */ #endif /* defined(__cplusplus) */ -#endif /* _WINE_WCIPX_ */ +#endif /* _WINE_WSIPX_ */ -- GitLab