BBN-V6/telnet/tcplib.c

#
# include "tcpstru.h"
# include "tcp.h"


/* misc constants */
# define MAXDATA        256     /* maximum port message data area */
# define NUMBCONNS      10      /* maximum number of connections/proc */

/* data declarations */

struct PortLdr PortHdr;

char CmdUsrName[]   CMDUSRNM;   /* user cmd port name */
char CmdTcpName[]   CMDTCPNM;   /* tcp cmd port name */
char SendName[]     SENDNM;     /* send data port name */
char RecvName[]     RECVNM;     /* recv data port name */

char CmdTcp[CMDTCPSIZE];      /* tcp command out buffer */
char CmdUsr[CMDUSRSIZE];      /* user command out buffer */

struct                     /* structure used to decompose long int */
{  int bb[2];
 } *p;


int CmdUsrFds;   /* fdesc for user cmd port */
int CmdTcpFds;  /* fdesc for tcp cmd port */

extern int errno;    /* system error number */
int tm[3];        /* used for qtime */

struct UserTcb ConnBlock[NUMBCONNS];


/* Library subroutines */

TcpInit(TimeOut)
int TimeOut;
{  int i;
   int ProcID;
   int EarFds;
   int Error;
   int More;
   struct PMask1 *InitPtr;
   struct PMask1 *AckPtr;
   struct PMask1 *ErrPtr;

   /* reset the ConnBlocks */
   for (i = 0;i < NUMBCONNS;i++)
   {  ConnBlock[i].ConnIndex = 0;
    }


   EarFds = open(EAR,1);
   if (EarFds == -1)
   {  /* can't find ear port */
      return(EEARPRT);
    }

   /* derive tcp <=> lib port names */
   ProcID = getpid();   /* get my process id */
   for (i = PRTPREFIX+2;i > PRTPREFIX-1; i--)
   {  CmdTcpName[i] = '0' + (ProcID&07);
      CmdUsrName[i] = '0' + (ProcID&07);
      SendName[i] = '0' + (ProcID&07);
      RecvName[i] = '0' + (ProcID&07);
      ProcID =>> 3;
    }
   unlink(CmdTcpName);
   CmdTcpFds = port(CmdTcpName,0170222,0);
   if (CmdTcpFds == -1)
   {  /* can't create tcp command port */
      close(EarFds);    /* for the retry */
      return(ERSPPRT);
    }

   /* send a listen down the ear */
   InitPtr = CmdUsr;
   InitPtr -> YOpCode = OINIT;
   write(EarFds,CmdUsr,2);
   /* wait for response from TCP */
   Error = ReadCmd(TimeOut);
   if (Error != 0)
   {  /* Something wrong */
      close(EarFds);    /* for the retry */
      close(CmdTcpFds);    /* for the retry */
      return(Error);
    }
   close(EarFds);       /* close the ear port */
   AckPtr = CmdTcp;
   switch(AckPtr -> YOpCode)
   {  case OERR:
      {  /* error from tcp */
         return(ErrPtr -> YMisc);
       }
      case OACK:

      {  CmdUsrFds = open(CmdUsrName,1);   /* open the user command port */
         if (CmdUsrFds == -1)
         {  /* no user command port */
            close(EarFds);    /* for the retry */
            close(CmdTcpFds);    /* for the retry */
            return(ECMDPRT);
          }

         unlink(CmdUsrName);
         unlink(CmdTcpName);

         return(0);
       }
    }
 }


TcpQuit()
{  int i;
   int Error;


   /* disable wakeups on command ports */
   awtdis(CmdUsrFds);
   awtdis(CmdTcpFds);

   /* search down UserTcb's for active connections */
   for (i = 0; i < NUMBCONNS; i++)
   {  if (ConnBlock[i].ConnIndex != 0)
      {  /* found an active connection block */

         ConnBlock[i].ConnIndex = 0;

       }
    }
   /* close out command ports */
   close(CmdUsrFds);
   close(CmdTcpFds);
 }



TcpOpen(CABPtr, ConnPtr, Mode, TimeOut)
struct CAB *CABPtr;
int *ConnPtr;
int Mode;
int TimeOut;

