DWORD LWNetSrvGetPrefixPath( PSTR* ppszPath ) { DWORD dwError = 0; PSTR pszPath = NULL; BOOLEAN bInLock = FALSE; LWNET_LOCK_SERVERINFO(bInLock); if (IsNullOrEmptyString(gpLwnetServerInfo->szPrefixPath)) { dwError = ERROR_PATH_NOT_FOUND; BAIL_ON_LWNET_ERROR(dwError); } dwError = LWNetAllocateString(gpLwnetServerInfo->szPrefixPath, &pszPath); BAIL_ON_LWNET_ERROR(dwError); *ppszPath = pszPath; cleanup: LWNET_UNLOCK_SERVERINFO(bInLock); return dwError; error: LWNET_SAFE_FREE_STRING(pszPath); *ppszPath = NULL; goto cleanup; }
/* "Second Level" NetBIOS name encoding */ DWORD LWNetNbStrToNbName2( PSTR Fqdn, UINT8 suffix, PBYTE *retNbNameL2, PDWORD retNbNameL2Len) { DWORD dwError = 0; DWORD len = 0; PSTR p = NULL; PSTR token = NULL; PSTR tokenPtr = NULL; UINT8 *retName = NULL; UINT8 *up = NULL; /* * 32=Max NetBIOS First Level encoding length * All . separators are replaced by 1 byte count, so * don't need to count number of dots to determine buffer length * 2=FirstLevel encoding length + ending length (by definition 0) */ len = LWNB_NETBIOS_ENCNAME_LEN + strlen(Fqdn) + 2; dwError = LWNetAllocateMemory(sizeof(CHAR) * len, (PVOID*)&retName); BAIL_ON_LWNET_ERROR(dwError); up = retName; dwError = LWNetAllocateString( Fqdn, &token); BAIL_ON_LWNET_ERROR(dwError); p = strchr(token, '.'); if (p) { *p++ = '\0'; Fqdn = token; } /* Store length of NetBIOS name component before that name */ *up++ = (UINT8) LWNB_NETBIOS_ENCNAME_LEN; LWNetNbStrToNbName(Fqdn, suffix, up); up += LWNB_NETBIOS_ENCNAME_LEN; /* Work through rest of Fqdn, replacing . with length of stuff before . */ if (p) { p = strtok_r(p, ".", &tokenPtr); } while (p) { len = strlen(p); *up++ = (UINT8) len; strncat((char *) up, p, sizeof(CHAR)*len - (up-retName)); up += len; p = strtok_r(NULL, ".", &tokenPtr); } *up++ = '\0'; *retNbNameL2 = (UINT8 *) retName; *retNbNameL2Len = up - retName; cleanup: LWNET_SAFE_FREE_MEMORY(token); return dwError; error: LWNET_SAFE_FREE_MEMORY(retName); goto cleanup; }
static DWORD LWNetSrvPingCLdapProcess( IN PLWNET_CLDAP_CONNECTION_CONTEXT pContext, IN DWORD dwDsFlags, IN LWNET_UNIX_MS_TIME_T StopTime, OUT PLWNET_DC_INFO* ppDcInfo, OUT PBOOLEAN pbFailedFindWritable ) { DWORD dwError = 0; DWORD dwResultType = 0; LDAPMessage* pMessage = NULL; PBYTE pNetlogonAttributeValue = NULL; DWORD dwNetlogonAttributeSize = 0; PLWNET_DC_INFO pDcInfo = NULL; BOOLEAN bFailedFindWritable = FALSE; struct timeval timeout = {0}; LDAP *ld = NULL; ld = LwLdapGetSession(pContext->hDirectory); dwResultType = ldap_result( ld, pContext->msgid, 0, &timeout, &pMessage); if (dwResultType == 0) { // timed out goto error; } else if (dwResultType == -1) { // -1 = problem dwError = LDAP_NO_SUCH_OBJECT; LWNET_LOG_VERBOSE("Caught LDAP_NO_SUCH_OBJECT Error on ldap search"); } else { // returns result type if (dwResultType != LDAP_RES_SEARCH_ENTRY) { dwError = LDAP_NO_SUCH_OBJECT; LWNET_LOG_DEBUG("Caught incorrect result type on ldap search: %d", dwError); } } dwError = LwMapLdapErrorToLwError(dwError); BAIL_ON_LWNET_ERROR(dwError); dwError = LwLdapGetBytes( pContext->hDirectory, pMessage, NETLOGON_LDAP_ATTRIBUTE_NAME, &pNetlogonAttributeValue, &dwNetlogonAttributeSize); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetBuildDCInfo(pNetlogonAttributeValue, dwNetlogonAttributeSize, &pDcInfo); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetAllocateString(pContext->pServerInfo->pszAddress, &pDcInfo->pszDomainControllerAddress); BAIL_ON_LWNET_ERROR(dwError); pDcInfo->dwPingTime = (DWORD)(StopTime - pContext->StartTime); if (StopTime < pContext->StartTime) { LWNET_LOG_ERROR("Stop time is earlier than start time"); } if (!LWNetSrvIsMatchingDcInfo(pDcInfo, dwDsFlags)) { dwError = LW_ERROR_NO_SUCH_OBJECT; if (LWNetSrvIsMatchingDcInfo(pDcInfo, dwDsFlags & ~DS_WRITABLE_REQUIRED)) { // We found something, but it failed only because it did // not satisfy writability. bFailedFindWritable = TRUE; } } error: if (pMessage) { ldap_msgfree(pMessage); } LWNET_SAFE_FREE_MEMORY(pNetlogonAttributeValue); if (dwError) { LWNET_SAFE_FREE_DC_INFO(pDcInfo); LWNetSrvPingCLdapEnd(pContext); } *ppDcInfo = pDcInfo; *pbFailedFindWritable = bFailedFindWritable; return dwError; }
DWORD ParseArgs( int argc, char* argv[], PSTR* ppszTargetFQDN, PSTR* ppszSiteName, PSTR* ppszPrimaryDomain, PDWORD pdwFlags ) { typedef enum { PARSE_MODE_OPEN = 0, PARSE_MODE_SITENAME, PARSE_MODE_PREFERRED_DOMAIN, PARSE_MODE_OPTIONS } ParseMode; DWORD dwError = 0; int iArg = 1; PSTR pszArg = NULL; ParseMode parseMode = PARSE_MODE_OPEN; PSTR pszTargetFQDN = NULL; PSTR pszSiteName = NULL; PSTR pszPrimaryDomain = NULL; DWORD dwFlags = 0; do { pszArg = argv[iArg++]; if (IsNullOrEmptyString(pszArg)) { break; } switch (parseMode) { case PARSE_MODE_OPEN: if ((strcmp(pszArg, "--help") == 0) || (strcmp(pszArg, "-h") == 0)) { ShowUsage(); exit(0); } else { dwError = LWNetAllocateString(pszArg, &pszTargetFQDN); BAIL_ON_LWNET_ERROR(dwError); parseMode = PARSE_MODE_OPTIONS; } break; case PARSE_MODE_OPTIONS: if(strcmp(pszArg, "--site") == 0) { parseMode = PARSE_MODE_SITENAME; } else if(strcmp(pszArg, "--preferred-domain") == 0) { parseMode = PARSE_MODE_PREFERRED_DOMAIN; } else if(strcmp(pszArg, "--force") == 0) { dwError = AddFlag(DS_FORCE_REDISCOVERY, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--ds-required") == 0) { dwError = AddFlag(DS_DIRECTORY_SERVICE_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--gc-required") == 0) { dwError = AddFlag(DS_GC_SERVER_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--pdc-required") == 0) { dwError = AddFlag(DS_PDC_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--background-only") == 0) { dwError = AddFlag(DS_BACKGROUND_ONLY, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--kdc-required") == 0) { dwError = AddFlag(DS_KDC_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--timeserv-required") == 0) { dwError = AddFlag(DS_TIMESERV_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--writeable-required") == 0) { dwError = AddFlag(DS_WRITABLE_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--good-timeserv-required") == 0) { dwError = AddFlag(DS_GOOD_TIMESERV_REQUIRED, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else if(strcmp(pszArg, "--avoid-self") == 0) { dwError = AddFlag(DS_AVOID_SELF, &dwFlags); BAIL_ON_LWNET_ERROR(dwError); } else { LWNET_LOG_ERROR("Invalid argument: %s", pszArg); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LWNET_ERROR(dwError); } break; case PARSE_MODE_SITENAME: if(!IsNullOrEmptyString(pszSiteName)) { LWNET_LOG_ERROR("Invalid argument: %s", pszArg); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LWNET_ERROR(dwError); } dwError = LWNetAllocateString(pszArg, &pszSiteName); BAIL_ON_LWNET_ERROR(dwError); parseMode = PARSE_MODE_OPTIONS; break; case PARSE_MODE_PREFERRED_DOMAIN: if(!IsNullOrEmptyString(pszPrimaryDomain)) { LWNET_LOG_ERROR("Invalid argument: %s", pszArg); dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LWNET_ERROR(dwError); } dwError = LWNetAllocateString(pszArg, &pszPrimaryDomain); BAIL_ON_LWNET_ERROR(dwError); parseMode = PARSE_MODE_OPTIONS; break; } } while (iArg < argc); if(IsNullOrEmptyString(pszTargetFQDN)) { ShowUsage(); exit(0); } error: if (dwError) { LWNET_SAFE_FREE_STRING(pszTargetFQDN); LWNET_SAFE_FREE_STRING(pszSiteName); LWNET_SAFE_FREE_STRING(pszPrimaryDomain); dwFlags = 0; } *ppszTargetFQDN = pszTargetFQDN; *ppszSiteName = pszSiteName; *ppszPrimaryDomain = pszPrimaryDomain; *pdwFlags = dwFlags; return dwError; }
DWORD LWNetDnsGetAddressForServer( IN PDLINKEDLIST pAdditionalsList, IN PCSTR pszHostname, OUT PSTR* ppszAddress ) { DWORD dwError = 0; PSTR pszAddress = NULL; PDLINKEDLIST pListMember = NULL; pListMember = pAdditionalsList; while (pListMember) { PDNS_RECORD pRecord = (PDNS_RECORD)pListMember->pItem; if ( (pRecord->wType == ns_t_a ) && !strcasecmp( pRecord->pszName, pszHostname ) ) { dwError = LwAllocateStringPrintf(&pszAddress, "%d.%d.%d.%d", pRecord->pData[0], pRecord->pData[1], pRecord->pData[2], pRecord->pData[3]); BAIL_ON_LWNET_ERROR(dwError); break; } pListMember = pListMember->pNext; } if (IsNullOrEmptyString(pszAddress)) { struct hostent * host; LWNET_LOG_VERBOSE("Getting address for '%s'", pszHostname); host = gethostbyname(pszHostname); if (host && host->h_name) { // ISSUE-2008/07/01-dalmeida -- Need to check that address type is IPv4 dwError = LWNetAllocateString(inet_ntoa(*(struct in_addr*)(host->h_addr_list[0])), &pszAddress); BAIL_ON_LWNET_ERROR(dwError); } } if (IsNullOrEmptyString(pszAddress)) { LWNET_LOG_WARNING("Unable to get IP address for '%s'", pszHostname); dwError = ERROR_NOT_FOUND; BAIL_ON_LWNET_ERROR(dwError); } error: if (dwError) { LWNET_SAFE_FREE_STRING(pszAddress); } *ppszAddress = pszAddress; return dwError; }
DWORD LWNetDnsGetHostInfoEx( OUT OPTIONAL PSTR* ppszHostname, OUT OPTIONAL PSTR* ppszFqdn, OUT OPTIONAL PSTR* ppszDomain ) { DWORD dwError = 0; struct hostent * host = NULL; CHAR szBuffer[256] = { 0 }; PSTR pszDot = NULL; PSTR pszFoundFqdn = NULL; PSTR pszFoundDomain = NULL; PSTR pszHostname = NULL; PSTR pszDomain = NULL; PSTR pszFqdn = NULL; if (!ppszHostname && !ppszFqdn && !ppszDomain) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_LWNET_ERROR(dwError); } if (gethostname(szBuffer, sizeof(szBuffer)-1) != 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LWNET_ERROR(dwError); } /* Test to see if the name is still dotted. If so we will chop it down to just the hostname field. */ pszDot = strchr(szBuffer, '.'); if (pszDot) { pszDot[0] = '\0'; } if (ppszHostname) { dwError = LWNetAllocateString(szBuffer, &pszHostname); BAIL_ON_LWNET_ERROR(dwError); } if (!ppszFqdn && !ppszDomain) { // done, so bail out dwError = 0; goto error; } host = gethostbyname(szBuffer); if ( !host ) { dwError = LwMapHErrnoToLwError(h_errno); BAIL_ON_LWNET_ERROR(dwError); } // // We look for the first name that looks like an FQDN. This is // the same heuristics used by other software such as Kerberos and // Samba. // pszDot = strchr(host->h_name, '.'); if (pszDot) { pszFoundFqdn = host->h_name; pszFoundDomain = pszDot + 1; } else { int i; for (i = 0; host->h_aliases[i]; i++) { pszDot = strchr(host->h_aliases[i], '.'); if (pszDot) { pszFoundFqdn = host->h_aliases[i]; pszFoundDomain = pszDot + 1; break; } } } // If we still have nothing, just return the first name, but no Domain part. if (!pszFoundFqdn) { pszFoundFqdn = host->h_name; } if (pszFoundFqdn && !pszFoundFqdn[0]) { pszFoundFqdn = NULL; } if (pszFoundDomain && !pszFoundDomain[0]) { pszFoundDomain = NULL; } if (ppszFqdn) { if (pszFoundFqdn) { dwError = LWNetAllocateString(pszFoundFqdn, &pszFqdn); BAIL_ON_LWNET_ERROR(dwError); } else { dwError = ERROR_NOT_FOUND; BAIL_ON_LWNET_ERROR(dwError); } } if (ppszDomain) { if (pszFoundDomain) { dwError = LWNetAllocateString(pszFoundDomain, &pszDomain); BAIL_ON_LWNET_ERROR(dwError); } else { dwError = ERROR_NOT_FOUND; BAIL_ON_LWNET_ERROR(dwError); } } error: if (dwError) { LWNET_SAFE_FREE_STRING(pszHostname); LWNET_SAFE_FREE_STRING(pszFqdn); LWNET_SAFE_FREE_STRING(pszDomain); } if (ppszHostname) { *ppszHostname = pszHostname; } if (ppszDomain) { *ppszDomain = pszDomain; } if (ppszFqdn) { *ppszFqdn = pszFqdn; } return dwError; }
DWORD LWNetDnsGetNameServerList( OUT PSTR** pppszNameServerList, OUT PDWORD pdwNumServers ) // Call LWNET_SAFE_FREE_STRING_ARRAY on returned server list { DWORD dwError = 0; PSTR* ppszNameServerList = NULL; DWORD dwNumServers = 0; FILE* fp = NULL; BOOLEAN bFileExists = FALSE; PCSTR pszConfigFilePath = "/etc/resolv.conf"; const DWORD dwMaxLineLen = 1024; CHAR szBuf[dwMaxLineLen + 1]; regex_t rx; PDLINKEDLIST pNameServerList = NULL; PSTR pszNameServer = NULL; memset(&rx, 0, sizeof(rx)); if (regcomp(&rx, "^nameserver[[:space:]].*$", REG_EXTENDED) < 0) { dwError = ERROR_BAD_FORMAT; BAIL_ON_LWNET_ERROR(dwError); } dwError = LwCheckFileTypeExists( pszConfigFilePath, LWFILE_REGULAR, &bFileExists); BAIL_ON_LWNET_ERROR(dwError); if (!bFileExists) { *pppszNameServerList = NULL; *pdwNumServers = 0; goto cleanup; } if ((fp = fopen(pszConfigFilePath, "r")) == NULL) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LWNET_ERROR(dwError); } while (1) { if (fgets(szBuf, dwMaxLineLen, fp) == NULL) { if (!feof(fp)) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LWNET_ERROR(dwError); } else { break; } } LwStripWhitespace(szBuf, TRUE, TRUE); if (!LWNetDnsConfigLineIsComment(szBuf) && !regexec(&rx, szBuf, (size_t)0, NULL, 0)) { PSTR pszLocation = NULL; PCSTR pszSearchString = "nameserver"; if ((pszLocation = strstr(szBuf, pszSearchString))) { pszLocation += strlen(pszSearchString); if (!IsNullOrEmptyString(pszLocation)) { dwError = LWNetAllocateString(pszLocation, &pszNameServer); BAIL_ON_LWNET_ERROR(dwError); } dwError = LWNetDLinkedListAppend( &pNameServerList, pszNameServer); BAIL_ON_LWNET_ERROR(dwError); pszNameServer = NULL; dwNumServers++; } } } if (dwNumServers) { PDLINKEDLIST pListMember = NULL; DWORD iMember = 0; dwError = LWNetAllocateMemory(dwNumServers * sizeof(PSTR), (PVOID*)&ppszNameServerList); BAIL_ON_LWNET_ERROR(dwError); pListMember = pNameServerList; while (pListMember) { ppszNameServerList[iMember++] = (PSTR)pListMember->pItem; pListMember->pItem = NULL; pListMember = pListMember->pNext; } } *pppszNameServerList = ppszNameServerList; *pdwNumServers = dwNumServers; cleanup: regfree(&rx); LWNetDLinkedListFree(pNameServerList); LWNET_SAFE_FREE_STRING(pszNameServer); if (fp) { fclose(fp); } return dwError; error: *pppszNameServerList = NULL; *pdwNumServers = 0; if (ppszNameServerList) { LWNetFreeStringArray(ppszNameServerList, dwNumServers); } goto cleanup; }