OpenGL support under Cygwin/SDL
[btb/d2x.git] / arch / linux_ipx_lin.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/linux_ipx_lin.c,v $
3  * $Revision: 1.2 $
4  * $Author: bradleyb $
5  * $Date: 2001-01-29 13:35:08 $
6  *
7  * Linux IPX
8  *
9  * $Log: not supported by cvs2svn $
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include <conf.h>
14 #endif
15
16 #include <stdio.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <string.h>
20
21 #ifdef HAVE_NETIPX_IPX_H
22 #include <netipx/ipx.h>
23 #else
24 # include <linux/ipx.h>
25 # ifndef IPX_TYPE
26 #  define IPX_TYPE 1
27 # endif
28 #endif
29
30 #include <netinet/in.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include "pstypes.h"
34
35 #include "ipx_ld.h"
36 #include "ipx_hlpr.h"
37 #include "ipx_lin.h"
38
39 extern unsigned char ipx_MyAddress[10];
40
41 int 
42 ipx_linux_GetMyAddress( void )
43 {
44   int sock;
45   struct sockaddr_ipx ipxs;
46   struct sockaddr_ipx ipxs2;
47   int len;
48   int i;
49   
50   sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
51   if(sock==-1)
52   {
53     n_printf("IPX: could not open socket in GetMyAddress\n");
54     return(-1);
55   }
56
57   /* bind this socket to network 0 */  
58   ipxs.sipx_family=AF_IPX;
59 #ifdef IPX_MANUAL_ADDRESS
60   memcpy(&ipxs.sipx_network, ipx_MyAddress, 4);
61 #else
62   ipxs.sipx_network=0;
63 #endif  
64   ipxs.sipx_port=0;
65   
66   if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1)
67   {
68     n_printf("IPX: could bind to network 0 in GetMyAddress\n");
69     close( sock );
70     return(-1);
71   }
72   
73   len = sizeof(ipxs2);
74   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
75     n_printf("IPX: could not get socket name in GetMyAddress\n");
76     close( sock );
77     return(-1);
78   }
79
80   memcpy(ipx_MyAddress, &ipxs2.sipx_network, 4);
81   for (i = 0; i < 6; i++) {
82     ipx_MyAddress[4+i] = ipxs2.sipx_node[i];
83   }
84   close( sock );
85   return(0);
86 }
87
88 int
89 ipx_linux_OpenSocket(ipx_socket_t *sk, int port)
90 {
91   int sock;                     /* sock here means Linux socket handle */
92   int opt;
93   struct sockaddr_ipx ipxs;
94   int len;
95   struct sockaddr_ipx ipxs2;
96
97   /* DANG_FIXTHIS - kludge to support broken linux IPX stack */
98   /* need to convert dynamic socket open into a real socket number */
99 /*  if (port == 0) {
100     n_printf("IPX: using socket %x\n", nextDynamicSocket);
101     port = nextDynamicSocket++;
102   }
103 */
104   /* do a socket call, then bind to this port */
105   sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
106   if (sock == -1) {
107     n_printf("IPX: could not open IPX socket.\n");
108     return -1;
109   }
110
111 #ifdef DOSEMU
112   opt = 1;
113   /* turn on socket debugging */
114   if (d.network) {
115     enter_priv_on();
116     if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) == -1) {
117       leave_priv_setting();
118       n_printf("IPX: could not set socket option for debugging.\n");
119       return -1;
120     }
121     leave_priv_setting();
122   }
123 #endif  
124   opt = 1;
125   /* Permit broadcast output */
126   enter_priv_on();
127   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
128                  &opt, sizeof(opt)) == -1) {
129     leave_priv_setting();
130     n_printf("IPX: could not set socket option for broadcast.\n");
131     return -1;
132   }
133 #ifdef DOSEMU
134   /* allow setting the type field in the IPX header */
135   opt = 1;
136 #if 0 /* this seems to be wrong: IPX_TYPE can only be set on level SOL_IPX */
137   if (setsockopt(sock, SOL_SOCKET, IPX_TYPE, &opt, sizeof(opt)) == -1) {
138 #else
139   /* the socket _is_ an IPX socket, hence it first passes ipx_setsockopt()
140    * in file linux/net/ipx/af_ipx.c. This one handles SOL_IPX itself and
141    * passes SOL_SOCKET-levels down to sock_setsockopt().
142    * Hence I guess the below is correct (can somebody please verify this?)
143    * -- Hans, June 14 1997
144    */
145   if (setsockopt(sock, SOL_IPX, IPX_TYPE, &opt, sizeof(opt)) == -1) {
146 #endif
147     leave_priv_setting();
148     n_printf("IPX: could not set socket option for type.\n");
149     return -1;
150   }
151 #endif  
152   ipxs.sipx_family = AF_IPX;
153   ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]);
154 /*  ipxs.sipx_network = htonl(MyNetwork); */
155   bzero(ipxs.sipx_node, 6);     /* Please fill in my node name */
156   ipxs.sipx_port = htons(port);
157
158   /* now bind to this port */
159   if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) {
160     n_printf("IPX: could not bind socket to address\n");
161     close( sock );
162     leave_priv_setting();
163     return -1;
164   }
165   
166   if( port==0 ) {
167     len = sizeof(ipxs2);
168     if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
169       n_printf("IPX: could not get socket name in IPXOpenSocket\n");
170       close( sock );
171       leave_priv_setting();
172       return -1;
173     } else {
174       port = htons(ipxs2.sipx_port);
175       n_printf("IPX: opened dynamic socket %04x\n", port);
176     }
177   }
178   leave_priv_setting();
179   sk->fd = sock;
180   sk->socket = port;
181   return 0;
182 }
183
184 void ipx_linux_CloseSocket(ipx_socket_t *mysock) {
185   /* now close the file descriptor for the socket, and free it */
186   n_printf("IPX: closing file descriptor on socket %x\n", mysock->socket);
187   close(mysock->fd);
188 }
189
190 int ipx_linux_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader,
191  u_char *data, int dataLen) {
192   struct sockaddr_ipx ipxs;
193  
194   ipxs.sipx_family = AF_IPX;
195   /* get destination address from IPX packet header */
196   memcpy(&ipxs.sipx_network, IPXHeader->Destination.Network, 4);
197   /* if destination address is 0, then send to my net */
198   if (ipxs.sipx_network == 0) {
199     ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]);
200 /*  ipxs.sipx_network = htonl(MyNetwork); */
201   }
202   memcpy(&ipxs.sipx_node, IPXHeader->Destination.Node, 6);
203   memcpy(&ipxs.sipx_port, IPXHeader->Destination.Socket, 2);
204   ipxs.sipx_type = IPXHeader->PacketType;
205   /*    ipxs.sipx_port=htons(0x452); */
206   return sendto(mysock->fd, data, dataLen, 0,
207              (struct sockaddr *) &ipxs, sizeof(ipxs));
208 }
209
210 int ipx_linux_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, 
211  struct ipx_recv_data *rd) {
212         int sz, size;
213         struct sockaddr_ipx ipxs;
214  
215         sz = sizeof(ipxs);
216         if ((size = recvfrom(s->fd, buffer, bufsize, 0,
217              (struct sockaddr *) &ipxs, &sz)) <= 0)
218              return size;
219         memcpy(rd->src_network, &ipxs.sipx_network, 4);
220         memcpy(rd->src_node, ipxs.sipx_node, 6);
221         rd->src_socket = ipxs.sipx_port;
222         rd->dst_socket = s->socket;
223         rd->pkt_type = ipxs.sipx_type;
224   
225         return size;
226 }