1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
4 * Copyright (C) 2006 MaxMind LLC
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "GeoIPCity.h"
23 #include "GeoIPUpdate.h"
24 #include "GeoIP_internal.h"
28 #include <sys/types.h>
29 #if !defined(WIN32) && !defined(WIN64)
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
43 #define BLOCK_SIZE 1024
45 /* Update DB Host & HTTP GET Request formats:
46 * ------------------------------------------
47 * GET must support an optional HTTP Proxy.
49 const char *GeoIPUpdateHost
= "updates.maxmind.com";
50 /* This is the direct, or proxy port number. */
51 static int GeoIPHTTPPort
= 80;
52 /* License-only format (OLD) */
53 const char *GeoIPHTTPRequest
= "GET %s%s/app/update?license_key=%s&md5=%s HTTP/1.0\nHost: updates.maxmind.com\n\n";
54 /* General DB Types formats */
55 const char *GeoIPHTTPRequestFilename
= "GET %s%s/app/update_getfilename?product_id=%s HTTP/1.0\nHost: %s\n\n";
56 const char *GeoIPHTTPRequestClientIP
= "GET %s%s/app/update_getipaddr HTTP/1.0\nHost: %s\n\n";
57 const char *GeoIPHTTPRequestMD5
= "GET %s%s/app/update_secure?db_md5=%s&challenge_md5=%s&user_id=%s&edition_id=%s HTTP/1.0\nHost: updates.maxmind.com\n\n";
60 const char *NoCurrentDB
= "%s can't be opened, proceeding to download database\n";
61 const char *MD5Info
= "MD5 Digest of installed database is %s\n";
62 const char *SavingGzip
= "Saving gzip file to %s ... ";
63 const char *WritingFile
= "Writing uncompressed data to %s ...";
65 const char * GeoIP_get_error_message(int i
) {
67 case GEOIP_NO_NEW_UPDATES
:
68 return "no new updates";
71 case GEOIP_LICENSE_KEY_INVALID_ERR
:
72 return "License Key Invalid";
74 return "Unable to resolve hostname";
75 case GEOIP_NON_IPV4_ERR
:
76 return "Non - IPv4 address";
77 case GEOIP_SOCKET_OPEN_ERR
:
78 return "Error opening socket";
79 case GEOIP_CONNECTION_ERR
:
80 return "Unable to connect";
81 case GEOIP_GZIP_IO_ERR
:
82 return "Unable to write GeoIP.dat.gz file";
83 case GEOIP_TEST_IO_ERR
:
84 return "Unable to write GeoIP.dat.test file";
85 case GEOIP_GZIP_READ_ERR
:
86 return "Unable to read gzip data";
87 case GEOIP_OUT_OF_MEMORY_ERR
:
88 return "Out of memory error";
89 case GEOIP_SOCKET_READ_ERR
:
90 return "Error reading from socket, see errno";
91 case GEOIP_SANITY_OPEN_ERR
:
92 return "Sanity check GeoIP_open error";
93 case GEOIP_SANITY_INFO_FAIL
:
94 return "Sanity check database_info string failed";
95 case GEOIP_SANITY_LOOKUP_FAIL
:
96 return "Sanity check ip address lookup failed";
97 case GEOIP_RENAME_ERR
:
98 return "Rename error while installing db, check errno";
99 case GEOIP_USER_ID_INVALID_ERR
:
100 return "Invalid userID";
101 case GEOIP_PRODUCT_ID_INVALID_ERR
:
102 return "Invalid product ID or subscription expired";
103 case GEOIP_INVALID_SERVER_RESPONSE
:
104 return "Server returned something unexpected";
109 int GeoIP_fprintf(int (*f
)(FILE *, char *),FILE *fp
, const char *str
, ...) {
116 vasprintf(&f_str
, str
, ap
);
120 rc
= (*f
)(fp
, f_str
);
125 void GeoIP_printf(void (*f
)(char *), const char *str
,...) {
130 va_start(params
, str
);
131 vasprintf(&f_str
, str
, params
);
139 /* Support HTTP Proxy Host
140 * --------------------------------------------------
141 * Use typical OS support for the optional HTTP Proxy.
143 * Proxy adds http://{real-hostname} to URI format strings:
144 * sprintf("GET %s%s/ HTTP/1.0\r\n",GeoIPProxyHTTP,GeoIPProxiedHost, ...);
147 /* The Protocol is usually "" OR "http://" with a proxy. */
148 static char *GeoIPProxyHTTP
= "";
149 /* GeoIP Hostname where proxy forwards requests. */
150 static char *GeoIPProxiedHost
= "";
152 /* Read http_proxy env. variable & parse it.
153 * -----------------------------------------
154 * Allow only these formats:
155 * "http://server.com", "http://server.com:8080"
157 * "server.com", "server.com:8080"
159 * A "user:password@" part will break this.
161 short int parse_http_proxy(char **proxy_host
, int *port
) {
165 if ((http_proxy
= getenv("http_proxy"))) {
167 if (! strncmp("http://", http_proxy
, 7)) http_proxy
+= 7;
169 *proxy_host
= strdup(http_proxy
);
170 if ( *proxy_host
== NULL
)
171 return 0; /* let the other functions deal with the memory error */
173 if ((port_value
= strchr(*proxy_host
, ':'))) {
174 *port_value
++ = '\0';
175 *port
= atoi(port_value
);
187 /* Get the GeoIP host or the current HTTP Proxy host. */
188 struct hostent
*GeoIP_get_host_or_proxy (void) {
189 char * hostname
= (char *) GeoIPUpdateHost
;
193 /* Set Proxy from OS: Unix/Linux */
194 if (parse_http_proxy(&proxy_host
,&proxy_port
)) {
195 hostname
= proxy_host
;
196 GeoIPProxyHTTP
= "http://";
197 GeoIPProxiedHost
= (char *) GeoIPUpdateHost
;
198 GeoIPHTTPPort
= proxy_port
;
201 /* Resolve DNS host entry. */
202 return(gethostbyname(hostname
));
205 short int GeoIP_update_database (char * license_key
, int verbose
, void (*f
)( char * )) {
206 struct hostent
*hostlist
;
209 struct sockaddr_in sa
;
213 unsigned long comprLen
;
214 FILE *comp_fh
, *cur_db_fh
, *gi_fh
;
216 char * file_path_gz
, * file_path_test
;
218 unsigned char buffer
[1024], digest
[16];
219 char hex_digest
[33] = "00000000000000000000000000000000\0";
223 char block
[BLOCK_SIZE
];
224 int block_size
= BLOCK_SIZE
;
227 _GeoIP_setup_dbfilename();
229 /* get MD5 of current GeoIP database file */
230 if ((cur_db_fh
= fopen (GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
], "rb")) == NULL
) {
231 GeoIP_printf(f
,"%s%s", NoCurrentDB
, GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
234 while ((len
= fread (buffer
, 1, 1024, cur_db_fh
)) > 0)
235 md5_write (&context
, buffer
, len
);
236 md5_final (&context
);
237 memcpy(digest
,context
.buf
,16);
239 for (i
= 0; i
< 16; i
++) {
240 // "%02x" will write 3 chars
241 snprintf (&hex_digest
[2*i
], 3, "%02x", digest
[i
]);
243 GeoIP_printf(f
, MD5Info
, hex_digest
);
246 hostlist
= GeoIP_get_host_or_proxy();
248 if (hostlist
== NULL
)
249 return GEOIP_DNS_ERR
;
251 if (hostlist
->h_addrtype
!= AF_INET
)
252 return GEOIP_NON_IPV4_ERR
;
254 if((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
255 return GEOIP_SOCKET_OPEN_ERR
;
258 memset(&sa
, 0, sizeof(struct sockaddr_in
));
259 sa
.sin_port
= htons(GeoIPHTTPPort
);
260 memcpy(&sa
.sin_addr
, hostlist
->h_addr_list
[0], hostlist
->h_length
);
261 sa
.sin_family
= AF_INET
;
264 GeoIP_printf(f
,"Connecting to MaxMind GeoIP Update server\n");
265 GeoIP_printf(f
, "via Host or Proxy Server: %s:%d\n", hostlist
->h_name
, GeoIPHTTPPort
);
268 /* Download gzip file */
269 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(struct sockaddr
))< 0)
270 return GEOIP_CONNECTION_ERR
;
272 request_uri
= malloc(sizeof(char) * (strlen(license_key
) + strlen(GeoIPHTTPRequest
)+36));
273 if (request_uri
== NULL
)
274 return GEOIP_OUT_OF_MEMORY_ERR
;
275 sprintf(request_uri
,GeoIPHTTPRequest
,GeoIPProxyHTTP
,GeoIPProxiedHost
,license_key
, hex_digest
);
276 send(sock
, request_uri
, strlen(request_uri
),0);
279 buf
= malloc(sizeof(char) * block_size
);
281 return GEOIP_OUT_OF_MEMORY_ERR
;
284 GeoIP_printf(f
,"Downloading gzipped GeoIP Database...\n");
288 amt
= recv(sock
, &buf
[offset
], block_size
,0);
291 } else if (amt
== -1) {
293 return GEOIP_SOCKET_READ_ERR
;
296 buf
= realloc(buf
, offset
+block_size
);
298 return GEOIP_OUT_OF_MEMORY_ERR
;
301 compr
= strstr(buf
, "\r\n\r\n") + 4;
302 comprLen
= offset
+ buf
- compr
;
304 if (strstr(compr
, "License Key Invalid") != NULL
) {
306 GeoIP_printf(f
,"Failed\n");
308 return GEOIP_LICENSE_KEY_INVALID_ERR
;
309 } else if (strstr(compr
, "Invalid product ID or subscription expired") != NULL
){
311 return GEOIP_PRODUCT_ID_INVALID_ERR
;
312 } else if (strstr(compr
, "No new updates available") != NULL
) {
314 return GEOIP_NO_NEW_UPDATES
;
318 GeoIP_printf(f
,"Done\n");
321 file_path_gz
= malloc(sizeof(char) * (strlen(GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]) + 4));
322 if (file_path_gz
== NULL
)
323 return GEOIP_OUT_OF_MEMORY_ERR
;
324 strcpy(file_path_gz
,GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
325 strcat(file_path_gz
,".gz");
327 GeoIP_printf(f
, SavingGzip
, file_path_gz
);
329 comp_fh
= fopen(file_path_gz
, "wb");
331 if(comp_fh
== NULL
) {
334 return GEOIP_GZIP_IO_ERR
;
337 fwrite(compr
, 1, comprLen
, comp_fh
);
342 GeoIP_printf(f
,"Done\n");
345 GeoIP_printf(f
,"Uncompressing gzip file ... ");
347 /* uncompress gzip file */
348 gz_fh
= gzopen(file_path_gz
, "rb");
349 file_path_test
= malloc(sizeof(char) * (strlen(GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]) + 6));
350 if (file_path_test
== NULL
)
351 return GEOIP_OUT_OF_MEMORY_ERR
;
352 strcpy(file_path_test
,GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
353 strcat(file_path_test
,".test");
354 gi_fh
= fopen(file_path_test
, "wb");
357 free(file_path_test
);
358 return GEOIP_TEST_IO_ERR
;
362 amt
= gzread(gz_fh
, block
, block_size
);
364 free(file_path_test
);
367 return GEOIP_GZIP_READ_ERR
;
372 fwrite(block
,1,amt
,gi_fh
);
375 unlink(file_path_gz
);
380 GeoIP_printf(f
,"Done\n");
383 GeoIP_printf(f
, WritingFile
, GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
387 gi
= GeoIP_open(file_path_test
, GEOIP_STANDARD
);
390 GeoIP_printf(f
,"Performing santity checks ... ");
393 GeoIP_printf(f
,"Error opening sanity check database\n");
394 return GEOIP_SANITY_OPEN_ERR
;
397 /* this checks to make sure the files is complete, since info is at the end */
398 /* dependent on future databases having MaxMind in info */
400 GeoIP_printf(f
,"database_info ");
401 db_info
= GeoIP_database_info(gi
);
402 if (db_info
== NULL
) {
405 GeoIP_printf(f
,"FAIL\n");
406 return GEOIP_SANITY_INFO_FAIL
;
408 if (strstr(db_info
, "MaxMind") == NULL
) {
412 GeoIP_printf(f
,"FAIL\n");
413 return GEOIP_SANITY_INFO_FAIL
;
417 GeoIP_printf(f
,"PASS ");
419 /* this performs an IP lookup test of a US IP address */
421 GeoIP_printf(f
,"lookup ");
422 if (strcmp(GeoIP_country_code_by_addr(gi
,"24.24.24.24"), "US") != 0) {
425 GeoIP_printf(f
,"FAIL\n");
426 return GEOIP_SANITY_LOOKUP_FAIL
;
430 GeoIP_printf(f
,"PASS\n");
432 /* install GeoIP.dat.test -> GeoIP.dat */
433 err
= rename(file_path_test
, GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
435 GeoIP_printf(f
,"GeoIP Install error while renaming file\n");
436 return GEOIP_RENAME_ERR
;
440 GeoIP_printf(f
,"Done\n");
445 short int GeoIP_update_database_general (char * user_id
,char * license_key
,char *data_base_type
, int verbose
,char ** client_ipaddr
, void (*f
)( char *)) {
446 struct hostent
*hostlist
;
449 struct sockaddr_in sa
;
453 unsigned long comprLen
;
454 FILE *comp_fh
, *cur_db_fh
, *gi_fh
;
456 char * file_path_gz
, * file_path_test
;
458 MD5_CONTEXT context2
;
459 unsigned char buffer
[1024], digest
[16] ,digest2
[16];
460 char hex_digest
[33] = "0000000000000000000000000000000\0";
461 char hex_digest2
[33] = "0000000000000000000000000000000\0";
470 int lookupresult
= 1;
471 char block
[BLOCK_SIZE
];
472 int block_size
= BLOCK_SIZE
;
474 size_t request_uri_len
;
476 hostlist
= GeoIP_get_host_or_proxy();
478 if (hostlist
== NULL
)
479 return GEOIP_DNS_ERR
;
481 if (hostlist
->h_addrtype
!= AF_INET
)
482 return GEOIP_NON_IPV4_ERR
;
483 if((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
484 return GEOIP_SOCKET_OPEN_ERR
;
487 memset(&sa
, 0, sizeof(struct sockaddr_in
));
488 sa
.sin_port
= htons(GeoIPHTTPPort
);
489 memcpy(&sa
.sin_addr
, hostlist
->h_addr_list
[0], hostlist
->h_length
);
490 sa
.sin_family
= AF_INET
;
493 GeoIP_printf(f
,"Connecting to MaxMind GeoIP server\n");
494 GeoIP_printf(f
, "via Host or Proxy Server: %s:%d\n", hostlist
->h_name
, GeoIPHTTPPort
);
497 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(struct sockaddr
))< 0)
498 return GEOIP_CONNECTION_ERR
;
499 request_uri
= malloc(sizeof(char) * (strlen(license_key
) + strlen(GeoIPHTTPRequestMD5
)+1036));
500 if (request_uri
== NULL
)
501 return GEOIP_OUT_OF_MEMORY_ERR
;
503 /* get the file name from a web page using the product id */
504 sprintf(request_uri
,GeoIPHTTPRequestFilename
,GeoIPProxyHTTP
,GeoIPProxiedHost
,data_base_type
,GeoIPUpdateHost
);
506 GeoIP_printf(f
, "sending request %s \n",request_uri
);
508 send(sock
, request_uri
, strlen(request_uri
),0); /* send the request */
510 buf
= malloc(sizeof(char) * (block_size
+4));
512 return GEOIP_OUT_OF_MEMORY_ERR
;
516 amt
= recv(sock
, &buf
[offset
], block_size
,0);
519 } else if (amt
== -1) {
521 return GEOIP_SOCKET_READ_ERR
;
524 buf
= realloc(buf
, offset
+ block_size
+ 4);
528 tmpstr
= strstr(buf
, "\r\n\r\n") + 4;
529 if (tmpstr
[0] == '.' || strchr(tmpstr
, '/') != NULL
) {
531 return GEOIP_INVALID_SERVER_RESPONSE
;
533 geoipfilename
= _GeoIP_full_path_to(tmpstr
);
536 /* print the database product id and the database filename */
538 GeoIP_printf(f
, "database product id %s database file name %s \n",data_base_type
,geoipfilename
);
540 _GeoIP_setup_dbfilename();
542 /* get MD5 of current GeoIP database file */
543 if ((cur_db_fh
= fopen (geoipfilename
, "rb")) == NULL
) {
544 GeoIP_printf(f
, NoCurrentDB
, geoipfilename
);
547 while ((len
= fread (buffer
, 1, 1024, cur_db_fh
)) > 0)
548 md5_write (&context
, buffer
, len
);
549 md5_final (&context
);
550 memcpy(digest
,context
.buf
,16);
552 for (i
= 0; i
< 16; i
++)
553 sprintf (&hex_digest
[2*i
], "%02x", digest
[i
]);
554 GeoIP_printf(f
, MD5Info
, hex_digest
);
557 GeoIP_printf(f
,"MD5 sum of database %s is %s \n",geoipfilename
,hex_digest
);
559 if (client_ipaddr
[0] == NULL
) {
560 /* We haven't gotten our IP address yet, so let's request it */
561 if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
563 return GEOIP_SOCKET_OPEN_ERR
;
566 memset(&sa
, 0, sizeof(struct sockaddr_in
));
567 sa
.sin_port
= htons(GeoIPHTTPPort
);
568 memcpy(&sa
.sin_addr
, hostlist
->h_addr_list
[0], hostlist
->h_length
);
569 sa
.sin_family
= AF_INET
;
572 GeoIP_printf(f
,"Connecting to MaxMind GeoIP Update server\n");
574 /* Download gzip file */
575 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(struct sockaddr
))< 0) {
577 return GEOIP_CONNECTION_ERR
;
579 request_uri
= malloc(sizeof(char) * (strlen(license_key
) + strlen(GeoIPHTTPRequestMD5
)+1036));
580 if (request_uri
== NULL
) {
582 return GEOIP_OUT_OF_MEMORY_ERR
;
585 /* get client ip address from MaxMind web page */
586 sprintf(request_uri
,GeoIPHTTPRequestClientIP
,GeoIPProxyHTTP
,GeoIPProxiedHost
,GeoIPUpdateHost
);
587 send(sock
, request_uri
, strlen(request_uri
),0); /* send the request */
589 GeoIP_printf(f
, "sending request %s", request_uri
);
592 buf
= malloc(sizeof(char) * (block_size
+1));
595 return GEOIP_OUT_OF_MEMORY_ERR
;
601 amt
= recv(sock
, &buf
[offset
], block_size
,0);
604 } else if (amt
== -1) {
606 return GEOIP_SOCKET_READ_ERR
;
609 buf
= realloc(buf
, offset
+block_size
+1);
614 ipaddress
= strstr(buf
, "\r\n\r\n") + 4; /* get the ip address */
615 ipaddress
= malloc(strlen(strstr(buf
, "\r\n\r\n") + 4)+5);
616 strcpy(ipaddress
,strstr(buf
, "\r\n\r\n") + 4);
617 client_ipaddr
[0] = ipaddress
;
619 GeoIP_printf(f
, "client ip address: %s\n",ipaddress
);
625 ipaddress
= client_ipaddr
[0];
627 /* make a md5 sum of ip address and license_key and store it in hex_digest2 */
628 request_uri_len
= sizeof(char) * 2036;
629 request_uri
= malloc(request_uri_len
);
631 md5_write (&context2
, license_key
, 12);//add license key to the md5 sum
632 md5_write (&context2
, ipaddress
, strlen(ipaddress
));//add ip address to the md5 sum
633 md5_final (&context2
);
634 memcpy(digest2
,context2
.buf
,16);
635 for (i
= 0; i
< 16; i
++)
636 snprintf (&hex_digest2
[2*i
], 3, "%02x", digest2
[i
]);// change the digest to a hex digest
638 GeoIP_printf(f
, "md5sum of ip address and license key is %s \n",hex_digest2
);
641 /* send the request using the user id,product id,
642 * md5 sum of the prev database and
643 * the md5 sum of the license_key and ip address */
644 if((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
645 return GEOIP_SOCKET_OPEN_ERR
;
647 memset(&sa
, 0, sizeof(struct sockaddr_in
));
648 sa
.sin_port
= htons(GeoIPHTTPPort
);
649 memcpy(&sa
.sin_addr
, hostlist
->h_addr_list
[0], hostlist
->h_length
);
650 sa
.sin_family
= AF_INET
;
651 if (connect(sock
, (struct sockaddr
*)&sa
, sizeof(struct sockaddr
))< 0)
652 return GEOIP_CONNECTION_ERR
;
653 snprintf(request_uri
, request_uri_len
, GeoIPHTTPRequestMD5
,GeoIPProxyHTTP
,GeoIPProxiedHost
,hex_digest
,hex_digest2
,user_id
,data_base_type
);
654 send(sock
, request_uri
, strlen(request_uri
),0);
656 GeoIP_printf(f
, "sending request %s\n",request_uri
);
662 buf
= malloc(sizeof(char) * block_size
);
664 return GEOIP_OUT_OF_MEMORY_ERR
;
667 GeoIP_printf(f
,"Downloading gzipped GeoIP Database...\n");
671 amt
= recv(sock
, &buf
[offset
], block_size
,0);
675 } else if (amt
== -1) {
677 return GEOIP_SOCKET_READ_ERR
;
680 buf
= realloc(buf
, offset
+block_size
);
682 return GEOIP_OUT_OF_MEMORY_ERR
;
685 compr
= strstr(buf
, "\r\n\r\n") + 4;
686 comprLen
= offset
+ buf
- compr
;
688 if (strstr(compr
, "License Key Invalid") != NULL
) {
690 GeoIP_printf(f
,"Failed\n");
692 return GEOIP_LICENSE_KEY_INVALID_ERR
;
693 } else if (strstr(compr
, "No new updates available") != NULL
) {
695 GeoIP_printf(f
, "%s is up to date, no updates required\n", geoipfilename
);
696 return GEOIP_NO_NEW_UPDATES
;
697 } else if (strstr(compr
, "Invalid UserId") != NULL
){
699 return GEOIP_USER_ID_INVALID_ERR
;
700 } else if (strstr(compr
, "Invalid product ID or subscription expired") != NULL
){
702 return GEOIP_PRODUCT_ID_INVALID_ERR
;
706 GeoIP_printf(f
,"Done\n");
708 GeoIP_printf(f
, "Updating %s\n", geoipfilename
);
711 file_path_gz
= malloc(sizeof(char) * (strlen(geoipfilename
) + 4));
713 if (file_path_gz
== NULL
)
714 return GEOIP_OUT_OF_MEMORY_ERR
;
715 strcpy(file_path_gz
,geoipfilename
);
716 strcat(file_path_gz
,".gz");
718 GeoIP_printf(f
, "%s%s", SavingGzip
, file_path_gz
);
720 comp_fh
= fopen(file_path_gz
, "wb");
722 if(comp_fh
== NULL
) {
725 return GEOIP_GZIP_IO_ERR
;
728 fwrite(compr
, 1, comprLen
, comp_fh
);
733 GeoIP_printf(f
, "download data to a gz file named %s \n",file_path_gz
);
734 GeoIP_printf(f
,"Done\n");
735 GeoIP_printf(f
,"Uncompressing gzip file ... ");
738 file_path_test
= malloc(sizeof(char) * (strlen(GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]) + 6));
739 if (file_path_test
== NULL
) {
741 return GEOIP_OUT_OF_MEMORY_ERR
;
743 strcpy(file_path_test
,GeoIPDBFileName
[GEOIP_COUNTRY_EDITION
]);
744 strcat(file_path_test
,".test");
745 gi_fh
= fopen(file_path_test
, "wb");
747 free(file_path_test
);
749 return GEOIP_TEST_IO_ERR
;
751 /* uncompress gzip file */
753 gz_fh
= gzopen(file_path_gz
, "rb");
756 amt
= gzread(gz_fh
, block
, block_size
);
759 free(file_path_test
);
762 return GEOIP_GZIP_READ_ERR
;
767 fwrite(block
,1,amt
,gi_fh
);
770 unlink(file_path_gz
);
775 GeoIP_printf(f
,"Done\n");
778 len
= strlen(WritingFile
) + strlen(geoipfilename
) - 1;
780 snprintf(f_str
,len
,WritingFile
,geoipfilename
);
785 gi
= GeoIP_open(file_path_test
, GEOIP_STANDARD
);
788 GeoIP_printf(f
,"Performing santity checks ... ");
791 GeoIP_printf(f
,"Error opening sanity check database\n");
792 return GEOIP_SANITY_OPEN_ERR
;
796 /* get the database type */
797 dbtype
= GeoIP_database_edition(gi
);
799 GeoIP_printf(f
, "Database type is %d\n",dbtype
);
802 /* this checks to make sure the files is complete, since info is at the end
803 dependent on future databases having MaxMind in info (ISP and Organization databases currently don't have info string */
805 if ((dbtype
!= GEOIP_ISP_EDITION
)&&
806 (dbtype
!= GEOIP_ORG_EDITION
)) {
808 GeoIP_printf(f
,"database_info ");
809 db_info
= GeoIP_database_info(gi
);
810 if (db_info
== NULL
) {
813 GeoIP_printf(f
,"FAIL null\n");
814 return GEOIP_SANITY_INFO_FAIL
;
816 if (strstr(db_info
, "MaxMind") == NULL
) {
820 GeoIP_printf(f
,"FAIL maxmind\n");
821 return GEOIP_SANITY_INFO_FAIL
;
825 GeoIP_printf(f
,"PASS ");
828 /* this performs an IP lookup test of a US IP address */
830 GeoIP_printf(f
,"lookup ");
831 if (dbtype
== GEOIP_NETSPEED_EDITION
) {
832 int netspeed
= GeoIP_id_by_name(gi
,"24.24.24.24");
834 if (netspeed
== GEOIP_CABLEDSL_SPEED
){
838 if (dbtype
== GEOIP_COUNTRY_EDITION
) {
839 /* if data base type is country then call the function
840 * named GeoIP_country_code_by_addr */
842 if (strcmp(GeoIP_country_code_by_addr(gi
,"24.24.24.24"), "US") != 0) {
846 GeoIP_printf(f
,"testing GEOIP_COUNTRY_EDITION\n");
849 if (dbtype
== GEOIP_REGION_EDITION_REV1
) {
850 /* if data base type is region then call the function
851 * named GeoIP_region_by_addr */
852 GeoIPRegion
*r
= GeoIP_region_by_addr(gi
,"24.24.24.24");
859 GeoIP_printf(f
,"testing GEOIP_REGION_EDITION\n");
862 if (dbtype
== GEOIP_CITY_EDITION_REV1
) {
863 /* if data base type is city then call the function
864 * named GeoIP_record_by_addr */
865 GeoIPRecord
*r
= GeoIP_record_by_addr(gi
,"24.24.24.24");
872 GeoIP_printf(f
,"testing GEOIP_CITY_EDITION\n");
875 if ((dbtype
== GEOIP_ISP_EDITION
)||
876 (dbtype
== GEOIP_ORG_EDITION
)) {
877 /* if data base type is isp or org then call the function
878 * named GeoIP_org_by_addr */
879 GeoIPRecord
*r
= (GeoIPRecord
*)GeoIP_org_by_addr(gi
,"24.24.24.24");
886 if (dbtype
== GEOIP_ISP_EDITION
) {
887 GeoIP_printf(f
,"testing GEOIP_ISP_EDITION\n");
889 if (dbtype
== GEOIP_ORG_EDITION
) {
890 GeoIP_printf(f
,"testing GEOIP_ORG_EDITION\n");
894 if (lookupresult
== 0) {
897 GeoIP_printf(f
,"FAIL\n");
898 return GEOIP_SANITY_LOOKUP_FAIL
;
902 GeoIP_printf(f
,"PASS\n");
904 /* install GeoIP.dat.test -> GeoIP.dat */
905 err
= rename(file_path_test
, geoipfilename
);
907 GeoIP_printf(f
,"GeoIP Install error while renaming file\n");
908 return GEOIP_RENAME_ERR
;
912 GeoIP_printf(f
,"Done\n");