/* * Function: get_hostent_from_etc_hosts * * Purpose: Read the ETC_HOSTS file and check if it contains the given name. * Return the result in a hostent structure. * * Parameters: * ctx -- The validation context. * name -- The domain name or IP address in string form. * af -- The address family: AF_INET or AF_INET6. * ret -- Pointer to a hostent structure to return the result. * This parameter must not be NULL. * buf -- A buffer to store auxiliary data. This parameter must not be NULL. * buflen -- Length of the buffer 'buf'. * offset -- Pointer to an integer variable that contains the offset in the buffer * 'buf', where data can be written. When this function writes any data * in the auxiliary data, the offset is incremented accordingly. This * parameter must not be NULL. * * Return value: Returns NULL on failure and 'ret' on success. * * See also: get_hostent_from_response() */ static struct hostent * get_hostent_from_etc_hosts(val_context_t * ctx, const char *name, int af, struct hostent *ret, char *buf, int buflen, int *offset) { int orig_offset = 0; struct hosts *hs = NULL; struct hosts *h_prev = NULL; if ((ret == NULL) || (buf == NULL) || (offset == NULL) || (*offset < 0)) { return NULL; } /* * Parse the /etc/hosts file */ hs = parse_etc_hosts(name); orig_offset = *offset; memset(ret, 0, sizeof(struct hostent)); /* * XXX: todo -- can hs have more than one element ? */ while (hs) { struct sockaddr_in sa; #if defined( WIN32 ) size_t addrlen4 = sizeof(struct sockaddr_in); #endif #ifdef VAL_IPV6 struct sockaddr_in6 sa6; #if defined( WIN32 ) size_t addrlen6 = sizeof(struct sockaddr_in6); #endif #endif char addr_buf[INET6_ADDRSTRLEN]; int i, alias_count; int len = 0; const char *addr = NULL; size_t buflen = INET6_ADDRSTRLEN; if ((af == AF_INET) && (INET_PTON(AF_INET, hs->address, ((struct sockaddr *)&sa), &addrlen4) > 0)) { INET_NTOP(AF_INET, (&sa), sizeof(sa), addr_buf, buflen, addr); val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv4"); val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s", addr ); } #ifdef VAL_IPV6 else if ((af == AF_INET6) && (INET_PTON(AF_INET6, hs->address, ((struct sockaddr *)&sa6), &addrlen6) > 0)) { INET_NTOP(AF_INET6, (&sa6), sizeof(sa6), addr_buf, buflen, addr); val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): type of address is IPv6"); val_log(ctx, LOG_DEBUG, "get_hostent_from_etc_hosts(): Address is: %s", addr ); } #endif else { /* * not a valid address ... skip this line */ val_log(ctx, LOG_WARNING, "get_hostent_from_etc_hosts(): error in address format: %s", hs->address); h_prev = hs; hs = hs->next; FREE_HOSTS(h_prev); continue; } // Name len = (hs->canonical_hostname == NULL) ? 0 : strlen(hs->canonical_hostname); if (hs->canonical_hostname) { ret->h_name = (char *) bufalloc(buf, buflen, offset, len + 1); if (ret->h_name == NULL) { goto err; } memcpy(ret->h_name, hs->canonical_hostname, len + 1); } else { ret->h_name = NULL; } // Aliases alias_count = 0; while (hs->aliases[alias_count]) { alias_count++; } alias_count++; ret->h_aliases = (char **) bufalloc(buf, buflen, offset, alias_count * sizeof(char *)); if (ret->h_aliases == NULL) { goto err; } for (i = 0; i < alias_count; i++) { len = (hs->aliases[i] == NULL) ? 0 : strlen(hs->aliases[i]); if (hs->aliases[i]) { ret->h_aliases[i] = (char *) bufalloc(buf, buflen, offset, len + 1); if (ret->h_aliases[i] == NULL) { goto err; } memcpy(ret->h_aliases[i], hs->aliases[i], len + 1); } else { ret->h_aliases[i] = NULL; } } // Addresses ret->h_addr_list = (char **) bufalloc(buf, buflen, offset, 2 * sizeof(char *)); if ((ret->h_addr_list == NULL) || ((af != AF_INET) && (af != AF_INET6))) { goto err; } if (af == AF_INET) { ret->h_addrtype = AF_INET; ret->h_length = sizeof(struct in_addr); ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, offset, sizeof(struct in_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr)); ret->h_addr_list[1] = 0; } #ifdef VAL_IPV6 else if (af == AF_INET6) { ret->h_addrtype = AF_INET6; ret->h_length = sizeof(struct in6_addr); ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, offset, sizeof(struct in6_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa6.sin6_addr, sizeof(struct in6_addr)); ret->h_addr_list[1] = 0; } #endif /* * clean up host list */ while (hs) { h_prev = hs; hs = hs->next; FREE_HOSTS(h_prev); } return ret; } return NULL; err: /* * clean up host list */ while (hs) { h_prev = hs; hs = hs->next; FREE_HOSTS(h_prev); } *offset = orig_offset; return NULL; } /* get_hostent_from_etc_hosts() */
int NetKeepaliveInit(char *src, char *dst, int maximal_keepalive, int family) { struct timeval tv; #ifdef WIN32 hndliphlp = LoadLibrary("IPHLPAPI.DLL"); if (!hndliphlp) { Display(LOG_LEVEL_3, ELError, "NetKeepaliveInit", HEX_STR_CANT_CREATE_ICMP_HNDL_FILE); return 1; } if (family == AF_INET6) { // Try to load IPv6 // support functions // from iphlpapi // Icmp6CreateFile = (HANDLE (WINAPI *)(void)) GetProcAddress(hndliphlp, "Icmp6CreateFile"); IcmpCloseHandle = (BOOL (WINAPI *)(HANDLE)) GetProcAddress(hndliphlp, "IcmpCloseHandle"); Icmp6SendEcho2 = (DWORD (WINAPI *)(HANDLE, HANDLE, FARPROC, PVOID, struct sockaddr_in6*, struct sockaddr_in6*, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD)) GetProcAddress(hndliphlp, "Icmp6SendEcho2"); Icmp6ParseReplies = (DWORD (WINAPI *)(LPVOID, DWORD)) GetProcAddress(hndliphlp, "Icmp6ParseReplies"); if( (Icmp6CreateFile == NULL) || (IcmpCloseHandle == NULL) || (Icmp6SendEcho2 == NULL) || (Icmp6ParseReplies == NULL) ) { Display(LOG_LEVEL_3, ELError, "NetKeepaliveInit", HEX_STR_CANT_CREATE_ICMP_HNDL_FILE); return 1; } hHandle = Icmp6CreateFile(); } #ifdef V4V6_SUPPORT else if (family == AF_INET) { // Try to load IPv4 // support functions // from iphlpapi // IcmpCreateFile = (HANDLE (WINAPI *)(VOID)) GetProcAddress(hndliphlp, "IcmpCreateFile"); IcmpCloseHandle = (BOOL (WINAPI *)(HANDLE)) GetProcAddress(hndliphlp, "IcmpCloseHandle"); IcmpSendEcho2 = (DWORD (WINAPI *)(HANDLE, HANDLE, FARPROC, PVOID, IPAddr, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD)) GetProcAddress(hndliphlp, "IcmpSendEcho2"); IcmpParseReplies = (DWORD (WINAPI *)(LPVOID, DWORD)) GetProcAddress(hndliphlp, "IcmpParseReplies"); if ( (IcmpCreateFile == NULL) || (IcmpCloseHandle == NULL) || (IcmpSendEcho2 == NULL) || (IcmpParseReplies == NULL) ) { Display(LOG_LEVEL_3, ELError, "NetKeepaliveInit", HEX_STR_CANT_CREATE_ICMP_HNDL_FILE); return 1; } hHandle = IcmpCreateFile(); } #endif if (hHandle == INVALID_HANDLE_VALUE) { Display(LOG_LEVEL_3, ELError, "NetKeepaliveInit", HEX_STR_CANT_CREATE_ICMP_HNDL_FILE); return 1; } #endif /* Load the structure with passed in AND * initial values */ seqn = 0; if (strncpy(ka.host, dst, sizeof(ka.host)) == NULL) return 1; ka.maximal_keepalive = maximal_keepalive; ka.current_keepalive = KA_INITIAL_KEEPALIVE; ka.major_fuzz = (float) 0.60; ka.minor_fuzz = (float) 0.075; /* And initialize the next event */ /* Initial timeout is set to five seconds */ GETTIMEOFDAY(&tv, NULL); ka.next_event.tv_sec = tv.tv_sec + KA_INITIAL_KEEPALIVE; ka.next_event.tv_usec = tv.tv_usec; /* initialize the random source */ SRANDOM(tv.tv_usec); /* set the family */ ka.family = family; /* get a ping socket and a monitor socket */ if (family == AF_INET6) { INET_PTON(AF_INET6, dst, &ka.sa6.sin6_addr); ka.sa6.sin6_family = AF_INET6; INET_PTON(AF_INET6, src, &ka.sa6_local.sin6_addr); ka.sa6_local.sin6_family = AF_INET6; #ifndef WIN32 ka.keepalive_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); #endif } #ifdef V4V6_SUPPORT else if (family == AF_INET) { INET_PTON(AF_INET, dst, &ka.sa.sin_addr); ka.sa.sin_family = AF_INET; INET_PTON(AF_INET, src, &ka.sa_local.sin_addr); ka.sa_local.sin_family = AF_INET; #ifndef WIN32 ka.keepalive_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); #endif } #endif /* V4V6_SUPPORT */ ka.consecutive_timeout = 0; ka.still_up = 0; ka.doit = 1; ka.count = 0; ka.got_read = 0; ka.got_write = 0; ka.pinged = 1; /* ok, we are inialized */ ka.init = 1; Display(LOG_LEVEL_3, ELInfo, "NetKeepaliveInit", HEX_STR_KEEPALIVE_INITIALIZED, dst, maximal_keepalive); return 0; }
/* * Function: val_gethostbyname2_r * * Purpose: A validating DNSSEC-aware version of the reentrant gethostbyname2_r * function. This function supports both IPv4 and IPv6 addresses. * * Parameters: * ctx -- The validation context. Can be NULL for default value. * name -- The domain name or IP address in string format. * af -- Address family AF_INET or AF_INET6 * ret -- Pointer to a hostent variable to store the return value. * This parameter must not be NULL. * buf -- Pointer to a buffer to store auxiliary data. This * parameter must not be NULL. * buflen -- Length of the buffer 'buf'. * result -- Pointer to a variable of type (struct hostent *). This * parameter must not be NULL. *result will contain NULL on * failure and will point to the 'ret' parameter on success. * h_errnop -- Pointer to an integer variable to return the h_errno error * code. This parameter must not be NULL. * val_status -- A pointer to a val_status_t variable to hold the * returned validation-status value. This parameter * must not be NULL. * If successful, *val_status will contain a success * code. If there is a failure, *val_status will contain * the validator error code. To test whether the returned * error code represents a trustworthy status, the caller * can use the val_istrusted() function. * * Return value: 0 on success, and a non-zero error-code on failure. * * See also: val_gethostbyname2(), val_gethostbyname_r(), val_istrusted() */ int val_gethostbyname2_r(val_context_t * context, const char *name, int af, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop, val_status_t * val_status) { struct sockaddr_in sa; #if defined( WIN32 ) size_t addrlen4 = sizeof(struct sockaddr_in); #endif #ifdef VAL_IPV6 struct sockaddr_in6 sa6; #if defined( WIN32 ) size_t addrlen6 = sizeof(struct sockaddr_in6); #endif #endif int offset = 0; val_status_t local_ans_status = VAL_OOB_ANSWER; int trusted = 0; int retval; struct val_result_chain *results = NULL; u_int16_t type; val_context_t *ctx = NULL; *val_status = VAL_DONT_KNOW; if (!name || !ret || !h_errnop || !val_status || !result || !buf) { goto err; } ctx = val_create_or_refresh_context(context); /* does CTX_LOCK_POL_SH */ if (ctx == NULL) goto err; if (VAL_NO_ERROR == val_is_local_trusted(ctx, &trusted)) { if (trusted) { local_ans_status = VAL_TRUSTED_ANSWER; } } /* * Check if the address-family is AF_INET and the address is an IPv4 address */ if ((af == AF_INET) && (INET_PTON(AF_INET, name, ((struct sockaddr *)&sa), &addrlen4) > 0)) { memset(ret, 0, sizeof(struct hostent)); // Name ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1); if (ret->h_name == NULL) { goto err; } memcpy(ret->h_name, name, strlen(name) + 1); // Alias ret->h_aliases = (char **) bufalloc(buf, buflen, &offset, sizeof(char *)); if (ret->h_aliases == NULL) { goto err; } ret->h_aliases[0] = 0; // Address ret->h_addrtype = AF_INET; ret->h_length = sizeof(struct in_addr); ret->h_addr_list = (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *)); if (ret->h_addr_list == NULL) { goto err; } ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, &offset, sizeof(struct in_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa.sin_addr, sizeof(struct in_addr)); ret->h_addr_list[1] = 0; *val_status = VAL_TRUSTED_ANSWER; *h_errnop = NETDB_SUCCESS; *result = ret; } #ifdef VAL_IPV6 /* * Check if the address-family is AF_INET6 and the address is an IPv6 address */ else if ((af == AF_INET6) && (INET_PTON(AF_INET6, name, ((struct sockaddr *)&sa6), &addrlen6) > 0)) { memset(ret, 0, sizeof(struct hostent)); // Name ret->h_name = bufalloc(buf, buflen, &offset, strlen(name) + 1); if (ret->h_name == NULL) { goto err; } memcpy(ret->h_name, name, strlen(name) + 1); // Alias ret->h_aliases = (char **) bufalloc(buf, buflen, &offset, sizeof(char *)); if (ret->h_aliases == NULL) { goto err; } ret->h_aliases[0] = 0; // Address ret->h_addrtype = AF_INET6; ret->h_length = sizeof(struct in6_addr); ret->h_addr_list = (char **) bufalloc(buf, buflen, &offset, 2 * sizeof(char *)); if (ret->h_addr_list == NULL) { goto err; } ret->h_addr_list[0] = (char *) bufalloc(buf, buflen, &offset, sizeof(struct in6_addr)); if (ret->h_addr_list[0] == NULL) { goto err; } memcpy(ret->h_addr_list[0], &sa6.sin6_addr, sizeof(struct in6_addr)); ret->h_addr_list[1] = 0; *val_status = VAL_TRUSTED_ANSWER; *h_errnop = NETDB_SUCCESS; *result = ret; } #endif else if (NULL != (*result = get_hostent_from_etc_hosts(ctx, name, af, ret, buf, buflen, &offset))) { /* * First check the ETC_HOSTS file * XXX: TODO check the order in the ETC_HOST_CONF file */ *val_status = local_ans_status; *h_errnop = NETDB_SUCCESS; } else { #ifdef VAL_IPV6 if (af == AF_INET6) type = ns_t_aaaa; else #endif type = ns_t_a; /* * Query the validator */ if (VAL_NO_ERROR == (retval = val_resolve_and_check(ctx, name, ns_c_in, type, 0, &results))) { /* * Convert the validator result into hostent */ *result = get_hostent_from_response(ctx, af, ret, results, h_errnop, buf, buflen, &offset, val_status); } else { val_log(ctx, LOG_ERR, "val_gethostbyname2_r(): val_resolve_and_check failed - %s", p_val_err(retval)); } if (*result == NULL) { goto err; } else { val_free_result_chain(results); results = NULL; *h_errnop = NETDB_SUCCESS; } } val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned success, herrno = %d, val_status = %s", *h_errnop, val_status? p_val_status(*val_status) : NULL); CTX_UNLOCK_POL(ctx); return 0; err: if (result) { *result = NULL; } if (h_errnop) *h_errnop = NO_RECOVERY; if (ctx) { val_log(ctx, LOG_DEBUG, "val_gethostbyname2_r returned failure, herrno = %d, val_status = %s", *h_errnop, val_status? p_val_status(*val_status) : NULL); CTX_UNLOCK_POL(ctx); } return (NO_RECOVERY); }