{  int Fdesc;
   int More;
   int i;
   int j;
   int Error;
   int Found;
   int Index;
   struct UserTcb *x;
   struct PMask1 *AckPtr;
   struct PMask1 *ErrPtr;
   struct MOpen *OpenPtr;


   if (CABPtr -> TccCnt > NUMBTCC)
   {  /* too many */
      return(EBADPARAM);
    }

   if (Mode > 2)
   {  /* illegal mode */
      return(EBADPARAM);
    }

   /* find an unused ConnBlock */
   Found = 0;
   Index = 0;
   while ((Index < NUMBCONNS)&&(Found == 0))
   {  if (ConnBlock[Index].ConnIndex == 0)
      {  Found = 1;
       }
      else
      {  Index++;
       }
    }
   if (Found == 0)
   {  /* too many connections for this process */
      return(EUSRC);
    }

   x = *ConnPtr = &ConnBlock[Index];   /* give user ptr to ConnBlock */

   /* initialize the UserTcb */
   x -> CNFlags = 0;
   x -> CNState = 0;
   x -> CNPrec = 0;
   x -> CNMsg = 0;
   x -> ResidData = 0;
   x -> SendCapac = 0;
   x -> RecvCapac = 0;
   x -> SndCount = 0;
   x -> RcvCount = 0;
   x -> UrgCount = 0;

   ConnBlock[Index].CmdFds = CmdTcpFds;   /* enter tcp command port fds */

   OpenPtr = CmdUsr;    /* inz the open mask ptr */

   OpenPtr -> OpCode = OOPEN;
   OpenPtr -> OpenMode = Mode;
   OpenPtr -> OHandle = Index;
   OpenPtr -> Net = CABPtr -> Network;
   OpenPtr -> HostH = CABPtr -> HostHigh;
   OpenPtr -> HostL = CABPtr -> HostLow;
   OpenPtr -> SrcPrt = CABPtr -> SrcPort;
   OpenPtr -> DstPrt = CABPtr -> DstPort;
   OpenPtr -> SendPrec = CABPtr -> PrecSend;
   OpenPtr -> RecvPrec = CABPtr -> PrecRecv;
   OpenPtr -> MaxSecur = CABPtr -> SecurMax;
   OpenPtr -> AbsSecur = CABPtr -> SecurAbs;
   OpenPtr -> NumbTcc = CABPtr -> TccCnt;

   /* copy the list of TCCs */
   for (i = 0; i < CABPtr -> TccCnt; i++)
   {
      OpenPtr -> OTcc[i] = CABPtr -> TCC[i];
    }


   /* derive the data send and receive port names */
   j = Index;
   for (i = PRTPREFIX+5;i > PRTPREFIX+2;i--)
   {  SendName[i] = '0' + (j&07);
      RecvName[i] = '0' + (j&07);
      j =>> 3;
    }


   /* create the receive data port */
   unlink(RecvName);
   Fdesc = port(RecvName,0170222,0);
   if (Fdesc == -1)
   {  /* couldn't create receive port */
      printf("Open1: errno = %d\n", errno);

      /* return ConnBlock to free list */
      ConnBlock[Index].ConnIndex = 0;

      return(ERCVPRT);
    }

   ConnBlock[Index].RecvFds = Fdesc;   /* enter fds for receive */

   /* send OPEN to tcp */
   write(CmdUsrFds,&CmdUsr,(19 + (OpenPtr -> NumbTcc)));

   /* wait for response from TCP */
   Error = ReadCmd(TimeOut);
   if (Error != 0)
   {  /* Something happened */

      /* return ConnBlock to free list */
      ConnBlock[Index].ConnIndex = 0;
      close(Fdesc);
      return(Error);
    }

   ErrPtr = CmdTcp;
   AckPtr = CmdTcp;
   switch (AckPtr -> YOpCode)
   {  case OERR:
      {  /* something wrong with open */

         /* return ConnBlock to free list */
         ConnBlock[Index].ConnIndex = 0;
         close(Fdesc);
         return(ErrPtr -> YMisc);
       }
      case OACK:
      {  /* open the send port */
         Fdesc = open(SendName,1);
         if (Fdesc == -1)
         {  /* couldn't open the send port */
            printf("Open2: errno = %d\n", errno);

            /* return ConnBlock to free list */
            ConnBlock[Index].ConnIndex = 0;
            close(Fdesc);
            return(ESNDPRT);
          }

         unlink(SendName);
         unlink(RecvName);

         ConnBlock[Index].SendFds = Fdesc;
         ConnBlock[Index].ConnIndex = AckPtr -> YHandle;
         return(0);
       }
    }
 }

TcpClose(ConnPtr, TimeOut)

struct UserTcb *ConnPtr;
int TimeOut;

{  int Error;
   struct MClose *ClosePtr;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   ClosePtr = CmdUsr;
   ClosePtr -> COpCode = OCLOSE;
   ClosePtr -> CHandle = ConnPtr -> ConnIndex;
   ClosePtr -> CFinNum = ConnPtr -> SndCount;
   write(CmdUsrFds, CmdUsr, 8);
   Error = ReadCmd(TimeOut);
   return(Error);
 }



TcpSend(ConnPtr,BuffPtr,Count,Security,Eol,Urgent)

struct UserTcb *ConnPtr;
char *BuffPtr;
int Count;
int Security;
int Eol;
int Urgent;

{  int ByteCnt[2];
   struct SendBlock *SendPtr;
   long Temp;
   struct MUrgent *UrgPtr;
   int d;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   /* prepare a long with Count */
   p = &Temp;
   p -> bb[0] = 0;
   p -> bb[1] = Count;

   if (Urgent != 0)
   {  /* urgent information in data */
      UrgPtr = CmdUsr;
      UrgPtr -> UOpCode = OURGENT;
      UrgPtr -> UHandle = ConnPtr -> ConnIndex;
      UrgPtr -> UByteNo = ConnPtr -> SndCount + Temp;
      write(CmdUsrFds, CmdUsr, 8);
    }

   capac(ConnPtr -> SendFds, ByteCnt, 4);
   if (ByteCnt[1] < Count + 2*HDRLNGTH + 4)
   {  /* not enough space in port */
      return(ENOSPC);
    }

   ConnPtr -> SndCount =+ Temp;

   /* create and send the header message */

   SendPtr = CmdUsr;
   SendPtr -> SnFlags = Eol + (Urgent << 1);
   SendPtr -> SnSecur = Security;
   SendPtr -> SnByteCnt = Count;

   d = write(ConnPtr -> SendFds,CmdUsr,4);

   /* write the actual data */
   d = write(ConnPtr -> SendFds,BuffPtr,Count);

   return(0);
 }



TcpReceive(ConnPtr, RecvPtr, MaxCount, RealCount, UrgentFlag)

struct ConnBlock *ConnPtr;
int *RecvPtr;
int MaxCount;
int *RealCount;
int *UrgentFlag;

{  int ByteCnt[2];
   int ReadCnt;
   long Temp;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   if (ConnPtr -> ResidData > 0)
   {  /* data left in port from previous msg */
      if (ConnPtr -> ResidData > MaxCount)
      {  read (ConnPtr -> RecvFds, RecvPtr, MaxCount);
         *RealCount = MaxCount;
         ConnPtr -> ResidData =- MaxCount;
       }
      else
      {  read(ConnPtr -> RecvFds, RecvPtr, ConnPtr -> ResidData);
         *RealCount = ConnPtr -> ResidData;
         ConnPtr -> ResidData = 0;
       }
    }
   else
   {  capac(ConnPtr -> RecvFds, ByteCnt, 4);

      if (ByteCnt[0] == 0)
      {  /* no data present */
         *RealCount = 0;
         return(ENODATA);
       }
      read(ConnPtr -> RecvFds, &PortHdr, HDRLNGTH);    /* get header */
      ReadCnt = PortHdr.DCount&077777;      /* mask out EOM bit */

      if (ReadCnt == 0)
      {  /* receive port closed */
         return(ERCVPRT);
       }

      if (ReadCnt > MaxCount)
      {  /* read only amount allowed */
         read(ConnPtr -> RecvFds, RecvPtr, MaxCount);
         *RealCount = MaxCount;
         ConnPtr -> ResidData = ReadCnt - MaxCount;
       }
      else
      {  read(ConnPtr -> RecvFds, RecvPtr, ReadCnt);
         *RealCount = ReadCnt;
       }
    }

   /* compare urgent count with current recv byte count */
   /* these tests will fail after about 2 billion bytes are
   sent over a connection */

   /* this is known to be beyond the MTBF of the system */

   *UrgentFlag = 0;
   if ((ConnPtr -> RcvCount) < (ConnPtr -> UrgCount))
   {  *UrgentFlag = 1;
    }

   /* update received byte count */
   /* this wierdness required as you can't add longs and ints */

   p = &Temp;
   p -> bb[0] = 0;
   p -> bb[1] = *RealCount;

   ConnPtr -> RcvCount =+ Temp;

   return(0);
 }


TcpStatus(ConnPtr, StatPtr, TimeOut)

struct ConnBlock *ConnPtr;
struct ConnStat *StatPtr;
int TimeOut;

{  struct PMask1 *SPtr;
   int ByteCnt[2];
   int Count;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   /* send request to tcp */
   SPtr = CmdUsr;
   SPtr -> YOpCode = OSTAT;
   SPtr -> YHandle = ConnPtr -> ConnIndex;
   write(CmdUsrFds, CmdUsr, 4);

   while(1)     /* exits by return */

   {  capac(CmdTcpFds, ByteCnt, 4);
      if (ByteCnt[0] == 0)
      {  sleep(1);     /* one second */
         if (TimeOut == 0)
         {  return(ETCPNRDY);
          }
         TimeOut--;
       }
      else
      {  read(CmdTcpFds, &PortHdr, HDRLNGTH);

         Count = PortHdr.DCount&~0100000;

         read(CmdTcpFds, CmdTcp, 2);

         /* check opcode here */

         read (CmdTcpFds, StatPtr, Count-2);
         return(0);
       }
    }
 }

TcpAbort(ConnPtr, TimeOut)

struct ConnBlock *ConnPtr;
int TimeOut;

{  int Error;
   struct PMask1 *AbortPtr;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   AbortPtr = CmdUsr;
   AbortPtr -> YOpCode = OABORT;
   AbortPtr -> YHandle = ConnPtr -> ConnIndex;
   write(CmdUsrFds, CmdUsr, 4);

   Error = ReadCmd(TimeOut);
   if (Error == 0)
   {  /* clean up library side of connection */
      awtdis(ConnPtr -> RecvFds);
      awtdis(ConnPtr -> SendFds);

      close(ConnPtr -> RecvFds);
      close(ConnPtr -> SendFds);

      ConnPtr -> ConnIndex = 0;    /* delete UserTcb */
    }
   return(Error);
 }



TcpCmd(CmdPtr)

struct CmdBlk *CmdPtr;

{  int ByteCnt[2];
   int i;
   int Count;
   struct MUrgent *UrgPtr;
   struct PMask1 *ChngPtr;
   struct PMask1 *PPtr;
   struct PMask1 *LPtr;
   struct PMask1 *ResetPtr;
   struct PMask1 *RejectPtr;
   struct MUpdate *UPtr;

   CmdPtr -> CFlags = 0;

   /* first check the UserTcb's for outstanding events */

   for (i = 0; i < NUMBCONNS; i++)
   {  if ((ConnBlock[i].CNFlags != 0)&&(ConnBlock[i].ConnIndex != 0))
      {  /* found an entry */
         CmdPtr -> XPtr = &ConnBlock[i];
         CmdPtr -> NewState = ConnBlock[i].CNState;
         CmdPtr -> NewPrec = ConnBlock[i].CNPrec;
         CmdPtr -> NetMsg = ConnBlock[i].CNMsg;
         CmdPtr -> CFlags =| ConnBlock[i].CNFlags;
         ConnBlock[i].CNFlags = 0;    /* reset flags */
         return(0);                 /* normal 'found entry' return */
       }
    }

   /* if we made it to here, there were no UserTcb's with info */
   /* now check the Tcp Cmd Port */

   capac(CmdTcpFds, ByteCnt, 4);
   if (ByteCnt[0] == 0)
   {  return(ENOCHNG);
    }

   /* something here */

   read(CmdTcpFds, &PortHdr, HDRLNGTH);
   Count = PortHdr.DCount&~0100000;      /* remove EOM bit */

   if (Count == 0)
   {  /* port closed by tcp */
      return(ECMDCLS);
    }

   read(CmdTcpFds, CmdTcp,Count);

   ChngPtr = CmdTcp;
   switch(ChngPtr -> YOpCode)

