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