📄 ipx.c
字号:
/*---------------------------------------------------------------- * ipx.c - IPX network driver for libnet *---------------------------------------------------------------- * libnet is (c) Copyright Chad Catlett and George Foot 1997-1999 * * Please look in `docs' for details, documentation and * distribution conditions. */#include "platdefs.h"/* If this platform supports Dos style IPX use them. Otherwise use * a dummy driver */#ifdef __USE_REAL_IPX_DOS__/* ugh, I really hate the nearptr hack... */#include <sys/nearptr.h>#define DPMI_real_segment(P) ((((uint)(P)-(uint)(__djgpp_conventional_base)) >> 4) & 0xffff)#define DPMI_real_offset(P) (((uint)(P)-(uint)(__djgpp_conventional_base)) & 0xf)#include <crt0.h>#include <mem.h>#include <string.h>#include <go32.h>#include <dpmi.h>#include <dos.h>#include <stdio.h>#include <stdlib.h>#include <assert.h>#include "libnet.h"#include "internal.h"#include "config.h"#include "types.h"static int ipx_init( int socket_number, int show_address, int detectonly );static void ipx_close(void);static int ipx_change_default_socket( ushort socket_number );static ubyte *ipx_get_my_local_address(void);static ubyte *ipx_get_my_server_address(void);static void ipx_get_local_target( ubyte * server, ubyte * node, ubyte * local_target );static int ipx_get_packet_data( ubyte * data, int detectonly, int maxsize, int channel );static void ipx_send_packet_data( ubyte * data, int datasize, ubyte *network, ubyte *address, ubyte *immediate_address );static void ipx_send_internetwork_packet_data( ubyte * data, int datasize, ubyte * server, ubyte *address );typedef struct PORTstruct PORT, *PORTp;typedef struct PORTstruct /* link structure */{ PORTp next; /* linked list next node */ PORTp prev; /* linked list previous node */ int port;} PORTstruct;static int add_port(int port);static void kill_port(int port);static PORTp findport(int port);static PORTp top_nodel, bottom_nodel; /* nodes in linked list */static int next_port=1;static DWORD ipx_network = 0;static ubyte ipx_myy_node[6];static ubyte ipx_from_node[6], ipx_from_server[4];static char dosipx_desc[80] = "IPX network driver";static int add_port(int port){ PORTp objp; objp=findport(port); if(objp!=NULL) return 0; objp=malloc(sizeof(PORT)); objp->port=port; if (bottom_nodel==(PORTp)NULL) { bottom_nodel=objp; objp->prev=(PORTp)NULL; } else { objp->prev=top_nodel; objp->prev->next=objp; } top_nodel=objp; objp->next=(PORTp)NULL; return 1;}static void kill_port(int port){ PORTp node, objp; objp=findport(port); if(objp==NULL) return; node=objp; if (node==bottom_nodel) { bottom_nodel=node->next; if (bottom_nodel!=(PORTp)NULL) bottom_nodel->prev=(PORTp)NULL; } else if (node==top_nodel) { top_nodel=node->prev; top_nodel->next=(PORTp)NULL; } else { node->prev->next=node->next; node->next->prev=node->prev; } free(node);}static PORTp findport(int port){ PORTp nodel; PORTp next_nodel; if(bottom_nodel!=NULL) { for (nodel=bottom_nodel;nodel!=(PORTp)NULL;nodel=next_nodel) { next_nodel=nodel->next; if(port==nodel->port) return nodel; } } return NULL;}/* disable_driver: set by the config loader to disable this driver */static int disable_driver = 0;/* detect: * This function returns one of the following: * * - NET_DETECT_YES (if the network driver can definitely work) * - NET_DETECT_NO (if the network driver definitely cannot work) */static int dosipx_detect (void){ if (disable_driver) return NET_DETECT_NO; if(ipx_init(0,0,1)!=0) return NET_DETECT_NO; return NET_DETECT_YES;}/* init: * Initialises the driver. Return zero if successful, non-zero if not. */static int dosipx_init (void) { top_nodel=NULL; bottom_nodel=NULL; return ipx_init(0x869d,0,0); }static int dosipx_exit (void) { PORTp nodel; PORTp next_nodel; ipx_close(); if(bottom_nodel!=NULL) { for (nodel=bottom_nodel;nodel!=(PORTp)NULL;nodel=next_nodel) { next_nodel=nodel->next; kill_port(nodel->port); } } return 0; }static int dosipx_init_channel (NET_CHANNEL *chan, const char *addr) { ubyte *ipx_real_buffer, *ipx_real_bufferx; ubyte broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; int port; char buffer[80]; if (!(chan->data = malloc(20))) return -1; /* binding specifies a channel # for the channel * "" is default port 0 * NULL is next avalible port * :port is port */ if(addr==NULL) { do { port=next_port; next_port+=1; } while (findport(port)!=NULL); next_port=1; } else { if (strcmp(addr,"")==0) { port=0; } else { if(addr[0]==':') { port=atoi(addr+1); } else { return 1; } } } if(add_port(port)==0) return 1; ipx_real_buffer=(ubyte *)&ipx_network; ipx_real_bufferx=(ubyte *)&ipx_myy_node; sprintf(chan->local_addr,"%02X%02X%02X%02X/%02X%02X%02X%02X%02X%02X:",ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3],ipx_real_bufferx[0],ipx_real_bufferx[1],ipx_real_bufferx[2],ipx_real_bufferx[3],ipx_real_bufferx[4],ipx_real_bufferx[5] ); itoa(port,buffer,10); strcat(chan->local_addr,buffer); memcpy(chan->data,ipx_real_buffer,4); // send to local network memcpy(chan->data+4,broadcast,6); // broadcast to all memcpy(chan->data+10,&port,4); // your channel memset(chan->data+14,0,4); // channel to send to return 0; }static int dosipx_destroy_channel (NET_CHANNEL *chan) { int port; memcpy(&port,chan->data+10,4); kill_port(port); free(chan->data); return 0;}static int dosipx_update_target (NET_CHANNEL *chan) { char *data, rad[3], **stop_at=NULL; ubyte tmpadr[14]; int i, offset; ubyte *ipx_real_buffer; data=chan->target_addr; if(strlen(data)<12) return 1; offset=0; ipx_real_buffer=(ubyte *)&ipx_network; memcpy(chan->data,ipx_real_buffer,4); if(data[8]=='/') { rad[2]=0; for(i=0;i<4;i++) { strncpy(rad,(data+(i*2)),2); tmpadr[i] = (ubyte)strtol(rad,stop_at,16); } memcpy(chan->data,tmpadr,4); offset=9; } rad[2]=0; for(i=0;i<6;i++) { strncpy(rad,(data+(i*2)+offset),2); tmpadr[i] = (ubyte)strtol(rad,stop_at,16); } memcpy(chan->data+4,tmpadr,6); memset(chan->data+14,0,4); if(data[offset+12]==':') { i=atoi(data+offset+13); memcpy((chan->data+14),&i,4); } return 0; }static int dosipx_send (NET_CHANNEL *chan, const void *buf, int size) { ubyte *packet; packet=malloc(size+8); memcpy(packet,(chan->data+10),8); memcpy((packet+8),buf,size); ipx_send_internetwork_packet_data(packet, size+8, chan->data, (chan->data+4)); free(packet); return 0; }static int dosipx_recv (NET_CHANNEL *chan, void *buf, int size, char *from) { int datasize; ubyte *ipx_real_buffer, *ipx_real_bufferx; ubyte *packet; int channel; char buffer[80]; packet=malloc(size+8); memcpy(&channel,(chan->data+10),4); datasize=ipx_get_packet_data(packet, 0, size+8, channel); if(datasize==0) { free(packet); return 0; } memcpy(buf,(packet+8),datasize-8); if(from!=NULL) { ipx_real_buffer=(ubyte *)&ipx_from_server; ipx_real_bufferx=(ubyte *)&ipx_from_node; sprintf(from,"%02X%02X%02X%02X/%02X%02X%02X%02X%02X%02X:",ipx_real_buffer[0],ipx_real_buffer[1],ipx_real_buffer[2],ipx_real_buffer[3],ipx_real_bufferx[0],ipx_real_bufferx[1],ipx_real_bufferx[2],ipx_real_bufferx[3],ipx_real_bufferx[4],ipx_real_bufferx[5] ); memcpy(&channel,packet,4); itoa(channel,buffer,10); strcat(from,buffer); } free(packet); return (datasize-8); }/* query: * Returns non-zero if there is data waiting to be read from the channel. */static int dosipx_query (NET_CHANNEL *chan){ int channel; memcpy(&channel,(chan->data+10),4); return (ipx_get_packet_data(NULL,1,0,channel));}/* load_config: * This will be called once when the library is initialised, inviting the * driver to load configuration information from the passed text file. */static void dosipx_load_config (NET_DRIVER *drv, FILE *fp) { char *option, *value, **stop_at=NULL; int x; if (__libnet_internal__seek_section (fp, "ipx")) return; while (__libnet_internal__get_setting (fp, &option, &value) == 0) { if (!strcmp (option, "socket")) { x = strtol (value,stop_at,0); ipx_change_default_socket((ushort)x); } else if (!strcmp (option, "disable")) { disable_driver = (atoi (value) || (value[0] == 'y')); } } if (drv->load_conn_config) drv->load_conn_config (drv, fp, "ipx");}NET_DRIVER net_driver_ipx_dos = { "IPX", dosipx_desc, NET_CLASS_IPX, dosipx_detect, dosipx_init, dosipx_exit, NULL, NULL, dosipx_init_channel, dosipx_destroy_channel, dosipx_update_target, dosipx_send, dosipx_recv, dosipx_query, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dosipx_load_config, NULL, NULL};#define IPX_MAX_DATA_SIZE (1024) static inline unsigned int swap_short( unsigned int sshort ) { asm("xchgb %h0,%b0" : "=q" (sshort) : "0" (sshort)); return sshort;}typedef struct local_address { ubyte address[6];} __pack__ local_address;typedef struct net_address { BYTE network_id[4]; local_address node_id; WORD socket_id;} __pack__ net_address;typedef struct ipx_header { WORD checksum; WORD length; BYTE transport_control; BYTE packet_type; net_address destination; net_address source;} __pack__ ipx_header;typedef struct ecb_header { WORD link[2]; WORD esr_address[2]; volatile BYTE in_use; BYTE completion_code; WORD socket_id; BYTE ipx_reserved[14]; WORD connection_id; local_address immediate_address; WORD fragment_count; WORD fragment_pointer[2]; WORD fragment_size;} __pack__ ecb_header;typedef struct packet_data { int packetnum; ubyte ipx_from_node[6]; ubyte ipx_from_server[4]; byte data[IPX_MAX_DATA_SIZE];} __pack__ packet_data;typedef struct ipx_packet { ecb_header ecb; ipx_header ipx; packet_data pd;} __pack__ ipx_packet;typedef struct user_address { ubyte network[4]; ubyte node[6]; ubyte address[6];} __pack__ user_address;typedef struct { ubyte network[4]; ubyte node[6]; ubyte local_target[6];} __pack__ net_xlat_info;#define MAX_NETWORKS 64static int Ipx_num_networks = 0;static uint Ipx_networks[MAX_NETWORKS];static int ipx_packetnum = 0;#define MAX_PACKETS 64static packet_data packet_buffers[MAX_PACKETS];static short packet_free_list[MAX_PACKETS];static int num_packets = 0;static int largest_packet_index = 0;static short packet_size[MAX_PACKETS];static WORD ipx_socket=0;static ubyte ipx_installed=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -