diff options
Diffstat (limited to 'src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c')
-rw-r--r-- | src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c | 850 |
1 files changed, 850 insertions, 0 deletions
diff --git a/src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c b/src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c new file mode 100644 index 0000000..a7bec6b --- /dev/null +++ b/src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c @@ -0,0 +1,850 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */ +/* GeoIPUpdate.c + * + * Copyright (C) 2006 MaxMind LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GeoIPCity.h" +#include "GeoIP.h" +#include "GeoIPUpdate.h" +#include "GeoIP_internal.h" + +#include "global.h" +#include "md5.h" +#include <sys/types.h> +#ifndef WIN32 +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <netdb.h> +#else +#include <windows.h> +#include <winsock.h> +#endif +#include <zlib.h> +#include <time.h> +#include <stdio.h> +#include <unistd.h> + +#define BLOCK_SIZE 1024 + +const char *GeoIPUpdateHost = "updates.maxmind.com"; +const char *GeoIPHTTPRequest = "GET /app/update?license_key=%s&md5=%s HTTP/1.0\nHost: updates.maxmind.com\n\n"; +const char *GeoIPHTTPRequestMD5 = "GET /app/update_secure?db_md5=%s&challenge_md5=%s&user_id=%s&edition_id=%s HTTP/1.0\nHost: updates.maxmind.com\n\n"; + +/* messages */ +const char *NoCurrentDB = "%s can't be opened, proceeding to download database\n"; +const char *MD5Info = "MD5 Digest of installed database is %s\n"; +const char *SavingGzip = "Saving gzip file to %s ... "; +const char *WritingFile = "Writing uncompressed data to %s ..."; + +/* TODO replace printf with GeoIP_printf - we need someway of having vargs with GeoIP_printf */ + +const char * GeoIP_get_error_message(int i) { + switch (i) { + case GEOIP_NO_NEW_UPDATES: + return "no new updates"; + case GEOIP_SUCCESS: + return "Success"; + case GEOIP_LICENSE_KEY_INVALID_ERR: + return "License Key Invalid"; + case GEOIP_DNS_ERR: + return "Unable to resolve hostname"; + case GEOIP_NON_IPV4_ERR: + return "Non - IPv4 address"; + case GEOIP_SOCKET_OPEN_ERR: + return "Error opening socket"; + case GEOIP_CONNECTION_ERR: + return "Unable to connect"; + case GEOIP_GZIP_IO_ERR: + return "Unable to write GeoIP.dat.gz file"; + case GEOIP_TEST_IO_ERR: + return "Unable to write GeoIP.dat.test file"; + case GEOIP_GZIP_READ_ERR: + return "Unable to read gzip data"; + case GEOIP_OUT_OF_MEMORY_ERR: + return "Out of memory error"; + case GEOIP_SOCKET_READ_ERR: + return "Error reading from socket, see errno"; + case GEOIP_SANITY_OPEN_ERR: + return "Sanity check GeoIP_open error"; + case GEOIP_SANITY_INFO_FAIL: + return "Sanity check database_info string failed"; + case GEOIP_SANITY_LOOKUP_FAIL: + return "Sanity check ip address lookup failed"; + case GEOIP_RENAME_ERR: + return "Rename error while installing db, check errno"; + case GEOIP_USER_ID_INVALID_ERR: + return "Invalid userID"; + case GEOIP_PRODUCT_ID_INVALID_ERR: + return "Invalid product ID or subscription expired"; + case GEOIP_INVALID_SERVER_RESPONSE: + return "Server returned something unexpected"; + default: + return "no error"; + } +} + +void GeoIP_printf(void (*f)(char *), const char *str) { + char * f_str; + size_t len = strlen(str)+1; + f_str = malloc(len); + strncpy(f_str,str,len); + if (f != NULL) + (*f)(f_str); + free(f_str); +} + +short int GeoIP_update_database (char * license_key, int verbose, void (*f)( char *)) { + struct hostent *hostlist; + int sock; + char * buf; + struct sockaddr_in sa; + int offset = 0, err; + char * request_uri; + char * compr; + unsigned long comprLen; + FILE *comp_fh, *cur_db_fh, *gi_fh; + gzFile gz_fh; + char * file_path_gz, * file_path_test; + MD5_CONTEXT context; + unsigned char buffer[1024], digest[16]; + char hex_digest[33] = "00000000000000000000000000000000\0"; + unsigned int i; + char *f_str; + GeoIP * gi; + char * db_info; + char block[BLOCK_SIZE]; + int block_size = BLOCK_SIZE; + size_t len; + + _GeoIP_setup_dbfilename(); + + /* get MD5 of current GeoIP database file */ + if ((cur_db_fh = fopen (GeoIPDBFileName[GEOIP_COUNTRY_EDITION], "rb")) == NULL) { + len = strlen(NoCurrentDB) + strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) - 1; + f_str = malloc(len); + snprintf(f_str, len, NoCurrentDB, GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + if (f != NULL) + (*f)(f_str); + free(f_str); + } else { + md5_init(&context); + while ((len = fread (buffer, 1, 1024, cur_db_fh)) > 0) + md5_write (&context, buffer, len); + md5_final (&context); + memcpy(digest,context.buf,16); + fclose (cur_db_fh); + for (i = 0; i < 16; i++) { + /*"%02x" will write 3 chars*/ + snprintf (&hex_digest[2*i], 3, "%02x", digest[i]); + } + len = strlen(MD5Info) + strlen(hex_digest) - 1; + f_str = malloc(len); + snprintf(f_str, len, MD5Info, hex_digest); + if (f != NULL) + (*f)(f_str); + free(f_str); + } + + hostlist = gethostbyname(GeoIPUpdateHost); + + if (hostlist == NULL) + return GEOIP_DNS_ERR; + + if (hostlist->h_addrtype != AF_INET) + return GEOIP_NON_IPV4_ERR; + + if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return GEOIP_SOCKET_OPEN_ERR; + } + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(80); + memcpy(&sa.sin_addr, hostlist->h_addr_list[0], hostlist->h_length); + sa.sin_family = AF_INET; + + if (verbose == 1) + GeoIP_printf(f,"Connecting to MaxMind GeoIP Update server\n"); + + /* Download gzip file */ + if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0) + return GEOIP_CONNECTION_ERR; + + request_uri = malloc(sizeof(char) * (strlen(license_key) + strlen(GeoIPHTTPRequest)+36)); + if (request_uri == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + sprintf(request_uri,GeoIPHTTPRequest,license_key, hex_digest); + send(sock, request_uri, strlen(request_uri),0); + free(request_uri); + + buf = malloc(sizeof(char) * block_size); + if (buf == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + + if (verbose == 1) + GeoIP_printf(f,"Downloading gzipped GeoIP Database...\n"); + + for (;;) { + int amt; + amt = recv(sock, &buf[offset], block_size,0); + if (amt == 0) { + break; + } else if (amt == -1) { + free(buf); + return GEOIP_SOCKET_READ_ERR; + } + offset += amt; + buf = realloc(buf, offset+block_size); + if (buf == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + } + + compr = strstr(buf, "\r\n\r\n") + 4; + comprLen = offset + buf - compr; + + if (strstr(compr, "License Key Invalid") != NULL) { + if (verbose == 1) + GeoIP_printf(f,"Failed\n"); + free(buf); + return GEOIP_LICENSE_KEY_INVALID_ERR; + } else if (strstr(compr, "No new updates available") != NULL) { + free(buf); + return GEOIP_NO_NEW_UPDATES; + } + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + /* save gzip file */ + file_path_gz = malloc(sizeof(char) * (strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) + 4)); + if (file_path_gz == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + strcpy(file_path_gz,GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + strcat(file_path_gz,".gz"); + if (verbose == 1) { + len = strlen(SavingGzip) + strlen(file_path_gz) - 1; + f_str = malloc(len); + snprintf(f_str, len, SavingGzip,file_path_gz); + if (f != NULL) + (*f)(f_str); + free(f_str); + } + comp_fh = fopen(file_path_gz, "wb"); + + if(comp_fh == NULL) { + free(file_path_gz); + free(buf); + return GEOIP_GZIP_IO_ERR; + } + + fwrite(compr, 1, comprLen, comp_fh); + fclose(comp_fh); + free(buf); + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + if (verbose == 1) + GeoIP_printf(f,"Uncompressing gzip file ... "); + + /* uncompress gzip file */ + gz_fh = gzopen(file_path_gz, "rb"); + file_path_test = malloc(sizeof(char) * (strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) + 6)); + if (file_path_test == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + strcpy(file_path_test,GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + strcat(file_path_test,".test"); + gi_fh = fopen(file_path_test, "wb"); + + if(gi_fh == NULL) { + free(file_path_test); + return GEOIP_TEST_IO_ERR; + } + for (;;) { + int amt; + amt = gzread(gz_fh, block, block_size); + if (amt == -1) { + free(file_path_test); + fclose(gi_fh); + gzclose(gz_fh); + return GEOIP_GZIP_READ_ERR; + } + if (amt == 0) { + break; + } + fwrite(block,1,amt,gi_fh); + } + gzclose(gz_fh); + unlink(file_path_gz); + free(file_path_gz); + fclose(gi_fh); + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + if (verbose == 1) { + f_str = malloc(strlen(WritingFile) + strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) - 1); + sprintf(f_str,WritingFile,GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + if (f != NULL) + (*f)(f_str); + free(f_str); + } + + /* sanity check */ + gi = GeoIP_open(file_path_test, GEOIP_STANDARD); + + if (verbose == 1) + GeoIP_printf(f,"Performing santity checks ... "); + + if (gi == NULL) { + GeoIP_printf(f,"Error opening sanity check database\n"); + return GEOIP_SANITY_OPEN_ERR; + } + + /* this checks to make sure the files is complete, since info is at the end */ + /* dependent on future databases having MaxMind in info */ + if (verbose == 1) + GeoIP_printf(f,"database_info "); + db_info = GeoIP_database_info(gi); + if (db_info == NULL) { + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL\n"); + return GEOIP_SANITY_INFO_FAIL; + } + if (strstr(db_info, "MaxMind") == NULL) { + free(db_info); + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL\n"); + return GEOIP_SANITY_INFO_FAIL; + } + free(db_info); + if (verbose == 1) + GeoIP_printf(f,"PASS "); + + /* this performs an IP lookup test of a US IP address */ + if (verbose == 1) + GeoIP_printf(f,"lookup "); + if (strcmp(GeoIP_country_code_by_addr(gi,"24.24.24.24"), "US") != 0) { + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL\n"); + return GEOIP_SANITY_LOOKUP_FAIL; + } + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"PASS\n"); + + /* install GeoIP.dat.test -> GeoIP.dat */ + err = rename(file_path_test, GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + if (err != 0) { + GeoIP_printf(f,"GeoIP Install error while renaming file\n"); + return GEOIP_RENAME_ERR; + } + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + return 0; +} + +short int GeoIP_update_database_general (char * user_id,char * license_key,char *data_base_type, int verbose,char ** client_ipaddr, void (*f)( char *)) { + struct hostent *hostlist; + int sock; + char * buf; + struct sockaddr_in sa; + int offset = 0, err; + char * request_uri; + char * compr; + unsigned long comprLen; + FILE *comp_fh, *cur_db_fh, *gi_fh; + gzFile gz_fh; + char * file_path_gz, * file_path_test; + MD5_CONTEXT context; + MD5_CONTEXT context2; + unsigned char buffer[1024], digest[16] ,digest2[16]; + char hex_digest[33] = "0000000000000000000000000000000\0"; + char hex_digest2[33] = "0000000000000000000000000000000\0"; + unsigned int i; + char *f_str; + GeoIP * gi; + char * db_info; + char *ipaddress; + char *geoipfilename; + char *tmpstr; + int dbtype; + int lookupresult = 1; + char block[BLOCK_SIZE]; + int block_size = BLOCK_SIZE; + size_t len; + size_t request_uri_len; + + hostlist = gethostbyname(GeoIPUpdateHost); + + if (hostlist == NULL) + return GEOIP_DNS_ERR; + + if (hostlist->h_addrtype != AF_INET) + return GEOIP_NON_IPV4_ERR; + if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return GEOIP_SOCKET_OPEN_ERR; + } + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(80); + memcpy(&sa.sin_addr, hostlist->h_addr_list[0], hostlist->h_length); + sa.sin_family = AF_INET; + if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0) + return GEOIP_CONNECTION_ERR; + request_uri = malloc(sizeof(char) * (strlen(license_key) + strlen(GeoIPHTTPRequestMD5)+1036)); + if (request_uri == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + + /* get the file name from a web page using the product id */ + sprintf(request_uri,"GET /app/update_getfilename?product_id=%s HTTP/1.0\nHost: %s\n\n",data_base_type,GeoIPUpdateHost); + if (verbose == 1) { + printf("sending request %s \n",request_uri); + } + send(sock, request_uri, strlen(request_uri),0); /* send the request */ + free(request_uri); + buf = malloc(sizeof(char) * (block_size+4)); + if (buf == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + offset = 0; + for (;;){ + int amt; + amt = recv(sock, &buf[offset], block_size,0); + if (amt == 0){ + break; + } else if (amt == -1) { + free(buf); + return GEOIP_SOCKET_READ_ERR; + } + offset += amt; + buf = realloc(buf, offset + block_size + 4); + } + buf[offset] = 0; + offset = 0; + tmpstr = strstr(buf, "\r\n\r\n") + 4; + if (tmpstr[0] == '.' || strchr(tmpstr, '/') != NULL) { + free(buf); + return GEOIP_INVALID_SERVER_RESPONSE; + } + geoipfilename = _GeoIP_full_path_to(tmpstr); + free(buf); + + /* print the database product id and the database filename */ + if (verbose == 1){ + printf("database product id %s database file name %s \n",data_base_type,geoipfilename); + } + _GeoIP_setup_dbfilename(); + + /* get MD5 of current GeoIP database file */ + if ((cur_db_fh = fopen (geoipfilename, "rb")) == NULL) { + len = strlen(NoCurrentDB) + strlen(geoipfilename) - 1; + f_str = malloc(len); + snprintf(f_str, len, NoCurrentDB, geoipfilename); + + if (f != NULL) + (*f)(f_str); + free(f_str); + } else { + md5_init(&context); + while ((len = fread (buffer, 1, 1024, cur_db_fh)) > 0) + md5_write (&context, buffer, len); + md5_final (&context); + memcpy(digest,context.buf,16); + fclose (cur_db_fh); + for (i = 0; i < 16; i++) + sprintf (&hex_digest[2*i], "%02x", digest[i]); + len = strlen(MD5Info) + strlen(hex_digest) - 1; + f_str = malloc(len); + snprintf(f_str, len, MD5Info, hex_digest); + if (f != NULL) + (*f)(f_str); + free(f_str); + } + if (verbose == 1) { + printf("MD5 sum of database %s is %s \n",geoipfilename,hex_digest); + } + if (client_ipaddr[0] == NULL) { + /* We haven't gotten our IP address yet, so let's request it */ + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + free(geoipfilename); + return GEOIP_SOCKET_OPEN_ERR; + } + + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(80); + memcpy(&sa.sin_addr, hostlist->h_addr_list[0], hostlist->h_length); + sa.sin_family = AF_INET; + + if (verbose == 1) + GeoIP_printf(f,"Connecting to MaxMind GeoIP Update server\n"); + + /* Download gzip file */ + if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0) { + free(geoipfilename); + return GEOIP_CONNECTION_ERR; + } + request_uri = malloc(sizeof(char) * (strlen(license_key) + strlen(GeoIPHTTPRequestMD5)+1036)); + if (request_uri == NULL) { + free(geoipfilename); + return GEOIP_OUT_OF_MEMORY_ERR; + } + + /* get client ip address from MaxMind web page */ + sprintf(request_uri,"GET /app/update_getipaddr HTTP/1.0\nHost: %s\n\n",GeoIPUpdateHost); + send(sock, request_uri, strlen(request_uri),0); /* send the request */ + if (verbose == 1) { + printf("sending request %s", request_uri); + } + free(request_uri); + buf = malloc(sizeof(char) * (block_size+1)); + if (buf == NULL) { + free(geoipfilename); + return GEOIP_OUT_OF_MEMORY_ERR; + } + offset = 0; + + for (;;){ + int amt; + amt = recv(sock, &buf[offset], block_size,0); + if (amt == 0) { + break; + } else if (amt == -1) { + free(buf); + return GEOIP_SOCKET_READ_ERR; + } + offset += amt; + buf = realloc(buf, offset+block_size+1); + } + + buf[offset] = 0; + offset = 0; + ipaddress = strstr(buf, "\r\n\r\n") + 4; /* get the ip address */ + ipaddress = malloc(strlen(strstr(buf, "\r\n\r\n") + 4)+5); + strcpy(ipaddress,strstr(buf, "\r\n\r\n") + 4); + client_ipaddr[0] = ipaddress; + if (verbose == 1) { + printf("client ip address: %s\n",ipaddress); + } + free(buf); + close(sock); + } + + ipaddress = client_ipaddr[0]; + + /* make a md5 sum of ip address and license_key and store it in hex_digest2 */ + request_uri_len = sizeof(char) * 2036; + request_uri = malloc(request_uri_len); + md5_init(&context2); + md5_write (&context2, (unsigned char *)license_key, 12); /*add license key to the md5 sum*/ + md5_write (&context2, (unsigned char *)ipaddress, strlen(ipaddress)); /*add ip address to the md5 sum*/ + md5_final (&context2); + memcpy(digest2,context2.buf,16); + for (i = 0; i < 16; i++) + snprintf (&hex_digest2[2*i], 3, "%02x", digest2[i]); /*change the digest to a hex digest*/ + if (verbose == 1) { + printf("md5sum of ip address and license key is %s \n",hex_digest2); + } + + /* send the request using the user id,product id, + * md5 sum of the prev database and + * the md5 sum of the license_key and ip address */ + if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return GEOIP_SOCKET_OPEN_ERR; + } + memset(&sa, 0, sizeof(struct sockaddr_in)); + sa.sin_port = htons(80); + memcpy(&sa.sin_addr, hostlist->h_addr_list[0], hostlist->h_length); + sa.sin_family = AF_INET; + if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0) + return GEOIP_CONNECTION_ERR; + snprintf(request_uri, request_uri_len, GeoIPHTTPRequestMD5,hex_digest,hex_digest2,user_id,data_base_type); + send(sock, request_uri, strlen(request_uri),0); + if (verbose == 1) { + printf("sending request %s\n",request_uri); + } + + free(request_uri); + + offset = 0; + buf = malloc(sizeof(char) * block_size); + if (buf == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + + if (verbose == 1) + GeoIP_printf(f,"Downloading gzipped GeoIP Database...\n"); + + for (;;) { + int amt; + amt = recv(sock, &buf[offset], block_size,0); + + if (amt == 0) { + break; + } else if (amt == -1) { + free(buf); + return GEOIP_SOCKET_READ_ERR; + } + offset += amt; + buf = realloc(buf, offset+block_size); + if (buf == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + } + + compr = strstr(buf, "\r\n\r\n") + 4; + comprLen = offset + buf - compr; + + if (strstr(compr, "License Key Invalid") != NULL) { + if (verbose == 1) + GeoIP_printf(f,"Failed\n"); + free(buf); + return GEOIP_LICENSE_KEY_INVALID_ERR; + } else if (strstr(compr, "No new updates available") != NULL) { + free(buf); + printf("%s is up to date, no updates required\n", geoipfilename); + return GEOIP_NO_NEW_UPDATES; + } else if (strstr(compr, "Invalid UserId") != NULL){ + free(buf); + return GEOIP_USER_ID_INVALID_ERR; + } else if (strstr(compr, "Invalid product ID or subscription expired") != NULL){ + free(buf); + return GEOIP_PRODUCT_ID_INVALID_ERR; + } + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + printf("Updating %s\n", geoipfilename); + + /* save gzip file */ + file_path_gz = malloc(sizeof(char) * (strlen(geoipfilename) + 4)); + + if (file_path_gz == NULL) + return GEOIP_OUT_OF_MEMORY_ERR; + strcpy(file_path_gz,geoipfilename); + strcat(file_path_gz,".gz"); + if (verbose == 1) { + len = strlen(SavingGzip) + strlen(file_path_gz) - 1; + f_str = malloc(len); + snprintf(f_str,len,SavingGzip,file_path_gz); + if (f != NULL) + (*f)(f_str); + free(f_str); + } + comp_fh = fopen(file_path_gz, "wb"); + + if(comp_fh == NULL) { + free(file_path_gz); + free(buf); + return GEOIP_GZIP_IO_ERR; + } + + fwrite(compr, 1, comprLen, comp_fh); + fclose(comp_fh); + free(buf); + + if (verbose == 1) { + printf("download data to a gz file named %s \n",file_path_gz); + } + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + if (verbose == 1) + GeoIP_printf(f,"Uncompressing gzip file ... "); + + file_path_test = malloc(sizeof(char) * (strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) + 6)); + if (file_path_test == NULL) { + free(file_path_gz); + return GEOIP_OUT_OF_MEMORY_ERR; + } + strcpy(file_path_test,GeoIPDBFileName[GEOIP_COUNTRY_EDITION]); + strcat(file_path_test,".test"); + gi_fh = fopen(file_path_test, "wb"); + if(gi_fh == NULL) { + free(file_path_test); + free(file_path_gz); + return GEOIP_TEST_IO_ERR; + } + /* uncompress gzip file */ + offset = 0; + gz_fh = gzopen(file_path_gz, "rb"); + for (;;) { + int amt; + amt = gzread(gz_fh, block, block_size); + if (amt == -1) { + free(file_path_gz); + free(file_path_test); + gzclose(gz_fh); + fclose(gi_fh); + return GEOIP_GZIP_READ_ERR; + } + if (amt == 0) { + break; + } + fwrite(block,1,amt,gi_fh); + } + gzclose(gz_fh); + unlink(file_path_gz); + free(file_path_gz); + fclose(gi_fh); + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + + if (verbose == 1) { + len = strlen(WritingFile) + strlen(geoipfilename) - 1; + f_str = malloc(len); + snprintf(f_str,len,WritingFile,geoipfilename); + free(f_str); + } + + /* sanity check */ + gi = GeoIP_open(file_path_test, GEOIP_STANDARD); + + if (verbose == 1) + GeoIP_printf(f,"Performing santity checks ... "); + + if (gi == NULL) { + GeoIP_printf(f,"Error opening sanity check database\n"); + return GEOIP_SANITY_OPEN_ERR; + } + + + /* get the database type */ + dbtype = GeoIP_database_edition(gi); + if (verbose == 1) { + printf("Database type is %d\n",dbtype); + } + + /* this checks to make sure the files is complete, since info is at the end + dependent on future databases having MaxMind in info (ISP and Organization databases currently don't have info string */ + + if ((dbtype != GEOIP_ISP_EDITION)&& + (dbtype != GEOIP_ORG_EDITION)) { + if (verbose == 1) + GeoIP_printf(f,"database_info "); + db_info = GeoIP_database_info(gi); + if (db_info == NULL) { + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL null\n"); + return GEOIP_SANITY_INFO_FAIL; + } + if (strstr(db_info, "MaxMind") == NULL) { + free(db_info); + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL maxmind\n"); + return GEOIP_SANITY_INFO_FAIL; + } + free(db_info); + if (verbose == 1) + GeoIP_printf(f,"PASS "); + } + + /* this performs an IP lookup test of a US IP address */ + if (verbose == 1) + GeoIP_printf(f,"lookup "); + if (dbtype == GEOIP_NETSPEED_EDITION) { + int netspeed = GeoIP_id_by_name(gi,"24.24.24.24"); + lookupresult = 0; + if (netspeed == GEOIP_CABLEDSL_SPEED){ + lookupresult = 1; + } + } + if (dbtype == GEOIP_COUNTRY_EDITION) { + /* if data base type is country then call the function + * named GeoIP_country_code_by_addr */ + lookupresult = 1; + if (strcmp(GeoIP_country_code_by_addr(gi,"24.24.24.24"), "US") != 0) { + lookupresult = 0; + } + if (verbose == 1) { + GeoIP_printf(f,"testing GEOIP_COUNTRY_EDITION\n"); + } + } + if (dbtype == GEOIP_REGION_EDITION_REV1) { + /* if data base type is region then call the function + * named GeoIP_region_by_addr */ + GeoIPRegion *r = GeoIP_region_by_addr(gi,"24.24.24.24"); + lookupresult = 0; + if (r != NULL) { + lookupresult = 1; + free(r); + } + if (verbose == 1) { + GeoIP_printf(f,"testing GEOIP_REGION_EDITION\n"); + } + } + if (dbtype == GEOIP_CITY_EDITION_REV1) { + /* if data base type is city then call the function + * named GeoIP_record_by_addr */ + GeoIPRecord *r = GeoIP_record_by_addr(gi,"24.24.24.24"); + lookupresult = 0; + if (r != NULL) { + lookupresult = 1; + free(r); + } + if (verbose == 1) { + GeoIP_printf(f,"testing GEOIP_CITY_EDITION\n"); + } + } + if ((dbtype == GEOIP_ISP_EDITION)|| + (dbtype == GEOIP_ORG_EDITION)) { + /* if data base type is isp or org then call the function + * named GeoIP_org_by_addr */ + GeoIPRecord *r = (GeoIPRecord*)GeoIP_org_by_addr(gi,"24.24.24.24"); + lookupresult = 0; + if (r != NULL) { + lookupresult = 1; + free(r); + } + if (verbose == 1) { + if (dbtype == GEOIP_ISP_EDITION) { + GeoIP_printf(f,"testing GEOIP_ISP_EDITION\n"); + } + if (dbtype == GEOIP_ORG_EDITION) { + GeoIP_printf(f,"testing GEOIP_ORG_EDITION\n"); + } + } + } + if (lookupresult == 0) { + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"FAIL\n"); + return GEOIP_SANITY_LOOKUP_FAIL; + } + GeoIP_delete(gi); + if (verbose == 1) + GeoIP_printf(f,"PASS\n"); + + /* install GeoIP.dat.test -> GeoIP.dat */ + err = rename(file_path_test, geoipfilename); + if (err != 0) { + GeoIP_printf(f,"GeoIP Install error while renaming file\n"); + return GEOIP_RENAME_ERR; + } + + if (verbose == 1) + GeoIP_printf(f,"Done\n"); + free(geoipfilename); + return 0; +} |