home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / NCSA / TEL2307S.ZIP / NET / ENET / LTALK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-22  |  21.3 KB  |  765 lines

  1. /*
  2.  * National Center for Supercomputing Applications (NCSA) Telnet source code
  3.  *
  4.  * February 10, 1989
  5.  * (C) Copyright 1989 Planning Research Corporation
  6.  *
  7.  * Permission is granted to any individual or institution to use, copy,
  8.  * modify, or redistribute this software and its documentation provided this
  9.  * notice and the copyright notices are retained.  This software may not be
  10.  * distributed for profit, either in original form or in derivative works.
  11.  * Planning Research Corporation makes no representations about the
  12.  * suitability of this software for any purpose.
  13.  *
  14.  * PLANNING RESEARCH CORPORATION GIVES NO WARRANTY, EITHER EXPRESS OR IMPLIED,
  15.  * FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT
  16.  * LIMITATION, WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A
  17.  * PARTICULAR PURPOSE.
  18.  */
  19.  
  20. /*
  21.  * Revision History:
  22.  *
  23.  * Date            Initials        Comment
  24.  * ----            --------        -------
  25.  * 02-10-89        JGN@PRC            Initial version.
  26.  * 03-04-89     TKK@NCSA        KIP code added.
  27.  * 10-20-90        QAK@NCSA        Twiddled for version 2.3
  28.  *
  29.  * Initials        Name            Organization
  30.  * --------        ----            ------------
  31.  * JGN@PRC        Jim Noble        Planning Research Corporation
  32.  * TKK@NCSA     Tim Krauskopf    National Center for Supercomputing Applications
  33.  * QAK@NCSA        Quincey Koziol    National Center for Supercomputing Applications
  34.  *
  35. */
  36.  
  37. #define KIPPER
  38. #define LTALK_MASTER
  39.  
  40. #if defined(MSC) && !defined(__TURBOC__)
  41. #define movmem(from,to,len)    memmove(to,from,len)
  42. #endif
  43.  
  44. #include <dos.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #ifdef MSC
  49. #ifdef __TURBOC__
  50. #include <mem.h>
  51. #include <alloc.h>
  52. #else
  53. #include <malloc.h>
  54. #endif
  55. #endif
  56. #include "protocol.h"
  57. #include "data.h"
  58. #include "ltalk.h"
  59. #ifdef KIPPER
  60. #include "kip.h"
  61. #endif
  62. #include "externs.h"
  63.  
  64. struct at_vector {
  65.     char name[9];
  66.     unsigned char    vers_minor,
  67.         vers_major,
  68.         driver_type,
  69.         reserved[4];
  70. };
  71.  
  72. extern unsigned char rstat;        /* last status from read */
  73. extern char *buforg;    /* pointer to beginning of buffer space */
  74. extern char *bufend;    /* pointer to end of buffer space (like EOT mark) */
  75. extern char *bufread;    /* pointer to packet program is working on */
  76. extern char *bufpt;        /* pointer to space for next packet */
  77. extern int   buflim;    /* number of useable bytes in buffer space */
  78. extern int   bufbig;    /* number of bytes in use in buffer space */
  79.  
  80. extern listen1();        /* ASM part of first-half DDP socket listener */
  81.  
  82. unsigned listen_ds;        /* Allows the ASM part of the socket listeners to */
  83.                         /* determine the data segment of the C part of the */
  84.                         /* socket listeners */
  85.  
  86. unsigned int LTalk_vector;    /* Interrupt vector to use to make AppleTalk driver calls */
  87.  
  88. static char ltinit=0,        /* has this driver been initialized yet? */
  89.         KIPzone[32]={"*"},    /* the zone to send KIP queries to */
  90.         *entity;            /* storage for entities to pass to driver */
  91. #ifdef KIPPER
  92. static IPGP    *gatedata;        /* configuration record to/from KIP server */
  93. #endif
  94. static BDSElement *bds;        /* buffer list for ATP request */
  95. static ATPParams *atp_pb;    /* ATP request parameter block */
  96. static NBPTabEntry mynbp;    /* storage for my own MBP registration */
  97. static NBPParams *nbp_pb;    /* NBP parameter block */
  98. extern int nnkip;            /* are we running KIP? */
  99.  
  100. static AddrBlk myaddr;        /* my network, node, socket */
  101. static ATARPKT arpbuffer;    /* alternate format for arps req'd for LocalTalk */
  102.  
  103. #define SHOW_MESSAGE        1        /* Display LTalk_call error messages */
  104. #define HIDE_MESSAGE        0        /* Don't display LTalk_call error messages */
  105. #define LTIP                22        /* DDP protocol type for IP */
  106. #define LTARP                23        /* DDP protocol type for ARP */
  107. #define IPSock                72        /* DDP socket for LocalTalk */
  108.  
  109. #define MAX_ADDR_TRIES        100        /* Maximum tries to get the addres */
  110.  
  111. static void    LTalk_error (char *caller,int status);        /* Displays AppleTalk driver error messages */
  112. static int LTalk_call(InfoParams *pb,char *caller,int display);    /* Makes AppleTalk driver calls */
  113.  
  114. /*
  115.  * LTalk_error
  116.  *
  117.  * Display an AppleTalk driver error message.
  118.  */
  119. static void LTalk_error(char *caller,int status)
  120. {
  121.     fputs(caller,stderr);
  122.     fputs(":  ", stderr);
  123.  
  124.     switch(status) {    /* Provide text for the errors that we might get */
  125.         case ATNOTINITIALIZED:
  126.             fputs("AppleTalk driver not initialized.",stderr);
  127.             break;
  128.  
  129.         case BAD_PARAMETER:
  130.             fputs("Illegal parameter or parameters.",stderr);
  131.             break;
  132.  
  133.         case BAD_SYNC_CALL:
  134.             fputs("Synchronous command was called at a time when the driver cannot handle it.",stderr);
  135.             break;
  136.  
  137.         case CALLNOTSUPPORTED:
  138.             fputs("Requested call not supported.",stderr);
  139.             break;
  140.  
  141.         case DDP_CANCELLED:
  142.             fputs("DDP transaction cancelled.",stderr);
  143.             break;
  144.  
  145.         case DDP_LENERR:
  146.             fputs("DDP data too long.",stderr);
  147.             break;
  148.  
  149.         case DDP_SKTERR:
  150.             fputs("Used unopen socket.",stderr);
  151.             break;
  152.  
  153.         case HARDWARE_ERROR:
  154.             fputs("Unrecoverable hardware error.",stderr);
  155.             break;
  156.  
  157.         case MAXCOLISERR:
  158.             fputs("Too many collisions detected.",stderr);
  159.             break;
  160.  
  161.         case MAXDEFERERR:
  162.             fputs("32 deferrals encountered (ALAP).",stderr);
  163.             break;
  164.  
  165.         case MEMORY_CORRUPTED:
  166.             fputs("Internal memory pool corrupted.  Reload driver.",stderr);
  167.             break;
  168.  
  169.         case NOBRDGERR:
  170.             fputs("No bridge found.",stderr);
  171.             break;
  172.  
  173.         case NO_MEM_ERROR:
  174.             fputs("Not enough memory to perform requested operation.",stderr);
  175.             break;
  176.  
  177.         case SOFTWARE_ERROR:
  178.             fputs("Internal software error.  Reinitialize driver.",stderr);
  179.             break;
  180.  
  181.         case STACKERROR:
  182.             fputs("Too many levels of nesting to complete call.",stderr);
  183.             break;
  184.  
  185.         default:    /* Handle anything else that might come up */
  186.             fprintf(stderr,"Unknown AppleTalk driver error %d.",status);
  187.       }    /* end switch */
  188.     fputs("\n",stderr);
  189. }    /* end LTalk_error() */
  190.  
  191. /*
  192.  * LTalk_call
  193.  *
  194.  * Make an AppleTalk driver call.  Return the driver error code.
  195.  */
  196. static int LTalk_call(InfoParams *pb,char *caller,int display)
  197. {
  198.     union REGS    rgisters;
  199.     struct SREGS    segments;
  200.     int        status;
  201.  
  202.     rgisters.x.bx=FP_OFF(pb);
  203.     segments.ds=FP_SEG(pb);
  204.     int86x(LTalk_vector,&rgisters,&rgisters,&segments);
  205.     status=pb->atd_status;
  206.     if(status!=NOERR && display)
  207.         LTalk_error(caller,status);
  208.     return status;
  209. }    /* end LTalk_call() */
  210.  
  211. /*
  212.  * LTopen
  213.  *
  214.  * Check if AppleTalk driver is installed, initialize driver, open DDP socket
  215.  * for IP packets, fill in network address parameter ('s') and return.  The
  216.  * return value is 0 if successful and a non-zero driver error code if
  217.  * something failed.  On entry the 'irq' parameter contains the 'interrupt=xx'
  218.  * value from the configuration file and specifies the interrupt to use when
  219.  * making driver calls.  The 'addr' and 'ioaddr' parameters are unused by this
  220.  * routine.
  221.  */
  222. int CDECL LTopen(AddrBlk *s,unsigned int irq,unsigned int addr,unsigned int ioaddr)
  223. {
  224.     char        buffr[100];
  225.     char        buffr2[100];
  226.     DDPParams    ddp_pb;
  227.     InfoParams    info_pb;
  228.     struct SREGS segregs;
  229.     int            status;
  230.     int         count;        /* counter for the number of tries to get the address */
  231.  
  232.     if(ltinit)                                /* we are initialized already */
  233.         return(0);
  234.  
  235.     /* Interrupt vector to use to make AppleTalk driver calls */
  236.     LTalk_vector=irq;
  237.  
  238.     if(strncmp("AppleTalk",(*((char **)((unsigned long)(LTalk_vector*4))))-16,9))
  239.     {
  240.         status=ATNOTINITIALIZED;
  241.         LTalk_error("LTopen",status);
  242.         fputs("...AppleTalk driver not installed\n",stderr);
  243.         return(status);
  244.     }    /* end if */
  245.  
  246.     /* Initialize AppleTalk driver */
  247.     info_pb.atd_command=ATInit;
  248.     info_pb.atd_compfun=(CPTR) 0;
  249.     info_pb.inf_nodeid=0;
  250.  
  251.     status=LTalk_call(&info_pb,"LTopen",SHOW_MESSAGE);
  252.     if(status!=NOERR)
  253.         return(status);
  254.  
  255.     ltinit=1;                                /* flag we are open */
  256.  
  257.     /*
  258.      * Store current DS register in listen_ds so that listen1 and listen2
  259.      * (asm) can set DS register before calling listen1_c and listen2_c (C).
  260.      */
  261.     segread(&segregs);
  262.     listen_ds=segregs.ds;
  263.  
  264.     /* Open a DDP socket */
  265.     ddp_pb.atd_command=DDPOpenSocket;
  266.     ddp_pb.atd_compfun=(CPTR) 0;
  267.     ddp_pb.ddp_socket=IPSock;        /* we use 72 like everyone else */
  268.     ddp_pb.ddp_bptr=(DPTR)listen1;    /* interrupt listener */
  269.  
  270.     status=LTalk_call((InfoParams *)&ddp_pb,"LTopen",SHOW_MESSAGE);
  271.     if(status!=NOERR)
  272.         return(status);
  273.  
  274.     myaddr.socket=ddp_pb.ddp_socket;    /* keep a copy, always=72 */
  275.  
  276. /*
  277. * Get the AppleTalk network and node numbers
  278. * Store a copy of the values in our structure for use by other routines.
  279. */
  280.     info_pb.atd_command=ATGetNetInfo;
  281.     info_pb.atd_status=-1;
  282.     info_pb.atd_compfun=NULL;
  283.     info_pb.inf_bptr=NULL;
  284.     info_pb.inf_buffsize=0;
  285.  
  286.     /* repeat this a few times if the network returns 0 */
  287.     for(count=0; count<MAX_ADDR_TRIES; count++) {
  288.         status=LTalk_call(&info_pb,"LTgetaddr",SHOW_MESSAGE);
  289.         if(status!=NOERR) {
  290.             myaddr.network=0;
  291.             myaddr.nodeid=0;
  292.             status=ATNOTINITIALIZED;
  293.             return(status);
  294.           }    /* end if */
  295.         else {
  296.             myaddr.network=info_pb.inf_network;
  297.             myaddr.nodeid=info_pb.inf_nodeid;
  298.           }    /* end else */
  299.         if(myaddr.network!=0)
  300.             break;
  301.       }    /* end for */
  302.     if(myaddr.network==0) {
  303.         sprintf(buffr2,"Error getting network number");
  304.         printf(buffr2);
  305. /*        n_puts(buffr2); */
  306.         return(-1);
  307.       }    /* end if */
  308.  
  309.     sprintf(buffr2,"Network: %u,  Node: %u",intswap(myaddr.network),myaddr.nodeid);
  310.     printf(buffr2);
  311. /*    n_puts(buffr2);*/
  312.  
  313.     broadaddr[0]=0;
  314.     broadaddr[1]=0;
  315.     broadaddr[2]=0xff;
  316.     broadaddr[3]=0x48;
  317.     bseed[0]=0;
  318.     bseed[1]=0;
  319.     bseed[2]=0xff;
  320.     bseed[3]=0x48;
  321.  
  322.  
  323. #ifdef KIPPER
  324.     if(nndto<1)            /* don't bother with KIP */
  325.         return(0);
  326.     if(nndto<2)            /* minimum value */
  327.         nndto=2;
  328.  
  329.     if(NULL==(entity=malloc(100)))
  330.         return(-1);
  331.     if(NULL==(nbp_pb=malloc(sizeof(NBPParams))))
  332.         return(-1);
  333.     if(NULL==(gatedata=malloc(sizeof(IPGP))))
  334.         return(-1);
  335.     if(NULL==(bds=malloc(sizeof(BDSElement))))
  336.         return(-1);
  337.     if(NULL==(atp_pb=malloc(sizeof(ATPParams))))
  338.         return(-1);
  339.  
  340.     nnkip=1;
  341.  
  342. /*
  343. *  Look for a KIP gateway with NBP
  344. */
  345.     sprintf(entity,"\001=\011IPGATEWAY%c%s",strlen(KIPzone),KIPzone);
  346.     sprintf(buffr,"%c%c%c%c",0,0,0,0);  /* set the buffer to 0 */
  347.  
  348.     nbp_pb->atd_command=NBPLookup;
  349.     nbp_pb->atd_compfun=NULL;
  350.     nbp_pb->nbp_toget=1;
  351.     nbp_pb->nbp_bptr=buffr;
  352.     nbp_pb->nbp_buffsize=100;
  353.     nbp_pb->nbp_interval=(unsigned char)(nndto/2);
  354.     nbp_pb->nbp_retry=3;
  355.     nbp_pb->nbp_entptr=entity;
  356.  
  357.     status=LTalk_call((InfoParams *)nbp_pb,"NBPLook",HIDE_MESSAGE);
  358.     if(status!=NOERR)
  359.         return(0);        /* cannot find KIP is not an error */
  360.     sprintf(buffr2,"IPGATEWAY at Net %u.%u Node %u Skt %u\n",
  361.         (int)(((unsigned char *)buffr)[0]),
  362.         (int)(((unsigned char *)buffr)[1]),
  363.         (int)(((unsigned char *)buffr)[2]),
  364.         (int)(((unsigned char *)buffr)[3]));
  365.     printf(buffr2);
  366. /*    n_puts(buffr2); */
  367.  
  368. /*
  369. *  get the parameters from the KIP server.
  370. *  This obtains a dynamically assigned IP address if it can get one.
  371. */
  372.     atp_pb->atd_command=ATPSndRequest;
  373.     atp_pb->atd_compfun=NULL;
  374.  
  375. #ifdef OLD_WAY
  376.     gatedata->opcode=longswap(1L);    /* Motorola byte order */
  377. #else
  378.     gatedata->opcode=0x1000000L;  /* Motorola byte order */
  379. #endif
  380.     gatedata->ipaddress=0;
  381.  
  382.     movmem(buffr,&atp_pb->atp_addr,sizeof(AddrBlk));
  383.     bds->bds_bptr=(DPTR)gatedata;
  384.     bds->bds_buffsize=sizeof(IPGP);
  385.     atp_pb->atp_bdsptr=bds;
  386.     atp_pb->atp_bptr=(DPTR)gatedata;
  387.     atp_pb->atp_buffsize=sizeof(IPGP);
  388.     atp_pb->atp_flags=32;
  389.     atp_pb->atp_interval=5;
  390.     atp_pb->atp_retry=5;
  391.     atp_pb->atp_bdsbuffs=1;
  392.  
  393.     status=LTalk_call((InfoParams *)atp_pb,"ATPget",SHOW_MESSAGE);
  394.     if(status!=NOERR)
  395.         return(status);
  396.  
  397. /*    if(longswap(gatedata->opcode)>0) */    /* if we didn't get an error */
  398.         netsetip((unsigned char *)&gatedata->ipaddress);    /* set the ipaddress */
  399. /*
  400. *  NBP register our IP number.
  401. *  We aren't allowed to register outside of our zone, so we don't
  402. *  use KIPzone in the entity.
  403. */
  404.     nbp_pb->atd_command=NBPRegister;
  405.     nbp_pb->atd_compfun=NULL;
  406.     nbp_pb->nbp_bptr=(DPTR)&mynbp;
  407.     nbp_pb->nbp_interval=1;
  408.     nbp_pb->nbp_retry=3;
  409.  
  410.     mynbp.tab_nxtentry=NULL;
  411.     mynbp.tab_tuple.tup_address.socket=72;
  412.     sprintf(buffr,"%d.%d.%d.%d",
  413.         (unsigned char)*((char *)&gatedata->ipaddress+0),
  414.         (unsigned char)*((char *)&gatedata->ipaddress+1),
  415.         (unsigned char)*((char *)&gatedata->ipaddress+2),
  416.         (unsigned char)*((char *)&gatedata->ipaddress+3));
  417.  
  418.     sprintf(mynbp.tab_tuple.tup_entname,"%c%s\011IPADDRESS\001*",strlen(buffr),buffr);
  419.  
  420.     status=LTalk_call((InfoParams *)nbp_pb,"NBPRegister",SHOW_MESSAGE);
  421.     if(status!=NOERR)
  422.         return(status);
  423. #endif
  424.     return (NOERR);
  425. }    /* end LTopen() */
  426.  
  427. /*
  428.  * LTgetaddr
  429.  *
  430.  * Return the AppleTalk network address in parameter 's'.  Parameters 'addr'
  431.  * and 'ioaddr' are unused by this routine.
  432.  */
  433. int CDECL LTgetaddr(AddrBlk *s,unsigned int addr,unsigned int ioaddr)
  434. {
  435.     int
  436. #ifdef NEW_WAY
  437.         count=10,
  438. #endif
  439.         open_status;
  440.  
  441.     s->network=0;
  442.     s->nodeid=0;
  443.     s->socket=0;
  444.  
  445. #ifdef NEW_WAY
  446.     while(count--) {
  447.         open_status=LTopen(s,LTalk_vector,addr,ioaddr);    /*  Make sure we are initialized */
  448.         if(open_status<0)
  449.             LTclose();
  450.         else
  451.             break;
  452.       }    /* end while */
  453. #else
  454.     open_status=LTopen(s,LTalk_vector,addr,ioaddr);
  455. #endif
  456.  
  457.     if(open_status<0)
  458.         return(1);
  459.  
  460.     s->network=myaddr.network;        /* copy from stored values */
  461.     s->nodeid=myaddr.nodeid;
  462.     s->socket=myaddr.socket;
  463.     return(0);
  464. }    /* end LTgetaddr() */
  465.  
  466. /*
  467.  * LTxmit
  468.  *
  469.  * Transmit IP packet at *ptr on DDP socket and return AppleTalk driver error
  470.  * code.  The return value is 0 for success and non-zero for failure.
  471.  * Ethernet packet types must be converted to DDP types.  The DLAYER header is
  472.  * not transmitted.
  473.  */
  474. int CDECL LTxmit(DLAYER *ptr,unsigned int size)
  475. {
  476.     DDPParams        ddp_pb;
  477.     int            status;
  478. /*
  479. *  First set up fields for xmit, if any of them have to change
  480. *  from the initial values, we'll change them.
  481. */
  482.     /* Transmit data (skipping DLAYER header) */
  483.     ddp_pb.atd_command=DDPWrite;
  484.     ddp_pb.atd_compfun=(CPTR) 0;
  485.     ddp_pb.ddp_addr=*((AddrBlk *)(ptr->dest));
  486.     ddp_pb.ddp_socket=IPSock;
  487.     ddp_pb.ddp_bptr=(char *)ptr+sizeof(DLAYER);
  488.     ddp_pb.ddp_buffsize=size-sizeof(DLAYER);
  489.     ddp_pb.ddp_chksum=0;
  490.  
  491.  
  492.     /* Convert packet type from Ethernet types to DDP types */
  493.     if(ptr->type==EIP)
  494.         ddp_pb.ddp_type=LTIP;
  495.     else if(ptr->type==EARP) {
  496.         ARPKT *aptr;
  497.  
  498.         ddp_pb.ddp_type=LTARP;
  499.         aptr=(ARPKT *)ptr;
  500. #ifdef OLD_WAY
  501.         arpbuffer.hrd=intswap(3);        /* appletalk == 3 */
  502. #else
  503.         arpbuffer.hrd=0x0300;            /* appletalk == 3 */
  504. #endif
  505.         arpbuffer.hln=4;            /* Ltalk length */
  506.         arpbuffer.pln=4;            /* IP length */
  507.         arpbuffer.pro=aptr->pro;        /* copy in command fields */
  508.         arpbuffer.op=aptr->op;
  509.  
  510.         movmem(aptr->sha,arpbuffer.sha,4);    /* re-align ARP fields */
  511.         movmem(aptr->spa,arpbuffer.spa,4);
  512.         movmem(aptr->tha,arpbuffer.tha,4);
  513.         movmem(aptr->tpa,arpbuffer.tpa,4);
  514.  
  515.         /* install new ARP format */
  516.           ddp_pb.ddp_bptr=((char *)&arpbuffer)+sizeof(ATdlayer);
  517.         ddp_pb.ddp_buffsize=sizeof(ATARPKT)-sizeof(ATdlayer);
  518.       }    /* end if */
  519.     status=LTalk_call((InfoParams *)&ddp_pb,"LTxmit",SHOW_MESSAGE);
  520.     return(status);
  521. }    /* end LTxmit() */
  522.  
  523. #ifdef KIPPER
  524. /******************************************************************/
  525. /* KIParp
  526. *  send the special KIParp request and return result.
  527. *  1=OK, less than zero=error.
  528. */
  529. int KIParp(unsigned char ipnum[4],AddrBlk *addrloc)
  530. {
  531.     char buffr[100];
  532.     int status;
  533.  
  534.     nbp_pb->atd_command=NBPLookup;
  535.     nbp_pb->atd_compfun=NULL;
  536.     nbp_pb->nbp_toget=1;
  537.     nbp_pb->nbp_bptr=buffr;
  538.     nbp_pb->nbp_buffsize=100;
  539.     nbp_pb->nbp_interval=1;
  540.     nbp_pb->nbp_retry=2;
  541.     nbp_pb->nbp_entptr=entity;
  542.  
  543.     sprintf(buffr,"%u.%u.%u.%u",ipnum[0],ipnum[1],ipnum[2],ipnum[3]);
  544.     sprintf(entity,"%c%s\011IPADDRESS%c%s",strlen(buffr),buffr,strlen(KIPzone),KIPzone);
  545.  
  546.     status=LTalk_call((InfoParams *)nbp_pb,"NBPFind",SHOW_MESSAGE);
  547.     if(status!=NOERR)
  548.         return(status);
  549.  
  550.     movmem(buffr,addrloc,4);        /* give back address */
  551.     return(1);
  552. }    /* end KIParp() */
  553.  
  554. #ifdef OLD_WAY
  555. /******************************************************************/
  556. /* KIPsetzone
  557. *  set the zone string for KIP lookups.
  558. */
  559. void KIPsetzone(char *s)
  560. {
  561.     strncpy(KIPzone,s,32);
  562.     KIPzone[31]='\0';
  563. }    /* end KIPsetzone() */
  564. #endif
  565. #endif
  566.  
  567. /*
  568.  * LTrecv
  569.  *
  570.  * Change DDP packet type of next packet in the queue to Ethernet packet type.
  571.  */
  572. void CDECL LTrecv(void )
  573. {
  574.     DLAYER        *dlptr;
  575.  
  576.     if(bufbig>0) {        /* Make DDP packet types look like Ethernet types */
  577.         dlptr=(DLAYER *) (bufread+sizeof(int));
  578.         if(dlptr->type==LTIP)
  579.             dlptr->type=EIP;
  580.         else if(dlptr->type==LTARP) {
  581. /*
  582. *  yes, I realize that this is an in-place modification of
  583. *  the packet buffer which lengthens it.  It is tricky, but it
  584. *  is planned that way.
  585. */
  586.             ARPKT *eptr;
  587.             ATARPKT *atptr;
  588.  
  589.             dlptr->type=EARP;
  590.             eptr=(ARPKT *)dlptr;
  591.             atptr=(ATARPKT *)dlptr;
  592. #ifdef OLD_WAY
  593.             eptr->hrd=intswap(1);    /* We are faking Ethernet */
  594. #else
  595.             eptr->hrd=0x0100;        /* We are faking Ethernet */
  596. #endif
  597.             eptr->hln=6;        /* Ethernet length */
  598.             eptr->pln=4;        /* IP length */
  599.             eptr->pro=atptr->pro;    /* copy in command fields */
  600.             eptr->op=atptr->op;
  601.             movmem(atptr->tpa,eptr->tpa,4);
  602.             movmem(atptr->tha,eptr->tha,4);
  603.             movmem(atptr->spa,eptr->spa,4);
  604.             movmem(atptr->sha,eptr->sha,4);    /* re-align ARP fields */
  605.             eptr->tha[4]=0;
  606.             eptr->tha[5]=0;
  607.             eptr->sha[4]=0;
  608.             eptr->sha[5]=0;
  609.           }    /* end if */
  610.       }    /* end if */
  611. }    /* end LTrecv() */
  612.  
  613. /*
  614.  * LTupdate
  615.  *
  616.  * Release next packet in the queue.
  617.  */
  618. void CDECL LTupdate(void )
  619. {
  620.     int    pkt_size;
  621.  
  622.     /* Adjust pointers to deallocate packet in buffer */
  623.     pkt_size=*((int *)bufread)+sizeof(int);
  624.  
  625. /* printf("s: %d, r: %ld, q: %d\n",pkt_size,(long)bufread,bufbig); */
  626.  
  627.     bufread+=pkt_size;
  628.     if(bufread>=bufend)
  629.         bufread=buforg;
  630.     bufbig -= pkt_size;
  631. }    /* end LTupdate() */
  632.  
  633. /*
  634.  * LTclose
  635.  *
  636.  * Close the DDP socket for IP packets.
  637.  */
  638. int CDECL LTclose(void)
  639. {
  640.     DDPParams        ddp_pb;
  641.  
  642.     if(nnkip) {
  643.         nbp_pb->atd_command=NBPRemove;
  644.         nbp_pb->atd_compfun=NULL;
  645.         nbp_pb->nbp_entptr=mynbp.tab_tuple.tup_entname;
  646.         nbp_pb->nbp_interval=1;
  647.         nbp_pb->nbp_retry=3;
  648.  
  649.         LTalk_call((InfoParams *)nbp_pb,"NBPRemove",SHOW_MESSAGE);
  650.       }    /* end if */
  651.  
  652.     /* Close the DDP socket */
  653.     ddp_pb.atd_command=DDPCloseSocket;
  654.     ddp_pb.atd_compfun=(CPTR) 0;
  655.     ddp_pb.ddp_socket=IPSock;
  656.  
  657.     LTalk_call((InfoParams *)&ddp_pb,"LTclose",SHOW_MESSAGE);
  658.     return(0);
  659. }    /* end LTclose() */
  660.  
  661. /*
  662.  * First-half DDP socket listener (C part)
  663.  *
  664.  * The first-half of the listener is called with the following inputs:
  665.  *
  666.  *         socket        Socket
  667.  *         datalen        Length of data
  668.  *         header        Pointer to (LAP & DDP) header
  669.  *
  670.  * The first-half of the listener must decide whether to keep or discard the
  671.  * data.  If the packet is to be discarded, the first-half listener must return
  672.  * with *bufflen equal to zero; in this case, the second-half of the listener
  673.  * will not be called.
  674.  *
  675.  * If the data is to be retained, the first-half listener must return with
  676.  * the following values:
  677.  *
  678.  *         *bptr Pointer to buffer for packet data
  679.  *         *bufflen Size of the buffer at *bptr
  680.  */
  681.  
  682. /* #pragma check_stack (off) */
  683.  
  684. void CDECL listen1_c(unsigned char socket,unsigned int datalen,unsigned char header[],unsigned int *bufflen,unsigned char *bptr[])
  685. {
  686.     static unsigned char    DDP_type,nethi,netlo,sock,nodeid;
  687.     static DLAYER            *dlptr;
  688.     static int                *intptr;
  689.  
  690.     *bufflen=0;                    /* Reject packet initially */
  691.     if(socket==IPSock) {        /* Is it for our socket? */
  692.                         /* Yes... */
  693.         if(header[2]==1) {            /* Get the DDP Protocol Type field */
  694.             DDP_type=header[7];        /* Short format DDP header */
  695.             nethi=(unsigned char)*(((char *)(unsigned long)myaddr.network)+1);
  696.             netlo=(unsigned char)*((char *)(unsigned long)myaddr.network);
  697.             nodeid=myaddr.nodeid;
  698.             sock=header[6];
  699.           }    /* end if */
  700.         else if(header[2]==2) {
  701.             DDP_type=header[15];           /* Long format DDP header */
  702.             nethi=header[9];
  703.             netlo=header[10];
  704.             nodeid=header[12];
  705.             sock=header[14];
  706.           }    /* end if */
  707.         else
  708.             DDP_type=0;            /* Not DDP packet; reject it */
  709.         if(DDP_type==LTIP || DDP_type==LTARP) { /* Is it an IP or ARP packet? */
  710.                         /* Yes... */
  711.             unsigned char *p;
  712.  
  713.             datalen+=4;            /* leave room for play */
  714.             if(bufbig<=buflim) {        /* Is there room in the buffer? */
  715.                     /* Yes... */
  716.                 *bufflen=datalen;    /* Accept whole packet */
  717.                 if(bufend<=bufpt)
  718.                     bufpt=buforg;
  719.                 intptr=(int *)bufpt;              /* Put packet at bufpt */
  720.                 *intptr=datalen+sizeof(DLAYER); /* Size of packet plus
  721.                                                         dummy DLAYER header */
  722.                 dlptr=(DLAYER *)++intptr;
  723.                 p=(char *)dlptr;
  724.                 dlptr->type=DDP_type;              /* Remember packet type */
  725.                 *bptr=(char *)++dlptr;        /* Put IP packet after dummy
  726.                                                    DLAYER header */
  727.                 /*  fill in addresses */
  728.                 *p++=(unsigned char)(myaddr.network&0xff);
  729.                 *p++=(unsigned char)(myaddr.network>>8);
  730.                 *p++=myaddr.nodeid;
  731.                 *p++=myaddr.socket;
  732.                 *p++=0;
  733.                 *p++=0;
  734.                 *p++=netlo;        /* fake src address */
  735.                 *p++=nethi;
  736.                 *p++=nodeid;
  737.                 *p++=sock;
  738.                 *p++=0;
  739.                 *p++=0;
  740.               }    /* end if */
  741.           }    /* end if */
  742.       }    /* end if */
  743. }    /* end listen1_c() */
  744.  
  745. /*
  746.  * Second-half DDP socket listener (C part)
  747.  *
  748.  * The second-half of the listener is called (through a FAR CALL) with
  749.  * the following inputs:
  750.  *
  751.  *         bptr        Pointer to buffer containing data
  752.  *         bufflen    Number of bytes of data in buffer at bptr
  753.  *
  754.  * The second-half listener may enable interrupts, and should exit with a FAR
  755.  * RETURN.
  756.  */
  757. void CDECL listen2_c(unsigned int bufflen,DLAYER *bptr)
  758. {
  759.     /* Calculate total size of new packet, leave 4 for good measure */
  760.  
  761.     bufflen+=sizeof(DLAYER)+sizeof(int)+4;
  762.     bufpt=&bufpt[bufflen];    /* Add total packet size to bufpt and bufbig */
  763.     bufbig+=bufflen;
  764. }    /* end listen2_c() */
  765.