home *** CD-ROM | disk | FTP | other *** search
/ Software Recommendations - 1998 Season 1 / DNBCD4.iso / share / DOS / ipxcopy / SRC.ZIP / SRC / IPX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-11  |  16.0 KB  |  537 lines

  1.  
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "ipx.h"
  5.  
  6. unsigned long ipx_entry = 0;
  7.  
  8. long __get_ipx_entry(void);
  9.  
  10. #pragma aux __get_ipx_entry =             \
  11.    "mov  AX,7A00h"                        \
  12.    "int  2Fh"                             \
  13.    "cmp  AL,0FFh"                         \
  14.    "jnz  ipx_init0"                       \
  15.    "mov  DX, ES"                          \
  16.    "mov  AX, DI"                          \
  17.    "jmp  ipx_init1"                       \
  18.    "ipx_init0:"                           \
  19.    "xor  DX,DX"                           \
  20.    "xor  AX,AX"                           \
  21.    "ipx_init1:"                           \
  22.    parm caller nomemory                   \
  23.    value [AX DX]                          \
  24.    modify [BX CX SI DI ES] nomemory;
  25.  
  26. int ipx_init(void)
  27. {
  28.    if ( ipx_entry != 0L )
  29.       return 1;
  30.    ipx_entry = __get_ipx_entry();
  31.    if ( ipx_entry == 0L )
  32.       return 0;
  33.    return 1;
  34. }
  35.  
  36. unsigned char far * __inline_get_network_number(unsigned char far *adr, long far *);
  37.  
  38. #pragma aux __inline_get_network_number = \
  39.    "push DS"                              \
  40.    "push BP"                              \
  41.    "mov  DS,CX"                           \
  42.    "mov  BX,0009h"                        \
  43.    "call far ptr DS:[DI]"                 \
  44.    "pop  BP"                              \
  45.    "pop  DS"                              \
  46.    parm caller [SI ES] [DI CX] nomemory   \
  47.    value [SI ES]                          \
  48.    modify [AX BX CX DX SI DI ES] nomemory;
  49.  
  50. int ___get_network_number(ipx_adr_struct far *adr)
  51. {
  52.    if ( ipx_entry == 0L )
  53.       return 0;
  54.    __inline_get_network_number((unsigned char far *)adr, (long far *)&ipx_entry);
  55.    return 1;
  56. }
  57.  
  58. ipx_adr_struct far *ipx_get_local_net_number(void)
  59. {
  60.    static ipx_adr_struct adr;
  61.    static is_ok = 0;
  62.    if ( is_ok != 0 )
  63.       return &adr;
  64.    if ( ipx_entry == 0L )
  65.       return NULL;
  66.    if ( ___get_network_number(&adr) == 0 )
  67.       return NULL;
  68.    is_ok = 1;
  69.    return &adr;
  70. }
  71.  
  72. short inline_ipx_open_socket(unsigned short far *socket, long far *adr);
  73. #pragma aux inline_ipx_open_socket =      \
  74.    "push DS"                              \
  75.    "push BP"                              \
  76.    "mov  BX,0000h"                        \
  77.    "mov  AL, 000h"                        \
  78.    "mov  DX, word ptr ES:[SI]"            \
  79.    "xchg DH, DL"                          \
  80.    "mov  DS,CX"                           \
  81.    "push ES"                              \
  82.    "call far ptr DS:[DI]"                 \
  83.    "pop  ES"                              \
  84.    "xchg DH, DL"                          \
  85.    "mov  word ptr ES:[SI], DX"            \
  86.    "pop  BP"                              \
  87.    "pop  DS"                              \
  88.    "mov  AH, 0"                           \
  89.    parm caller [SI ES] [DI CX]            \
  90.    value [AX]                             \
  91.    modify [AX BX CX DX SI DI ES];
  92.  
  93. /* 0: ok    0x0fe: full    0x0ff: open */
  94. int ipx_open_socket(unsigned short socket)
  95. {
  96.    return (int)inline_ipx_open_socket((unsigned short far *)&socket, (long far *)&ipx_entry);
  97. }
  98.  
  99. /* 0: ok    0x0fe: full    0x0ff: open */
  100. int ipx_open_new_socket(unsigned short far *socket)
  101. {
  102.    *socket = 0;
  103.    return (int)inline_ipx_open_socket(socket, (long far *)&ipx_entry);
  104. }
  105.  
  106. void inline_ipx_close_socket(unsigned short socket, long far *adr);
  107. #pragma aux inline_ipx_close_socket =      \
  108.    "push DS"                              \
  109.    "push BP"                              \
  110.    "mov  DS,CX"                           \
  111.    "mov  BX,0001h"                        \
  112.    "xchg DH,DL"                           \
  113.    "call far ptr DS:[DI]"                 \
  114.    "pop  BP"                              \
  115.    "pop  DS"                              \
  116.    parm caller [DX] [DI CX] nomemory      \
  117.    value [DX]                             \
  118.    modify [AX BX CX DX SI DI ES] nomemory;
  119.  
  120. void ipx_close_socket(unsigned short socket)
  121. {
  122.    inline_ipx_close_socket(socket, (long far *)&ipx_entry);
  123. }
  124.  
  125.  
  126. /* RELINQUISH CONTROL */
  127. void inline_ipx_dispatch(long far *adr);
  128. #pragma aux inline_ipx_dispatch =         \
  129.    "push DS"                              \
  130.    "push BP"                              \
  131.    "mov  DS,CX"                           \
  132.    "mov  BX,000ah"                        \
  133.    "call far ptr DS:[DI]"                 \
  134.    "pop  BP"                              \
  135.    "pop  DS"                              \
  136.    parm caller [DI CX] nomemory           \
  137.    modify [AX BX CX DX SI DI ES] nomemory;
  138.  
  139. void inline_send_ecb(ipx_ecb_struct far *ecb, long far *adr);
  140. #pragma aux inline_send_ecb =             \
  141.    "push DS"                              \
  142.    "push BP"                              \
  143.    "mov  DS,CX"                           \
  144.    "mov  BX,0003h"                        \
  145.    "call far ptr DS:[DI]"                 \
  146.    "pop  BP"                              \
  147.    "pop  DS"                              \
  148.    parm caller [SI ES] [DI CX] nomemory   \
  149.    modify [AX BX CX DX SI DI ES] nomemory;
  150.  
  151. int ipx_send_ecb(ipx_ecb_struct far *ecb)
  152. {
  153.    if ( ipx_entry == 0L )
  154.       return 0;
  155.    inline_send_ecb(ecb, (long far *)&ipx_entry);
  156.    return 1;
  157. }
  158.  
  159. void ipx_dispatch(void)
  160. {
  161.    inline_ipx_dispatch((long far *)&ipx_entry);
  162. }
  163.  
  164. int ipx_is_ecb_in_use(ipx_ecb_struct far *ecb)
  165. {
  166.    if ( ipx_entry == 0L )
  167.       return 0;
  168.    if ( ecb == NULL )
  169.       return 0;
  170.    ipx_dispatch();
  171.    if ( ecb->inuse != 0 )
  172.       return 1;
  173.    return 0;
  174. }
  175.  
  176. unsigned short inline_ipx_listen_ecb(ipx_ecb_struct far *ecb, long far *adr);
  177. #pragma aux inline_ipx_listen_ecb = \
  178.    "push DS"                              \
  179.    "push BP"                              \
  180.    "mov  DS,CX"                           \
  181.    "mov  BX,0004h"                        \
  182.    "call far ptr DS:[DI]"                 \
  183.    "mov  AH, 0"                           \
  184.    "pop  BP"                              \
  185.    "pop  DS"                              \
  186.    parm caller [SI ES] [DI CX] nomemory   \
  187.    value [AX]                             \
  188.    modify [AX BX CX DX SI DI ES DS] nomemory;
  189.  
  190. int ipx_listen_ecb(ipx_ecb_struct far *ecb)
  191. {
  192.    if ( ipx_entry == 0L )
  193.       return 0;
  194.    if ( inline_ipx_listen_ecb(ecb, (long far *)&ipx_entry) != 0 )
  195.       return 0;
  196.    return 1;
  197. }
  198.  
  199. unsigned short inline_ipx_cancel_ecb(ipx_ecb_struct far *ecb, long far *adr);
  200. #pragma aux inline_ipx_cancel_ecb = \
  201.    "push DS"                              \
  202.    "push BP"                              \
  203.    "mov  DS,CX"                           \
  204.    "mov  BX,0006h"                        \
  205.    "call far ptr DS:[DI]"                 \
  206.    "mov  AH, 0"                           \
  207.    "pop  BP"                              \
  208.    "pop  DS"                              \
  209.    parm caller [SI ES] [DI CX] nomemory   \
  210.    value [AX]                             \
  211.    modify [AX BX CX DX SI DI ES DS] nomemory;
  212.  
  213. int ipx_cancel_ecb(ipx_ecb_struct far *ecb)
  214. {
  215.    if ( ipx_entry == 0L )
  216.       return 0;
  217.    if ( inline_ipx_cancel_ecb(ecb, (long far *)&ipx_entry) != 0 )
  218.       return 0;
  219.    return 1;
  220. }
  221.  
  222. char far *get_str_net_adr(ipx_adr_struct far *adr)
  223. {
  224.    static char s[10];
  225.    sprintf(s, "%02x%02x%02x%02x", 
  226.       adr->netadd[3],
  227.       adr->netadd[2],
  228.       adr->netadd[1],
  229.       adr->netadd[0] );
  230.    return s;
  231. }
  232.  
  233. char far *get_str_node_adr(ipx_adr_struct far *adr)
  234. {
  235.    static char s[14];
  236.    sprintf(s, "%02x%02x%02x%02x%02x%02x", 
  237.       adr->nodeadd[5],
  238.       adr->nodeadd[4],
  239.       adr->nodeadd[3],
  240.       adr->nodeadd[2],
  241.       adr->nodeadd[1],
  242.       adr->nodeadd[0] );
  243.    return s;
  244. }
  245.  
  246. ipx_header_struct far *ipx_get_header(ipx_adr_struct far *dest,
  247.    unsigned short dest_socket, unsigned short source_socket)
  248. {
  249.    static ipx_header_struct head;
  250.    head.checksum = 0;
  251.    head.length = 0;
  252.    head.tc = 0;
  253.    head.type = 4;      // packet exchange packet, see ralf brown's intlist
  254.    if ( dest == NULL )
  255.    {
  256.       head.dest.netadd[3] = 0;
  257.       head.dest.netadd[2] = 0;
  258.       head.dest.netadd[1] = 0;
  259.       head.dest.netadd[0] = 0;
  260.       head.dest.nodeadd[5] = 0x0ff;
  261.       head.dest.nodeadd[4] = 0x0ff;
  262.       head.dest.nodeadd[3] = 0x0ff;
  263.       head.dest.nodeadd[2] = 0x0ff;
  264.       head.dest.nodeadd[1] = 0x0ff;
  265.       head.dest.nodeadd[0] = 0x0ff;
  266.    }
  267.    else
  268.    {
  269.       head.dest = *dest;
  270.    }
  271.    head.source = *ipx_get_local_net_number();
  272.    head.dest.socket = reverse_word(dest_socket);
  273.    head.source.socket = reverse_word(source_socket);
  274.    return &head;
  275. }
  276.  
  277. char *ipx_get_ecb_inuse_string(ipx_ecb_struct far *ecb)
  278. {
  279.    static char s[80];
  280.    switch(ecb->inuse)
  281.    {
  282.       case 0x0000: strcpy(s, "available");                     break;
  283.       case 0x00E0: strcpy(s, "AES temporary");                 break;
  284.       case 0x00F6: strcpy(s, "special IPX/SPX processing");    break;
  285.       case 0x00F7: strcpy(s, "special IPX/SPX processing");    break;
  286.       case 0x00F8: strcpy(s, "IPX in critical section");       break;
  287.       case 0x00F9: strcpy(s, "SPX listening");                 break;
  288.       case 0x00FA: strcpy(s, "processing");                    break;
  289.       case 0x00FB: strcpy(s, "holding");                       break;
  290.       case 0x00FC: strcpy(s, "AES waiting");                   break;
  291.       case 0x00FD: strcpy(s, "AES counting down delay time");  break;
  292.       case 0x00FE: strcpy(s, "awaiting packet reception");     break;
  293.       case 0x00FF: strcpy(s, "sending packet");                break;
  294.       default:
  295.          strcpy(s, "unknown ecb state");
  296.    }
  297.    return (char *)s;
  298. }
  299.  
  300. char *ipx_get_ecb_cc_string(ipx_ecb_struct far *ecb)
  301. {
  302.    static char s[80];
  303.    switch(ecb->cc)
  304.    {
  305.       case 0x0000:
  306.          strcpy(s, "success");
  307.          break;
  308.       case 0x00EC:
  309.          strcpy(s, "remote terminated connection without acknowledging packet");
  310.          break;
  311.       case 0x00ED:
  312.          strcpy(s, "abnormal connection termination");
  313.          break;
  314.       case 0x00EE:
  315.          strcpy(s, "invalid connection ID");
  316.          break;
  317.       case 0x00EF:
  318.          strcpy(s, "SPX connection table full");
  319.          break;
  320.       case 0x00F9:
  321.          strcpy(s, "event should not be cancelled");
  322.          break;
  323.       case 0x00FA:
  324.          strcpy(s, "cannot establish connection with specified destination");
  325.          break;
  326.       case 0x00FC:
  327.          strcpy(s, "cancelled");
  328.          break;
  329.       case 0x00FD:
  330.          strcpy(s, "malformed packet");
  331.          break;
  332.       case 0x00FE:
  333.          strcpy(s, "packet undeliverable");
  334.          break;
  335.       case 0x00FF:
  336.          strcpy(s, "physical error or wrong socket");
  337.          break;
  338.       default:
  339.          strcpy(s, "unknown ecb completion code");
  340.    }
  341.    return (char *)s;
  342. }
  343.  
  344. ipx_ecb_struct far *ipx_fill_send_ecb(ipx_ecb_struct far *ecb,
  345.    ipx_header_struct far *head, void far *data, unsigned short size)
  346. {
  347.    if ( head == NULL )
  348.       return NULL;
  349.    if ( data == NULL )
  350.       return NULL;
  351.  
  352.    ecb->head = *head;
  353.    ecb->linkaddress = NULL;
  354.    ecb->esraddress = NULL;
  355.    ecb->inuse = 0;                    /* In-Use Status */
  356.    ecb->cc = 11;                      /* Completion Flag */
  357.    ecb->socket = head->dest.socket;   /* destination socket */
  358.    ecb->immedaddr[0] = ecb->head.dest.nodeadd[0];
  359.    ecb->immedaddr[1] = ecb->head.dest.nodeadd[1];
  360.    ecb->immedaddr[2] = ecb->head.dest.nodeadd[2];
  361.    ecb->immedaddr[3] = ecb->head.dest.nodeadd[3];
  362.    ecb->immedaddr[4] = ecb->head.dest.nodeadd[4];
  363.    ecb->immedaddr[5] = ecb->head.dest.nodeadd[5];
  364.    ecb->fragcount = 2;                /* we always have ipx header and data */
  365.    ecb->fragaddr1 = &(ecb->head);
  366.    ecb->fragsize1 = (unsigned short)sizeof(ipx_header_struct);
  367.    ecb->fragaddr2 = data;
  368.    ecb->fragsize2 = size;
  369.    return ecb;
  370. }
  371.  
  372. ipx_ecb_struct far *ipx_get_send_ecb(ipx_header_struct far *head, void far *data, unsigned short size)
  373. {
  374.    static ipx_ecb_struct ecb;
  375.    return ipx_fill_send_ecb(&ecb, head, data, size);
  376. }
  377.  
  378. ipx_ecb_struct far *ipx_fill_receive_ecb(ipx_ecb_struct far *ecb,
  379.    unsigned short socket, void far *data, unsigned short size)
  380. {
  381.    if ( data == NULL )
  382.       return NULL;
  383.  
  384.    ecb->linkaddress = NULL;
  385.    ecb->esraddress = NULL;
  386.    ecb->inuse = 0;                    /* In-Use Status (available) */
  387.    ecb->cc = 0;                       /* Completion Flag */
  388.    ecb->socket = reverse_word(socket);
  389.    ecb->fragcount = 2;                /* we always have ipx header and data */
  390.    ecb->fragaddr1 = &(ecb->head);
  391.    ecb->fragsize1 = (unsigned short)sizeof(ipx_header_struct);
  392.    ecb->fragaddr2 = data;
  393.    ecb->fragsize2 = size;
  394.    return ecb;
  395. }
  396.  
  397. ipx_ecb_struct far *ipx_get_receive_ecb(unsigned short socket, void far *data, unsigned short size)
  398. {
  399.    static ipx_ecb_struct ecb;
  400.    return ipx_fill_receive_ecb(&ecb, socket, data, size);
  401. }
  402.  
  403. #ifdef CREATE_MONITOR
  404.  
  405. #define IPX_MONITOR_SIZE 80
  406.  
  407. #include <conio.h>
  408. void monitor(unsigned short socket)
  409. {
  410.    ipx_ecb_struct far *ecb;
  411.    unsigned char data[IPX_MONITOR_SIZE];
  412.  
  413.    if ( ipx_init() == 0 )
  414.    {
  415.       puts("kein ipx vorhanden");
  416.       return;
  417.    }
  418.    printf("ipx_entry: %lx\n", ipx_entry);
  419.    printf("net-adr: %s\n", get_str_net_adr(ipx_get_local_net_number()));
  420.    printf("node-adr: %s\n", get_str_node_adr(ipx_get_local_net_number()));
  421.  
  422.    switch(ipx_open_socket(socket))
  423.    {
  424.       case 0x0fe:
  425.          puts("socket table full");
  426.          return;
  427.       case 0x0ff:
  428.          puts("socket open");
  429.          return;
  430.    }
  431.    printf("socket: %d\n", socket);
  432.  
  433.    for(;;)
  434.    {
  435.  
  436.       ecb = ipx_get_receive_ecb(socket, (void far *)data, IPX_MONITOR_SIZE);
  437.       if ( ecb == NULL )
  438.       {
  439.          puts("cannot generate ecb");
  440.          return;
  441.       }
  442.  
  443.       if ( ipx_listen_ecb(ecb) == 0 )
  444.       {
  445.          puts("cannot listen to ecb");
  446.          ipx_close_socket(socket);
  447.          return;
  448.       }
  449.  
  450.       for(;;)
  451.       {
  452.          if ( kbhit() != 0 )
  453.             break;
  454.          if ( ipx_is_ecb_in_use(ecb) == 0 )
  455.          {  
  456.             printf("received packet\n");
  457.             printf("inuse:    %s                        \n", 
  458.                ipx_get_ecb_inuse_string(ecb));
  459.             printf("cc:       %s\n", ipx_get_ecb_cc_string(ecb));
  460.             printf("socket:   %d\n", reverse_word(ecb->socket));
  461.             printf("dest net-adr:    %s\n",  get_str_net_adr(&(ecb->head.dest  )));
  462.             printf("dest node-adr:   %s\n", get_str_node_adr(&(ecb->head.dest  )));
  463.             printf("dest socket:     %d\n", reverse_word(ecb->head.dest.socket));
  464.             printf("source net-adr:  %s\n",  get_str_net_adr(&(ecb->head.source)));
  465.             printf("source node-adr: %s\n", get_str_node_adr(&(ecb->head.source)));
  466.             printf("source socket:   %d\n", reverse_word(ecb->head.source.socket));
  467.             break;
  468.          }
  469.          else
  470.          {
  471.             printf("inuse:    %s                       \r", 
  472.                ipx_get_ecb_inuse_string(ecb));
  473.          }
  474.       }
  475.       if ( kbhit() != 0 )
  476.       {
  477.          getch();
  478.          break;
  479.       }
  480.    }
  481.  
  482.    ipx_close_socket(socket);
  483. }
  484.  
  485. int xmain(void)
  486. {
  487.    monitor(2007); 
  488.    /* monitor(2000); */
  489.    return 0;
  490. }
  491.  
  492. void ymain(void)
  493. {
  494.    ipx_ecb_struct far *ecb;
  495.    if ( ipx_init() == 0 )
  496.    {
  497.       puts("kein ipx vorhanden");
  498.       return;
  499.    }
  500.    printf("ipx_entry: %lx\n", ipx_entry);
  501.    printf("net-adr: %s\n", get_str_net_adr(ipx_get_local_net_number()));
  502.    printf("node-adr: %s\n", get_str_node_adr(ipx_get_local_net_number()));
  503.  
  504.    ecb = ipx_get_send_ecb(ipx_get_header(NULL, 2417, 2419), " ", 2);
  505.    printf("<%d,%d>", ecb->inuse, ecb->cc);
  506.    ipx_send_ecb(ecb);
  507.    printf("<%d,%d>", ecb->inuse, ecb->cc);
  508.    while ( ipx_is_ecb_in_use(ecb) != 0 )
  509.    {
  510.       printf("<%d,%d>", ecb->inuse, ecb->cc);
  511.       if ( kbhit() != 0 )
  512.          break;
  513.    }
  514.    printf("<%d,%d>", ecb->inuse, ecb->cc);
  515. }
  516.  
  517. #endif
  518.  
  519. #ifdef CREATE_SOCKET_FREE
  520. int main(int argc, char *argv[])
  521. {
  522.    if ( argc < 2 )
  523.    {
  524.       puts("sfree socket-number");
  525.       return 1;
  526.    }
  527.    if ( ipx_init() == 0 )
  528.    {
  529.       puts("no ipx found");
  530.       return 1;
  531.    }
  532.    printf("close socket %d\n", atoi(argv[1]));
  533.    ipx_close_socket((short)atoi(argv[1]));
  534.    return 0;
  535. }
  536. #endif
  537.