struct in_addr * wd_gethostbyname(const char *name) { struct hostent *he; struct in_addr *h_addr, *in_addr_temp; /* XXX Calling function is reponsible for free() */ h_addr = safe_malloc(sizeof(struct in_addr)); LOCK_GHBN(); he = gethostbyname(name); if (he == NULL) { free(h_addr); UNLOCK_GHBN(); return NULL; } mark_online(); in_addr_temp = (struct in_addr *)he->h_addr_list[0]; h_addr->s_addr = in_addr_temp->s_addr; UNLOCK_GHBN(); return h_addr; }
void mark_auth_online() { int before; int after; before = is_auth_online(); time(&last_auth_online_time); after = is_auth_online(); if (before != after) { debug(LOG_INFO, "AUTH_ONLINE status became %s", (after ? "ON" : "OFF")); } /* If auth server is online it means we're definately online */ mark_online(); }
struct in_addr * wd_gethostbyname(const char *name) { struct addrinfo hints; struct addrinfo *result, *rp; struct in_addr *h_addr; int s; /* XXX Calling function is reponsible for free() */ h_addr = safe_malloc(sizeof(struct in_addr)); //h_addr = (struct in_addr *)malloc(sizeof(struct in_addr)); //h_addr->s_addr = 0x78c58112; //return h_addr; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = 0; hints.ai_protocol = 0; /* Any protocol */ s = getaddrinfo(name, NULL, &hints, &result); if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); free(h_addr); return NULL; } for (rp = result; rp != NULL; rp = rp->ai_next) { struct sockaddr_in *addr = (struct sockaddr_in *)rp->ai_addr; //const char *ip = inet_ntoa(addr->sin_addr); //fprintf(stdout, "ip=%s, name=%p\n", ip, rp->ai_canonname); *h_addr = addr->sin_addr; break; } freeaddrinfo(result); mark_online(); return h_addr; }
/* Helper function called by connect_auth_server() to do the actual work including recursion * DO NOT CALL DIRECTLY @param level recursion level indicator must be 0 when not called by _connect_auth_server() */ int _connect_auth_server(int level) { s_config *config = config_get_config(); t_auth_serv *auth_server = NULL; struct in_addr *h_addr; int num_servers = 0; char *hostname = NULL; char *popular_servers[] = { "www.google.com", "www.yahoo.com", NULL }; char **popularserver; char *ip; struct sockaddr_in their_addr; int sockfd; /* If there are no auth servers, error out, from scan-build warning. */ if (NULL == config->auth_servers) { return (-1); } /* XXX level starts out at 0 and gets incremented by every iterations. */ level++; /* * Let's calculate the number of servers we have */ for (auth_server = config->auth_servers; auth_server; auth_server = auth_server->next) { num_servers++; } debug(LOG_DEBUG, "Level %d: Calculated %d auth servers in list", level, num_servers); if (level > num_servers) { /* * We've called ourselves too many times * This means we've cycled through all the servers in the server list * at least once and none are accessible */ return (-1); } /* * Let's resolve the hostname of the top server to an IP address */ auth_server = config->auth_servers; hostname = auth_server->authserv_hostname; debug(LOG_DEBUG, "Level %d: Resolving auth server [%s]", level, hostname); h_addr = wd_gethostbyname(hostname); if (!h_addr) { /* * DNS resolving it failed * * Can we resolve any of the popular servers ? */ debug(LOG_DEBUG, "Level %d: Resolving auth server [%s] failed", level, hostname); for (popularserver = popular_servers; *popularserver; popularserver++) { debug(LOG_DEBUG, "Level %d: Resolving popular server [%s]", level, *popularserver); h_addr = wd_gethostbyname(*popularserver); if (h_addr) { debug(LOG_DEBUG, "Level %d: Resolving popular server [%s] succeeded = [%s]", level, *popularserver, inet_ntoa(*h_addr)); break; } else { debug(LOG_DEBUG, "Level %d: Resolving popular server [%s] failed", level, *popularserver); } } /* * If we got any h_addr buffer for one of the popular servers, in other * words, if one of the popular servers resolved, we'll assume the DNS * works, otherwise we'll deal with net connection or DNS failure. */ if (h_addr) { free(h_addr); /* * Yes * * The auth server's DNS server is probably dead. Try the next auth server */ debug(LOG_DEBUG, "Level %d: Marking auth server [%s] as bad and trying next if possible", level, hostname); if (auth_server->last_ip) { free(auth_server->last_ip); auth_server->last_ip = NULL; } mark_auth_server_bad(auth_server); return _connect_auth_server(level); } else { /* * No * * It's probably safe to assume that the internet connection is malfunctioning * and nothing we can do will make it work */ mark_offline(); debug(LOG_DEBUG, "Level %d: Failed to resolve auth server and all popular servers. " "The internet connection is probably down", level); return (-1); } } else { /* * DNS resolving was successful */ mark_online(); ip = safe_strdup(inet_ntoa(*h_addr)); debug(LOG_DEBUG, "Level %d: Resolving auth server [%s] succeeded = [%s]", level, hostname, ip); if (!auth_server->last_ip || strcmp(auth_server->last_ip, ip) != 0) { /* * But the IP address is different from the last one we knew * Update it */ debug(LOG_DEBUG, "Level %d: Updating last_ip IP of server [%s] to [%s]", level, hostname, ip); if (auth_server->last_ip) free(auth_server->last_ip); auth_server->last_ip = ip; /* Update firewall rules */ fw_clear_authservers(); fw_set_authservers(); } else { /* * IP is the same as last time */ free(ip); } /* * Connect to it */ int port = 0; #ifdef USE_CYASSL if (auth_server->authserv_use_ssl) { debug(LOG_DEBUG, "Level %d: Connecting to SSL auth server %s:%d", level, hostname, auth_server->authserv_ssl_port); port = htons(auth_server->authserv_ssl_port); } else { debug(LOG_DEBUG, "Level %d: Connecting to auth server %s:%d", level, hostname, auth_server->authserv_http_port); port = htons(auth_server->authserv_http_port); } #endif #ifndef USE_CYASSL debug(LOG_DEBUG, "Level %d: Connecting to auth server %s:%d", level, hostname, auth_server->authserv_http_port); port = htons(auth_server->authserv_http_port); #endif their_addr.sin_port = port; their_addr.sin_family = AF_INET; their_addr.sin_addr = *h_addr; memset(&(their_addr.sin_zero), '\0', sizeof(their_addr.sin_zero)); free(h_addr); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { debug(LOG_ERR, "Level %d: Failed to create a new SOCK_STREAM socket: %s", strerror(errno)); return (-1); } if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) { /* * Failed to connect * Mark the server as bad and try the next one */ debug(LOG_DEBUG, "Level %d: Failed to connect to auth server %s:%d (%s). Marking it as bad and trying next if possible", level, hostname, ntohs(port), strerror(errno)); close(sockfd); mark_auth_server_bad(auth_server); return _connect_auth_server(level); /* Yay recursion! */ } else { /* * We have successfully connected */ debug(LOG_DEBUG, "Level %d: Successfully connected to auth server %s:%d", level, hostname, ntohs(port)); return sockfd; } } }