This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / arch / win32 / ipx_win.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/win32/ipx_win.c,v $
3  * $Revision: 1.3 $
4  * $Author: bradleyb $
5  * $Date: 2001-10-19 10:52:38 $
6  *
7  * IPX driver using BSD style sockets
8  * Mostly taken from dosemu
9  *
10  * $Log: not supported by cvs2svn $
11  * Revision 1.2  2001/10/19 00:23:56  bradleyb
12  * Moved win32_* to win32/ (a la d1x), starting to get net working.
13  *
14  * Revision 1.3  2001/01/29 13:35:09  bradleyb
15  * Fixed build system, minor fixes
16  *
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <conf.h>
21 #endif
22
23 #include <string.h>
24 #include <stdlib.h>
25 #include <winsock.h>
26 //#include <errno.h>
27
28 #include "ipx_drv.h"
29 #include "wsipx.h"
30
31 #include "mono.h"
32
33 static ipx_socket_t mysock;
34
35 //#define n_printf(format, args...) mprintf((1, format, ## args))
36
37 static int ipx_win_GetMyAddress( void )
38 {
39 #if 0
40   int sock;
41   struct sockaddr_ipx ipxs;
42   struct sockaddr_ipx ipxs2;
43   int len;
44   int i;
45   
46 //  sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
47   sock=socket(AF_IPX,SOCK_DGRAM,0);
48
49   if(sock==-1)
50   {
51     mprintf((1,"IPX: could not open socket in GetMyAddress\n"));
52     return(-1);
53   }
54
55   /* bind this socket to network 0 */  
56   ipxs.sa_family=AF_IPX;
57 #ifdef IPX_MANUAL_ADDRESS
58   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
59 #else
60   memset(ipxs.sa_netnum, 0, 4);
61 #endif  
62   ipxs.sa_socket=0;
63   
64   if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1)
65   {
66     mprintf((1,"IPX: could bind to network 0 in GetMyAddress\n"));
67     closesocket( sock );
68     return(-1);
69   }
70   
71   len = sizeof(ipxs2);
72   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
73     mprintf((1,"IPX: could not get socket name in GetMyAddress\n"));
74     closesocket( sock );
75     return(-1);
76   }
77
78   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
79   for (i = 0; i < 6; i++) {
80     ipx_MyAddress[4+i] = ipxs2.sa_nodenum[i];
81   }
82 /*  printf("My address is 0x%.4X:%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n", *((int *)ipxs2.sa_netnum), ipxs2.sa_nodenum[0],
83   ipxs2.sa_nodenum[1], ipxs2.sa_nodenum[2], ipxs2.sa_nodenum[3], ipxs2.sa_nodenum[4], ipxs2.sa_nodenum[5]);*/
84
85     closesocket( sock );
86
87 #endif
88   return(0);
89 }
90
91 static int ipx_win_OpenSocket(int port)
92 {
93   int sock;                     /* sock here means Linux socket handle */
94   int opt;
95   struct sockaddr_ipx ipxs;
96   int len;
97   struct sockaddr_ipx ipxs2;
98
99         WORD wVersionRequested;
100         WSADATA wsaData;
101
102         wVersionRequested = MAKEWORD(2, 0);
103         if (WSAStartup( wVersionRequested, &wsaData))
104         {
105           return -1;
106         }
107 #if 0
108         if ( LOBYTE( wsaData.wVersion ) != 2 ||
109           HIBYTE( wsaData.wVersion ) != 0 ) {
110            /* We couldn't find a usable WinSock DLL. */
111            WSACleanup( );
112            return -2;
113         }
114 #endif
115
116
117   /* DANG_FIXTHIS - kludge to support broken linux IPX stack */
118   /* need to convert dynamic socket open into a real socket number */
119 /*  if (port == 0) {
120     mprintf((1,"IPX: using socket %x\n", nextDynamicSocket));
121     port = nextDynamicSocket++;
122   }
123 */
124   /* do a socket call, then bind to this port */
125 //  sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
126 //  sock = socket(AF_IPX, SOCK_DGRAM, 0);
127   sock = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);//why NSPROTO_IPX?  I looked in the quake source and thats what they used. :) -MPM  (on w2k 0 and PF_IPX don't work)
128   if (sock == -1) {
129     mprintf((1,"IPX: could not open IPX socket.\n"));
130     return -1;
131   }
132
133
134   opt = 1;
135   /* Permit broadcast output */
136   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
137                  (const char *)&opt, sizeof(opt)) == -1) {
138     mprintf((1,"IPX: could not set socket option for broadcast.\n"));
139     return -1;
140   }
141   ipxs.sa_family = AF_IPX;
142   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
143 //  *((unsigned int *)&ipxs.sa_netnum[0]) = *((unsigned int *)&ipx_MyAddress[0]);
144 /*  ipxs.sa_netnum = htonl(MyNetwork); */
145   memset(ipxs.sa_nodenum, 0, 6);
146 //  bzero(ipxs.sa_nodenum, 6);  /* Please fill in my node name */
147   ipxs.sa_socket = htons((short)port);
148
149   /* now bind to this port */
150   if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) {
151     mprintf((1,"IPX: could not bind socket to address\n"));
152     closesocket( sock );
153     return -1;
154   }
155   
156 //  if( port==0 ) {
157 //    len = sizeof(ipxs2);
158 //    if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
159 //       //n_printf("IPX: could not get socket name in IPXOpenSocket\n");
160 //     closesocket( sock );
161 //      return -1;
162 //    } else {
163 //      port = htons(ipxs2.sa_socket);
164 //      //n_printf("IPX: opened dynamic socket %04x\n", port);
165 //    }
166   len = sizeof(ipxs2);
167   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
168     mprintf((1,"IPX: could not get socket name in IPXOpenSocket\n"));
169     closesocket( sock );
170     return -1;
171   } 
172   if (port == 0) {
173     port = htons(ipxs2.sa_socket);
174     mprintf((1,"IPX: opened dynamic socket %04x\n", port));
175   }
176
177   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
178   memcpy(ipx_MyAddress + 4, ipxs2.sa_nodenum, 6);
179
180   mysock.fd = sock;
181   mysock.socket = port;
182
183   ipx_win_GetMyAddress();
184
185   return 0;
186 }
187
188 static void ipx_win_CloseSocket(void) {
189   /* now close the file descriptor for the socket, and free it */
190   mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock.socket));
191   closesocket(mysock.fd);
192   WSACleanup();
193 }
194
195 static int ipx_win_SendPacket(IPXPacket_t *IPXHeader,
196  ubyte *data, int dataLen) {
197   struct sockaddr_ipx ipxs;
198  
199   ipxs.sa_family = AF_IPX;
200   /* get destination address from IPX packet header */
201   memcpy(&ipxs.sa_netnum, IPXHeader->Destination.Network, 4);
202   /* if destination address is 0, then send to my net */
203   if ((*(unsigned int *)&ipxs.sa_netnum) == 0) {
204     (*(unsigned int *)&ipxs.sa_netnum)= *((unsigned int *)&ipx_MyAddress[0]);
205 /*  ipxs.sa_netnum = htonl(MyNetwork); */
206   }
207   memcpy(&ipxs.sa_nodenum, IPXHeader->Destination.Node, 6);
208 //  memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2);
209   ipxs.sa_socket=htons(mysock.socket);
210 //  ipxs.sa_type = IPXHeader->PacketType;
211   /*    ipxs.sipx_port=htons(0x452); */
212   return sendto(mysock.fd, data, dataLen, 0,
213              (struct sockaddr *) &ipxs, sizeof(ipxs));
214 }
215
216 static int ipx_win_ReceivePacket(char *buffer, int bufsize, 
217  struct ipx_recv_data *rd) {
218         int sz, size;
219         struct sockaddr_ipx ipxs;
220  
221         sz = sizeof(ipxs);
222         if ((size = recvfrom(mysock.fd, buffer, bufsize, 0,
223              (struct sockaddr *) &ipxs, &sz)) <= 0)
224              return size;
225         memcpy(rd->src_network, ipxs.sa_netnum, 4);
226         memcpy(rd->src_node, ipxs.sa_nodenum, 6);
227         rd->src_socket = ipxs.sa_socket;
228         rd->dst_socket = mysock.socket;
229 //      rd->pkt_type = ipxs.sipx_type;
230   
231         return size;
232 }
233
234 static int ipx_win_general_PacketReady(void) {
235         return ipx_general_PacketReady(mysock.fd);
236 }
237
238 struct ipx_driver ipx_win = {
239 //      ipx_win_GetMyAddress,
240         ipx_win_OpenSocket,
241         ipx_win_CloseSocket,
242         ipx_win_SendPacket,
243         ipx_win_ReceivePacket,
244         ipx_win_general_PacketReady,
245         NULL,
246         1,
247         NULL,
248         NULL,
249         NULL
250 };