]> jfr.im git - irc/quakenet/newserv.git/blob - geoip/libGeoIP/GeoIPUpdate.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / geoip / libGeoIP / GeoIPUpdate.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* GeoIPUpdate.c
3 *
4 * Copyright (C) 2006 MaxMind LLC
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "GeoIPCity.h"
22 #include "GeoIP.h"
23 #include "GeoIPUpdate.h"
24 #include "GeoIP_internal.h"
25
26 #include "global.h"
27 #include "md5.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>
33 #include <netdb.h>
34 #else
35 #include <windows.h>
36 #include <winsock.h>
37 #endif
38 #include <zlib.h>
39 #include <time.h>
40 #include <stdio.h>
41 #include <unistd.h>
42
43 #define BLOCK_SIZE 1024
44
45 /* Update DB Host & HTTP GET Request formats:
46 * ------------------------------------------
47 * GET must support an optional HTTP Proxy.
48 */
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";
58
59 /* messages */
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 ...";
64
65 const char * GeoIP_get_error_message(int i) {
66 switch (i) {
67 case GEOIP_NO_NEW_UPDATES:
68 return "no new updates";
69 case GEOIP_SUCCESS:
70 return "Success";
71 case GEOIP_LICENSE_KEY_INVALID_ERR:
72 return "License Key Invalid";
73 case GEOIP_DNS_ERR:
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";
105 default:
106 return "no error";
107 }
108 }
109 int GeoIP_fprintf(int (*f)(FILE *, char *),FILE *fp, const char *str, ...) {
110 va_list ap;
111 int rc;
112 char * f_str;
113 if ( f == NULL )
114 return 0;
115 va_start(ap, str);
116 vasprintf(&f_str, str, ap);
117 va_end(ap);
118 if ( f_str == NULL )
119 return -1;
120 rc = (*f)(fp, f_str);
121 free(f_str);
122 return(rc);
123 }
124
125 void GeoIP_printf(void (*f)(char *), const char *str,...) {
126 va_list params;
127 char * f_str;
128 if (f == NULL)
129 return;
130 va_start(params, str);
131 vasprintf(&f_str, str, params);
132 va_end(params);
133 if ( f_str == NULL )
134 return;
135 (*f)(f_str);
136 free(f_str);
137 }
138
139 /* Support HTTP Proxy Host
140 * --------------------------------------------------
141 * Use typical OS support for the optional HTTP Proxy.
142 *
143 * Proxy adds http://{real-hostname} to URI format strings:
144 * sprintf("GET %s%s/ HTTP/1.0\r\n",GeoIPProxyHTTP,GeoIPProxiedHost, ...);
145 */
146
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 = "";
151
152 /* Read http_proxy env. variable & parse it.
153 * -----------------------------------------
154 * Allow only these formats:
155 * "http://server.com", "http://server.com:8080"
156 * OR
157 * "server.com", "server.com:8080"
158 *
159 * A "user:password@" part will break this.
160 */
161 short int parse_http_proxy(char **proxy_host, int *port) {
162 char * http_proxy;
163 char * port_value;
164
165 if ((http_proxy = getenv("http_proxy"))) {
166
167 if (! strncmp("http://", http_proxy, 7)) http_proxy += 7;
168
169 *proxy_host = strdup(http_proxy);
170 if ( *proxy_host == NULL )
171 return 0; /* let the other functions deal with the memory error */
172
173 if ((port_value = strchr(*proxy_host, ':'))) {
174 *port_value++ = '\0';
175 *port = atoi(port_value);
176 }
177 else {
178 *port = 80;
179 }
180 return(1);
181 }
182 else {
183 return(0);
184 }
185 }
186
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;
190 char * proxy_host;
191 int proxy_port;
192
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;
199 }
200
201 /* Resolve DNS host entry. */
202 return(gethostbyname(hostname));
203 }
204
205 short int GeoIP_update_database (char * license_key, int verbose, void (*f)( char * )) {
206 struct hostent *hostlist;
207 int sock;
208 char * buf;
209 struct sockaddr_in sa;
210 int offset = 0, err;
211 char * request_uri;
212 char * compr;
213 unsigned long comprLen;
214 FILE *comp_fh, *cur_db_fh, *gi_fh;
215 gzFile gz_fh;
216 char * file_path_gz, * file_path_test;
217 MD5_CONTEXT context;
218 unsigned char buffer[1024], digest[16];
219 char hex_digest[33] = "00000000000000000000000000000000\0";
220 unsigned int i;
221 GeoIP * gi;
222 char * db_info;
223 char block[BLOCK_SIZE];
224 int block_size = BLOCK_SIZE;
225 size_t len;
226
227 _GeoIP_setup_dbfilename();
228
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]);
232 } else {
233 md5_init(&context);
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);
238 fclose (cur_db_fh);
239 for (i = 0; i < 16; i++) {
240 // "%02x" will write 3 chars
241 snprintf (&hex_digest[2*i], 3, "%02x", digest[i]);
242 }
243 GeoIP_printf(f, MD5Info, hex_digest);
244 }
245
246 hostlist = GeoIP_get_host_or_proxy();
247
248 if (hostlist == NULL)
249 return GEOIP_DNS_ERR;
250
251 if (hostlist->h_addrtype != AF_INET)
252 return GEOIP_NON_IPV4_ERR;
253
254 if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
255 return GEOIP_SOCKET_OPEN_ERR;
256 }
257
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;
262
263 if (verbose == 1){
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);
266 }
267
268 /* Download gzip file */
269 if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0)
270 return GEOIP_CONNECTION_ERR;
271
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);
277 free(request_uri);
278
279 buf = malloc(sizeof(char) * block_size);
280 if (buf == NULL)
281 return GEOIP_OUT_OF_MEMORY_ERR;
282
283 if (verbose == 1)
284 GeoIP_printf(f,"Downloading gzipped GeoIP Database...\n");
285
286 for (;;) {
287 int amt;
288 amt = recv(sock, &buf[offset], block_size,0);
289 if (amt == 0) {
290 break;
291 } else if (amt == -1) {
292 free(buf);
293 return GEOIP_SOCKET_READ_ERR;
294 }
295 offset += amt;
296 buf = realloc(buf, offset+block_size);
297 if (buf == NULL)
298 return GEOIP_OUT_OF_MEMORY_ERR;
299 }
300
301 compr = strstr(buf, "\r\n\r\n") + 4;
302 comprLen = offset + buf - compr;
303
304 if (strstr(compr, "License Key Invalid") != NULL) {
305 if (verbose == 1)
306 GeoIP_printf(f,"Failed\n");
307 free(buf);
308 return GEOIP_LICENSE_KEY_INVALID_ERR;
309 } else if (strstr(compr, "Invalid product ID or subscription expired") != NULL){
310 free(buf);
311 return GEOIP_PRODUCT_ID_INVALID_ERR;
312 } else if (strstr(compr, "No new updates available") != NULL) {
313 free(buf);
314 return GEOIP_NO_NEW_UPDATES;
315 }
316
317 if (verbose == 1)
318 GeoIP_printf(f,"Done\n");
319
320 /* save gzip file */
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");
326 if (verbose == 1) {
327 GeoIP_printf(f, SavingGzip, file_path_gz);
328 }
329 comp_fh = fopen(file_path_gz, "wb");
330
331 if(comp_fh == NULL) {
332 free(file_path_gz);
333 free(buf);
334 return GEOIP_GZIP_IO_ERR;
335 }
336
337 fwrite(compr, 1, comprLen, comp_fh);
338 fclose(comp_fh);
339 free(buf);
340
341 if (verbose == 1)
342 GeoIP_printf(f,"Done\n");
343
344 if (verbose == 1)
345 GeoIP_printf(f,"Uncompressing gzip file ... ");
346
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");
355
356 if(gi_fh == NULL) {
357 free(file_path_test);
358 return GEOIP_TEST_IO_ERR;
359 }
360 for (;;) {
361 int amt;
362 amt = gzread(gz_fh, block, block_size);
363 if (amt == -1) {
364 free(file_path_test);
365 fclose(gi_fh);
366 gzclose(gz_fh);
367 return GEOIP_GZIP_READ_ERR;
368 }
369 if (amt == 0) {
370 break;
371 }
372 fwrite(block,1,amt,gi_fh);
373 }
374 gzclose(gz_fh);
375 unlink(file_path_gz);
376 free(file_path_gz);
377 fclose(gi_fh);
378
379 if (verbose == 1)
380 GeoIP_printf(f,"Done\n");
381
382 if (verbose == 1) {
383 GeoIP_printf(f, WritingFile, GeoIPDBFileName[GEOIP_COUNTRY_EDITION]);
384 }
385
386 /* sanity check */
387 gi = GeoIP_open(file_path_test, GEOIP_STANDARD);
388
389 if (verbose == 1)
390 GeoIP_printf(f,"Performing santity checks ... ");
391
392 if (gi == NULL) {
393 GeoIP_printf(f,"Error opening sanity check database\n");
394 return GEOIP_SANITY_OPEN_ERR;
395 }
396
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 */
399 if (verbose == 1)
400 GeoIP_printf(f,"database_info ");
401 db_info = GeoIP_database_info(gi);
402 if (db_info == NULL) {
403 GeoIP_delete(gi);
404 if (verbose == 1)
405 GeoIP_printf(f,"FAIL\n");
406 return GEOIP_SANITY_INFO_FAIL;
407 }
408 if (strstr(db_info, "MaxMind") == NULL) {
409 free(db_info);
410 GeoIP_delete(gi);
411 if (verbose == 1)
412 GeoIP_printf(f,"FAIL\n");
413 return GEOIP_SANITY_INFO_FAIL;
414 }
415 free(db_info);
416 if (verbose == 1)
417 GeoIP_printf(f,"PASS ");
418
419 /* this performs an IP lookup test of a US IP address */
420 if (verbose == 1)
421 GeoIP_printf(f,"lookup ");
422 if (strcmp(GeoIP_country_code_by_addr(gi,"24.24.24.24"), "US") != 0) {
423 GeoIP_delete(gi);
424 if (verbose == 1)
425 GeoIP_printf(f,"FAIL\n");
426 return GEOIP_SANITY_LOOKUP_FAIL;
427 }
428 GeoIP_delete(gi);
429 if (verbose == 1)
430 GeoIP_printf(f,"PASS\n");
431
432 /* install GeoIP.dat.test -> GeoIP.dat */
433 err = rename(file_path_test, GeoIPDBFileName[GEOIP_COUNTRY_EDITION]);
434 if (err != 0) {
435 GeoIP_printf(f,"GeoIP Install error while renaming file\n");
436 return GEOIP_RENAME_ERR;
437 }
438
439 if (verbose == 1)
440 GeoIP_printf(f,"Done\n");
441
442 return 0;
443 }
444
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;
447 int sock;
448 char * buf;
449 struct sockaddr_in sa;
450 int offset = 0, err;
451 char * request_uri;
452 char * compr;
453 unsigned long comprLen;
454 FILE *comp_fh, *cur_db_fh, *gi_fh;
455 gzFile gz_fh;
456 char * file_path_gz, * file_path_test;
457 MD5_CONTEXT context;
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";
462 unsigned int i;
463 char *f_str;
464 GeoIP * gi;
465 char * db_info;
466 char *ipaddress;
467 char *geoipfilename;
468 char *tmpstr;
469 int dbtype;
470 int lookupresult = 1;
471 char block[BLOCK_SIZE];
472 int block_size = BLOCK_SIZE;
473 size_t len;
474 size_t request_uri_len;
475
476 hostlist = GeoIP_get_host_or_proxy();
477
478 if (hostlist == NULL)
479 return GEOIP_DNS_ERR;
480
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;
485 }
486
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;
491
492 if (verbose == 1) {
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);
495 }
496
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;
502
503 /* get the file name from a web page using the product id */
504 sprintf(request_uri,GeoIPHTTPRequestFilename,GeoIPProxyHTTP,GeoIPProxiedHost,data_base_type,GeoIPUpdateHost);
505 if (verbose == 1) {
506 GeoIP_printf(f, "sending request %s \n",request_uri);
507 }
508 send(sock, request_uri, strlen(request_uri),0); /* send the request */
509 free(request_uri);
510 buf = malloc(sizeof(char) * (block_size+4));
511 if (buf == NULL)
512 return GEOIP_OUT_OF_MEMORY_ERR;
513 offset = 0;
514 for (;;){
515 int amt;
516 amt = recv(sock, &buf[offset], block_size,0);
517 if (amt == 0){
518 break;
519 } else if (amt == -1) {
520 free(buf);
521 return GEOIP_SOCKET_READ_ERR;
522 }
523 offset += amt;
524 buf = realloc(buf, offset + block_size + 4);
525 }
526 buf[offset] = 0;
527 offset = 0;
528 tmpstr = strstr(buf, "\r\n\r\n") + 4;
529 if (tmpstr[0] == '.' || strchr(tmpstr, '/') != NULL) {
530 free(buf);
531 return GEOIP_INVALID_SERVER_RESPONSE;
532 }
533 geoipfilename = _GeoIP_full_path_to(tmpstr);
534 free(buf);
535
536 /* print the database product id and the database filename */
537 if (verbose == 1){
538 GeoIP_printf(f, "database product id %s database file name %s \n",data_base_type,geoipfilename);
539 }
540 _GeoIP_setup_dbfilename();
541
542 /* get MD5 of current GeoIP database file */
543 if ((cur_db_fh = fopen (geoipfilename, "rb")) == NULL) {
544 GeoIP_printf(f, NoCurrentDB, geoipfilename);
545 } else {
546 md5_init(&context);
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);
551 fclose (cur_db_fh);
552 for (i = 0; i < 16; i++)
553 sprintf (&hex_digest[2*i], "%02x", digest[i]);
554 GeoIP_printf(f, MD5Info, hex_digest );
555 }
556 if (verbose == 1) {
557 GeoIP_printf(f,"MD5 sum of database %s is %s \n",geoipfilename,hex_digest);
558 }
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) {
562 free(geoipfilename);
563 return GEOIP_SOCKET_OPEN_ERR;
564 }
565
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;
570
571 if (verbose == 1)
572 GeoIP_printf(f,"Connecting to MaxMind GeoIP Update server\n");
573
574 /* Download gzip file */
575 if (connect(sock, (struct sockaddr *)&sa, sizeof(struct sockaddr))< 0) {
576 free(geoipfilename);
577 return GEOIP_CONNECTION_ERR;
578 }
579 request_uri = malloc(sizeof(char) * (strlen(license_key) + strlen(GeoIPHTTPRequestMD5)+1036));
580 if (request_uri == NULL) {
581 free(geoipfilename);
582 return GEOIP_OUT_OF_MEMORY_ERR;
583 }
584
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 */
588 if (verbose == 1) {
589 GeoIP_printf(f, "sending request %s", request_uri);
590 }
591 free(request_uri);
592 buf = malloc(sizeof(char) * (block_size+1));
593 if (buf == NULL) {
594 free(geoipfilename);
595 return GEOIP_OUT_OF_MEMORY_ERR;
596 }
597 offset = 0;
598
599 for (;;){
600 int amt;
601 amt = recv(sock, &buf[offset], block_size,0);
602 if (amt == 0) {
603 break;
604 } else if (amt == -1) {
605 free(buf);
606 return GEOIP_SOCKET_READ_ERR;
607 }
608 offset += amt;
609 buf = realloc(buf, offset+block_size+1);
610 }
611
612 buf[offset] = 0;
613 offset = 0;
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;
618 if (verbose == 1) {
619 GeoIP_printf(f, "client ip address: %s\n",ipaddress);
620 }
621 free(buf);
622 close(sock);
623 }
624
625 ipaddress = client_ipaddr[0];
626
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);
630 md5_init(&context2);
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
637 if (verbose == 1) {
638 GeoIP_printf(f, "md5sum of ip address and license key is %s \n",hex_digest2);
639 }
640
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;
646 }
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);
655 if (verbose == 1) {
656 GeoIP_printf(f, "sending request %s\n",request_uri);
657 }
658
659 free(request_uri);
660
661 offset = 0;
662 buf = malloc(sizeof(char) * block_size);
663 if (buf == NULL)
664 return GEOIP_OUT_OF_MEMORY_ERR;
665
666 if (verbose == 1)
667 GeoIP_printf(f,"Downloading gzipped GeoIP Database...\n");
668
669 for (;;) {
670 int amt;
671 amt = recv(sock, &buf[offset], block_size,0);
672
673 if (amt == 0) {
674 break;
675 } else if (amt == -1) {
676 free(buf);
677 return GEOIP_SOCKET_READ_ERR;
678 }
679 offset += amt;
680 buf = realloc(buf, offset+block_size);
681 if (buf == NULL)
682 return GEOIP_OUT_OF_MEMORY_ERR;
683 }
684
685 compr = strstr(buf, "\r\n\r\n") + 4;
686 comprLen = offset + buf - compr;
687
688 if (strstr(compr, "License Key Invalid") != NULL) {
689 if (verbose == 1)
690 GeoIP_printf(f,"Failed\n");
691 free(buf);
692 return GEOIP_LICENSE_KEY_INVALID_ERR;
693 } else if (strstr(compr, "No new updates available") != NULL) {
694 free(buf);
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){
698 free(buf);
699 return GEOIP_USER_ID_INVALID_ERR;
700 } else if (strstr(compr, "Invalid product ID or subscription expired") != NULL){
701 free(buf);
702 return GEOIP_PRODUCT_ID_INVALID_ERR;
703 }
704
705 if (verbose == 1)
706 GeoIP_printf(f,"Done\n");
707
708 GeoIP_printf(f, "Updating %s\n", geoipfilename);
709
710 /* save gzip file */
711 file_path_gz = malloc(sizeof(char) * (strlen(geoipfilename) + 4));
712
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");
717 if (verbose == 1) {
718 GeoIP_printf(f, "%s%s", SavingGzip, file_path_gz );
719 }
720 comp_fh = fopen(file_path_gz, "wb");
721
722 if(comp_fh == NULL) {
723 free(file_path_gz);
724 free(buf);
725 return GEOIP_GZIP_IO_ERR;
726 }
727
728 fwrite(compr, 1, comprLen, comp_fh);
729 fclose(comp_fh);
730 free(buf);
731
732 if (verbose == 1) {
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 ... ");
736 }
737
738 file_path_test = malloc(sizeof(char) * (strlen(GeoIPDBFileName[GEOIP_COUNTRY_EDITION]) + 6));
739 if (file_path_test == NULL) {
740 free(file_path_gz);
741 return GEOIP_OUT_OF_MEMORY_ERR;
742 }
743 strcpy(file_path_test,GeoIPDBFileName[GEOIP_COUNTRY_EDITION]);
744 strcat(file_path_test,".test");
745 gi_fh = fopen(file_path_test, "wb");
746 if(gi_fh == NULL) {
747 free(file_path_test);
748 free(file_path_gz);
749 return GEOIP_TEST_IO_ERR;
750 }
751 /* uncompress gzip file */
752 offset = 0;
753 gz_fh = gzopen(file_path_gz, "rb");
754 for (;;) {
755 int amt;
756 amt = gzread(gz_fh, block, block_size);
757 if (amt == -1) {
758 free(file_path_gz);
759 free(file_path_test);
760 gzclose(gz_fh);
761 fclose(gi_fh);
762 return GEOIP_GZIP_READ_ERR;
763 }
764 if (amt == 0) {
765 break;
766 }
767 fwrite(block,1,amt,gi_fh);
768 }
769 gzclose(gz_fh);
770 unlink(file_path_gz);
771 free(file_path_gz);
772 fclose(gi_fh);
773
774 if (verbose == 1)
775 GeoIP_printf(f,"Done\n");
776
777 if (verbose == 1) {
778 len = strlen(WritingFile) + strlen(geoipfilename) - 1;
779 f_str = malloc(len);
780 snprintf(f_str,len,WritingFile,geoipfilename);
781 free(f_str);
782 }
783
784 /* sanity check */
785 gi = GeoIP_open(file_path_test, GEOIP_STANDARD);
786
787 if (verbose == 1)
788 GeoIP_printf(f,"Performing santity checks ... ");
789
790 if (gi == NULL) {
791 GeoIP_printf(f,"Error opening sanity check database\n");
792 return GEOIP_SANITY_OPEN_ERR;
793 }
794
795
796 /* get the database type */
797 dbtype = GeoIP_database_edition(gi);
798 if (verbose == 1) {
799 GeoIP_printf(f, "Database type is %d\n",dbtype);
800 }
801
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 */
804
805 if ((dbtype != GEOIP_ISP_EDITION)&&
806 (dbtype != GEOIP_ORG_EDITION)) {
807 if (verbose == 1)
808 GeoIP_printf(f,"database_info ");
809 db_info = GeoIP_database_info(gi);
810 if (db_info == NULL) {
811 GeoIP_delete(gi);
812 if (verbose == 1)
813 GeoIP_printf(f,"FAIL null\n");
814 return GEOIP_SANITY_INFO_FAIL;
815 }
816 if (strstr(db_info, "MaxMind") == NULL) {
817 free(db_info);
818 GeoIP_delete(gi);
819 if (verbose == 1)
820 GeoIP_printf(f,"FAIL maxmind\n");
821 return GEOIP_SANITY_INFO_FAIL;
822 }
823 free(db_info);
824 if (verbose == 1)
825 GeoIP_printf(f,"PASS ");
826 }
827
828 /* this performs an IP lookup test of a US IP address */
829 if (verbose == 1)
830 GeoIP_printf(f,"lookup ");
831 if (dbtype == GEOIP_NETSPEED_EDITION) {
832 int netspeed = GeoIP_id_by_name(gi,"24.24.24.24");
833 lookupresult = 0;
834 if (netspeed == GEOIP_CABLEDSL_SPEED){
835 lookupresult = 1;
836 }
837 }
838 if (dbtype == GEOIP_COUNTRY_EDITION) {
839 /* if data base type is country then call the function
840 * named GeoIP_country_code_by_addr */
841 lookupresult = 1;
842 if (strcmp(GeoIP_country_code_by_addr(gi,"24.24.24.24"), "US") != 0) {
843 lookupresult = 0;
844 }
845 if (verbose == 1) {
846 GeoIP_printf(f,"testing GEOIP_COUNTRY_EDITION\n");
847 }
848 }
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");
853 lookupresult = 0;
854 if (r != NULL) {
855 lookupresult = 1;
856 free(r);
857 }
858 if (verbose == 1) {
859 GeoIP_printf(f,"testing GEOIP_REGION_EDITION\n");
860 }
861 }
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");
866 lookupresult = 0;
867 if (r != NULL) {
868 lookupresult = 1;
869 free(r);
870 }
871 if (verbose == 1) {
872 GeoIP_printf(f,"testing GEOIP_CITY_EDITION\n");
873 }
874 }
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");
880 lookupresult = 0;
881 if (r != NULL) {
882 lookupresult = 1;
883 free(r);
884 }
885 if (verbose == 1) {
886 if (dbtype == GEOIP_ISP_EDITION) {
887 GeoIP_printf(f,"testing GEOIP_ISP_EDITION\n");
888 }
889 if (dbtype == GEOIP_ORG_EDITION) {
890 GeoIP_printf(f,"testing GEOIP_ORG_EDITION\n");
891 }
892 }
893 }
894 if (lookupresult == 0) {
895 GeoIP_delete(gi);
896 if (verbose == 1)
897 GeoIP_printf(f,"FAIL\n");
898 return GEOIP_SANITY_LOOKUP_FAIL;
899 }
900 GeoIP_delete(gi);
901 if (verbose == 1)
902 GeoIP_printf(f,"PASS\n");
903
904 /* install GeoIP.dat.test -> GeoIP.dat */
905 err = rename(file_path_test, geoipfilename);
906 if (err != 0) {
907 GeoIP_printf(f,"GeoIP Install error while renaming file\n");
908 return GEOIP_RENAME_ERR;
909 }
910
911 if (verbose == 1)
912 GeoIP_printf(f,"Done\n");
913 free(geoipfilename);
914 return 0;
915 }