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