1 /* $Id: ipx.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $ */
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.
17 * Routines for IPX communications.
22 static char rcsid[] = "$Id: ipx.c,v 1.4 2004-08-28 23:17:45 schaffner Exp $";
26 #define _BORLAND_DOS_REGS 1
46 typedef unsigned char BYTE;
47 typedef unsigned short WORD;
48 typedef unsigned long DWORD;
50 typedef struct local_address {
52 } __pack__ local_address;
54 typedef struct net_address {
56 local_address node_id;
58 } __pack__ net_address;
60 typedef struct ipx_header {
63 BYTE transport_control;
65 net_address destination;
67 } __pack__ ipx_header;
69 typedef struct ecb_header {
75 BYTE ipx_reserved[14];
77 local_address immediate_address;
79 WORD fragment_pointer[2];
81 } __pack__ ecb_header;
83 typedef struct packet_data {
85 byte data[IPX_MAX_DATA_SIZE];
86 } __pack__ packet_data;
88 typedef struct ipx_packet {
92 } __pack__ ipx_packet;
94 typedef struct user_address {
98 } __pack__ user_address;
101 int Ipx_num_users = 0;
102 user_address Ipx_users[MAX_USERS];
104 #define MAX_NETWORKS 64
105 int Ipx_num_networks = 0;
106 uint Ipx_networks[MAX_NETWORKS];
108 int ipx_packetnum = 0;
110 #define MAX_PACKETS 64
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];
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
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;
133 ushort ipx_packets_selector;
135 ecb_header * last_ecb=NULL;
138 void got_new_packet( ecb_header * ecb );
139 void ipx_listen_for_packet(ecb_header * ecb );
141 void free_packet( int id )
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 ));
149 int ipx_get_packet_data( ubyte * data )
151 int i, n, best, best_id, size;
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);
165 for (i=0; i<=largest_packet_index; i++ ) {
166 if ( packet_buffers[i].packetnum > -1 ) {
168 if ( best == -1 || (packet_buffers[i].packetnum<best) ) {
169 best = packet_buffers[i].packetnum;
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 ));
178 if ( best_id < 0 ) return 0;
180 size = packet_size[best_id];
181 memcpy( data, packet_buffers[best_id].data, size );
182 free_packet(best_id);
188 unsigned int swap_short( unsigned int short )
189 #pragma aux swap_short parm [eax] = "xchg al,ah";
191 static inline unsigned int swap_short( unsigned int sshort ) {
193 asm("xchg %%ah,%%al" : "=a" (__retval) : "a" (sshort));
198 void got_new_packet( ecb_header * ecb )
202 unsigned short datasize;
206 p = (ipx_packet *)ecb;
208 if ( p->ecb.in_use ) { neterrors++; return; }
209 if ( p->ecb.completion_code ) { neterrors++; return; }
211 // Error( "Recieve error %d for completion code", p->ecb.completion_code );
213 if ( memcmp( &p->ipx.source.node_id, &ipx_my_node, 6 ) ) {
214 datasize=swap_short(p->ipx.length);
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" );
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] );
236 //ipx_listen_for_packet(&p->ecb);
239 ubyte * ipx_get_my_local_address()
241 return ipx_my_node.address;
244 ubyte * ipx_get_my_server_address()
246 return (ubyte *)&ipx_network;
249 void ipx_listen_for_packet(ecb_header * ecb )
251 dpmi_real_regs rregs;
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 );
260 void ipx_cancel_listen_for_packet(ecb_header * ecb )
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 );
271 void ipx_send_packet(ecb_header * ecb )
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 );
284 ubyte local_target[6];
285 } __pack__ net_xlat_info;
287 void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target )
289 net_xlat_info * info;
290 dpmi_real_regs rregs;
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 );
298 memset(&rregs,0,sizeof(dpmi_real_regs));
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);
305 dpmi_real_int386x( 0x7A, &rregs );
307 // Save the local target...
308 memcpy( local_target, info->local_target, 6 );
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.
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 );
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
332 int ipx_init( int socket_number, int show_address )
334 dpmi_real_regs rregs;
335 ubyte *ipx_real_buffer;
342 // init packet buffers.
343 for (i=0; i<MAX_PACKETS; i++ ) {
344 packet_buffers[i].packetnum = -1;
345 packet_free_list[i] = i;
348 largest_packet_index = 0;
350 // Get the IPX vector
351 memset(&rregs,0,sizeof(dpmi_real_regs));
352 rregs.eax=0x00007a00;
353 dpmi_real_int386x( 0x2f, &rregs );
355 if ( (rregs.eax & 0xFF) != 0xFF ) {
356 return IPX_NOT_INSTALLED;
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 );
362 // Open a socket for IPX
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 );
371 ipx_socket = rregs.edx & 0xFFFF;
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;
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;
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 );
393 if ( rregs.eax & 0xFF ) {
394 //printf( "Error getting internetwork address!\n" );
395 return IPX_SOCKET_TABLE_FULL;
398 memcpy( &ipx_network, ipx_real_buffer, 4 );
399 memcpy( &ipx_my_node, &ipx_real_buffer[4], 6 );
401 Ipx_num_networks = 0;
402 memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 );
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] );
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;
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;
422 memset( packets, 0, sizeof(ipx_packet)*ipx_num_packets );
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);
433 ipx_listen_for_packet(&packets[i].ecb);
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);
447 for(i=0;i<ipx_num_outgoing_packets;i++)
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 );
459 //end this section replace - Kevin Bently
463 void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address )
466 ipx_packet *sendpacket = NULL;
468 assert(ipx_installed);
470 if ( datasize >= IPX_MAX_DATA_SIZE ) {
471 printf( "Data too big\n" );
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 )
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
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
495 // Fill in destination address
496 if ( memcmp( network, &ipx_network, 4 ) )
497 memcpy( sendpacket->ipx.destination.network_id, network, 4 );
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++;
504 // Fill in data to send
505 sendpacket->ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + datasize;
507 assert( datasize > 1 );
508 assert( sendpacket->ecb.fragment_size <= 576 );
510 memcpy( sendpacket->pd.data, data, datasize );
513 ipx_send_packet( &sendpacket->ecb );
517 void ipx_send_broadcast_packet_data( ubyte * data, int datasize )
520 ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
521 ubyte local_address[6];
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 );
529 ipx_send_packet_data( data, datasize, (ubyte *)&Ipx_networks[i], broadcast, broadcast );
533 //OLDipx_send_packet_data( data, datasize, (ubyte *)&ipx_network, broadcast, broadcast );
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 ))
542 ipx_send_packet_data( data, datasize, Ipx_users[i].network, Ipx_users[i].node, Ipx_users[i].address );
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 )
552 ubyte local_address[6];
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 );
558 // Old method, no server info.
559 ipx_send_packet_data( data, datasize, server, address, address );
563 int ipx_change_default_socket( ushort socket_number )
567 dpmi_real_regs rregs;
569 if ( !ipx_installed ) return -3;
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 );
579 new_ipx_socket = rregs.edx & 0xFFFF;
581 if ( rregs.eax & 0xFF ) {
582 //printf( (1, "IPX error opening channel %d\n", socket_number-IPX_DEFAULT_SOCKET ));
586 for (i=1; i<ipx_num_packets; i++ ) {
587 ipx_cancel_listen_for_packet(&packets[i].ecb);
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 );
596 ipx_socket = new_ipx_socket;
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);
605 packets[0].ecb.socket_id = ipx_socket;
606 packets[0].ipx.destination.socket_id = ipx_socket;
609 // init packet buffers.
610 for (i=0; i<MAX_PACKETS; i++ ) {
611 packet_buffers[i].packetnum = -1;
612 packet_free_list[i] = i;
615 largest_packet_index = 0;
620 void ipx_read_user_file(char * filename)
624 char temp_line[132], *p1;
627 if (!filename) return;
631 fp = fopen( filename, "rt" );
634 printf( "Broadcast Users:\n" );
636 while (fgets(temp_line, 132, fp)) {
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] );
650 printf( "Too many addresses in %s! (Limit of %d)\n", filename, MAX_USERS );
659 void ipx_read_network_file(char * filename)
663 char temp_line[132], *p1;
666 if (!filename) return;
668 fp = fopen( filename, "rt" );
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] );
677 while (fgets(temp_line, 132, fp)) {
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 ) {
686 for (j=0; j<Ipx_num_networks; j++ )
687 if ( !memcmp( &Ipx_networks[j], tmp.network, 4 ) )
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] );
694 printf( "Too many networks in %s! (Limit of %d)\n", filename, MAX_NETWORKS );
703 //---typedef struct rip_entry {
709 //---typedef struct rip_packet {
710 //--- ushort operation; //1=request, 2=response
711 //--- rip_entry rip[50];
715 //---void ipx_find_all_servers()
718 //--- rip_packet * rp;
719 //--- assert(ipx_installed);
721 //--- ipx_change_default_socket( 0x0453 );
722 //--- // ipx_change_default_socket( 0x5304 );
724 //--- // Make sure no one is already sending something
725 //--- while( packets[0].ecb.in_use )
729 //--- if (packets[0].ecb.completion_code) {
730 //--- printf( "AAAA:Send error %d for completion code\n", packets[0].ecb.completion_code );
734 //--- rp = (rip_packet *)&packets[0].pd;
736 //--- // Fill in destination address
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 );
744 //--- memcpy( packets[0].ipx.destination.network_id, mzero1, 4 );
745 //--- memcpy( packets[0].ipx.destination.node_id.address, mzero, 6 );
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;
762 //--- packets[0].ipx.packet_type = 1; // RIP packet
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 );
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;
776 //--- ipx_send_packet( &packets[0].ecb );
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 );