/** @internal * This function does the actual request. */ static void ping(void) { ssize_t numbytes; size_t totalbytes; int sockfd, nfds, done; char request[MAX_BUF]; fd_set readfds; struct timeval timeout; FILE * fh; unsigned long int sys_uptime = 0; unsigned int sys_memfree = 0; float sys_load = 0; t_auth_serv *auth_server = NULL; // auth_server = get_auth_server(); debug(LOG_DEBUG, "Entering ping()"); /* * The ping thread does not really try to see if the auth server is actually * working. Merely that there is a web server listening at the port. And that * is done by connect_auth_server() internally. */ sockfd = connect_auth_server(); if (sockfd == -1) { /* * No auth servers for me to talk to */ return; } auth_server = get_auth_server(); /* * Populate uptime, memfree and load */ if ((fh = fopen("/proc/uptime", "r"))) { if(fscanf(fh, "%lu", &sys_uptime) != 1) debug(LOG_CRIT, "Failed to read uptime"); fclose(fh); } if ((fh = fopen("/proc/meminfo", "r"))) { while (!feof(fh)) { if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) { /* Not on this line */ while (!feof(fh) && fgetc(fh) != '\n'); } else { /* Found it */ break; } } fclose(fh); } if ((fh = fopen("/proc/loadavg", "r"))) { if(fscanf(fh, "%f", &sys_load) != 1) debug(LOG_CRIT, "Failed to read loadavg"); fclose(fh); } /* * Prep & send request */ snprintf(request, sizeof(request) - 1, "GET %s%sgw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu HTTP/1.0\r\n" "User-Agent: WiFiDog %s\r\n" "Host: %s\r\n" "\r\n", auth_server->authserv_path, auth_server->authserv_ping_script_path_fragment, config_get_config()->gw_id, sys_uptime, sys_memfree, sys_load, (long unsigned int)((long unsigned int)sys_uptime - (long unsigned int)started_time), VERSION, auth_server->authserv_hostname); debug(LOG_DEBUG, "HTTP Request to Server: [%s]", request); send(sockfd, request, strlen(request), 0); debug(LOG_DEBUG, "Reading response"); numbytes = totalbytes = 0; done = 0; do { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); timeout.tv_sec = 30; /* XXX magic... 30 second */ timeout.tv_usec = 0; nfds = sockfd + 1; nfds = select(nfds, &readfds, NULL, NULL, &timeout); if (nfds > 0) { /** We don't have to use FD_ISSET() because there * was only one fd. */ numbytes = read(sockfd, request + totalbytes, MAX_BUF - (totalbytes + 1)); if (numbytes < 0) { debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return; } else if (numbytes == 0) { done = 1; } else { totalbytes += numbytes; debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes); } } else if (nfds == 0) { debug(LOG_ERR, "Timed out reading data via select() from auth server"); /* FIXME */ close(sockfd); return; } else if (nfds < 0) { debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return; } } while (!done); close(sockfd); debug(LOG_DEBUG, "Done reading reply, total %d bytes", totalbytes); request[totalbytes] = '\0'; debug(LOG_DEBUG, "HTTP Response from Server: [%s]", request); if (strstr(request, "Pong") == 0) { debug(LOG_WARNING, "Auth server did NOT say pong!"); /* FIXME */ } else { debug(LOG_DEBUG, "Auth Server Says: Pong"); } return; }
/** Initiates a transaction with the auth server, either to authenticate or to * update the traffic counters at the server @param authresponse Returns the information given by the central server @param request_type Use the REQUEST_TYPE_* defines in centralserver.h @param ip IP adress of the client this request is related to @param mac MAC adress of the client this request is related to @param token Authentification token of the client @param incoming Current counter of the client's total incoming traffic, in bytes @param outgoing Current counter of the client's total outgoing traffic, in bytes */ t_authcode auth_server_request(t_authresponse *authresponse, const char *request_type, const char *ip, const char *mac, const char *token, unsigned long long int incoming, unsigned long long int outgoing) { int sockfd; ssize_t numbytes; size_t totalbytes; char buf[MAX_BUF]; char *tmp; char *safe_token; int done, nfds; fd_set readfds; struct timeval timeout; t_auth_serv *auth_server = NULL; auth_server = get_auth_server(); /* Blanket default is error. */ authresponse->authcode = AUTH_ERROR; sockfd = connect_auth_server(); if (sockfd == -1) { /* Could not connect to any auth server */ return (AUTH_ERROR); } /** * TODO: XXX change the PHP so we can harmonize stage as request_type * everywhere. */ memset(buf, 0, sizeof(buf)); safe_token=httpdUrlEncode(token); snprintf(buf, (sizeof(buf) - 1), "GET %s%sstage=%s&ip=%s&mac=%s&token=%s&incoming=%llu&outgoing=%llu&gw_id=%s HTTP/1.0\r\n" "User-Agent: WiFiDog %s\r\n" "Host: %s\r\n" "\r\n", auth_server->authserv_path, auth_server->authserv_auth_script_path_fragment, request_type, ip, mac, safe_token, incoming, outgoing, config_get_config()->gw_id, VERSION, auth_server->authserv_hostname ); free(safe_token); debug(LOG_DEBUG, "Sending HTTP request to auth server: [%s]\n", buf); send(sockfd, buf, strlen(buf), 0); debug(LOG_DEBUG, "Reading response"); numbytes = totalbytes = 0; done = 0; do { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); timeout.tv_sec = 30; /* XXX magic... 30 second is as good a timeout as any */ timeout.tv_usec = 0; nfds = sockfd + 1; nfds = select(nfds, &readfds, NULL, NULL, &timeout); if (nfds > 0) { /** We don't have to use FD_ISSET() because there * was only one fd. */ numbytes = read(sockfd, buf + totalbytes, MAX_BUF - (totalbytes + 1)); if (numbytes < 0) { debug(LOG_ERR, "An error occurred while reading from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return (AUTH_ERROR); } else if (numbytes == 0) { done = 1; } else { totalbytes += numbytes; debug(LOG_DEBUG, "Read %d bytes, total now %d", numbytes, totalbytes); } } else if (nfds == 0) { debug(LOG_ERR, "Timed out reading data via select() from auth server"); /* FIXME */ close(sockfd); return (AUTH_ERROR); } else if (nfds < 0) { debug(LOG_ERR, "Error reading data via select() from auth server: %s", strerror(errno)); /* FIXME */ close(sockfd); return (AUTH_ERROR); } } while (!done); close(sockfd); buf[totalbytes] = '\0'; debug(LOG_DEBUG, "HTTP Response from Server: [%s]", buf); if ((tmp = strstr(buf, "Auth: "))) { if (sscanf(tmp, "Auth: %d", (int *)&authresponse->authcode) == 1) { debug(LOG_INFO, "Auth server returned authentication code %d", authresponse->authcode); return(authresponse->authcode); } else { debug(LOG_WARNING, "Auth server did not return expected authentication code"); return(AUTH_ERROR); } } else { return(AUTH_ERROR); } /* XXX Never reached because of the above if()/else pair. */ return(AUTH_ERROR); }
/** Initiates a transaction with the auth server, either to authenticate or to * update the traffic counters at the server @param authresponse Returns the information given by the central server @param request_type Use the REQUEST_TYPE_* defines in centralserver.h @param ip IP adress of the client this request is related to @param mac MAC adress of the client this request is related to @param token Authentification token of the client @param incoming Current counter of the client's total incoming traffic, in bytes @param outgoing Current counter of the client's total outgoing traffic, in bytes */ t_authcode auth_server_request(t_authresponse * authresponse, const char *request_type, const char *ip, const char *mac, const char *token, unsigned long long int incoming, unsigned long long int outgoing) { int sockfd; char buf[MAX_BUF]; char *tmp; char *safe_token; t_auth_serv *auth_server = NULL; auth_server = get_auth_server(); /* Blanket default is error. */ authresponse->authcode = AUTH_ERROR; sockfd = connect_auth_server(); /** * TODO: XXX change the PHP so we can harmonize stage as request_type * everywhere. */ memset(buf, 0, sizeof(buf)); safe_token = httpdUrlEncode(token); snprintf(buf, (sizeof(buf) - 1), "GET %s%sstage=%s&ip=%s&mac=%s&token=%s&incoming=%llu&outgoing=%llu&gw_id=%s HTTP/1.0\r\n" "User-Agent: WiFiDog %s\r\n" "Host: %s\r\n" "\r\n", auth_server->authserv_path, auth_server->authserv_auth_script_path_fragment, request_type, ip, mac, safe_token, incoming, outgoing, config_get_config()->gw_id, VERSION, auth_server->authserv_hostname); free(safe_token); char *res; #ifdef USE_CYASSL if (auth_server->authserv_use_ssl) { res = https_get(sockfd, buf, auth_server->authserv_hostname); } else { res = http_get(sockfd, buf); } #endif #ifndef USE_CYASSL res = http_get(sockfd, buf); #endif if (NULL == res) { debug(LOG_ERR, "There was a problem talking to the auth server!"); return (AUTH_ERROR); } if ((tmp = strstr(res, "Auth: "))) { if (sscanf(tmp, "Auth: %d", (int *)&authresponse->authcode) == 1) { debug(LOG_INFO, "Auth server returned authentication code %d", authresponse->authcode); free(res); return (authresponse->authcode); } else { debug(LOG_WARNING, "Auth server did not return expected authentication code"); free(res); return (AUTH_ERROR); } } free(res); return (AUTH_ERROR); }
/** @internal * This function does the actual request. */ static void ping(void) { char request[MAX_BUF]; FILE *fh; int sockfd; unsigned long int sys_uptime = 0; unsigned int sys_memfree = 0; float sys_load = 0; t_auth_serv *auth_server = NULL; auth_server = get_auth_server(); static int authdown = 0; debug(LOG_DEBUG, "Entering ping()"); memset(request, 0, sizeof(request)); /* * The ping thread does not really try to see if the auth server is actually * working. Merely that there is a web server listening at the port. And that * is done by connect_auth_server() internally. */ sockfd = connect_auth_server(); if (sockfd == -1) { /* * No auth servers for me to talk to */ if (!authdown) { fw_set_authdown(); authdown = 1; } return; } /* * Populate uptime, memfree and load */ if ((fh = fopen("/proc/uptime", "r"))) { if (fscanf(fh, "%lu", &sys_uptime) != 1) debug(LOG_CRIT, "Failed to read uptime"); fclose(fh); } if ((fh = fopen("/proc/meminfo", "r"))) { while (!feof(fh)) { if (fscanf(fh, "MemFree: %u", &sys_memfree) == 0) { /* Not on this line */ while (!feof(fh) && fgetc(fh) != '\n') ; } else { /* Found it */ break; } } fclose(fh); } if ((fh = fopen("/proc/loadavg", "r"))) { if (fscanf(fh, "%f", &sys_load) != 1) debug(LOG_CRIT, "Failed to read loadavg"); fclose(fh); } /* * Prep & send request */ snprintf(request, sizeof(request) - 1, "GET %s%sgw_id=%s&sys_uptime=%lu&sys_memfree=%u&sys_load=%.2f&wifidog_uptime=%lu&prop=%s&network_id=%s&lat=%s&lon=%s&node_name=%s HTTP/1.0\r\n" "User-Agent: WiFiDog-ffw %s\r\n" "Host: %s\r\n" "\r\n", auth_server->authserv_path, auth_server->authserv_ping_script_path_fragment, config_get_config()->gw_id, sys_uptime, sys_memfree, sys_load, (long unsigned int)((long unsigned int)time(NULL) - (long unsigned int)started_time), config_get_config()->owner, config_get_config()->network, config_get_config()->lat, config_get_config()->lon, config_get_config()->node_name, VERSION, auth_server->authserv_hostname); char *res; #ifdef USE_CYASSL if (auth_server->authserv_use_ssl) { res = https_get(sockfd, request, auth_server->authserv_hostname); } else { res = http_get(sockfd, request); } #endif #ifndef USE_CYASSL res = http_get(sockfd, request); #endif if (NULL == res) { debug(LOG_ERR, "There was a problem pinging the auth server!"); if (!authdown) { fw_set_authdown(); authdown = 1; } } else if (strstr(res, "Pong") == 0) { debug(LOG_WARNING, "Auth server did NOT say Pong!"); if (!authdown) { fw_set_authdown(); authdown = 1; } free(res); } else { debug(LOG_DEBUG, "Auth Server Says: Pong"); if (authdown) { fw_set_authup(); authdown = 0; } free(res); } return; }