[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
[0325]
[0326]
[0327]
[0328]
[0329]
[0330]
[0331]
[0332]
[0333]
[0334]
[0335]
[0336]
[0337]
[0338]
[0339]
[0340]
[0341]
[0342]
[0343]
[0344]
[0345]
[0346]
[0347]
[0348]
[0349]
[0350]
[0351]
[0352]
[0353]
[0354]
[0355]
[0356]
[0357]
[0358]
[0359]
[0360]
[0361]
[0362]
[0363]
[0364]
[0365]
[0366]
[0367]
[0368]
[0369]
[0370]
[0371]
[0372]
[0373]
[0374]
[0375]
[0376]
[0377]
[0378]
[0379]
[0380]
[0381]
[0382]
[0383]
[0384]
[0385]
[0386]
[0387]
[0388]
[0389]
[0390]
[0391]
[0392]
[0393]
[0394]
[0395]
[0396]
[0397]
[0398]
[0399]
[0400]
[0401]
[0402]
[0403]
[0404]
[0405]
[0406]
[0407]
[0408]
[0409]
[0410]
[0411]
[0412]
[0413]
[0414]
[0415]
[0416]
[0417]
[0418]
[0419]
[0420]
[0421]
[0422]
[0423]
[0424]
[0425]
[0426]
[0427]
[0428]
[0429]
[0430]
[0431]
[0432]
[0433]
[0434]
[0435]
[0436]
[0437]
[0438]
[0439]
[0440]
[0441]
[0442]
[0443]
[0444]
[0445]
[0446]
[0447]
[0448]
[0449]
[0450]
[0451]
[0452]
[0453]
[0454]
[0455]
[0456]
[0457]
[0458]
[0459]
[0460]
[0461]
[0462]
[0463]
[0464]
[0465]
[0466]
[0467]
[0468]
[0469]
[0470]
[0471]
[0472]
[0473]
[0474]
[0475]
[0476]
[0477]
[0478]
[0479]
[0480]
[0481]
[0482]
[0483]
[0484]
[0485]
[0486]
[0487]
[0488]
[0489]
[0490]
[0491]
[0492]
[0493]
[0494]
[0495]
[0496]
[0497]
[0498]
[0499]
[0500]
[0501]
[0502]
[0503]
[0504]
[0505]
[0506]
[0507]
[0508]
[0509]
[0510]
[0511]
[0512]
[0513]
[0514]
[0515]
[0516]
[0517]
[0518]
[0519]
[0520]
[0521]
[0522]
[0523]
[0524]
[0525]
[0526]
[0527]
[0528]
[0529]
[0530]
[0531]
[0532]
[0533]
[0534]
[0535]
[0536]
[0537]
[0538]
[0539]
[0540]
[0541]
[0542]
[0543]
[0544]
[0545]
[0546]
[0547]
[0548]
[0549]
[0550]
[0551]
[0552]
[0553]
[0554]
[0555]
[0556]
[0557]
[0558]
[0559]
[0560]
[0561]
[0562]
[0563]
[0564]
[0565]
[0566]
[0567]
[0568]
[0569]
[0570]
[0571]
[0572]
[0573]
[0574]
[0575]
[0576]
[0577]
[0578]
[0579]
[0580]
[0581]
[0582]
[0583]
[0584]
[0585]
[0586]
[0587]
[0588]
[0589]
[0590]
[0591]
[0592]
[0593]
[0594]
/*****************************************************************************/
/*
                                 TCPIPalt.c

Alternate TCP/IP functions, lookup by name and by address.

Currently experimental.

Both inline (synchronous) and by agent (DCL script, asynchronous).

The agent can take on the role of a network agent and drop connections.  This
means that if using a lookup agent there is no need also to use a network
agent.  A drop connection is cached.

These are (currently) controlled using logical names WASD_TCPIP_LOOKUP_INLINE
and WASD_TCPIP_LOOKUP_AGENT.  Without one or the other the (historic) TCP/IP
$QIO INETACP_FUNC$C_GETHOSTBYADDR and INETACP_FUNC$C_GETHOSTBYNAME are used.


VERSION HISTORY
---------------
01-JUN-2021  MGD  initial
*/
/*****************************************************************************/

#ifdef WASD_VMS_V7
#undef _VMS__V6__SOURCE
#define _VMS__V6__SOURCE
#undef __VMS_VER
#define __VMS_VER 70000000
#undef __CRTL_VER
#define __CRTL_VER 70000000
#endif

/* standard C header files */
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

/* VMS related header files */
#include <descrip.h>
#include <iodef.h>
#include <lnmdef.h>
#include <ssdef.h>

/* application-related header files */
#include "wasd.h"
#include "tcpip.h"

#define WASD_MODULE "TCPIPALT"

#define FI_LI WASD_MODULE, __LINE__

#define DBUG 1

/******************/
/* global storage */
/******************/

char  TcpIpAltAgentScript [] = "/cgiplus-bin/lookagent";

char  ProblemTcpIpAgent [] = "Problem initiating TCP/IP DNS agent";

#define TCPIP_AGENT_ACTIVE_MAX 8
#define TCPIP_AGENT_BUSY_MAX 100
static int  TcpIpAltAgentActiveCount,
            TcpIpAltAgentActiveMax = TCPIP_AGENT_ACTIVE_MAX,
            TcpIpAltAgentBusyMax = TCPIP_AGENT_BUSY_MAX,
            TcpIpAltAgentBusyCount,
            TcpIpAltAgentBusyLimit;

/********************/
/* external storage */
/********************/

extern int  HttpdTickSecond;
            TcpIpLookupAddrCount,
            TcpIpLookupNameCount;

extern const int64  Delta100mSec;

extern uint64  TcpIpLookupAddrDelta64,
               TcpIpLookupAddrMax64,
               TcpIpLookupAddrMin64,
               TcpIpLookupNameDelta64,
               TcpIpLookupNameMax64,
               TcpIpLookupNameMin64;

extern char  ErrorSanityCheck[];

extern ACCOUNTING_STRUCT  *AccountingPtr;
extern CONFIG_STRUCT  Config;
extern WATCH_STRUCT  Watch;

/*****************************************************************************/
/*
Not actually used :-)
TcpIpNameToAddress() calls the relevant inline functions directly.
*/

#if 0

int TcpIpAltInlineLookup (TCPIP_HOST_LOOKUP *hlptr)

{
   int  status;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltInlineLookup()");

   if (hlptr->AddrToName)
      status = TcpIpAltInlineAddressToName (hlptr);
   else
      status = TcpIpAltInlineNameToAddress (hlptr);

   return (status);
}

#endif /* 0 */

/*****************************************************************************/
/*
Set up by TcpIpAddressToName().
*/

int TcpIpAltInlineAddressToName (TCPIP_HOST_LOOKUP *hlptr)

{
   int  retval;
   char  *cptr, *sptr, *zptr;
   char  strerr [128];

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltInlineAddressToName()");

   retval = TcpIpAltGetNameInfo (hlptr);
   if (retval)
   {
      hlptr->LookupIOsb.Status = SS$_ENDOFFILE;
      *(USHORTPTR)hlptr->HostName = '?\0';
      hlptr->HostNameLength = 1;
   }
   else
   {
      hlptr->LookupIOsb.Status = SS$_NORMAL;
      hlptr->HostNameLength = strlen(hlptr->HostName);
   }

   TcpIpLookupDelta (hlptr);

   TcpIpCacheSetEntry (hlptr);

   InstanceGblSecIncrLong (&AccountingPtr->LookupDnsAddressCount);

   if (WATCH_MODULE(WATCH_MOD_NET))
   {
      sprintf (strerr, "%s", (char*)gai_strerror(retval));
      WatchThis (WATCHALL, WATCH_MOD_NET,
"host:!AZ retval:!UL (!AZ) !&S delta:!ULmS min:!ULmS max:!ULmS",
                 &hlptr->HostName, retval, strerr, hlptr->LookupIOsb.Status,
                 hlptr->LookupDeltaTime64 / 10000,
                 TcpIpLookupNameMin64 / 10000,
                 TcpIpLookupNameMax64 / 10000);
   }

   if (hlptr->AstFunction) SysDclAst (hlptr->AstFunction, hlptr->AstParam);

   return (hlptr->LookupIOsb.Status);
}

/*****************************************************************************/
/*
Wrap the getnameinfo() name resolution function.  SYNCHRONOUS!
*/

int TcpIpAltGetNameInfo (TCPIP_HOST_LOOKUP *hlptr)

{
   static int  flags = NI_NAMEREQD;

   int  retval;
   struct sockaddr_in  SockAddr;
   struct sockaddr_in6  Sock6Addr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET,
                 "TcpIpAltGetNameInfo() !&Z !UL",
                 hlptr->HostName, IPADDRESS_SIZE(&hlptr->IpAddress));

   *(ULONGPTR)hlptr->HostName = 0;

   if (IPADDRESS_IS_V4 (&hlptr->IpAddress))
   {
      memset (&SockAddr, 0, sizeof(SockAddr));
      SockAddr.sin_family = TCPIP$C_AF_INET;
      memcpy (&SockAddr.sin_addr,
              IPADDRESS_ADR4(&hlptr->IpAddress),
              sizeof(SockAddr.sin_addr));

      retval = getnameinfo (&SockAddr, sizeof(SockAddr),
                           hlptr->HostName, sizeof(hlptr->HostName),
                           NULL, NULL, flags);
   }
   else
   if (IPADDRESS_IS_V6 (&hlptr->IpAddress))
   {
      memset (&Sock6Addr, 0, sizeof(Sock6Addr));
      Sock6Addr.sin6_family = TCPIP$C_AF_INET6;
      memcpy (&Sock6Addr.sin6_addr,
              IPADDRESS_ADR6(&hlptr->IpAddress),
              sizeof(Sock6Addr.sin6_addr));

      retval = getnameinfo (&Sock6Addr, sizeof(Sock6Addr),
                           hlptr->HostName, sizeof(hlptr->HostName),
                           NULL, NULL, flags);
   }
   else
      return (false);

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET,
                 "retval:!UL host:!&Z", retval, hlptr->HostName);

   return (retval);
}

