From dc163422a126c8d0e770a207f7b2697d2b715410 Mon Sep 17 00:00:00 2001 From: Stephen Langasek Date: Sun, 8 Nov 1998 15:42:40 +0000 Subject: [PATCH] Support for IPX networking via winsock under Linux. --- configure | 2 +- configure.in | 2 +- include/config.h.in | 3 + include/winsock.h | 20 ++++ misc/winsock.c | 219 ++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 226 insertions(+), 20 deletions(-) diff --git a/configure b/configure index a553e5e1d08..5d07c4d07a7 100755 --- a/configure +++ b/configure @@ -2805,7 +2805,7 @@ else fi done -for ac_hdr in wctype.h sys/syscall.h syscall.h sys/param.h sys/vfs.h sys/mount.h sys/statfs.h float.h linux/cdrom.h linux/ucdrom.h sys/cdio.h sys/filio.h sys/modem.h strings.h sys/strtio.h dlfcn.h unistd.h sys/sockio.h net/if.h netinet/in.h +for ac_hdr in wctype.h sys/syscall.h syscall.h sys/param.h sys/vfs.h sys/mount.h sys/statfs.h float.h linux/cdrom.h linux/ucdrom.h sys/cdio.h sys/filio.h sys/modem.h strings.h sys/strtio.h dlfcn.h unistd.h sys/sockio.h net/if.h netinet/in.h linux/ipx.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 diff --git a/configure.in b/configure.in index fe6979fa8d3..a3e681a2a31 100644 --- a/configure.in +++ b/configure.in @@ -284,7 +284,7 @@ fi dnl **** Check for functions and header files **** AC_CHECK_FUNCS(clone getpagesize memmove sendmsg sigaltstack strerror stricmp tcgetattr timegm usleep wait4 waitpid vfscanf) -AC_CHECK_HEADERS(wctype.h sys/syscall.h syscall.h sys/param.h sys/vfs.h sys/mount.h sys/statfs.h float.h linux/cdrom.h linux/ucdrom.h sys/cdio.h sys/filio.h sys/modem.h strings.h sys/strtio.h dlfcn.h unistd.h sys/sockio.h net/if.h netinet/in.h) +AC_CHECK_HEADERS(wctype.h sys/syscall.h syscall.h sys/param.h sys/vfs.h sys/mount.h sys/statfs.h float.h linux/cdrom.h linux/ucdrom.h sys/cdio.h sys/filio.h sys/modem.h strings.h sys/strtio.h dlfcn.h unistd.h sys/sockio.h net/if.h netinet/in.h linux/ipx.h) AC_HEADER_STAT() AC_C_CONST() AC_TYPE_SIZE_T() diff --git a/include/config.h.in b/include/config.h.in index c7700d02e64..88fc085cf76 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -120,6 +120,9 @@ /* Define if you have the header file. */ #undef HAVE_LINUX_CDROM_H +/* Define if you have the header file. */ +#undef HAVE_LINUX_IPX_H + /* Define if you have the header file. */ #undef HAVE_LINUX_UCDROM_H diff --git a/include/winsock.h b/include/winsock.h index 363615bb21c..0cbc6b0b843 100644 --- a/include/winsock.h +++ b/include/winsock.h @@ -13,6 +13,10 @@ #include #include #include +#ifdef HAVE_LINUX_IPX_H +# include +# include +#endif #include #include "windows.h" #include "task.h" @@ -419,6 +423,22 @@ INT32 WINAPI WSAAsyncSelect32(SOCKET32 s, HWND32 hWnd, UINT32 uMsg, UINT32 l #define WSAAsyncSelect WINELIB_NAME(WSAAsyncSelect) +#ifdef HAVE_LINUX_IPX_H + +/* + * socket domains + */ +#define WS_AF_IPX 6 + +struct ws_sockaddr_ipx +{ + INT16 sipx_family __attribute__((packed)); + UINT32 sipx_network __attribute__((packed)); + CHAR sipx_node[6] __attribute__((packed)); + UINT16 sipx_port __attribute__((packed)); +}; +#endif + #ifdef __cplusplus } #endif diff --git a/misc/winsock.c b/misc/winsock.c index dbf45ef1c2c..ae97743f6ab 100644 --- a/misc/winsock.c +++ b/misc/winsock.c @@ -552,8 +552,11 @@ struct ws_protoent* _check_buffer_pe(LPWSINFO pwsi, int size) SOCKET32 WINAPI WINSOCK_accept32(SOCKET32 s, struct sockaddr *addr, INT32 *addrlen32) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR((SOCKET16)s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR((SOCKET16)s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* addr2 = (struct ws_sockaddr_ipx *)addr; +#endif TRACE(winsock, "(%08x): socket %04x\n", (unsigned)pwsi, (UINT16)s ); @@ -577,12 +580,36 @@ SOCKET32 WINAPI WINSOCK_accept32(SOCKET32 s, struct sockaddr *addr, WSAAsyncSelect32( s, pws->psop->hWnd, pws->psop->uMsg, pws->flags & ~WS_FD_ACCEPT ); } +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) { + addr = (struct sockaddr *) malloc(*addrlen32); + memcpy(addr, addr2, *addrlen32); + 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 return s; } else pwsi->err = WSAENOBUFS; } else pwsi->err = wsaErrno(); } +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)addr)->sipx_family == AF_IPX) { + addr = (struct sockaddr *) malloc(*addrlen32); + memcpy(addr, addr2, *addrlen32); + 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 return INVALID_SOCKET32; } @@ -603,8 +630,11 @@ SOCKET16 WINAPI WINSOCK_accept16(SOCKET16 s, struct sockaddr* addr, */ INT32 WINAPI WINSOCK_bind32(SOCKET32 s, struct sockaddr *name, INT32 namelen) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; +#endif TRACE(winsock, "(%08x): socket %04x, ptr %8x, length %d\n", (unsigned)pwsi, s, (int) name, namelen); @@ -614,9 +644,26 @@ INT32 WINAPI WINSOCK_bind32(SOCKET32 s, struct sockaddr *name, INT32 namelen) if ( _check_ws(pwsi, pws) ) { +#ifdef HAVE_LINUX_IPX_H + if (((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 ( ((struct ws_sockaddr_in *)name)->sin_family == AF_INET ) + if ( ((struct ws_sockaddr_in *)name)->sin_family == AF_INET +#ifdef HAVE_LINUX_IPX_H + || ((struct sockaddr_ipx *)name)->sipx_family == AF_IPX +#endif + ) { if ( bind(pws->fd, name, namelen) < 0 ) { @@ -687,8 +734,11 @@ INT16 WINAPI WINSOCK_closesocket16(SOCKET16 s) */ INT32 WINAPI WINSOCK_connect32(SOCKET32 s, struct sockaddr *name, INT32 namelen) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; +#endif TRACE(winsock, "(%08x): socket %04x, ptr %8x, length %d\n", (unsigned)pwsi, s, (int) name, namelen); @@ -698,6 +748,18 @@ INT32 WINAPI WINSOCK_connect32(SOCKET32 s, struct sockaddr *name, INT32 namelen) if( _check_ws(pwsi, pws) ) { +#ifdef HAVE_LINUX_IPX_H + if (((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(pws->fd, name, namelen) == 0) { if( pws->psop && (pws->flags & WS_FD_CONNECT) ) @@ -724,10 +786,18 @@ INT32 WINAPI WINSOCK_connect32(SOCKET32 s, struct sockaddr *name, INT32 namelen) } pws->flags |= WS_FD_CONNECTED; pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT | WS_FD_LISTENING); +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) + free(name); +#endif return 0; } pwsi->err = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno(); } +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) + free(name); +#endif return SOCKET_ERROR; } @@ -745,17 +815,45 @@ INT16 WINAPI WINSOCK_connect16(SOCKET16 s, struct sockaddr *name, INT16 namelen) INT32 WINAPI WINSOCK_getpeername32(SOCKET32 s, struct sockaddr *name, INT32 *namelen) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; +#endif TRACE(winsock, "(%08x): socket: %04x, ptr %8x, ptr %8x\n", (unsigned)pwsi, s, (int) name, *namelen); if( _check_ws(pwsi, pws) ) { - if (getpeername(pws->fd, name, namelen) == 0) + if (getpeername(pws->fd, name, namelen) == 0) { +#ifdef HAVE_LINUX_IPX_H + if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) { + name = (struct sockaddr *) malloc(*namelen); + memcpy(name, name2, *namelen); + 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 return 0; + } pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno(); } +#ifdef HAVE_LINUX_IPX_H + if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) { + name = (struct sockaddr *) malloc(*namelen); + memcpy(name, name2, *namelen); + 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 return SOCKET_ERROR; } @@ -782,17 +880,45 @@ INT16 WINAPI WINSOCK_getpeername16(SOCKET16 s, struct sockaddr *name, INT32 WINAPI WINSOCK_getsockname32(SOCKET32 s, struct sockaddr *name, INT32 *namelen) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* name2 = (struct ws_sockaddr_ipx *)name; +#endif TRACE(winsock, "(%08x): socket: %04x, ptr %8x, ptr %8x\n", (unsigned)pwsi, s, (int) name, (int) *namelen); if( _check_ws(pwsi, pws) ) { - if (getsockname(pws->fd, name, namelen) == 0) + if (getsockname(pws->fd, name, namelen) == 0) { +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)name)->sipx_family == AF_IPX) { + name = (struct sockaddr *) malloc(*namelen); + memcpy(name, name2, *namelen); + 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 return 0; + } pwsi->err = (h_errno < 0) ? wsaErrno() : wsaHerrno(); } +#ifdef HAVE_LINUX_IPX_H + if (((struct ws_sockaddr_ipx *)name)->sipx_family == AF_IPX) { + name = (struct sockaddr *) malloc(*namelen); + memcpy(name, name2, *namelen); + 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 return SOCKET_ERROR; } @@ -1055,8 +1181,11 @@ INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags) INT32 WINAPI WINSOCK_recvfrom32(SOCKET32 s, char *buf, INT32 len, INT32 flags, struct sockaddr *from, INT32 *fromlen32) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* from2 = (struct ws_sockaddr_ipx *)from; +#endif TRACE(winsock, "(%08x): socket %04x, ptr %08x, " "len %d, flags %d\n", (unsigned)pwsi, s, (unsigned)buf, @@ -1077,12 +1206,36 @@ INT32 WINAPI WINSOCK_recvfrom32(SOCKET32 s, char *buf, INT32 len, INT32 flags, if( pws->psop && (pws->flags & (WS_FD_READ | WS_FD_CLOSE)) ) EVENT_AddIO( pws->fd, EVENT_IO_READ ); /* reenabler */ +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { + from = (struct sockaddr *) malloc(*fromlen32); + memcpy(from, from2, *fromlen32); + 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 return (INT16)length; } pwsi->err = wsaErrno(); } else if( pwsi ) pwsi->err = WSAENOTSOCK; WARN(winsock, " -> ERROR\n"); +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)from)->sipx_family == AF_IPX) { + from = (struct sockaddr *) malloc(*fromlen32); + memcpy(from, from2, *fromlen32); + 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 return SOCKET_ERROR; } @@ -1222,8 +1375,11 @@ INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags) INT32 WINAPI WINSOCK_sendto32(SOCKET32 s, char *buf, INT32 len, INT32 flags, struct sockaddr *to, INT32 tolen) { - ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); - LPWSINFO pwsi = wsi_find(GetCurrentTask()); + ws_socket* pws = (ws_socket*)WS_HANDLE2PTR(s); + LPWSINFO pwsi = wsi_find(GetCurrentTask()); +#ifdef HAVE_LINUX_IPX_H + struct ws_sockaddr_ipx* to2 = (struct ws_sockaddr_ipx *)to; +#endif TRACE(winsock, "(%08x): socket %04x, ptr %08x, length %d, flags %d\n", (unsigned)pwsi, s, (unsigned) buf, len, flags); @@ -1231,6 +1387,18 @@ INT32 WINAPI WINSOCK_sendto32(SOCKET32 s, char *buf, INT32 len, INT32 flags, { INT32 length; +#ifdef HAVE_LINUX_IPX_H + if (((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 ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 ) { pwsi->err = wsaErrno(); @@ -1238,9 +1406,21 @@ INT32 WINAPI WINSOCK_sendto32(SOCKET32 s, char *buf, INT32 len, INT32 flags, pws->psop && pws->flags & WS_FD_WRITE ) EVENT_AddIO( pws->fd, EVENT_IO_WRITE ); /* reenabler */ } - else return length; + else { +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { + free(to); + } +#endif + return length; + } } else if( pwsi ) pwsi->err = WSAENOTSOCK; +#ifdef HAVE_LINUX_IPX_H + if (((struct sockaddr_ipx *)to)->sipx_family == AF_IPX) { + free(to); + } +#endif return SOCKET_ERROR; } @@ -1377,6 +1557,9 @@ SOCKET32 WINAPI WINSOCK_socket32(INT32 af, INT32 type, INT32 protocol) /* check the socket family */ switch(af) { +#ifdef HAVE_LINUX_IPX_H + case WS_AF_IPX: af = AF_IPX; +#endif case AF_INET: case AF_UNSPEC: break; default: pwsi->err = WSAEAFNOSUPPORT;