   {  case OCHNG:
      {  CmdPtr -> NewState = ChngPtr -> YMisc;
         CmdPtr -> CFlags =| 01;   /* set flag */
         CmdPtr -> XPtr = &ConnBlock[ChngPtr -> YHandle];
         ConnBlock[ChngPtr -> YHandle].CNState = ChngPtr -> YMisc;
         return(0);
       }

      case OURGENT:
      {  UrgPtr = CmdTcp;

         if ((UrgPtr -> UByteNo) > (ConnBlock[UrgPtr -> UHandle].RcvCount))
         {  /* go into urgent mode */
            CmdPtr -> CFlags =| 02;      /* set flag */
            ConnBlock[UrgPtr -> UHandle].UrgCount = UrgPtr -> UByteNo;
            CmdPtr -> XPtr = &ConnBlock[UrgPtr -> UHandle];
            return(0);
          }
         return(ENOCHNG);
       }

      case OSECERR:
      {  /* bad security level */
         LPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[LPtr -> YHandle];
         CmdPtr -> CFlags =| 04;   /* set flag */

         /* decrement the number of bytes sent */
         ConnBlock[LPtr -> YHandle].SndCount =- LPtr -> YMisc;

         return(0);
       }

      case OPROCNR:
      {  /* foreign process not responding */
         LPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[LPtr -> YHandle];
         CmdPtr -> CFlags =| 010;   /* set flag */
         return(0);
       }

      case OPROCR:
      {  /* foreign process responding again */
         PPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[PPtr -> YHandle];
         CmdPtr -> CFlags =| 020;   /* set flag */
         return(0);
       }

      case ONETMSG:
      {  /* net message arrived */
         LPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[LPtr -> YHandle];
         CmdPtr -> NetMsg = LPtr -> YMisc;
         CmdPtr -> CFlags =| 040;    /* set flag */
         return(0);
       }

      case ORESET:
      {  /* connection reset */
         ResetPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[ResetPtr -> YHandle];
         CmdPtr -> CFlags =| 0100;    /* set flag */

         /* delete the connection in case of preemption */
         ConnBlock[ResetPtr -> YHandle].ConnIndex = 0;

         return(0);
       }

      case OREJECT:
      {  /* foreign TCP rejecting */
         RejectPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[RejectPtr -> YHandle];
         CmdPtr -> CFlags =| 0200;    /* set flag */
         return(0);
       }

      case OPRECCHNG:
      {  /* send precedence level raised */
         LPtr = CmdTcp;
         CmdPtr -> XPtr = &ConnBlock[LPtr -> YHandle];
         CmdPtr -> NewPrec = LPtr -> YMisc;
         CmdPtr -> CFlags =| 0400;     /* set flag */
         return(0);
       }

      case OUPDATE:
      {  /* response to move - update utcb parameters */
         UPtr = CmdTcp;
         ConnBlock[UPtr -> ZHandle].ConnIndex = UPtr -> ZConnIndex;
         ConnBlock[UPtr -> ZHandle].SndCount =+ UPtr -> ZSndCnt;
         ConnBlock[UPtr -> ZHandle].RcvCount = UPtr -> ZRcvCnt;

         return(ENOCHNG);
       }

      default:
      {  /* found something strange */
         return(ENOCHNG);
       }
    }
 }




TcpMove(ConnPtr, NewProcId, TimeOut)

struct UserTcp *ConnPtr;
int NewProcId;
int TimeOut;

{  int Error;
   struct PMask1 *MovePtr;

   if (ConnPtr -> ConnIndex == 0)
   {  /* connection doesn't exist */
      return(ENOCONN);
    }

   MovePtr = CmdUsr;
   MovePtr -> YOpCode = OMOVE;
   MovePtr -> YHandle = ConnPtr -> ConnIndex;
   MovePtr -> YMisc = NewProcId;

   write(CmdUsrFds, CmdUsr, 6);

   Error = ReadCmd(TimeOut);
   return(Error);
 }



TcpStop(Type, StopIdPtr, TimeOut)

int Type;
struct
{  long FSocket;
 } *StopIdPtr;
int TimeOut;

{  int Error;
   struct MClose *StopPtr;

   StopPtr = CmdUsr;
   StopPtr -> COpCode = OSTOP;
   StopPtr -> CHandle = Type;
   StopPtr -> CFinNum = StopIdPtr -> FSocket;

   write(CmdUsrFds, CmdUsr, 8);

   Error = ReadCmd(TimeOut);
   return(Error);
 }



TcpResume(Type, RsmIdPtr, TimeOut)

int Type;
struct
{  long FSocket;
 } *RsmIdPtr;
int TimeOut;

