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