1 /* $Id: ipx_bsd.c,v 1.6 2003-03-13 00:20:21 btb Exp $ */
4 * IPX driver using BSD style sockets
5 * Mostly taken from dosemu
14 #include <sys/types.h>
15 #include <sys/socket.h>
18 #ifdef HAVE_NETIPX_IPX_H
19 #include <netipx/ipx.h>
21 # include <linux/ipx.h>
27 #include <netinet/in.h>
37 #define n_printf(format, args...) mprintf((1, format, ## args))
38 #define enter_priv_on()
39 #define leave_priv_setting()
42 static int ipx_bsd_GetMyAddress(void)
45 struct sockaddr_ipx ipxs;
46 struct sockaddr_ipx ipxs2;
50 sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
52 n_printf("IPX: could not open socket in GetMyAddress\n");
56 /* bind this socket to network 0 */
57 ipxs.sipx_family=AF_IPX;
58 #ifdef IPX_MANUAL_ADDRESS
59 memcpy(&ipxs.sipx_network, ipx_MyAddress, 4);
65 if (bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs)) == -1) {
66 n_printf("IPX: could bind to network 0 in GetMyAddress\n");
72 if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
73 n_printf("IPX: could not get socket name in GetMyAddress\n");
78 memcpy(ipx_MyAddress, &ipxs2.sipx_network, 4);
79 for (i = 0; i < 6; i++) {
80 ipx_MyAddress[4+i] = ipxs2.sipx_node[i];
86 static int ipx_bsd_OpenSocket(ipx_socket_t *sk, int port)
88 int sock; /* sock here means Linux socket handle */
90 struct sockaddr_ipx ipxs;
92 struct sockaddr_ipx ipxs2;
94 /* DANG_FIXTHIS - kludge to support broken linux IPX stack */
95 /* need to convert dynamic socket open into a real socket number */
98 n_printf("IPX: using socket %x\n", nextDynamicSocket);
99 port = nextDynamicSocket++;
102 /* do a socket call, then bind to this port */
103 sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
105 n_printf("IPX: could not open IPX socket.\n");
111 /* turn on socket debugging */
114 if (setsockopt(sock, SOL_SOCKET, SO_DEBUG, &opt, sizeof(opt)) == -1) {
115 leave_priv_setting();
116 n_printf("IPX: could not set socket option for debugging.\n");
119 leave_priv_setting();
123 /* Permit broadcast output */
125 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
126 &opt, sizeof(opt)) == -1) {
127 leave_priv_setting();
128 n_printf("IPX: could not set socket option for broadcast.\n");
132 /* allow setting the type field in the IPX header */
134 #if 0 /* this seems to be wrong: IPX_TYPE can only be set on level SOL_IPX */
135 if (setsockopt(sock, SOL_SOCKET, IPX_TYPE, &opt, sizeof(opt)) == -1) {
137 /* the socket _is_ an IPX socket, hence it first passes ipx_setsockopt()
138 * in file linux/net/ipx/af_ipx.c. This one handles SOL_IPX itself and
139 * passes SOL_SOCKET-levels down to sock_setsockopt().
140 * Hence I guess the below is correct (can somebody please verify this?)
141 * -- Hans, June 14 1997
143 if (setsockopt(sock, SOL_IPX, IPX_TYPE, &opt, sizeof(opt)) == -1) {
145 leave_priv_setting();
146 n_printf("IPX: could not set socket option for type.\n");
150 ipxs.sipx_family = AF_IPX;
151 ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]);
152 /* ipxs.sipx_network = htonl(MyNetwork); */
153 bzero(ipxs.sipx_node, 6); /* Please fill in my node name */
154 ipxs.sipx_port = htons(port);
156 /* now bind to this port */
157 if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) {
158 n_printf("IPX: could not bind socket to address\n");
160 leave_priv_setting();
166 if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
167 n_printf("IPX: could not get socket name in IPXOpenSocket\n");
169 leave_priv_setting();
172 port = htons(ipxs2.sipx_port);
173 n_printf("IPX: opened dynamic socket %04x\n", port);
176 leave_priv_setting();
182 static void ipx_bsd_CloseSocket(ipx_socket_t *mysock) {
183 /* now close the file descriptor for the socket, and free it */
184 n_printf("IPX: closing file descriptor on socket %x\n", mysock->socket);
188 static int ipx_bsd_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader,
189 u_char *data, int dataLen) {
190 struct sockaddr_ipx ipxs;
192 ipxs.sipx_family = AF_IPX;
193 /* get destination address from IPX packet header */
194 memcpy(&ipxs.sipx_network, IPXHeader->Destination.Network, 4);
195 /* if destination address is 0, then send to my net */
196 if (ipxs.sipx_network == 0) {
197 ipxs.sipx_network = *((unsigned int *)&ipx_MyAddress[0]);
198 /* ipxs.sipx_network = htonl(MyNetwork); */
200 memcpy(&ipxs.sipx_node, IPXHeader->Destination.Node, 6);
201 memcpy(&ipxs.sipx_port, IPXHeader->Destination.Socket, 2);
202 ipxs.sipx_type = IPXHeader->PacketType;
203 /* ipxs.sipx_port=htons(0x452); */
204 return sendto(mysock->fd, data, dataLen, 0,
205 (struct sockaddr *) &ipxs, sizeof(ipxs));
208 static int ipx_bsd_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize,
209 struct ipx_recv_data *rd) {
211 struct sockaddr_ipx ipxs;
214 if ((size = recvfrom(s->fd, buffer, bufsize, 0,
215 (struct sockaddr *) &ipxs, &sz)) <= 0)
217 memcpy(rd->src_network, &ipxs.sipx_network, 4);
218 memcpy(rd->src_node, ipxs.sipx_node, 6);
219 rd->src_socket = ipxs.sipx_port;
220 rd->dst_socket = s->socket;
221 rd->pkt_type = ipxs.sipx_type;
226 struct ipx_driver ipx_bsd = {
227 ipx_bsd_GetMyAddress,
231 ipx_bsd_ReceivePacket,
232 ipx_general_PacketReady