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