/*****************************************************************************/
/*
Set up by TcpIpNameToAddress().
*/

int TcpIpAltInlineNameToAddress (TCPIP_HOST_LOOKUP *hlptr)

{
   int  retval;
   char  *cptr, *sptr, *zptr;
   char  strerr [128];

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltInlineNameToAddress()");

   if (retval = TcpIpAltGet4AddrInfo (hlptr))
      retval = TcpIpAltGet6AddrInfo (hlptr);

   if (retval)
   {
      hlptr->LookupIOsb.Status = SS$_ENDOFFILE;
      IPADDRESS_SET_UNUSABLE (&hlptr->IpAddress);
   }
   else
      hlptr->LookupIOsb.Status = SS$_NORMAL;

   TcpIpLookupDelta (hlptr);

   InstanceGblSecIncrLong (&AccountingPtr->LookupDnsNameCount);

   if (WATCH_MODULE(WATCH_MOD_NET))
   {
      sprintf (strerr, "%s", (char*)gai_strerror(retval));
      WatchThis (WATCHALL, WATCH_MOD_NET,
"IP:!&I retval:!UL (!AZ) !&S delta:!ULmS min:!ULmS max:!ULmS",
                 &hlptr->IpAddress, retval, strerr, hlptr->LookupIOsb.Status,
                 hlptr->LookupDeltaTime64 / 10000,
                 TcpIpLookupNameMin64 / 10000,
                 TcpIpLookupNameMax64 / 10000);
   }

   if (hlptr->AstFunction) SysDclAst (hlptr->AstFunction, hlptr->AstParam);

   return (hlptr->LookupIOsb.Status);
}

/*****************************************************************************/
/*
Wrap the getaddrinfo() address resolution function.  SYNCHRONOUS!
*/

int TcpIpAltGet4AddrInfo (TCPIP_HOST_LOOKUP *hlptr)

{
   static struct addrinfo  IPv4Hint = { AI_ALL, TCPIP$C_AF_INET,
                                        0, 0, 0, NULL, NULL, NULL };
   int  retval;
   void  *addptr;
   struct  addrinfo  *raiptr,
                     *RetAddrInfo;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltGet4AddrInfo() !&Z !UL",
                 hlptr->HostName, IPADDRESS_SIZE(&hlptr->IpAddress));

   IPADDRESS_V4 (&hlptr->IpAddress);

   retval = getaddrinfo (hlptr->HostName, NULL, &IPv4Hint, &RetAddrInfo);

   if (retval) return (retval);

   for (raiptr = RetAddrInfo; raiptr; raiptr = raiptr->ai_next)
   {
      if (raiptr->ai_family == AF_INET)
      {
         addptr = &((struct sockaddr_in *)raiptr->ai_addr)->sin_addr;
         IPADDRESS_GET4 (&hlptr->IpAddress, addptr);
         TcpIpCacheSetEntry (hlptr);
      }
   }

   freeaddrinfo (&RetAddrInfo);

   return (retval);
}

/*****************************************************************************/
/*
Wrap the getaddrinfo() address resolution function.  SYNCHRONOUS!
*/

int TcpIpAltGet6AddrInfo (TCPIP_HOST_LOOKUP *hlptr)

{
   static struct addrinfo  IPv6Hint = { AI_ALL, TCPIP$C_AF_INET,
                                        0, 0, 0, NULL, NULL, NULL };
   int  retval;
   void  *addptr;
   struct  addrinfo  *raiptr,
                     *RetAddrInfo;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltGet6AddrInfo() !&Z !UL",
                 hlptr->HostName, IPADDRESS_SIZE(&hlptr->IpAddress));

   IPADDRESS_V6 (&hlptr->IpAddress);

   retval = getaddrinfo (hlptr->HostName, NULL, &IPv6Hint, &RetAddrInfo);

   if (retval) return (retval);

   for (raiptr = RetAddrInfo; raiptr; raiptr = raiptr->ai_next)
   {
      if (raiptr->ai_family == AF_INET6)
      {
         addptr = &((struct sockaddr_in6 *)raiptr->ai_addr)->sin6_addr;
         IPADDRESS_GET6 (&hlptr->IpAddress, addptr);
      }
   }

   freeaddrinfo (&RetAddrInfo);

   return (retval);
}

/*****************************************************************************/
/*
Activate a TCP/IP DNS agent (script) to perform the lookup.  ASYNCHRONOUS!
A TCP/IP agent does not have an associated request.
*/

int TcpIpAltAgentBegin (TCPIP_HOST_LOOKUP *hlptr)

{
   int  status;
   REQUEST_STRUCT  *rqptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAgentBegin()");

   if (!hlptr->AstFunction)
   {
      /* no AST supplied then do it inline */
      if (hlptr->AddrToName)
         status = TcpIpAltInlineAddressToName (hlptr);
      else
         status = TcpIpAltInlineNameToAddress (hlptr);
      return (status);
   }

   if (TcpIpAltAgentActiveCount >= TcpIpAltAgentActiveMax)
   {
      /* busy, busy, busy ... requeue for a delayed subsequent attempt */
      if (hlptr->AgentBusyCount++ <= TcpIpAltAgentBusyMax)
      {
         if (hlptr->AgentBusyCount <= TcpIpAltAgentBusyMax / 4)
            SysDclAst (TcpIpAltAgentBegin, hlptr);
         else
            sys$setimr (0, &Delta100mSec, TcpIpAltAgentBegin, hlptr, 0);
         return (SS$_NORMAL);
      }
      else
      {
         ErrorNoticed (NULL, SS$_TOOMANYREDS, "!UL exceeded (!UL)",
                       FI_LI, TcpIpAltAgentBusyMax, TcpIpAltAgentBusyLimit);
         TcpIpAltAgentBusyCount++;
         hlptr->LookupIOsb.Status = SS$_ABORT;
         SysDclAst (hlptr->AstFunction, hlptr->AstParam);
         return (SS$_ABORT);
      }
   }
   if (hlptr->AgentBusyCount)
   {
      if (hlptr->AgentBusyCount > TcpIpAltAgentBusyLimit)
         TcpIpAltAgentBusyLimit = hlptr->AgentBusyCount;
      hlptr->AgentBusyCount = 0;
   }

   /************/
   /* continue */
   /************/

   rqptr = DclFauxRequest (NULL, NULL, NULL);

   rqptr->AgentAstParam = hlptr;

   rqptr->AgentRequestPtr = VmGetHeap (rqptr, 256);
   if (hlptr->AddrToName)
      FaoToBuffer (rqptr->AgentRequestPtr, 256, NULL,
                   "!&I", &hlptr->IpAddress);
   else
      FaoToBuffer (rqptr->AgentRequestPtr, 256, NULL,
                   "!AZ", hlptr->HostName);

   rqptr = DclFauxRequest (rqptr, TcpIpAltAgentScript, &TcpIpAltAgentEnd);

   if (!rqptr)
   {
      if (WATCHING (rqptr, WATCH_NETWORK))
         WatchThis (WATCHITM(rqptr), WATCH_NETWORK, "LOOKUP AGENT !AZ",
                    TcpIpAltAgentScript);
      ErrorNoticed (NULL, SS$_ABORT, ProblemTcpIpAgent, FI_LI);
      hlptr->LookupIOsb.Status = SS$_ABORT;
      SysDclAst (hlptr->AstFunction, hlptr->AstParam);
      return (SS$_ABORT);
   }

   TcpIpAltAgentActiveCount++;

   return (SS$_NORMAL);
}

/*****************************************************************************/
/*
The agent (script) has completed.
*/

void TcpIpAltAgentEnd (REQUEST_STRUCT *rqptr)

{
   int  count, status;
   char  *cptr, *sptr, *zptr;
   TCPIP_HOST_LOOKUP  *hlptr;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD_NET))
      WatchThis (WATCHALL, WATCH_MOD_NET, "TcpIpAltAgentEnd()");

   hlptr = (TCPIP_HOST_LOOKUP*)rqptr->AgentAstParam;

   TcpIpLookupDelta (hlptr);

   if (cptr = rqptr->AgentResponsePtr)
   {
      status = atoi(cptr);
      while (isdigit (*cptr)) cptr++;
      while (*cptr == ' ') cptr++;

      if (status >= 200 && status <= 299)
      {
         /***********/
         /* success */
         /***********/

         if (hlptr->AddrToName)
         {
            hlptr->LookupIOsb.Status = SS$_NORMAL;
            zptr = (sptr = hlptr->HostName) + sizeof(hlptr->HostName)-1;
            while (*cptr && sptr < zptr) *sptr++ = *cptr++;
            *sptr = '\0';
            hlptr->HostNameLength = sptr - hlptr->HostName;
            TcpIpCacheSetEntry (hlptr);
         }
         else
         {
            /* possible multiple space-separated IP addresses */
            hlptr->LookupIOsb.Status = SS$_NORMAL;
            count = 0;
            while (*cptr)
            {
               while (*cptr && *cptr == ' ') cptr++;
               if (!*cptr) break;
               status = TcpIpStringToAddress (cptr, &hlptr->IpAddress);
               if (VMSnok (status)) 
               {
                  if (!count)
                  {
                     /* primary host address */
                     hlptr->LookupIOsb.Status = status;
                     IPADDRESS_SET_UNUSABLE (&hlptr->IpAddress);
                     ErrorNoticed (NULL, SS$_ABORT, cptr, FI_LI);
                     break;
                  }
               }
               count++;
               TcpIpCacheSetEntry (hlptr);
               while (*cptr && *cptr != ' ') cptr++;
            }
         }
      }
      else
      if (status == 418)
      {
         /********/
         /* drop */
         /********/

         hlptr->DropConnect = true;
         TcpIpCacheSetEntry (hlptr);
      }
      else
      {
         /**********/
         /* failed */
         /**********/

         if (hlptr->AddrToName)
         {
            hlptr->LookupIOsb.Status = SS$_ENDOFFILE;
            *(USHORTPTR)hlptr->HostName = '?\0';
            hlptr->HostNameLength = 1;
         }
         else
            IPADDRESS_SET_UNUSABLE (&hlptr->IpAddress);
         TcpIpCacheSetEntry (hlptr);

         if (MATCH3 (cptr, "[%X"))
         {
            /* if agent reporting VMS error */
            status = strtol (cptr+3, NULL, 16);
            ErrorNoticed (NULL, status, cptr, FI_LI);
            hlptr->LookupIOsb.Status = status;
         }
      }
   }
   else
   {
      ErrorNoticed (NULL, SS$_ABORT, ProblemTcpIpAgent, FI_LI);
      hlptr->LookupIOsb.Status = SS$_ABORT;
   }

   if (TcpIpAltAgentActiveCount) TcpIpAltAgentActiveCount--;

   SysDclAst (hlptr->AstFunction, hlptr->AstParam);

   /* remove from any supervisory list */
   HttpdSupervisorList (rqptr, -1);

   VmFreeRequest (rqptr, FI_LI);
}

/*****************************************************************************/