{  int Error;
   struct MClose *ResPtr;

   ResPtr = CmdUsr;
   ResPtr -> COpCode = ORESUME;
   ResPtr -> CHandle = Type;
   ResPtr -> CFinNum = RsmIdPtr -> FSocket;

   write(CmdUsrFds, CmdUsr, 8);

   Error = ReadCmd(TimeOut);
   return(Error);
 }







/* Miscellaneous subroutines */


ReadCmd(TimeOut)

/* wait for a command from TCP and then read it */

int TimeOut;

{  int ByteCnt[2];
   int Count;
   struct MUrgent *UrgPtr;
   struct PMask1 *ChngPtr;
   struct PMask1 *AckPtr;
   struct PMask1 *ErrPtr;
   struct PMask1 *PPtr;
   struct PMask1 *LPtr;
   struct PMask1 *ResetPtr;
   struct PMask1 *RejectPtr;

   while(1)             /* all exits by return */
   {  capac(CmdTcpFds, ByteCnt, 4);
      if (ByteCnt[0] == 0)
      {  sleep(1);             /* sleep for one second */
         if (TimeOut == 0)
         {  return(ETCPNRDY);
          }
         TimeOut--;
       }

      else
      {
         read(CmdTcpFds, &PortHdr, HDRLNGTH);
         Count = PortHdr.DCount&~0100000;     /* remove EOM bit */
         read(CmdTcpFds, CmdTcp, Count);

         ErrPtr = CmdTcp;

         switch (ErrPtr -> YOpCode)

         {  case OACK:
            {
               return(0);
             }

            case OERR:
            {  return(ErrPtr -> YMisc);
             }

            case OCHNG:
            {  /* found an injected change notice here */
               ChngPtr = CmdTcp;
               /* update new state */
               ConnBlock[ChngPtr -> YHandle].CNState = ChngPtr -> YMisc;
               /* set change state bit */
               ConnBlock[ChngPtr -> YHandle].CNFlags =| 01;
               break;
             }

            case OURGENT:
            {  /* found an injected urgent notice here */
               UrgPtr = CmdTcp;

               if ((UrgPtr -> UByteNo) > (ConnBlock[UrgPtr -> UHandle].RcvCount))
               {  /* go into urgent mode */
                  ConnBlock[UrgPtr -> UHandle].CNFlags =| 02;
                  ConnBlock[UrgPtr -> UHandle].UrgCount = UrgPtr -> UByteNo;
                }
               break;
             }

            case OSECERR:
            {  /* bad security level */
               LPtr = CmdTcp;
               ConnBlock[LPtr -> YHandle].CNFlags =| 04;  /* set flag */

               /* decrement the number of bytes sent */
               ConnBlock[LPtr -> YHandle].SndCount =- LPtr -> YMisc;

               break;
             }

            case OPROCNR:
            {  /* foreign process not responding */
               LPtr = CmdTcp;
               ConnBlock[LPtr -> YHandle].CNFlags =| 010;  /* set flag */
               break;
             }

            case OPROCR:
            {  /* foreign process responding again */
               PPtr = CmdTcp;
               ConnBlock[PPtr -> YHandle].CNFlags =| 020;  /* set flag */
               break;
             }

            case ONETMSG:
            {  /* network message arrived */
               LPtr = CmdTcp;
               ConnBlock[LPtr -> YHandle].CNMsg = LPtr -> YMisc;
               ConnBlock[LPtr -> YHandle].CNFlags =| 040;  /* set flag */
               break;
             }

            case ORESET:
            {  /* connection reset */
               ResetPtr = CmdTcp;
               /* ConnBlock[ResetPtr -> YHandle].CNFlags =| 0100; */

               /* delete the connection in case of preemption */
               ConnBlock[ResetPtr -> YHandle].ConnIndex = 0;
               break;
             }

            case OREJECT:
            {  /* foreign TCP rejecting */
               RejectPtr = CmdTcp;
               ConnBlock[RejectPtr -> YHandle].CNFlags =| 0200;    /* set flag */
               break;
             }

            case OPRECCHNG:
            {  /* send precedence level raised */
               LPtr = CmdTcp;
               /* update new state */
               ConnBlock[LPtr -> YHandle].CNPrec = LPtr -> YMisc;
               ConnBlock[LPtr -> YHandle].CNFlags =| 0400;   /* set flag */
               break;
             }

            default:
            {  return(EBADRESP);
             }
          }
       }
    }
 }