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