Beispiel #1
0
MyString get_hostname(const condor_sockaddr& addr) {
	MyString ret;
	if (nodns_enabled())
		return convert_ipaddr_to_hostname(addr);

	condor_sockaddr targ_addr;

	// just like sin_to_string(), if given address is 0.0.0.0 or equivalent,
	// it changes to local IP address.
	if (addr.is_addr_any())
		targ_addr = get_local_ipaddr(addr.get_protocol());
	else
		targ_addr = addr;

	int e;
	char hostname[NI_MAXHOST];

	// if given address is link-local IPv6 address, it will have %NICname
	// at the end of string
	// we would like to avoid it
	if (targ_addr.is_ipv6())
		targ_addr.set_scope_id(0);

	e = condor_getnameinfo(targ_addr, hostname, sizeof(hostname), NULL, 0, 0);
	if (e)
		return ret;

	ret = hostname;
	return ret;
}
Beispiel #2
0
// This is obsolete function. do not use.
struct hostent *
condor_gethostbyaddr_ipv6(const char *addr, SOCKET_LENGTH_TYPE len, int type) {
    char _hostname[NI_MAXHOST];
    struct sockaddr_in sinaddr;
    int e;

    MSC_SUPPRESS_WARNING(6287) // warning: Redundant code: the left and right sub-expressions are identical
    if (type != AF_INET || type != PF_INET) {
        // fallback
        return condor_gethostbyaddr_ipv4(addr, len, type);
    }

	if (nodns_enabled()) {
	    return get_nodns_addr(addr);
	}

	memset(&sinaddr, 0, sizeof(sinaddr));
	sinaddr.sin_family = type;
	sinaddr.sin_addr = *(const struct in_addr*)addr;

#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
	sinaddr.sin_len = sizeof(struct sockaddr_in);
#endif

	e = getnameinfo((const struct sockaddr*)&sinaddr, sizeof(sinaddr), _hostname, sizeof(_hostname), NULL, 0, 0);
	if (e != 0)
        return NULL;

    // getnameinfo only returns hostname. in order to fill up struct hostent, call condor_gethotsbyname_ipv6
    return condor_gethostbyname_ipv6(_hostname);
}
Beispiel #3
0
std::vector<MyString> get_hostname_with_alias(const condor_sockaddr& addr)
{
	std::vector<MyString> ret;
	MyString hostname = get_hostname(addr);
	if (hostname.IsEmpty())
		return ret;
	ret.push_back(hostname);

	if (nodns_enabled())
		return ret; // no need to call further DNS functions.

	hostent* ent;
		//int aftype = addr.get_aftype();
		//ent = gethostbyname2(hostname.Value(), addr.get_aftype());

		// really should call gethostbyname2() however most platforms do not
		// support. (Solaris, HP-UX, IRIX)
		// complete DNS aliases can be only obtained by gethostbyname.
		// however, what happens if we call it in IPv6-only system?
		// can we get DNS aliases for the hostname that only contains
		// IPv6 addresses?
	ent = gethostbyname(hostname.Value());

	if (!ent)
		return ret;

	char** alias = ent->h_aliases;
	for (; *alias; ++alias) {
		ret.push_back(MyString(*alias));
	}
	return ret;
}
Beispiel #4
0
struct hostent *
condor_gethostbyname_ipv4(const char *name) {
	if (nodns_enabled()) {
	    return get_nodns_hostent(name);
	} else {
		return gethostbyname(name);
	}
}
Beispiel #5
0
struct hostent *
condor_gethostbyaddr_ipv4(const char *addr, SOCKET_LENGTH_TYPE len, int type) {
	if (nodns_enabled()) {
	    return get_nodns_addr(addr);
	} else {
		return gethostbyaddr(addr, len, type);
	}
}
Beispiel #6
0
std::vector<MyString> get_hostname_with_alias(const condor_sockaddr& addr)
{
	std::vector<MyString> prelim_ret;
	std::vector<MyString> actual_ret;

	MyString hostname = get_hostname(addr);
	if (hostname.IsEmpty())
		return prelim_ret;

	// we now start to construct a list (prelim_ret) of the hostname and all
	// the aliases.  first the name itself.
	prelim_ret.push_back(hostname);

	if (nodns_enabled())
		// don't need to verify this... the string is actually an IP here
		return prelim_ret; // no need to call further DNS functions.

	// now, add the aliases

	hostent* ent;
		//int aftype = addr.get_aftype();
		//ent = gethostbyname2(hostname.Value(), addr.get_aftype());

		// really should call gethostbyname2() however most platforms do not
		// support. (Solaris, HP-UX, IRIX)
		// complete DNS aliases can be only obtained by gethostbyname.
		// however, what happens if we call it in IPv6-only system?
		// can we get DNS aliases for the hostname that only contains
		// IPv6 addresses?
	ent = gethostbyname(hostname.Value());

	if (ent) {
		char** alias = ent->h_aliases;
		for (; *alias; ++alias) {
			prelim_ret.push_back(MyString(*alias));
		}
	}

	// WARNING! there is a reason this is implimented as two separate loops,
	// so please don't try to combine them.
	//
	// calling verify_name_has_ip() will potentially overwrite static data that
	// is referred to by ent->h_aliases (man 3 gethostbyname, see notes).  so
	// first, we push the name and then all aliases into the MyString vector
	// prelim_ret, and then verify them in the following loop.

	for (unsigned int i = 0; i < prelim_ret.size(); i++) {
		if(verify_name_has_ip(prelim_ret[i], addr)) {
			actual_ret.push_back(prelim_ret[i]);
		} else {
			dprintf(D_ALWAYS, "WARNING: forward resolution of %s doesn't match %s!\n",
					prelim_ret[i].Value(), addr.to_ip_string().Value());
		}
	}

	return actual_ret;
}
Beispiel #7
0
std::vector<condor_sockaddr> resolve_hostname(const MyString& hostname)
{
	std::vector<condor_sockaddr> ret;
	if (nodns_enabled()) {
		condor_sockaddr addr = convert_hostname_to_ipaddr(hostname);
		if (addr == condor_sockaddr::null)
			return ret;
		ret.push_back(addr);
		return ret;
	}
	return resolve_hostname_raw(hostname);
}
Beispiel #8
0
MyString get_fqdn_from_hostname(const MyString& hostname) {
	if (hostname.FindChar('.') != -1)
		return hostname;

	MyString ret;

	if (!nodns_enabled()) {
		addrinfo_iterator ai;
		int res  = ipv6_getaddrinfo(hostname.Value(), NULL, ai);
		if (res) {
			dprintf(D_HOSTNAME, "ipv6_getaddrinfo() could not look up %s: %s (%d)\n", 
				hostname.Value(), gai_strerror(res), res);
			return ret;
		}

		while (addrinfo* info = ai.next()) {
			if (info->ai_canonname) {
				if (strchr(info->ai_canonname, '.'))
					return info->ai_canonname;
			}
		}

		hostent* h = gethostbyname(hostname.Value());
		if (h && h->h_name && strchr(h->h_name, '.')) {
			return h->h_name;
		}
		if (h && h->h_aliases && *h->h_aliases) {
			for (char** alias = h->h_aliases; *alias; ++alias) {
				if (strchr(*alias, '.'))
					return *alias;
			}
		}
	}

	MyString default_domain;
	if (param(default_domain, "DEFAULT_DOMAIN_NAME")) {
		ret = hostname;
		if (ret[ret.Length() - 1] != '.')
			ret += ".";
		ret += default_domain;
	}
	return ret;
}
Beispiel #9
0
bool init_local_hostname_impl()
{
	bool local_hostname_initialized = false;
	if (param(local_hostname, "NETWORK_HOSTNAME")) {
		local_hostname_initialized = true;
		dprintf(D_HOSTNAME, "NETWORK_HOSTNAME says we are %s\n", local_hostname.Value());
	}

	if( ! local_hostname_initialized ) {
		// [TODO:IPV6] condor_gethostname is not IPv6 safe. Reimplement it.
		char hostname[MAXHOSTNAMELEN];
		int ret = condor_gethostname(hostname, sizeof(hostname));
		if (ret) {
			dprintf(D_ALWAYS, "condor_gethostname() failed. Cannot initialize "
					"local hostname, ip address, FQDN.\n");
			return false;
		}
		local_hostname = hostname;
	}

	MyString test_hostname = local_hostname;

	bool local_ipaddr_initialized = false;
	bool local_ipv4addr_initialized = false;
	bool local_ipv6addr_initialized = false;

	MyString network_interface;
	if (param(network_interface, "NETWORK_INTERFACE")) {
		if(local_ipaddr_initialized == false &&
			local_ipaddr.from_ip_string(network_interface)) {
			local_ipaddr_initialized = true;
			if(local_ipaddr.is_ipv4()) { 
				local_ipv4addr = local_ipaddr;
				local_ipv4addr_initialized = true;
			}
			if(local_ipaddr.is_ipv6()) { 
				local_ipv6addr = local_ipaddr;
				local_ipv6addr_initialized = true;
			}
		}
	}

	if( ! local_ipaddr_initialized ) {
		std::string ipv4, ipv6, ipbest;
		if( network_interface_to_ip("NETWORK_INTERFACE", network_interface.Value(), ipv4, ipv6, ipbest, NULL)) {
			ASSERT(local_ipaddr.from_ip_string(ipbest));
			// If this fails, network_interface_to_ip returns something invalid.
			local_ipaddr_initialized = true;
		} else {
			dprintf(D_ALWAYS, "Unable to identify IP address from interfaces.  None match NETWORK_INTERFACE=%s. Problems are likely.\n", network_interface.Value());
		}
		if((!ipv4.empty()) && local_ipv4addr.from_ip_string(ipv4)) {
			local_ipv4addr_initialized = true;
			ASSERT(local_ipv4addr.is_ipv4());
		}
		if((!ipv6.empty()) && local_ipv6addr.from_ip_string(ipv6)) {
			local_ipv6addr_initialized = true;
			ASSERT(local_ipv6addr.is_ipv6());
		}
	}

	bool local_fqdn_initialized = false;
	if (nodns_enabled()) {
			// condor_gethostname() returns a hostname with
			// DEFAULT_DOMAIN_NAME. Thus, it is always fqdn
		local_fqdn = local_hostname;
		local_fqdn_initialized = true;
		if (!local_ipaddr_initialized) {
			local_ipaddr = convert_hostname_to_ipaddr(local_hostname);
			local_ipaddr_initialized = true;
		}
	}

	addrinfo_iterator ai;

	if( ! nodns_enabled() ) {
		const int MAX_TRIES = 20;
		const int SLEEP_DUR = 3;
		bool gai_success = false;
		for(int try_count = 1; true; try_count++) {
			addrinfo hint = get_default_hint();
			hint.ai_family = AF_UNSPEC;
			int ret = ipv6_getaddrinfo(test_hostname.Value(), NULL, ai, hint);
			if(ret == 0) { gai_success = true; break; }
			if(ret != EAI_AGAIN ) {
				dprintf(D_ALWAYS, "init_local_hostname_impl: ipv6_getaddrinfo() could not look up '%s': %s (%d).  Error is not recoverable; giving up.  Problems are likely.\n", test_hostname.Value(), gai_strerror(ret), ret );
				gai_success = false;
				break;
			}

			dprintf(D_ALWAYS, "init_local_hostname_impl: ipv6_getaddrinfo() returned EAI_AGAIN for '%s'.  Will try again after sleeping %d seconds (try %d of %d).\n", test_hostname.Value(), SLEEP_DUR, try_count + 1, MAX_TRIES );
			if(try_count == MAX_TRIES) {
				dprintf(D_ALWAYS, "init_local_hostname_impl: ipv6_getaddrinfo() never succeeded. Giving up. Problems are likely\n");
				break;
			}
			sleep(SLEEP_DUR);
		}

		if(gai_success) {
			int local_hostname_desireability = 0;
#ifdef TEST_DNS_TODO
			int local_ipaddr_desireability = 0;
			int local_ipv4addr_desireability = 0;
			int local_ipv6addr_desireability = 0;
#endif
			while (addrinfo* info = ai.next()) {
				// TODO: the only time ai_canonname should be set is the first
				// record. Why are we testing its desirability?
				const char* name = info->ai_canonname;
				if (!name)
					continue;
				condor_sockaddr addr(info->ai_addr);

				int desireability = addr.desirability();

				const char * result = "skipped for low score";
				if(desireability > local_hostname_desireability) {
					result = "new winner";
					dprintf(D_HOSTNAME, "   I like it.\n");
					local_hostname_desireability = desireability;

					const char* dotpos = strchr(name, '.');
					if (dotpos) { // consider it as a FQDN
						local_fqdn = name;
						local_hostname = local_fqdn.Substr(0, dotpos-name-1);
					} else {
						local_hostname = name;
						local_fqdn = local_hostname;
						MyString default_domain;
						if (param(default_domain, "DEFAULT_DOMAIN_NAME")) {
							if (default_domain[0] != '.')
								local_fqdn += ".";
							local_fqdn += default_domain;
						}
					}
				}
				dprintf(D_HOSTNAME, "hostname: %s (score %d) %s\n", name, desireability, result);

#ifdef TEST_DNS_TODO
				// Resist urge to set local_ip*addr_initialized=true,
				// We want to repeatedly retest this looking for 
				// better results.
				if (!local_ipaddr_initialized) {
					replace_higher_scoring_addr("IP", 
						local_ipaddr, local_ipaddr_desireability, 
						addr, desireability);
				}

				if (addr.is_ipv4() && !local_ipv4addr_initialized) {
					replace_higher_scoring_addr("IPv4", 
						local_ipv4addr, local_ipv4addr_desireability, 
						addr, desireability);
				}

				if (addr.is_ipv6() && !local_ipv6addr_initialized) {
					replace_higher_scoring_addr("IPv6", 
						local_ipv6addr, local_ipv6addr_desireability, 
						addr, desireability);
				}
#else
	// Make Fedora quit complaining.
	if( local_ipv4addr_initialized && local_ipv6addr_initialized && local_fqdn_initialized ) {
		local_ipv4addr_initialized = false;
		local_ipv6addr_initialized = false;
		local_fqdn_initialized = false;
	}
#endif
			}
		}

	}

	return true;
}
Beispiel #10
0
int get_fqdn_and_ip_from_hostname(const MyString& hostname,
		MyString& fqdn, condor_sockaddr& addr) {

	MyString ret;
	condor_sockaddr ret_addr;
	bool found_ip = false;

	// if the hostname contains dot, hostname is assumed to be full hostname
	if (hostname.FindChar('.') != -1) {
		ret = hostname;
	}

	if (nodns_enabled()) {
		// if nodns is enabled, convert hostname to ip address directly
		ret_addr = convert_hostname_to_ipaddr(hostname);
		found_ip = true;
	} else {
		// we look through getaddrinfo and gethostbyname
		// to further seek fully-qualified domain name and corresponding
		// ip address
		addrinfo_iterator ai;
		int res  = ipv6_getaddrinfo(hostname.Value(), NULL, ai);
		if (res) {
			dprintf(D_HOSTNAME, "ipv6_getaddrinfo() could not look up %s: %s (%d)\n", hostname.Value(),
				gai_strerror(res), res);
			return 0;
		}

		while (addrinfo* info = ai.next()) {
			if (info->ai_canonname) {
				fqdn = info->ai_canonname;
				addr = condor_sockaddr(info->ai_addr);
				return 1;
			}
		}

		hostent* h = gethostbyname(hostname.Value());
		if (h && h->h_name && strchr(h->h_name, '.')) {
			fqdn = h->h_name;
			addr = condor_sockaddr((sockaddr*)h->h_addr);
			return 1;
		}
		if (h && h->h_aliases && *h->h_aliases) {
			for (char** alias = h->h_aliases; *alias; ++alias) {
				if (strchr(*alias, '.')) {
					fqdn = *alias;
					addr = condor_sockaddr((sockaddr*)h->h_addr);
					return 1;
				}
			}
		}
	}

	MyString default_domain;

	// if FQDN is still unresolved, try DEFAULT_DOMAIN_NAME
	if (ret.Length() == 0 && param(default_domain, "DEFAULT_DOMAIN_NAME")) {
		ret = hostname;
		if (ret[ret.Length() - 1] != '.')
			ret += ".";
		ret += default_domain;
	}

	if (ret.Length() > 0 && found_ip) {
		fqdn = ret;
		addr = ret_addr;
		return 1;
	}
	return 0;
}
Beispiel #11
0
// This is obsolete function. do not use.
struct hostent *
condor_gethostbyname_ipv6(const char* name) {
    #define MAXADDR 16
    static struct hostent hostent;
	static struct in_addr addr_list[MAXADDR];
	static char *h_addr_list[MAXADDR+1];
	static char h_name[NI_MAXHOST];
	struct addrinfo hints;
	struct addrinfo* res = NULL;
	struct addrinfo* iter;
	struct hostent* hostent_alias = NULL;
	int e;
	int addrcount = 0;
	int first = 1;

    if (nodns_enabled()) {
        return get_nodns_hostent(name);
    }

    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
#ifdef WIN32
	// AI_ADDRCONFIG is supported since Windows Server 2008 SDK.
    hints.ai_flags = AI_CANONNAME;
#else
    hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME;
#endif 

    e = getaddrinfo(name, NULL, &hints, &res);
    if (e != 0)
        return NULL;

    memset(h_addr_list, 0, sizeof(h_addr_list));
    memset(h_name, 0, sizeof(h_name));
    memset(&hostent, 0, sizeof(hostent));
    hostent.h_name = h_name;

	// fill up h_aliases field by calling gethostbyname().
	// it seems there is no way to get DNS aliases from IPv6 functions.
	// **YOU SHOULD NOT CALL gethostbyname() inside this fn after this point**
	hostent_alias = gethostbyname(name);
	if (hostent_alias) {
		hostent.h_aliases = hostent_alias->h_aliases;
	}

    hostent.h_addrtype = AF_INET;
    hostent.h_length = sizeof(struct in_addr);
    hostent.h_addr_list = &h_addr_list[0];

    for ( iter = res; iter != NULL; iter = iter->ai_next ) {
        if (first) {
            // first canonical name is primary name for the host.
            // rest is aliases
            if ( iter->ai_canonname ) {
                strncpy(h_name, iter->ai_canonname, sizeof(h_name)-1);
                first = 0;
            }
        }
        // pick only IPv4 address
        if (iter->ai_addr && iter->ai_addr->sa_family == AF_INET) {
            struct sockaddr_in* _sin = (struct sockaddr_in*)iter->ai_addr;
            memcpy(&addr_list[addrcount], &_sin->sin_addr, sizeof(struct in_addr));
            h_addr_list[addrcount] = (char*)&addr_list[addrcount];
            addrcount++;
            if (addrcount == MAXADDR)
                break;
        }
    }

    h_addr_list[addrcount] = NULL;
    freeaddrinfo(res);
    return &hostent;
}
Beispiel #12
0
int
condor_gethostname(char *name, size_t namelen) {

	if (nodns_enabled()) {

		char tmp[MAXHOSTNAMELEN];
		char *param_buf;

			// First, we try NETWORK_INTERFACE
		if ( (param_buf = param( "NETWORK_INTERFACE" )) ) {
			char ip_str[MAXHOSTNAMELEN];

			// reimplement with condor_sockaddr and to_ip_string()
			condor_sockaddr addr;

			dprintf( D_HOSTNAME, "NO_DNS: Using NETWORK_INTERFACE='%s' "
					 "to determine hostname\n", param_buf );

			snprintf( ip_str, MAXHOSTNAMELEN, "%s", param_buf );
			free( param_buf );

			if (!addr.from_ip_string(ip_str)) {
				dprintf(D_HOSTNAME,
						"NO_DNS: NETWORK_INTERFACE is invalid: %s\n",
						ip_str);
				return -1;
			}

			MyString hostname = convert_ipaddr_to_hostname(addr);
			if (hostname.Length() >= (int) namelen) {
				return -1;
			}
			strcpy(name, hostname.Value());
			return 0;
		}

			// Second, we try COLLECTOR_HOST

			// To get the hostname with NODNS we are going to jump
			// through some hoops. We will try to make a UDP
			// connection to the COLLECTOR_HOST. This will result in not
			// only letting us call getsockname to find an IP for this
			// machine, but it will select the proper IP that we can
			// use to contact the COLLECTOR_HOST
		if ( (param_buf = param( "COLLECTOR_HOST" )) ) {

			//struct hostent *collector_ent;
			int s;
			//SOCKET_LENGTH_TYPE addr_len;
			char collector_host[MAXHOSTNAMELEN];
			char *idx;
			//struct sockaddr_in addr, collector_addr;
			condor_sockaddr collector_addr;
			condor_sockaddr addr;
			std::vector<condor_sockaddr> collector_addrs;

			dprintf( D_HOSTNAME, "NO_DNS: Using COLLECTOR_HOST='%s' "
					 "to determine hostname\n", param_buf );

				// Get only the name portion of the COLLECTOR_HOST
			if ((idx = index(param_buf, ':'))) {
				*idx = '\0';
			}
			snprintf( collector_host, MAXHOSTNAMELEN, "%s", param_buf );
			free( param_buf );

				// Now that we have the name we need an IP

			collector_addrs = resolve_hostname(collector_host);
			if (collector_addrs.empty()) {
				dprintf(D_HOSTNAME,
						"NO_DNS: Failed to get IP address of collector "
						"host '%s'\n", collector_host);
				return -1;
			}

			collector_addr = collector_addrs.front();
			collector_addr.set_port(1980);

				// We are doing UDP, the benefit is connect will not send
				// any network traffic on a UDP socket
			if (-1 == (s = socket(collector_addr.get_aftype(), 
								  SOCK_DGRAM, 0))) {
				dprintf(D_HOSTNAME,
						"NO_DNS: Failed to create socket, errno=%d (%s)\n",
						errno, strerror(errno));
				return -1;
			}

			if (condor_connect(s, collector_addr)) {
				perror("connect");
				dprintf(D_HOSTNAME,
						"NO_DNS: Failed to bind socket, errno=%d (%s)\n",
						errno, strerror(errno));
				return -1;
			}

			if (condor_getsockname(s, addr)) {
				dprintf(D_HOSTNAME,
						"NO_DNS: Failed to get socket name, errno=%d (%s)\n",
						errno, strerror(errno));
				return -1;
			}

			MyString hostname = convert_ipaddr_to_hostname(addr);
			if (hostname.Length() >= (int) namelen) {
				return -1;
			}
			strcpy(name, hostname.Value());
			return 0;
		}

			// Last, we try gethostname()
		if ( gethostname( tmp, MAXHOSTNAMELEN ) == 0 ) {

			dprintf( D_HOSTNAME, "NO_DNS: Using gethostname()='%s' "
					 "to determine hostname\n", tmp );

			std::vector<condor_sockaddr> addrs;
			MyString my_hostname(tmp);
			addrs = resolve_hostname_raw(my_hostname);
			if (addrs.empty()) {
				dprintf(D_HOSTNAME,
						"NO_DNS: resolve_hostname_raw() failed, errno=%d"
						" (%s)\n", errno, strerror(errno));
				return -1;
			}

			MyString hostname = convert_ipaddr_to_hostname(addrs.front());
			if (hostname.Length() >= (int) namelen) {
				return -1;
			}
			strcpy(name, hostname.Value());
			return 0;
		}

		dprintf(D_HOSTNAME,
				"Failed in determining hostname for this machine\n");
		return -1;

	} else {
		return gethostname(name, namelen);
	}
}
Beispiel #13
0
void init_local_hostname()
{
		// [m.]
		// initializing local hostname, ip address, fqdn was
		// super complex.
		//
		// implementation was scattered over condor_netdb and
		// my_hostname, get_full_hostname.
		//
		// above them has duplicated code in many ways.
		// so I aggregated all of them into here.

	bool ipaddr_inited = false;
	char hostname[MAXHOSTNAMELEN];
	int ret;

		// [TODO:IPV6] condor_gethostname is not IPv6 safe.
		// reimplement it.
	ret = condor_gethostname(hostname, sizeof(hostname));
	if (ret) {
		dprintf(D_ALWAYS, "condor_gethostname() failed. Cannot initialize "
				"local hostname, ip address, FQDN.\n");
		return;
	}

	dprintf(D_HOSTNAME, "condor_gethostname() claims we are %s\n", hostname);

	// Fallback case.
	local_hostname = hostname;

		// if NETWORK_INTERFACE is defined, we use that as a local ip addr.
	MyString network_interface;
	if (param(network_interface, "NETWORK_INTERFACE", "*")) {
		if (local_ipaddr.from_ip_string(network_interface))
			ipaddr_inited = true;
	}

		// Dig around for an IP address in the interfaces
		// TODO WARNING: Will only return IPv4 addresses!
	if( ! ipaddr_inited ) {
		std::string ip;
		if( ! network_interface_to_ip("NETWORK_INTERFACE", network_interface.Value(), ip, NULL)) {
			dprintf(D_ALWAYS, "Unable to identify IP address from interfaces.  None matches NETWORK_INTERFACE=%s. Problems are likely.\n", network_interface.Value());
			return;
		}
		if ( ! local_ipaddr.from_ip_string(ip))
		{
			// Should not happen; means network_interface_to_ip returned
			// invalid IP address.
			ASSERT(FALSE);
		}
		ipaddr_inited = true;
	}

		// now initialize hostname and fqdn
	if (nodns_enabled()) { // if nodns is enabled, we can cut some slack.
			// condor_gethostname() returns a hostname with
			// DEFAULT_DOMAIN_NAME. Thus, it is always fqdn
		local_fqdn = hostname;
		if (!ipaddr_inited) {
			local_ipaddr = convert_hostname_to_ipaddr(local_hostname);
		}
		return;
	}

	addrinfo_iterator ai;
	ret = ipv6_getaddrinfo(hostname, NULL, ai);
	if (ret) {
			// write some error message
		dprintf(D_HOSTNAME, "hostname %s cannot be resolved by getaddrinfo\n",
				hostname);
		return;
	}
	
	int local_hostname_desireability = 0;
	while (addrinfo* info = ai.next()) {
		const char* name = info->ai_canonname;
		if (!name)
			continue;
		condor_sockaddr addr(info->ai_addr);

		int desireability = 0;
		if (addr.is_loopback())            { desireability = 1; }
		else if(addr.is_private_network()) { desireability = 2; }
		else                               { desireability = 3; }
		dprintf(D_HOSTNAME, "Considering %s (Ranked at %d) as possible local hostname versus %s/%s (%d)\n", name, desireability, local_hostname.Value(), local_fqdn.Value(), local_hostname_desireability);
		if(desireability < local_hostname_desireability) { continue; }
		local_hostname_desireability = desireability;

		if (!ipaddr_inited)
			local_ipaddr = addr;

		const char* dotpos = strchr(name, '.');
		if (dotpos) { // consider it as a FQDN
			local_fqdn = name;
			local_hostname = local_fqdn.Substr(0, dotpos-name-1);
		} else {
			local_hostname = name;
			local_fqdn = local_hostname;
			MyString default_domain;
			if (param(default_domain, "DEFAULT_DOMAIN_NAME")) {
				if (default_domain[0] != '.')
					local_fqdn += ".";
				local_fqdn += default_domain;
			}
		}
	}

	dprintf(D_HOSTNAME, "Identifying myself as: Short:: %s, Long: %s, IP: %s\n", local_hostname.Value(), local_fqdn.Value(), local_ipaddr.to_ip_string().Value());
	hostname_initialized = true;
}