summaryrefslogtreecommitdiffstats
path: root/src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c')
-rw-r--r--src/GeoIP-1.4.0/libGeoIP/GeoIPUpdate.c850
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;
+}