]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/bak/ipx.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / arch / dos / bak / ipx.c
1 /* $Id: ipx.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Routines for IPX communications.
18  *
19  */
20
21 #ifdef RCS
22 static char rcsid[] = "$Id: ipx.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $";
23 #endif
24
25 #ifdef __GNUC__
26 #define _BORLAND_DOS_REGS 1
27 #define far
28 #endif
29
30 #include <i86.h>
31 #include <dos.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <malloc.h>
35 #include <stdlib.h>
36 #include <conio.h>
37 #include <assert.h>
38
39 #include "types.h"
40 #include "timer.h"
41 #include "ipx.h"
42 #include "error.h"
43 #include "u_dpmi.h"
44 #include "key.h"
45
46 typedef unsigned char BYTE;
47 typedef unsigned short WORD;
48 typedef unsigned long DWORD;
49
50 typedef struct local_address {
51         ubyte address[6];
52 } __pack__ local_address;
53
54 typedef struct net_address {
55         BYTE                            network_id[4];                  
56         local_address   node_id;
57         WORD                            socket_id;
58 } __pack__ net_address;
59
60 typedef struct ipx_header {
61         WORD                    checksum;
62         WORD                    length;
63         BYTE                    transport_control;
64         BYTE                    packet_type;
65         net_address     destination;
66         net_address     source;
67 } __pack__ ipx_header;
68
69 typedef struct ecb_header {
70         WORD                    link[2];
71         WORD                    esr_address[2];
72         BYTE                    in_use;
73         BYTE                    completion_code;
74         WORD                    socket_id;
75         BYTE                    ipx_reserved[14];        
76         WORD                    connection_id;
77         local_address immediate_address;
78         WORD                    fragment_count;
79         WORD                    fragment_pointer[2];
80         WORD                    fragment_size;
81 } __pack__ ecb_header;
82
83 typedef struct packet_data {
84         int                     packetnum;
85         byte                    data[IPX_MAX_DATA_SIZE];
86 } __pack__ packet_data;
87
88 typedef struct ipx_packet {
89         ecb_header      ecb;
90         ipx_header      ipx;
91         packet_data     pd;
92 } __pack__ ipx_packet;
93
94 typedef struct user_address {
95         ubyte network[4];
96         ubyte node[6];
97         ubyte address[6];
98 } __pack__ user_address;
99
100 #define MAX_USERS 64
101 int Ipx_num_users = 0;
102 user_address Ipx_users[MAX_USERS];
103
104 #define MAX_NETWORKS 64
105 int Ipx_num_networks = 0;
106 uint Ipx_networks[MAX_NETWORKS];
107
108 int ipx_packetnum = 0;
109
110 #define MAX_PACKETS 64
111
112 static packet_data packet_buffers[MAX_PACKETS];
113 static short packet_free_list[MAX_PACKETS];
114 static int num_packets = 0;
115 static int largest_packet_index = 0;
116 static short packet_size[MAX_PACKETS];
117
118 //added on 10/29/98 by Kevin Bently to add ipx stuff
119 WORD ipx_num_outgoing_packets = 8;
120 ipx_packet * outpackets;
121 //end this section addition - Kevin Bently
122
123 WORD ipx_socket=0;
124 ubyte ipx_installed=0;
125 WORD ipx_vector_segment;
126 WORD ipx_vector_offset;
127 ubyte ipx_socket_life = 0;      // 0=closed at prog termination, 0xff=closed when requested.
128 DWORD ipx_network = 0;
129 local_address ipx_my_node;
130 WORD ipx_num_packets=32;                // 32 Ipx packets
131 ipx_packet * packets;
132 int neterrors = 0;
133 ushort ipx_packets_selector;
134
135 ecb_header * last_ecb=NULL;
136 int lastlen=0;
137
138 void got_new_packet( ecb_header * ecb );
139 void ipx_listen_for_packet(ecb_header * ecb );
140
141 void free_packet( int id )
142 {
143         packet_buffers[id].packetnum = -1;
144         packet_free_list[ --num_packets ] = id;
145         if (largest_packet_index==id)   
146                 while ((--largest_packet_index>0) && (packet_buffers[largest_packet_index].packetnum == -1 ));
147 }
148
149 int ipx_get_packet_data( ubyte * data )
150 {
151         int i, n, best, best_id, size;
152
153         for (i=1; i<ipx_num_packets; i++ )      {
154                 if ( !packets[i].ecb.in_use )   {
155                         got_new_packet( &packets[i].ecb );
156                         packets[i].ecb.in_use = 0;
157                         ipx_listen_for_packet(&packets[i].ecb);
158                 }                       
159         }
160
161         best = -1;
162         n = 0;
163         best_id = -1;
164
165         for (i=0; i<=largest_packet_index; i++ )        {
166                 if ( packet_buffers[i].packetnum > -1 ) {
167                         n++;
168                         if ( best == -1 || (packet_buffers[i].packetnum<best) ) {
169                                 best = packet_buffers[i].packetnum;
170                                 best_id = i;
171                         }
172                 }                       
173         }
174
175         //mprintf( (0, "Best id = %d, pn = %d, last_ecb = %x, len=%x, ne = %d\n", best_id, best, last_ecb, lastlen, neterrors ));
176         //mprintf( (1, "<%d> ", neterrors ));
177
178         if ( best_id < 0 ) return 0;
179
180         size = packet_size[best_id];
181         memcpy( data, packet_buffers[best_id].data, size );
182         free_packet(best_id);
183
184         return size;
185 }
186
187 #ifndef __GNUC__
188 unsigned int swap_short( unsigned int short )
189 #pragma aux swap_short parm [eax] = "xchg al,ah";
190 #else
191 static inline unsigned int swap_short( unsigned int sshort ) {
192         int __retval;
193         asm("xchg %%ah,%%al" : "=a" (__retval) : "a" (sshort));
194         return __retval;
195 }
196 #endif
197
198 void got_new_packet( ecb_header * ecb )
199 {
200         ipx_packet * p;
201         int id;
202         unsigned short datasize;
203
204         datasize = 0;
205         last_ecb = ecb;
206         p = (ipx_packet *)ecb;
207
208         if ( p->ecb.in_use ) { neterrors++; return; }
209         if      ( p->ecb.completion_code )      { neterrors++; return; }
210
211         //      Error( "Recieve error %d for completion code", p->ecb.completion_code );
212         
213         if ( memcmp( &p->ipx.source.node_id, &ipx_my_node, 6 ) )        {
214                 datasize=swap_short(p->ipx.length);
215                 lastlen=datasize;
216                 datasize -= sizeof(ipx_header);
217                 // Find slot to put packet in...
218                 if ( datasize > 0 && datasize <= sizeof(packet_data) )  {
219                         if ( num_packets >= MAX_PACKETS ) {
220                                 //printf( 1, "IPX: Packet buffer overrun!!!\n" );
221                                 neterrors++;
222                                 return;
223                         }               
224                         id = packet_free_list[ num_packets++ ];
225                         if (id > largest_packet_index ) largest_packet_index = id;
226                         packet_size[id] = datasize-sizeof(int);
227                         packet_buffers[id].packetnum =  p->pd.packetnum;
228                         if ( packet_buffers[id].packetnum < 0 ) { neterrors++; return; }
229                         memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] );
230                 } else {
231                         neterrors++; return;
232                 }
233         } 
234         // Repost the ecb
235         p->ecb.in_use = 0;
236         //ipx_listen_for_packet(&p->ecb);
237 }
238
239 ubyte * ipx_get_my_local_address()
240 {
241         return ipx_my_node.address;
242 }
243
244 ubyte * ipx_get_my_server_address()
245 {
246         return (ubyte *)&ipx_network;
247 }
248
249 void ipx_listen_for_packet(ecb_header * ecb )   
250 {
251         dpmi_real_regs rregs;
252         ecb->in_use = 0x1d;
253         memset(&rregs,0,sizeof(dpmi_real_regs));
254         rregs.ebx = 4;  // Listen For Packet function
255         rregs.esi = DPMI_real_offset(ecb);
256         rregs.es = DPMI_real_segment(ecb);
257         dpmi_real_int386x( 0x7A, &rregs );
258 }
259
260 void ipx_cancel_listen_for_packet(ecb_header * ecb )    
261 {
262         dpmi_real_regs rregs;
263         memset(&rregs,0,sizeof(dpmi_real_regs));
264         rregs.ebx = 6;  // IPX Cancel event
265         rregs.esi = DPMI_real_offset(ecb);
266         rregs.es = DPMI_real_segment(ecb);
267         dpmi_real_int386x( 0x7A, &rregs );
268 }
269
270
271 void ipx_send_packet(ecb_header * ecb ) 
272 {
273         dpmi_real_regs rregs;
274         memset(&rregs,0,sizeof(dpmi_real_regs));
275         rregs.ebx = 3;  // Send Packet function
276         rregs.esi = DPMI_real_offset(ecb);
277         rregs.es = DPMI_real_segment(ecb);
278         dpmi_real_int386x( 0x7A, &rregs );
279 }
280
281 typedef struct {
282         ubyte   network[4];
283         ubyte           node[6];
284         ubyte           local_target[6];
285 } __pack__ net_xlat_info;
286
287 void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target )
288 {
289         net_xlat_info * info;
290         dpmi_real_regs rregs;
291                 
292         // Get dos memory for call...
293         info = (net_xlat_info *)dpmi_get_temp_low_buffer( sizeof(net_xlat_info) );      
294         assert( info != NULL );
295         memcpy( info->network, server, 4 );
296         memcpy( info->node, node, 6 );
297         
298         memset(&rregs,0,sizeof(dpmi_real_regs));
299
300         rregs.ebx = 2;          // Get Local Target     
301         rregs.es = DPMI_real_segment(info);
302         rregs.esi = DPMI_real_offset(info->network);
303         rregs.edi = DPMI_real_offset(info->local_target);
304
305         dpmi_real_int386x( 0x7A, &rregs );
306
307         // Save the local target...
308         memcpy( local_target, info->local_target, 6 );
309 }
310
311 void ipx_close()
312 {
313         dpmi_real_regs rregs;
314         if ( ipx_installed )    {
315                 // When using VLM's instead of NETX, the sockets don't
316                 // seem to automatically get closed, so we must explicitly
317                 // close them at program termination.
318                 ipx_installed = 0;
319                 memset(&rregs,0,sizeof(dpmi_real_regs));
320                 rregs.edx = ipx_socket;
321                 rregs.ebx = 1;  // Close socket
322                 dpmi_real_int386x( 0x7A, &rregs );
323         }
324 }
325
326
327 //---------------------------------------------------------------
328 // Initializes all IPX internals. 
329 // If socket_number==0, then opens next available socket.
330 // Returns one of the constants defined in include/ipx.h
331
332 int ipx_init( int socket_number, int show_address )
333 {
334         dpmi_real_regs rregs;
335         ubyte *ipx_real_buffer;
336         int i;
337
338         atexit(ipx_close);
339
340         ipx_packetnum = 0;
341
342         // init packet buffers.
343         for (i=0; i<MAX_PACKETS; i++ )  {
344                 packet_buffers[i].packetnum = -1;
345                 packet_free_list[i] = i;
346         }
347         num_packets = 0;
348         largest_packet_index = 0;
349
350         // Get the IPX vector
351         memset(&rregs,0,sizeof(dpmi_real_regs));
352         rregs.eax=0x00007a00;
353         dpmi_real_int386x( 0x2f, &rregs );
354
355         if ( (rregs.eax & 0xFF) != 0xFF )       {
356                 return IPX_NOT_INSTALLED;   
357         }
358         ipx_vector_offset = rregs.edi & 0xFFFF;
359         ipx_vector_segment = rregs.es;
360         //printf( "IPX entry point at %.4x:%.4x\n", ipx_vector_segment, ipx_vector_offset );
361
362         // Open a socket for IPX
363
364         memset(&rregs,0,sizeof(dpmi_real_regs));
365         swab( (char *)&socket_number,(char *)&ipx_socket, 2 );
366         rregs.edx = ipx_socket;
367         rregs.eax = ipx_socket_life;
368         rregs.ebx = 0;  // Open socket
369         dpmi_real_int386x( 0x7A, &rregs );
370         
371         ipx_socket = rregs.edx & 0xFFFF;
372         
373         if ( rregs.eax & 0xFF ) {
374                 //mprintf( (1, "IPX error opening channel %d\n", socket_number-IPX_DEFAULT_SOCKET ));
375                 return IPX_SOCKET_TABLE_FULL;
376         }
377         
378         ipx_installed = 1;
379
380         // Find our internetwork address
381         ipx_real_buffer = dpmi_get_temp_low_buffer( 1024 );     // 1k block
382         if ( ipx_real_buffer == NULL )  {
383                 //printf( "Error allocation realmode memory\n" );
384                 return IPX_NO_LOW_DOS_MEM;
385         }
386
387         memset(&rregs,0,sizeof(dpmi_real_regs));
388         rregs.ebx = 9;          // Get internetwork address
389         rregs.esi = DPMI_real_offset(ipx_real_buffer);
390         rregs.es = DPMI_real_segment(ipx_real_buffer);
391         dpmi_real_int386x( 0x7A, &rregs );
392
393         if ( rregs.eax & 0xFF ) {
394                 //printf( "Error getting internetwork address!\n" );
395                 return IPX_SOCKET_TABLE_FULL;
396         }
397
398         memcpy( &ipx_network, ipx_real_buffer, 4 );
399         memcpy( &ipx_my_node, &ipx_real_buffer[4], 6 );
400
401         Ipx_num_networks = 0;
402         memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 );
403
404         if ( show_address )     {
405                 printf( "My IPX addresss is " );
406                 printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
407                 printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] );
408                 printf( "\n" );
409         }
410
411         packets = dpmi_real_malloc( sizeof(ipx_packet)*ipx_num_packets, &ipx_packets_selector );
412         if ( packets == NULL )  {
413                 //printf( "Couldn't allocate real memory for %d packets\n", ipx_num_packets );
414                 return IPX_NO_LOW_DOS_MEM;
415         }
416 #if 0 /* adb: not needed, fails with cwsdpmi */
417         if (!dpmi_lock_region( packets, sizeof(ipx_packet)*ipx_num_packets ))   {
418                 //printf( "Couldn't lock real memory for %d packets\n", ipx_num_packets );
419                 return IPX_NO_LOW_DOS_MEM;
420         }
421 #endif
422         memset( packets, 0, sizeof(ipx_packet)*ipx_num_packets );
423
424         for (i=1; i<ipx_num_packets; i++ )      {
425                 packets[i].ecb.in_use = 0x1d;
426                 //packets[i].ecb.in_use = 0;
427                 packets[i].ecb.socket_id = ipx_socket;
428                 packets[i].ecb.fragment_count = 1;
429                 packets[i].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[i].ipx);
430                 packets[i].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[i].ipx);
431                 packets[i].ecb.fragment_size = sizeof(ipx_packet)-sizeof(ecb_header);                   //-sizeof(ecb_header);
432
433                 ipx_listen_for_packet(&packets[i].ecb);
434         }
435
436 //added/replaced on 10/29/98 by Kevin Bently for new ipx stuff
437 //-killed-        packets[0].ecb.socket_id = ipx_socket;
438 //-killed-        packets[0].ecb.fragment_count = 1;
439 //-killed-        packets[0].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[0].ipx);
440 //-killed-        packets[0].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[0].ipx);
441 //-killed-        packets[0].ipx.packet_type = 4;         // IPX packet
442 //-killed-        packets[0].ipx.destination.socket_id = ipx_socket;
443 //-killed-//      memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 );
444 //-killed-        memset( packets[0].ipx.destination.network_id, 0, 4 );
445 outpackets = dpmi_real_malloc( sizeof(ipx_packet)*ipx_num_packets, &ipx_packets_selector);
446
447      for(i=0;i<ipx_num_outgoing_packets;i++)
448       {
449         outpackets[i].ecb.socket_id = ipx_socket;
450         outpackets[i].ecb.fragment_count = 1;
451         outpackets[i].ecb.fragment_pointer[0] = DPMI_real_offset(&outpackets[i].ipx);
452         outpackets[i].ecb.fragment_pointer[1] = DPMI_real_segment(&outpackets[i].ipx);
453         outpackets[i].ipx.packet_type = 4;              // IPX packet
454         outpackets[i].ipx.destination.socket_id = ipx_socket;
455         memset( outpackets[i].ipx.destination.network_id, 0, 4 );
456       }
457
458
459 //end this section replace - Kevin Bently
460         return IPX_INIT_OK;
461 }
462
463 void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address )
464 {
465         int i;
466         ipx_packet *sendpacket = NULL;
467
468         assert(ipx_installed);
469
470         if ( datasize >= IPX_MAX_DATA_SIZE )    {
471                 printf( "Data too big\n" );
472                 exit(1);
473         }
474
475
476
477 //added/replaced on 10/29/98 by Kevin Bently for new ipx stuff
478 //-killed-        // Make sure no one is already sending something
479 //-killed-        while( packets[0].ecb.in_use )
480 //-killed-        {
481 //-killed-        }
482 //-killed- 
483 //-killed-        if (packets[0].ecb.completion_code)     {
484 //-killed-                printf( "Send error %d for completion code\n", packets[0].ecb.completion_code );
485 //-killed-               //killed on 10/25/98 by Victor Rachels to fix LAN crash
486 //-killed-               //-killed- exit(1);
487 //-killed-               //end this section kill - Victor 
488 //-killed-        }
489         while(!sendpacket)
490          for(i=0;i<ipx_num_outgoing_packets;i++)
491           if(!outpackets[i].ecb.in_use)
492            sendpacket= &outpackets[i];
493 //end this section replacement - Kevin Bently
494
495         // Fill in destination address
496         if ( memcmp( network, &ipx_network, 4 ) )
497                 memcpy( sendpacket->ipx.destination.network_id, network, 4 );
498         else
499                 memset( sendpacket->ipx.destination.network_id, 0, 4 );
500         memcpy( sendpacket->ipx.destination.node_id.address, address, 6 );
501         memcpy( sendpacket->ecb.immediate_address.address, immediate_address, 6 );
502         sendpacket->pd.packetnum = ipx_packetnum++;
503
504         // Fill in data to send
505         sendpacket->ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + datasize;
506
507         assert( datasize > 1 );
508         assert( sendpacket->ecb.fragment_size <= 576 );
509
510         memcpy( sendpacket->pd.data, data, datasize );
511
512         // Send it
513         ipx_send_packet( &sendpacket->ecb );
514
515 }
516
517 void ipx_send_broadcast_packet_data( ubyte * data, int datasize )       
518 {
519         int i, j;
520         ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
521         ubyte local_address[6];
522
523         // Set to all networks besides mine
524         for (i=0; i<Ipx_num_networks; i++ )     {
525                 if ( memcmp( &Ipx_networks[i], &ipx_network, 4 ) )      {
526                         ipx_get_local_target( (ubyte *)&Ipx_networks[i], broadcast, local_address );
527                         ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast, local_address );
528                 } else {
529                         ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast, broadcast );
530                 }
531         }
532
533         //OLDipx_send_packet_data( data, datasize, (ubyte *)&ipx_network, broadcast, broadcast );
534
535         // Send directly to all users not on my network or in the network list.
536         for (i=0; i<Ipx_num_users; i++ )        {
537                 if ( memcmp( Ipx_users[i].network, &ipx_network, 4 ) )  {
538                         for (j=0; j<Ipx_num_networks; j++ )             {
539                                 if (!memcmp( Ipx_users[i].network, &Ipx_networks[j], 4 ))
540                                         goto SkipUser;
541                         }
542                         ipx_send_packet_data( data, datasize, Ipx_users[i].network, Ipx_users[i].node, Ipx_users[i].address );
543 SkipUser:
544                         j = 0;
545                 }
546         }
547 }
548
549 // Sends a non-localized packet... needs 4 byte server, 6 byte address
550 void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address )
551 {
552         ubyte local_address[6];
553
554         if ( (*(uint *)server) != 0 )   {
555                 ipx_get_local_target( server, address, local_address );
556                 ipx_send_packet_data( data, datasize, server, address, local_address );
557         } else {
558                 // Old method, no server info.
559                 ipx_send_packet_data( data, datasize, server, address, address );
560         }
561 }
562
563 int ipx_change_default_socket( ushort socket_number )
564 {
565         int i;
566         WORD new_ipx_socket;
567         dpmi_real_regs rregs;
568
569         if ( !ipx_installed ) return -3;
570
571         // Open a new socket    
572         memset(&rregs,0,sizeof(dpmi_real_regs));
573         swab( (char *)&socket_number,(char *)&new_ipx_socket, 2 );
574         rregs.edx = new_ipx_socket;
575         rregs.eax = ipx_socket_life;
576         rregs.ebx = 0;  // Open socket
577         dpmi_real_int386x( 0x7A, &rregs );
578         
579         new_ipx_socket = rregs.edx & 0xFFFF;
580         
581         if ( rregs.eax & 0xFF ) {
582                 //printf( (1, "IPX error opening channel %d\n", socket_number-IPX_DEFAULT_SOCKET ));
583                 return -2;
584         }
585
586         for (i=1; i<ipx_num_packets; i++ )      {
587                 ipx_cancel_listen_for_packet(&packets[i].ecb);
588         }
589
590         // Close existing socket...
591         memset(&rregs,0,sizeof(dpmi_real_regs));
592         rregs.edx = ipx_socket;
593         rregs.ebx = 1;  // Close socket
594         dpmi_real_int386x( 0x7A, &rregs );
595
596         ipx_socket = new_ipx_socket;
597
598         // Repost all listen requests on the new socket...      
599         for (i=1; i<ipx_num_packets; i++ )      {
600                 packets[i].ecb.in_use = 0;
601                 packets[i].ecb.socket_id = ipx_socket;
602                 ipx_listen_for_packet(&packets[i].ecb);
603         }
604
605         packets[0].ecb.socket_id = ipx_socket;
606         packets[0].ipx.destination.socket_id = ipx_socket;
607
608         ipx_packetnum = 0;
609         // init packet buffers.
610         for (i=0; i<MAX_PACKETS; i++ )  {
611                 packet_buffers[i].packetnum = -1;
612                 packet_free_list[i] = i;
613         }
614         num_packets = 0;
615         largest_packet_index = 0;
616
617         return 0;
618 }
619
620 void ipx_read_user_file(char * filename)
621 {
622         FILE * fp;
623         user_address tmp;
624         char temp_line[132], *p1;
625         int n, ln=0;
626
627         if (!filename) return;
628
629         Ipx_num_users = 0;
630
631         fp = fopen( filename, "rt" );
632         if ( !fp ) return;
633
634         printf( "Broadcast Users:\n" );
635
636         while (fgets(temp_line, 132, fp)) {
637                 ln++;
638                 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
639                 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
640                 n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x",(unsigned int *)&tmp.network[0],(unsigned int *) &tmp.network[1],(unsigned int *) &tmp.network[2],(unsigned int *) &tmp.network[3],(unsigned int *) &tmp.node[0],(unsigned int *) &tmp.node[1],(unsigned int *) &tmp.node[2],(unsigned int *)&tmp.node[3],(unsigned int *) &tmp.node[4],(unsigned int *) &tmp.node[5] );
641 //                n = sscanf( temp_line, "%2x%2x%2x%2x/%2x%2x%2x%2x%2x%2x",&tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3], &tmp.node[0], &tmp.node[1], &tmp.node[2],&tmp.node[3], &tmp.node[4], &tmp.node[5] );
642                 if ( n != 10 ) continue;
643                 if ( Ipx_num_users < MAX_USERS )        {
644                         ubyte * ipx_real_buffer = (ubyte *)&tmp;
645                         ipx_get_local_target( tmp.network, tmp.node, tmp.address );
646                         Ipx_users[Ipx_num_users++] = tmp;
647                         printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] );
648                         printf( "%02X%02X%02X%02X%02X%02X\n", ipx_real_buffer[4],ipx_real_buffer[5],ipx_real_buffer[6],ipx_real_buffer[7],ipx_real_buffer[8],ipx_real_buffer[9] );
649                 } else {
650                         printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
651                         fclose(fp);
652                         return;
653                 }
654         }
655         fclose(fp);
656 }
657
658
659 void ipx_read_network_file(char * filename)
660 {
661         FILE * fp;
662         user_address tmp;
663         char temp_line[132], *p1;
664         int i, n, ln=0;
665
666         if (!filename) return;
667
668         fp = fopen( filename, "rt" );
669         if ( !fp ) return;
670
671         printf( "Using Networks:\n" );
672         for (i=0; i<Ipx_num_networks; i++ )             {
673                 ubyte * n1 = (ubyte *)&Ipx_networks[i];
674                 printf("* %02x%02x%02x%02x\n", n1[0], n1[1], n1[2], n1[3] );
675         }
676
677         while (fgets(temp_line, 132, fp)) {
678                 ln++;
679                 p1 = strchr(temp_line,'\n'); if (p1) *p1 = '\0';
680                 p1 = strchr(temp_line,';'); if (p1) *p1 = '\0';
681                 n = sscanf( temp_line, "%2x%2x%2x%2x",(unsigned int *) &tmp.network[0],(unsigned int *) &tmp.network[1],(unsigned int *) &tmp.network[2],(unsigned int *) &tmp.network[3] );
682 //                n = sscanf( temp_line, "%2x%2x%2x%2x", &tmp.network[0], &tmp.network[1], &tmp.network[2], &tmp.network[3] );
683                 if ( n != 4 ) continue;
684                 if ( Ipx_num_networks < MAX_NETWORKS  ) {
685                         int j;
686                         for (j=0; j<Ipx_num_networks; j++ )     
687                                 if ( !memcmp( &Ipx_networks[j], tmp.network, 4 ) )
688                                         break;
689                         if ( j >= Ipx_num_networks )    {
690                                 memcpy( &Ipx_networks[Ipx_num_networks++], tmp.network, 4 );
691                                 printf("  %02x%02x%02x%02x\n", tmp.network[0], tmp.network[1], tmp.network[2], tmp.network[3] );
692                         }
693                 } else {
694                         printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS );
695                         fclose(fp);
696                         return;
697                 }
698         }
699         fclose(fp);
700
701 }
702
703 //---typedef struct rip_entry {
704 //---   uint            network;
705 //---   ushort  nhops;
706 //---   ushort  nticks;
707 //---} rip_entry;
708 //---
709 //---typedef struct rip_packet {
710 //---   ushort          operation;              //1=request, 2=response
711 //---   rip_entry       rip[50];
712 //---} rip_packet;
713 //---
714 //---
715 //---void  ipx_find_all_servers()
716 //---{
717 //---   int i;
718 //---   rip_packet * rp;
719 //---   assert(ipx_installed);
720 //---
721 //---   ipx_change_default_socket( 0x0453 );
722 //---   //      ipx_change_default_socket( 0x5304 );
723 //---
724 //---   // Make sure no one is already sending something
725 //---   while( packets[0].ecb.in_use )
726 //---   {
727 //---   }
728 //---   
729 //---   if (packets[0].ecb.completion_code)     {
730 //---           printf( "AAAA:Send error %d for completion code\n", packets[0].ecb.completion_code );
731 //---           //exit(1);
732 //---   }
733 //---
734 //---   rp = (rip_packet *)&packets[0].pd;
735 //---
736 //---   // Fill in destination address
737 //---   {
738 //---           char mzero1[] = {0,0,0,1};
739 //---           char mzero[] = {0,0,0,0,0,1};
740 //---           char immediate[6];
741 //---           //memcpy( packets[0].ipx.destination.network_id, &ipx_network, 4 );
742 //---           //memcpy( packets[0].ipx.destination.node_id.address, ipx_my_node.address, 6 );
743 //---
744 //---           memcpy( packets[0].ipx.destination.network_id, mzero1, 4 );
745 //---           memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 );
746 //---
747 //---           memcpy( packets[0].ipx.destination.socket_id, &ipx_socket, 2 );
748 //---           memcpy( packets[0].ipx.source.network_id, &ipx_network, 4 );
749 //---           memcpy( packets[0].ipx.source.node_id.address, ipx_my_node.address, 6 );
750 //---           memcpy( packets[0].ipx.source.socket_id, &ipx_socket, 2 );
751 //---           //memcpy( packets[0].ecb.immediate_address.address, ipx_my_node.address, 6 );
752 //---           //mzero1[3] = 1;
753 //---           //memcpy( packets[0].ipx.destination.network_id, mzero1, 4 );
754 //---           //mzero[5] = 1;
755 //---           //memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 );
756 //---           //ipx_get_local_target( mzero1, mzero, immediate );
757 //---           //memcpy( packets[0].ecb.immediate_address.address, mzero, 6 );
758 //---           //memcpy( packets[0].ecb.immediate_address.address, immediate, 6 );
759 //---           //mzero[5] = 0;
760 //---   }
761 //---
762 //---   packets[0].ipx.packet_type = 1;         // RIP packet
763 //---
764 //---   // Fill in data to send
765 //---   packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(rip_packet);
766 //---   assert( packets[0].ecb.fragment_size <= 576 );
767 //---
768 //---   rp->operation = 0;              // Request
769 //---   for (i=0;i<50; i++)     {
770 //---           rp->rip[i].network = 0xFFFFFFFF;
771 //---           rp->rip[i].nhops = 0;
772 //---           rp->rip[i].nticks = 0;
773 //---   }
774 //---
775 //---   // Send it
776 //---   ipx_send_packet( &packets[0].ecb );
777 //---
778 //---   for (i=0;i<50; i++)     {
779 //---           if ( rp->rip[i].network != 0xFFFFFFFF )
780 //---                   printf( "Network = %8x, Hops=%d, Ticks=%d\n", rp->rip[i].network, rp->rip[i].nhops, rp->rip[i].nticks );
781 //---   }
782 //---}
783 //---
784 //---