📄 ipx.c
字号:
static WORD ipx_vector_segment;static WORD ipx_vector_offset;static ubyte ipx_socket_life = 0; // 0=closed at prog termination, 0xff=closed when requested.static local_address ipx_my_node;static WORD ipx_num_packets=32; // 32 Ipx packetsstatic ipx_packet * packets;static int neterrors = 0;static int ipx_packets_selector;static ecb_header * last_ecb=NULL;static int lastlen=0;static void got_new_packet( ecb_header * ecb );static void ipx_listen_for_packet(ecb_header * ecb );static void free_packet( int id );static void ipx_cancel_listen_for_packet(ecb_header * ecb );static void ipx_send_packet(ecb_header * ecb );static void free_packet( int id ){ packet_buffers[id].packetnum = -1; packet_free_list[ --num_packets ] = id; if (largest_packet_index==id) while ((--largest_packet_index>0) && (packet_buffers[largest_packet_index].packetnum == -1 ));}static int ipx_get_packet_data( ubyte * data, int detectonly, int maxsize, int channel ){ int i, best, best_id, size; int n0, n1; for (i=1; i<ipx_num_packets; i++ ) { if ( !packets[i].ecb.in_use ) { got_new_packet( &packets[i].ecb ); packets[i].ecb.in_use = 0; ipx_listen_for_packet(&packets[i].ecb); } } best = -1; best_id = -1; for (i=0; i<=largest_packet_index; i++ ) { if ( packet_buffers[i].packetnum > -1 ) { if ( best == -1 || (packet_buffers[i].packetnum<best) ) { memcpy(&n0,packet_buffers[i].data,4); memcpy(&n1,(packet_buffers[i].data+4),4); if(n0==channel && n1==channel && memcmp( &packet_buffers[i].ipx_from_node, &ipx_my_node, 6 )==0) { free_packet(i); } else { if((n0!=channel || memcmp( &packet_buffers[i].ipx_from_node, &ipx_my_node, 6 )) && n1==channel) { best = packet_buffers[i].packetnum; best_id = i; } } } } } if ( best_id < 0 ) return 0; if(detectonly==1) return 1; size = packet_size[best_id]; if(size>maxsize) size=maxsize; memcpy( data, packet_buffers[best_id].data, size ); memcpy( &ipx_from_node,&packet_buffers[best_id].ipx_from_node, 6 ); memcpy( &ipx_from_server,&packet_buffers[best_id].ipx_from_server, 4 ); free_packet(best_id); return size;}static void got_new_packet( ecb_header * ecb ){ ipx_packet * p; int id; unsigned short datasize; datasize = 0; last_ecb = ecb; p = (ipx_packet *)ecb; if ( p->ecb.in_use ) { neterrors++; return; } if( p->ecb.completion_code ) { neterrors++; return; } datasize=swap_short(p->ipx.length); lastlen=datasize; datasize -= sizeof(ipx_header); // Find slot to put packet in... if ( datasize > 0 && datasize <= sizeof(packet_data) ) { if ( num_packets >= MAX_PACKETS ) { neterrors++; return; } id = packet_free_list[ num_packets++ ]; if (id > largest_packet_index ) largest_packet_index = id; packet_size[id] = datasize-sizeof(int)-(10*sizeof(ubyte)); packet_buffers[id].packetnum = p->pd.packetnum; if ( packet_buffers[id].packetnum < 0 ) { neterrors++; return; } memcpy( &packet_buffers[id].ipx_from_node, &p->ipx.source.node_id, 6 ); memcpy( &packet_buffers[id].ipx_from_server, &p->ipx.source.network_id, 4 ); memcpy( packet_buffers[id].data, p->pd.data, packet_size[id] ); } else { neterrors++; return; } // Repost the ecb p->ecb.in_use = 0;}static ubyte *ipx_get_my_local_address(void){ return ipx_my_node.address;}static ubyte *ipx_get_my_server_address(void){ return (ubyte *)&ipx_network;}static void ipx_listen_for_packet(ecb_header * ecb ) { __dpmi_regs regs; ecb->in_use = 0x1d; memset(®s,0,sizeof regs); regs.d.ebx = 4; // Listen For Packet function regs.d.esi = DPMI_real_offset(ecb); regs.x.es = DPMI_real_segment(ecb); __dpmi_int( 0x7a, ®s );}static void ipx_cancel_listen_for_packet(ecb_header * ecb ) { __dpmi_regs regs; memset(®s,0,sizeof regs); regs.d.ebx = 6; // IPX Cancel event regs.d.esi = DPMI_real_offset(ecb); regs.x.es = DPMI_real_segment(ecb); __dpmi_int( 0x7A, ®s );}static void ipx_send_packet(ecb_header * ecb ) { __dpmi_regs regs; memset(®s,0,sizeof regs); regs.d.ebx = 3; // Send Packet function regs.d.esi = DPMI_real_offset(ecb); regs.x.es = DPMI_real_segment(ecb); __dpmi_int( 0x7A, ®s );}static void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target ){ net_xlat_info * info; __dpmi_regs regs; // Get dos memory for call... info = (net_xlat_info *) (((__tb + 15) & ~15) + __djgpp_conventional_base); assert( info != NULL ); memcpy( info->network, server, 4 ); memcpy( info->node, node, 6 ); memset(®s,0,sizeof regs); regs.d.ebx = 2; // Get Local Target regs.x.es = DPMI_real_segment(info); regs.d.esi = DPMI_real_offset(info->network); regs.d.edi = DPMI_real_offset(info->local_target); __dpmi_int( 0x7A, ®s ); // Save the local target... memcpy( local_target, info->local_target, 6 );}static void ipx_close(void){ __dpmi_regs regs; if ( ipx_installed ) { // When using VLM's instead of NETX, the sockets don't // seem to automatically get closed, so we must explicitly // close them at program termination. ipx_installed = 0; memset(®s,0,sizeof regs); regs.d.edx = ipx_socket; regs.d.ebx = 1; // Close socket __dpmi_int( 0x7A, ®s ); }}//---------------------------------------------------------------// Initializes all IPX internals. // If socket_number==0, then opens next available socket.// Returns: 0 if successful.// -1 if socket already open.// -2 if socket table full.// -3 if IPX not installed.// -4 if couldn't allocate low dos memory// -5 if error with getting internetwork address// -6 if nearptrs not availablestatic int ipx_init( int socket_number, int show_address, int detectonly ){ __dpmi_regs regs; ubyte *ipx_real_buffer; int i; if (~_crt0_startup_flags & _CRT0_FLAG_NONMOVE_SBRK) return -6; if (~_crt0_startup_flags & _CRT0_FLAG_NEARPTR) if (!__djgpp_nearptr_enable()) return -6; atexit(ipx_close); ipx_packetnum = 0; // init packet buffers. for (i=0; i<MAX_PACKETS; i++ ) { packet_buffers[i].packetnum = -1; packet_free_list[i] = i; } num_packets = 0; largest_packet_index = 0; // Get the IPX vector memset(®s,0,sizeof regs); regs.d.eax=0x00007a00; __dpmi_int( 0x2f, ®s ); if ( (regs.d.eax & 0xFF) != 0xFF ) { return 3; } if(detectonly==1) return 0; ipx_vector_offset = regs.d.edi & 0xFFFF; ipx_vector_segment = regs.x.es; // Open a socket for IPX memset(®s,0,sizeof regs); swab( (char *)&socket_number,(char *)&ipx_socket, 2 ); regs.d.edx = ipx_socket; regs.d.eax = ipx_socket_life; regs.d.ebx = 0; // Open socket __dpmi_int( 0x7A, ®s ); ipx_socket = regs.d.edx & 0xFFFF; if ( regs.d.eax & 0xFF ) { return -2; } ipx_installed = 1; // Find our internetwork address ipx_real_buffer = (void *) (((__tb + 15) & ~15) + __djgpp_conventional_base); /* need 1k */ if ( ipx_real_buffer == NULL ) { return -4; } memset(®s,0,sizeof regs); regs.d.ebx = 9; // Get internetwork address regs.d.esi = DPMI_real_offset(ipx_real_buffer); regs.x.es = DPMI_real_segment(ipx_real_buffer); __dpmi_int( 0x7A, ®s ); if ( regs.d.eax & 0xFF ) { return -2; } memcpy( &ipx_network, ipx_real_buffer, 4 ); memcpy( &ipx_my_node, &ipx_real_buffer[4], 6 ); memcpy( &ipx_myy_node, &ipx_real_buffer[4], 6 ); Ipx_num_networks = 0; memcpy( &Ipx_networks[Ipx_num_networks++], &ipx_network, 4 ); if ( show_address ) { printf( "My IPX addresss is " ); printf( "%02X%02X%02X%02X/", ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3] ); 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] ); printf( "\n" ); } { int result = __dpmi_allocate_dos_memory ((sizeof(ipx_packet)*ipx_num_packets + 15)/16, &ipx_packets_selector); if (result == -1) return -4; packets = (void *) ((result << 4) + __djgpp_conventional_base); } memset( packets, 0, sizeof(ipx_packet)*ipx_num_packets ); for (i=1; i<ipx_num_packets; i++ ) { packets[i].ecb.in_use = 0x1d; packets[i].ecb.socket_id = ipx_socket; packets[i].ecb.fragment_count = 1; packets[i].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[i].ipx); packets[i].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[i].ipx); packets[i].ecb.fragment_size = sizeof(ipx_packet)-sizeof(ecb_header); //-sizeof(ecb_header); ipx_listen_for_packet(&packets[i].ecb); } packets[0].ecb.socket_id = ipx_socket; packets[0].ecb.fragment_count = 1; packets[0].ecb.fragment_pointer[0] = DPMI_real_offset(&packets[0].ipx); packets[0].ecb.fragment_pointer[1] = DPMI_real_segment(&packets[0].ipx); packets[0].ipx.packet_type = 4; // IPX packet packets[0].ipx.destination.socket_id = ipx_socket; memset( packets[0].ipx.destination.network_id, 0, 4 ); return 0;}static void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address ){ assert(ipx_installed); if ( datasize >= IPX_MAX_DATA_SIZE ) datasize = IPX_MAX_DATA_SIZE; if(datasize<1) return; // Make sure no one is already sending something while( packets[0].ecb.in_use ) { } if (packets[0].ecb.completion_code) { printf( "Send error %d for completion code\n", packets[0].ecb.completion_code ); exit(1); } // Fill in destination address if ( memcmp( network, &ipx_network, 4 ) ) memcpy( packets[0].ipx.destination.network_id, network, 4 ); else memset( packets[0].ipx.destination.network_id, 0, 4 ); memcpy( packets[0].ipx.destination.node_id.address, address, 6 ); memcpy( packets[0].ecb.immediate_address.address, immediate_address, 6 ); packets[0].pd.packetnum = ipx_packetnum++; // Fill in data to send packets[0].ecb.fragment_size = sizeof(ipx_header) + sizeof(int) + 10*sizeof(ubyte) + datasize; memcpy( packets[0].pd.data, data, datasize ); // Send it ipx_send_packet( &packets[0].ecb );}// Sends a non-localized packet... needs 4 byte server, 6 byte addressstatic void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address ){ ubyte local_address[6]; if ( (*(uint *)server) != 0 ) { ipx_get_local_target( server, address, local_address ); ipx_send_packet_data( data, datasize, server, address, local_address ); } else { // Old method, no server info. ipx_send_packet_data( data, datasize, server, address, address ); }}static int ipx_change_default_socket( ushort socket_number ){ int i; WORD new_ipx_socket; __dpmi_regs regs; if ( !ipx_installed ) return -3; // Open a new socket memset(®s,0,sizeof regs); swab( (char *)&socket_number,(char *)&new_ipx_socket, 2 ); regs.d.edx = new_ipx_socket; regs.d.eax = ipx_socket_life; regs.d.ebx = 0; // Open socket __dpmi_int( 0x7A, ®s ); new_ipx_socket = regs.d.edx & 0xFFFF; if ( regs.d.eax & 0xFF ) { return -2; } for (i=1; i<ipx_num_packets; i++ ) { ipx_cancel_listen_for_packet(&packets[i].ecb); } // Close existing socket... memset(®s,0,sizeof regs); regs.d.edx = ipx_socket; regs.d.ebx = 1; // Close socket __dpmi_int( 0x7A, ®s ); ipx_socket = new_ipx_socket; // Repost all listen requests on the new socket... for (i=1; i<ipx_num_packets; i++ ) { packets[i].ecb.in_use = 0; packets[i].ecb.socket_id = ipx_socket; ipx_listen_for_packet(&packets[i].ecb); } packets[0].ecb.socket_id = ipx_socket; packets[0].ipx.destination.socket_id = ipx_socket; ipx_packetnum = 0; // init packet buffers. for (i=0; i<MAX_PACKETS; i++ ) { packet_buffers[i].packetnum = -1; packet_free_list[i] = i; } num_packets = 0; largest_packet_index = 0; return 0;}#else /* __USE_REAL_IPX_DOS__ *//* Can't use the DOS-style IPX on this platform, so put in a dummy * driver. */#include <stdlib.h>#include <stdio.h>#include "libnet.h"#include "internal.h"static int detect (void) { return NET_DETECT_NO; }static void load_config (NET_DRIVER *drv, FILE *fp) { }NET_DRIVER net_driver_ipx_dos = { "IPX from DOS", "Dummy driver", NET_CLASS_IPX, detect, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, load_config, NULL, NULL};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -