[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); } /*****************************************************************************/