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