Skip to content
Snippets Groups Projects
Commit dc163422 authored by Stephen Langasek's avatar Stephen Langasek Committed by Alexandre Julliard
Browse files

Support for IPX networking via winsock under Linux.

parent e2ed0c92
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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()
......
......@@ -120,6 +120,9 @@
/* Define if you have the <linux/cdrom.h> header file. */
#undef HAVE_LINUX_CDROM_H
/* Define if you have the <linux/ipx.h> header file. */
#undef HAVE_LINUX_IPX_H
/* Define if you have the <linux/ucdrom.h> header file. */
#undef HAVE_LINUX_UCDROM_H
......
......@@ -13,6 +13,10 @@
#include <sys/time.h>
#include <fcntl.h>
#include <netdb.h>
#ifdef HAVE_LINUX_IPX_H
# include <asm/types.h>
# include <linux/ipx.h>
#endif
#include <sys/socket.h>
#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
......
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment