#include #include #include "ipx.h" unsigned long ipx_entry = 0; long __get_ipx_entry(void); #pragma aux __get_ipx_entry = \ "mov AX,7A00h" \ "int 2Fh" \ "cmp AL,0FFh" \ "jnz ipx_init0" \ "mov DX, ES" \ "mov AX, DI" \ "jmp ipx_init1" \ "ipx_init0:" \ "xor DX,DX" \ "xor AX,AX" \ "ipx_init1:" \ parm caller nomemory \ value [AX DX] \ modify [BX CX SI DI ES] nomemory; int ipx_init(void) { if ( ipx_entry != 0L ) return 1; ipx_entry = __get_ipx_entry(); if ( ipx_entry == 0L ) return 0; return 1; } unsigned char far * __inline_get_network_number(unsigned char far *adr, long far *); #pragma aux __inline_get_network_number = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,0009h" \ "call far ptr DS:[DI]" \ "pop BP" \ "pop DS" \ parm caller [SI ES] [DI CX] nomemory \ value [SI ES] \ modify [AX BX CX DX SI DI ES] nomemory; int ___get_network_number(ipx_adr_struct far *adr) { if ( ipx_entry == 0L ) return 0; __inline_get_network_number((unsigned char far *)adr, (long far *)&ipx_entry); return 1; } ipx_adr_struct far *ipx_get_local_net_number(void) { static ipx_adr_struct adr; static is_ok = 0; if ( is_ok != 0 ) return &adr; if ( ipx_entry == 0L ) return NULL; if ( ___get_network_number(&adr) == 0 ) return NULL; is_ok = 1; return &adr; } short inline_ipx_open_socket(unsigned short far *socket, long far *adr); #pragma aux inline_ipx_open_socket = \ "push DS" \ "push BP" \ "mov BX,0000h" \ "mov AL, 000h" \ "mov DX, word ptr ES:[SI]" \ "xchg DH, DL" \ "mov DS,CX" \ "push ES" \ "call far ptr DS:[DI]" \ "pop ES" \ "xchg DH, DL" \ "mov word ptr ES:[SI], DX" \ "pop BP" \ "pop DS" \ "mov AH, 0" \ parm caller [SI ES] [DI CX] \ value [AX] \ modify [AX BX CX DX SI DI ES]; /* 0: ok 0x0fe: full 0x0ff: open */ int ipx_open_socket(unsigned short socket) { return (int)inline_ipx_open_socket((unsigned short far *)&socket, (long far *)&ipx_entry); } /* 0: ok 0x0fe: full 0x0ff: open */ int ipx_open_new_socket(unsigned short far *socket) { *socket = 0; return (int)inline_ipx_open_socket(socket, (long far *)&ipx_entry); } void inline_ipx_close_socket(unsigned short socket, long far *adr); #pragma aux inline_ipx_close_socket = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,0001h" \ "xchg DH,DL" \ "call far ptr DS:[DI]" \ "pop BP" \ "pop DS" \ parm caller [DX] [DI CX] nomemory \ value [DX] \ modify [AX BX CX DX SI DI ES] nomemory; void ipx_close_socket(unsigned short socket) { inline_ipx_close_socket(socket, (long far *)&ipx_entry); } /* RELINQUISH CONTROL */ void inline_ipx_dispatch(long far *adr); #pragma aux inline_ipx_dispatch = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,000ah" \ "call far ptr DS:[DI]" \ "pop BP" \ "pop DS" \ parm caller [DI CX] nomemory \ modify [AX BX CX DX SI DI ES] nomemory; void inline_send_ecb(ipx_ecb_struct far *ecb, long far *adr); #pragma aux inline_send_ecb = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,0003h" \ "call far ptr DS:[DI]" \ "pop BP" \ "pop DS" \ parm caller [SI ES] [DI CX] nomemory \ modify [AX BX CX DX SI DI ES] nomemory; int ipx_send_ecb(ipx_ecb_struct far *ecb) { if ( ipx_entry == 0L ) return 0; inline_send_ecb(ecb, (long far *)&ipx_entry); return 1; } void ipx_dispatch(void) { inline_ipx_dispatch((long far *)&ipx_entry); } int ipx_is_ecb_in_use(ipx_ecb_struct far *ecb) { if ( ipx_entry == 0L ) return 0; if ( ecb == NULL ) return 0; ipx_dispatch(); if ( ecb->inuse != 0 ) return 1; return 0; } unsigned short inline_ipx_listen_ecb(ipx_ecb_struct far *ecb, long far *adr); #pragma aux inline_ipx_listen_ecb = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,0004h" \ "call far ptr DS:[DI]" \ "mov AH, 0" \ "pop BP" \ "pop DS" \ parm caller [SI ES] [DI CX] nomemory \ value [AX] \ modify [AX BX CX DX SI DI ES DS] nomemory; int ipx_listen_ecb(ipx_ecb_struct far *ecb) { if ( ipx_entry == 0L ) return 0; if ( inline_ipx_listen_ecb(ecb, (long far *)&ipx_entry) != 0 ) return 0; return 1; } unsigned short inline_ipx_cancel_ecb(ipx_ecb_struct far *ecb, long far *adr); #pragma aux inline_ipx_cancel_ecb = \ "push DS" \ "push BP" \ "mov DS,CX" \ "mov BX,0006h" \ "call far ptr DS:[DI]" \ "mov AH, 0" \ "pop BP" \ "pop DS" \ parm caller [SI ES] [DI CX] nomemory \ value [AX] \ modify [AX BX CX DX SI DI ES DS] nomemory; int ipx_cancel_ecb(ipx_ecb_struct far *ecb) { if ( ipx_entry == 0L ) return 0; if ( inline_ipx_cancel_ecb(ecb, (long far *)&ipx_entry) != 0 ) return 0; return 1; } char far *get_str_net_adr(ipx_adr_struct far *adr) { static char s[10]; sprintf(s, "%02x%02x%02x%02x", adr->netadd[3], adr->netadd[2], adr->netadd[1], adr->netadd[0] ); return s; } char far *get_str_node_adr(ipx_adr_struct far *adr) { static char s[14]; sprintf(s, "%02x%02x%02x%02x%02x%02x", adr->nodeadd[5], adr->nodeadd[4], adr->nodeadd[3], adr->nodeadd[2], adr->nodeadd[1], adr->nodeadd[0] ); return s; } ipx_header_struct far *ipx_get_header(ipx_adr_struct far *dest, unsigned short dest_socket, unsigned short source_socket) { static ipx_header_struct head; head.checksum = 0; head.length = 0; head.tc = 0; head.type = 4; // packet exchange packet, see ralf brown's intlist if ( dest == NULL ) { head.dest.netadd[3] = 0; head.dest.netadd[2] = 0; head.dest.netadd[1] = 0; head.dest.netadd[0] = 0; head.dest.nodeadd[5] = 0x0ff; head.dest.nodeadd[4] = 0x0ff; head.dest.nodeadd[3] = 0x0ff; head.dest.nodeadd[2] = 0x0ff; head.dest.nodeadd[1] = 0x0ff; head.dest.nodeadd[0] = 0x0ff; } else { head.dest = *dest; } head.source = *ipx_get_local_net_number(); head.dest.socket = reverse_word(dest_socket); head.source.socket = reverse_word(source_socket); return &head; } char *ipx_get_ecb_inuse_string(ipx_ecb_struct far *ecb) { static char s[80]; switch(ecb->inuse) { case 0x0000: strcpy(s, "available"); break; case 0x00E0: strcpy(s, "AES temporary"); break; case 0x00F6: strcpy(s, "special IPX/SPX processing"); break; case 0x00F7: strcpy(s, "special IPX/SPX processing"); break; case 0x00F8: strcpy(s, "IPX in critical section"); break; case 0x00F9: strcpy(s, "SPX listening"); break; case 0x00FA: strcpy(s, "processing"); break; case 0x00FB: strcpy(s, "holding"); break; case 0x00FC: strcpy(s, "AES waiting"); break; case 0x00FD: strcpy(s, "AES counting down delay time"); break; case 0x00FE: strcpy(s, "awaiting packet reception"); break; case 0x00FF: strcpy(s, "sending packet"); break; default: strcpy(s, "unknown ecb state"); } return (char *)s; } char *ipx_get_ecb_cc_string(ipx_ecb_struct far *ecb) { static char s[80]; switch(ecb->cc) { case 0x0000: strcpy(s, "success"); break; case 0x00EC: strcpy(s, "remote terminated connection without acknowledging packet"); break; case 0x00ED: strcpy(s, "abnormal connection termination"); break; case 0x00EE: strcpy(s, "invalid connection ID"); break; case 0x00EF: strcpy(s, "SPX connection table full"); break; case 0x00F9: strcpy(s, "event should not be cancelled"); break; case 0x00FA: strcpy(s, "cannot establish connection with specified destination"); break; case 0x00FC: strcpy(s, "cancelled"); break; case 0x00FD: strcpy(s, "malformed packet"); break; case 0x00FE: strcpy(s, "packet undeliverable"); break; case 0x00FF: strcpy(s, "physical error or wrong socket"); break; default: strcpy(s, "unknown ecb completion code"); } return (char *)s; } ipx_ecb_struct far *ipx_fill_send_ecb(ipx_ecb_struct far *ecb, ipx_header_struct far *head, void far *data, unsigned short size) { if ( head == NULL ) return NULL; if ( data == NULL ) return NULL; ecb->head = *head; ecb->linkaddress = NULL; ecb->esraddress = NULL; ecb->inuse = 0; /* In-Use Status */ ecb->cc = 11; /* Completion Flag */ ecb->socket = head->dest.socket; /* destination socket */ ecb->immedaddr[0] = ecb->head.dest.nodeadd[0]; ecb->immedaddr[1] = ecb->head.dest.nodeadd[1]; ecb->immedaddr[2] = ecb->head.dest.nodeadd[2]; ecb->immedaddr[3] = ecb->head.dest.nodeadd[3]; ecb->immedaddr[4] = ecb->head.dest.nodeadd[4]; ecb->immedaddr[5] = ecb->head.dest.nodeadd[5]; ecb->fragcount = 2; /* we always have ipx header and data */ ecb->fragaddr1 = &(ecb->head); ecb->fragsize1 = (unsigned short)sizeof(ipx_header_struct); ecb->fragaddr2 = data; ecb->fragsize2 = size; return ecb; } ipx_ecb_struct far *ipx_get_send_ecb(ipx_header_struct far *head, void far *data, unsigned short size) { static ipx_ecb_struct ecb; return ipx_fill_send_ecb(&ecb, head, data, size); } ipx_ecb_struct far *ipx_fill_receive_ecb(ipx_ecb_struct far *ecb, unsigned short socket, void far *data, unsigned short size) { if ( data == NULL ) return NULL; ecb->linkaddress = NULL; ecb->esraddress = NULL; ecb->inuse = 0; /* In-Use Status (available) */ ecb->cc = 0; /* Completion Flag */ ecb->socket = reverse_word(socket); ecb->fragcount = 2; /* we always have ipx header and data */ ecb->fragaddr1 = &(ecb->head); ecb->fragsize1 = (unsigned short)sizeof(ipx_header_struct); ecb->fragaddr2 = data; ecb->fragsize2 = size; return ecb; } ipx_ecb_struct far *ipx_get_receive_ecb(unsigned short socket, void far *data, unsigned short size) { static ipx_ecb_struct ecb; return ipx_fill_receive_ecb(&ecb, socket, data, size); } #ifdef CREATE_MONITOR #define IPX_MONITOR_SIZE 80 #include void monitor(unsigned short socket) { ipx_ecb_struct far *ecb; unsigned char data[IPX_MONITOR_SIZE]; if ( ipx_init() == 0 ) { puts("kein ipx vorhanden"); return; } printf("ipx_entry: %lx\n", ipx_entry); printf("net-adr: %s\n", get_str_net_adr(ipx_get_local_net_number())); printf("node-adr: %s\n", get_str_node_adr(ipx_get_local_net_number())); switch(ipx_open_socket(socket)) { case 0x0fe: puts("socket table full"); return; case 0x0ff: puts("socket open"); return; } printf("socket: %d\n", socket); for(;;) { ecb = ipx_get_receive_ecb(socket, (void far *)data, IPX_MONITOR_SIZE); if ( ecb == NULL ) { puts("cannot generate ecb"); return; } if ( ipx_listen_ecb(ecb) == 0 ) { puts("cannot listen to ecb"); ipx_close_socket(socket); return; } for(;;) { if ( kbhit() != 0 ) break; if ( ipx_is_ecb_in_use(ecb) == 0 ) { printf("received packet\n"); printf("inuse: %s \n", ipx_get_ecb_inuse_string(ecb)); printf("cc: %s\n", ipx_get_ecb_cc_string(ecb)); printf("socket: %d\n", reverse_word(ecb->socket)); printf("dest net-adr: %s\n", get_str_net_adr(&(ecb->head.dest ))); printf("dest node-adr: %s\n", get_str_node_adr(&(ecb->head.dest ))); printf("dest socket: %d\n", reverse_word(ecb->head.dest.socket)); printf("source net-adr: %s\n", get_str_net_adr(&(ecb->head.source))); printf("source node-adr: %s\n", get_str_node_adr(&(ecb->head.source))); printf("source socket: %d\n", reverse_word(ecb->head.source.socket)); break; } else { printf("inuse: %s \r", ipx_get_ecb_inuse_string(ecb)); } } if ( kbhit() != 0 ) { getch(); break; } } ipx_close_socket(socket); } int xmain(void) { monitor(2007); /* monitor(2000); */ return 0; } void ymain(void) { ipx_ecb_struct far *ecb; if ( ipx_init() == 0 ) { puts("kein ipx vorhanden"); return; } printf("ipx_entry: %lx\n", ipx_entry); printf("net-adr: %s\n", get_str_net_adr(ipx_get_local_net_number())); printf("node-adr: %s\n", get_str_node_adr(ipx_get_local_net_number())); ecb = ipx_get_send_ecb(ipx_get_header(NULL, 2417, 2419), " ", 2); printf("<%d,%d>", ecb->inuse, ecb->cc); ipx_send_ecb(ecb); printf("<%d,%d>", ecb->inuse, ecb->cc); while ( ipx_is_ecb_in_use(ecb) != 0 ) { printf("<%d,%d>", ecb->inuse, ecb->cc); if ( kbhit() != 0 ) break; } printf("<%d,%d>", ecb->inuse, ecb->cc); } #endif #ifdef CREATE_SOCKET_FREE int main(int argc, char *argv[]) { if ( argc < 2 ) { puts("sfree socket-number"); return 1; } if ( ipx_init() == 0 ) { puts("no ipx found"); return 1; } printf("close socket %d\n", atoi(argv[1])); ipx_close_socket((short)atoi(argv[1])); return 0; } #endif