Support for IPX networking via winsock under Linux.
diff --git a/misc/winsock.c b/misc/winsock.c
index dbf45ef..ae97743 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -552,8 +552,11 @@
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 @@
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 @@
*/
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 @@
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 @@
*/
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
/* 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;