1/* geoipupdate.c 2 * 3 * Copyright (C) 2006 MaxMind LLC 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20#include "GeoIP.h" 21#include "GeoIPUpdate.h" 22 23#include <unistd.h> 24#include <stdio.h> 25#include <stdlib.h> 26#ifdef HAVE_GETOPT_H 27#include <getopt.h> 28#endif 29#include <ctype.h> 30 31#define PRODUCT_ID_TOKEN "ProductIds" 32#define USER_ID_TOKEN "UserId" 33#define LICENSE_KEY_TOKEN "LicenseKey" 34#define LICENSE_KEY_LENGTH 12 35 36const char *GeoIPConfFile = "GeoIP.conf"; 37 38static void * realloc_or_die( void * ptr, size_t size ){ 39 void * new = realloc( ptr, size ); 40 if ( !new ) { 41 free(ptr); 42 fprintf(stderr, "Out of memory\n"); 43 exit(1); 44 } 45 return new; 46} 47 48void usage() { 49 fprintf(stderr,"Usage: geoipupdate [-hv] [-f license_file] [-d custom directory]\n"); 50} 51 52void my_printf(char * str) { 53 printf("%s", str); 54} 55 56void print_status (int err, char * license_file) { 57 if (err == GEOIP_NO_NEW_UPDATES) { 58 fprintf(stdout,"GeoIP Database up to date\n"); 59 } else if (err == GEOIP_LICENSE_KEY_INVALID_ERR) { 60 fprintf(stderr,"Invalid License Key in %s - Please visit http://www.maxmind.com/app/products for a subscription\n",license_file); 61 } else if (err == GEOIP_USER_ID_INVALID_ERR){ 62 fprintf(stderr,"Invalid UserID\n"); 63 } else if (err == GEOIP_PRODUCT_ID_INVALID_ERR){ 64 fprintf(stderr,"Invalid product ID or subscription expired\n"); 65 } else if (err < 0) { 66 fprintf(stderr,"Received Error %d (%s) when attempting to update GeoIP Database\n",err, GeoIP_get_error_message(err)); 67 } else { 68 fprintf(stdout,"Updated database\n"); 69 } 70} 71 72int main (int argc, char *argv[]) { 73 int verbose = 0; 74 char * license_file = NULL; 75 FILE * license_fh; 76 int n = 40; 77 int line_index = 0; 78 unsigned char *lineptr = malloc(sizeof(char) * n); 79 char *a_license_key_str, *a_ptr; 80 char *the_license_key_str = ""; 81 char * the_reference_empty_license_key_str = the_license_key_str; 82 char *a_user_id_str = NULL; 83 /* the string that holds the user id */ 84 char *the_user_id_str = NULL; 85 /* the integer that holds the length of the string the_user_id_str */ 86 int the_user_id_strl = 0; 87 /* the integer that holds the alloc length of the string the_user_id_str */ 88 int the_user_id_stral = 0; 89 char *a_product_id_str = NULL; 90 char **the_product_id_str = NULL; 91 int *the_product_id_strl = NULL; 92 int *the_product_id_stral = NULL; 93 int num_product_ids = 0; 94 char * client_ipaddr = NULL; 95 char * custom_directory = NULL; 96 int c; 97 int err = 0; 98 int i; 99 100 opterr = 0; 101 102 while ((c = getopt (argc, argv, "hvf:d:")) != -1) 103 switch (c) { 104 case 'h': 105 usage(); 106 exit(0); 107 case 'v': 108 verbose = 1; 109 break; 110 case 'f': 111 license_file = optarg; 112 break; 113 case 'd': 114 custom_directory = optarg; 115 break; 116 case '?': 117 if (isprint (optopt)) 118 fprintf (stderr, "Unknown option `-%c'.\n", optopt); 119 else 120 fprintf (stderr, 121 "Unknown option character `\\x%x'.\n", 122 optopt); 123 usage(); 124 exit(1); 125 default: 126 abort(); 127 } 128 129 if (custom_directory != NULL) { 130 GeoIP_setup_custom_directory(custom_directory); 131 } 132 if (license_file == NULL) { 133 license_file = malloc(sizeof(char) * (strlen(SYSCONFDIR)+strlen(GeoIPConfFile)+2)); 134 license_file[0] = '\0'; 135 strcat(license_file, SYSCONFDIR); 136 strcat(license_file, "/"); 137 strcat(license_file, GeoIPConfFile); 138 } 139 140 license_fh = fopen(license_file,"r"); 141 if (license_fh == NULL) { 142 fprintf(stderr,"Error opening GeoIP Configuration file %s\n",license_file); 143 exit(1); 144 } 145 146 if (verbose == 1) 147 printf("Opened License file %s\n", license_file); 148 149 do { 150 c = fgetc(license_fh); 151 if (line_index >= n) { 152 n += 20; 153 lineptr = realloc_or_die(lineptr, n); 154 } 155 if ( c == 13 ) { 156 continue; 157 } 158 if (c == 10 || c == EOF) { 159 lineptr[line_index++] = '\0'; 160 line_index = 0; 161 if (lineptr[0] == '#') 162 continue; 163 /* get the product ids from the config file */ 164 a_product_id_str = strstr((char *)lineptr, PRODUCT_ID_TOKEN);//search for a product id token in the line 165 if (a_product_id_str != NULL) { 166 a_ptr = a_product_id_str; 167 /* set pos at the end of product id token */ 168 a_ptr += strlen(PRODUCT_ID_TOKEN) + 1; 169 while (a_ptr[0] == ' ') { 170 /* skip spaces */ 171 a_ptr++; 172 } 173 /* alloc the array of product ids */ 174 the_product_id_str = (char **) malloc((num_product_ids+1) * sizeof(char*)); /* array of strings */ 175 the_product_id_strl = (int *) malloc((num_product_ids+1) * sizeof(char*)); /* array of string lengths */ 176 the_product_id_stral = (int *) malloc((num_product_ids+1) * sizeof(char*)); /* array of string alloc lengths */ 177 while (a_ptr[0] != '\0') { 178 /* add new product id to the array of product ids */ 179 the_product_id_str[num_product_ids] = (char *) malloc(20); /* the string */ 180 the_product_id_strl[num_product_ids] = 0; /* the length of the string */ 181 the_product_id_stral[num_product_ids] = 20; /* the alloc length of the string */ 182 while ((a_ptr[0] != ' ') & (a_ptr[0] != '\0')) { 183 if (the_product_id_strl[num_product_ids] >= the_product_id_stral[num_product_ids]) { 184 /* if the length of the string is equal or more than 185 * alloc length of the string then realloc the string and 186 * increase the alloc length by 20 */ 187 the_product_id_stral[num_product_ids] = the_product_id_stral[num_product_ids] + 20; 188 the_product_id_str[num_product_ids] = (char *) realloc_or_die(the_product_id_str[num_product_ids],the_product_id_stral[num_product_ids]+4); 189 } 190 /* read the product id from the line in the config file */ 191 the_product_id_str[num_product_ids][the_product_id_strl[num_product_ids]] = a_ptr[0]; 192 the_product_id_strl[num_product_ids]++; 193 a_ptr++; 194 } 195 the_product_id_str[num_product_ids][the_product_id_strl[num_product_ids]] = 0; 196 while ((a_ptr[0] == ' ') & (a_ptr[0] != '\0')) { 197 a_ptr++;//skip spaces 198 } 199 /* new product id add, realloc the arrays */ 200 num_product_ids = num_product_ids + 1; 201 /* array of string */ 202 the_product_id_str = (char **) realloc_or_die(the_product_id_str,(num_product_ids+1) * sizeof(char*)); 203 /* array of string lengths */ 204 the_product_id_strl = (int *) realloc_or_die(the_product_id_strl,(num_product_ids+1) * sizeof(char*)); 205 /* array of string alloc lengths */ 206 the_product_id_stral = (int *) realloc_or_die(the_product_id_stral,(num_product_ids+1) * sizeof(char*)); 207 } 208 } 209 210 /* get the user id from the config file */ 211 a_user_id_str = strstr((char *)lineptr, USER_ID_TOKEN); /* search for a user id token in the line */ 212 if (a_user_id_str != NULL) { 213 a_ptr = a_user_id_str; 214 /* set the position at the end of user id token */ 215 a_ptr += strlen(USER_ID_TOKEN) + 1; 216 while (a_ptr[0] == ' ') { 217 /* skip spaces */ 218 a_ptr++; 219 } 220 /* get the string that has the user id */ 221 the_user_id_stral = 20; 222 the_user_id_str = (char *)malloc(the_user_id_stral); 223 /* loop while the chars are numbers */ 224 while ((a_ptr[0] >= '0') & (a_ptr[0] <= '9')) { 225 the_user_id_str[the_user_id_strl++] = a_ptr[0]; 226 a_ptr++; 227 if (the_user_id_strl >= the_user_id_stral) { 228 /* if the length of user id string is greater or equal to 229 * the alloc length of user id string then 230 * add 20 to the alloc length and realloc the user id string */ 231 the_user_id_stral += 20; 232 the_user_id_str = realloc_or_die(the_user_id_str,the_user_id_stral); 233 } 234 } 235 the_user_id_str[the_user_id_strl] = 0; /* add NUL char */ 236 } 237 a_license_key_str = strstr((char *)lineptr, LICENSE_KEY_TOKEN); 238 if (a_license_key_str != NULL) { 239 a_ptr = a_license_key_str; 240 a_ptr += strlen(LICENSE_KEY_TOKEN) + 1; 241 while (a_ptr[0] == ' ') { 242 a_ptr++; 243 } 244 the_license_key_str = malloc(sizeof(char) * (LICENSE_KEY_LENGTH + 1)); 245 strncpy(the_license_key_str, a_ptr, LICENSE_KEY_LENGTH); 246 the_license_key_str[LICENSE_KEY_LENGTH] = '\0'; 247 } 248 } else { 249 lineptr[line_index++] = c; 250 } 251 } while (c != EOF); 252 253 free(lineptr); 254 255 fclose(license_fh); 256 257 if (verbose == 1) { 258 printf("Read in license key %s\n", the_license_key_str); 259 printf("number of product ids %d \n",num_product_ids); 260 } 261 262 if (the_user_id_str != NULL) { 263 /* update the databases using the user id string, the license key string and the product id for each database */ 264 client_ipaddr = NULL; 265 for (i = 0; i < num_product_ids; i++) { 266 err = GeoIP_update_database_general(the_user_id_str, the_license_key_str, the_product_id_str[i], verbose,&client_ipaddr, &my_printf); 267 print_status(err, license_file); 268 } 269 } else { 270 /* Old format with just license key for MaxMind GeoIP Country database updates 271 * here for backwards compatibility */ 272 err = GeoIP_update_database(the_license_key_str, verbose, &my_printf); 273 print_status(err, license_file); 274 } 275 276 if (the_product_id_str != NULL) { 277 /* free the product ids */ 278 for (i = 0; i < num_product_ids; i++ ) { 279 free(the_product_id_str[i]); 280 } 281 free(the_product_id_str); 282 free(the_product_id_strl); 283 free(the_product_id_stral); 284 } 285 286 if ( the_reference_empty_license_key_str != the_license_key_str ) 287 free(the_license_key_str); 288 289 if (the_user_id_str) 290 free(the_user_id_str); 291 292 if (client_ipaddr) { 293 free(client_ipaddr); 294 } 295 exit(err); 296} 297