Exemple #1
0
int
esgf_geolookup (char *hostname, struct geo_output_struct *geo_output)
{
  char *db_info;
  GeoIP *gi;
  int i, ret_code;
  char *custom_directory = NULL;
  char *custom_file = NULL;
  char geoipdat[1024] = { '\0' };

  sprintf (geoipdat, "%s/share/GeoIP/%s", GEOIP_DATA_PATH, GEOIPIDATABASE);

  pmesg(LOG_DEBUG,__FILE__,__LINE__,"Loading GeoLiteCity from %s...\n",geoipdat);
  if (gi = GeoIP_open (geoipdat, GEOIP_STANDARD))
    {
      i = GeoIP_database_edition (gi);
      pmesg(LOG_DEBUG,__FILE__,__LINE__," GeoIP database found [Ok]\n");
      if (ret_code = geoiplookup (gi, hostname, i, geo_output))
	{
	GeoIP_delete (gi);
	return ret_code;
	}
    }
  else
    {
      pmesg(LOG_ERROR,__FILE__,__LINE__,"%s not available, skipping.Please check ! [Exit]\n",geoipdat);
      GeoIP_delete (gi);
      return (-4);
    }

  GeoIP_delete (gi);
  pmesg(LOG_DEBUG,__FILE__,__LINE__,"Geoiplookup ok [code=%d]\n", ret_code);
  return 0;
}
Exemple #2
0
/* Set city data by geoid or record into the given `location` buffer
 * based on the IP version and currently used database edition.
 * It uses the custom GeoIP database - i.e., GeoLiteCity.dat */
void
geoip_get_city (const char *ip, char *location, GTypeIP type_ip)
{
  unsigned char rec = GeoIP_database_edition (geo_location_data);

  if (conf.geoip_database == NULL || geo_location_data == NULL)
    return;

  switch (rec) {
  case GEOIP_CITY_EDITION_REV0:
  case GEOIP_CITY_EDITION_REV1:
    if (TYPE_IPV4 == type_ip)
      geoip_set_city_by_record (ip, location, TYPE_IPV4);
    else
      geoip_set_city (NULL, NULL, location);
    break;
  case GEOIP_CITY_EDITION_REV0_V6:
  case GEOIP_CITY_EDITION_REV1_V6:
    if (TYPE_IPV6 == type_ip)
      geoip_set_city_by_record (ip, location, TYPE_IPV6);
    else
      geoip_set_city (NULL, NULL, location);
    break;
  }
}
Exemple #3
0
/* Set continent data by geoid or record into the given `location` buffer
 * based on the IP version and currently used database edition.  */
void
geoip_get_continent (const char *ip, char *location, GTypeIP type_ip)
{
  unsigned char rec = GeoIP_database_edition (geo_location_data);

  switch (rec) {
  case GEOIP_COUNTRY_EDITION:
    if (TYPE_IPV4 == type_ip)
      geoip_set_continent_by_geoid (ip, location, TYPE_IPV4);
    else
      geoip_set_continent (NULL, location);
    break;
  case GEOIP_COUNTRY_EDITION_V6:
    if (TYPE_IPV6 == type_ip)
      geoip_set_continent_by_geoid (ip, location, TYPE_IPV6);
    else
      geoip_set_continent (NULL, location);
    break;
  case GEOIP_CITY_EDITION_REV0:
  case GEOIP_CITY_EDITION_REV1:
    if (TYPE_IPV4 == type_ip)
      geoip_set_continent_by_record (ip, location, TYPE_IPV4);
    else
      geoip_set_continent (NULL, location);
    break;
  case GEOIP_CITY_EDITION_REV0_V6:
  case GEOIP_CITY_EDITION_REV1_V6:
    if (TYPE_IPV6 == type_ip)
      geoip_set_continent_by_record (ip, location, TYPE_IPV6);
    else
      geoip_set_continent (NULL, location);
    break;
  }
}
Exemple #4
0
static PyObject *GeoIP_get_database_edition(PyObject *self,
                                            void *UNUSED(closure))
{
    GeoIP_GeoIPObject *GeoIP = (GeoIP_GeoIPObject *)self;
    return Py_BuildValue("z",
                         GeoIPDBDescription[GeoIP_database_edition
                                                (GeoIP->gi)]);
}
int main(int argc, char **argv) {
	const char *geoipfilename = DEFAULT_GEOIPFILE;
	GeoIP *gip = NULL;
	GeoIPRecord *gir = NULL;
	char *name;
	const char *region_name;
	int edition, i;

	if ((argc != 2) && (argc != 4)) {
		printf("Usage: geoiplookup_city [-f custom_file] <hostname_or_ip>\n");
		return 1;
	}

	i = 1;
	while (i < argc) {
                if (strcmp(argv[i],"-f") == 0) {
                        if ((i+1) < argc){
                                i++;
                                geoipfilename = argv[i];
                        }
                } else {
			name = argv[i];
		}
                i++;
        }

	gip = GeoIP_open(geoipfilename, GEOIP_STANDARD);
	edition = GeoIP_database_edition(gip);

	if (edition == GEOIP_COUNTRY_EDITION) {
		short int country_id = GeoIP_country_id_by_name(gip, name);
		region_name = GeoIP_country_continent[country_id];
		printf("%s\n", region_name);
        } else if ((edition == GEOIP_CITY_EDITION_REV0) || 
		   (edition == GEOIP_CITY_EDITION_REV1)) {
                gir = GeoIP_record_by_name(gip, name);
                if (NULL == gir) {
                        printf("%s: IP Address not found\n", GeoIPDBDescription[edition]);
			return 1;
                } else {
                        printf("Continent: %s\n"
			       "Country:   %s\n"
			       "Region id: %s\n"
			       "Region:    %s\n"
			       "City:      %s\n"
			       "Latitude:  %f\n"
			       "Longitude: %f\n", gir->continent_code, 
			       			  gir->country_code, 
						  gir->region, 
						  GeoIP_region_name_by_code(gir->country_code, gir->region),
						  gir->city, 
						  gir->latitude, 
						  gir->longitude);
		}
	}
 
	return 0;
}
Exemple #6
0
static PyObject *
GeoIP_GetAttr(PyObject *self, char *attrname)
{
  PyObject * ret;
  char * database_info;
  GeoIP_GeoIPObject* GeoIP = (GeoIP_GeoIPObject*)self;
  if (strcmp(attrname, "GEOIP_STANDARD") == 0) {
    return Py_BuildValue("i", 0);
  } else if (strcmp(attrname, "database_info") == 0) {
    database_info = GeoIP_database_info(GeoIP->gi);
    ret = Py_BuildValue("z", database_info);
    free(database_info);
    return ret;
  } else if (strcmp(attrname, "database_edition") == 0) {
    return Py_BuildValue("z", GeoIPDBDescription[GeoIP_database_edition(GeoIP->gi)]);
	}
  return Py_FindMethod(GeoIP_Object_methods, self, attrname);
}
Exemple #7
0
int main(int argc, char *argv[])
{
    char * filename = NULL;
    char * db_info;
    GeoIP * gi;
    int i;
    char *custom_directory = NULL;
    char *custom_file = NULL;
    int version_flag = 0;
    int charset = GEOIP_CHARSET_UTF8;

    if (argc < 2) {
        usage();
        exit(1);
    }
    i = 1;
    while (i < argc) {
        if (strcmp(argv[i], "-v") == 0) {
            version_flag = 1;
        } else if (strcmp(argv[i], "-l") == 0) {
            charset = GEOIP_CHARSET_ISO_8859_1;
        } else if (strcmp(argv[i], "-i") == 0) {
            info_flag = 1;
        } else if (( strcmp(argv[i], "-?" ) == 0 )
                   || ( strcmp(argv[i], "-h" ) == 0 )) {
            usage();
            exit(0);
        } else if (strcmp(argv[i], "-f") == 0) {
            if ((i + 1) < argc) {
                i++;
                custom_file = argv[i];
            }
        } else if (strcmp(argv[i], "-d") == 0) {
            if ((i + 1) < argc) {
                i++;
                custom_directory = argv[i];
            }
        } else {
            filename = argv[i];
        }
        i++;
    }
    if (filename == NULL) {
        usage();
        exit(1);
    }

    FILE *hostname_file = fopen(filename, "r");
    if (hostname_file == NULL) {
        usage();
        exit(1);
    }

    if (custom_directory != NULL) {
        GeoIP_setup_custom_directory(custom_directory);
    }
    _GeoIP_setup_dbfilename();

    if (custom_file != NULL) {
        gi = GeoIP_open(custom_file, GEOIP_STANDARD | GEOIP_SILENCE);

        if (NULL == gi) {
            printf("%s not available, skipping...\n", custom_file);
        } else {
            gi->charset = charset;
            i = GeoIP_database_edition(gi);
            if (version_flag == 1) {
                db_info = GeoIP_database_info(gi);
                printf("%s: %s\n", GeoIPDBDescription[i],
                       db_info == NULL ? "" : db_info );
                free(db_info);
            } else {
                char *hostname = NULL;
                ssize_t read;
                size_t len = 0;
                while ((read = getline(&hostname, &len, hostname_file)) != -1) {
                    if (hostname[read - 1] == '\n') {
                        hostname[read - 1] = '\0';
                        --read;
                    }
                    geoiplookup(gi, hostname, i);
                }
            }
        }
        GeoIP_delete(gi);
    } else {
        /* iterate through different database types */
        for (i = 0; i < NUM_DB_TYPES; ++i) {
            if (GeoIP_db_avail(i)) {
                gi = GeoIP_open_type(i, GEOIP_STANDARD | GEOIP_SILENCE);
                if (NULL == gi) {
                    /* Ignore these errors. It's possible
                     * to use the same database name for
                     * different databases.
                     */
                    ;
                } else {
                    gi->charset = charset;
                    if (version_flag == 1) {
                        db_info = GeoIP_database_info(gi);
                        printf("%s: %s\n", GeoIPDBDescription[i],
                               db_info == NULL ? "" : db_info );
                        free(db_info);
                    } else {
                        char *hostname = NULL;
                        ssize_t read;
                        size_t len = 0;
                        while ((read = getline(&hostname, &len, hostname_file)) != -1) {
                            if (hostname[read -1] == '\n') {
                                hostname[read - 1] = '\0';
                                --read;
                            }
                            geoiplookup(gi, hostname, i);
                        }
                    }
                }
                GeoIP_delete(gi);
            }
        }
    }
    return 0;
}
static int geoip_header_parser(request_rec * r)
{
    char *orgorisp;
    char *ipaddr;
    char *free_me = NULL;
    short int country_id;
    const char *continent_code;
    const char *country_code;
    const char *country_name;
    const char *region_name;

    geoip_server_config_rec *cfg;

    unsigned char databaseType;
    GeoIPRecord *gir;
    GeoIPRegion *giregion;
    int i;
    int netspeed;
    /* For splitting proxy headers */
    char *ipaddr_ptr = NULL;
    char *comma_ptr;
    cfg = ap_get_module_config(r->server->module_config, &geoip_module);

    if (!cfg)
        return DECLINED;

    if (!cfg->scanProxyHeaders) {
        ipaddr = _get_client_ip(r);
    } else {
        ap_add_common_vars(r);
        if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP");
        } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env,
                                      "HTTP_X_FORWARDED_FOR");
        } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->headers_in, "X-Forwarded-For");
        } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) {
            ipaddr_ptr =
                (char *)apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR");
        }
        if (!ipaddr_ptr) {
            ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
                         r->server,
                         "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR.");
            ipaddr = _get_client_ip(r);
        } else {
            /* Found XFF like header */
            ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0,
                         r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr);

            if (cfg->proxyHeaderMode ==
                GEOIP_PROXY_HEADER_MODE_FIRST_NON_PRIVATE_IP) {
                ipaddr = free_me = _get_ip_from_xff(ipaddr_ptr);
                if (!ipaddr)
                    ipaddr = _get_client_ip(r);
            } else {
                ipaddr = free_me = (char *)calloc(8 * 4 + 7 + 1, sizeof(char));
                /* proxyHeaderMode is
                 * GEOIP_PROXY_HEADER_MODE_LAST_IP or GEOIP_PROXY_HEADER_MODE_FIRST_IP
                 */

                /*
                 * Check to ensure that the HTTP_CLIENT_IP or
                 * X-Forwarded-For header is not a comma separated
                 * list of addresses, which would cause mod_geoip to
                 * return no country code. If the header is a comma
                 * separated list, return the first IP address in the
                 * list, which is (hopefully!) the real client IP.
                 */

                if (cfg->proxyHeaderMode == GEOIP_PROXY_HEADER_MODE_LAST_IP) {
                    comma_ptr = strrchr(ipaddr_ptr, ',');
                    if (comma_ptr) {
                        /* skip over whitespace */
                        ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t");
                    }
                }

                strncpy(ipaddr, ipaddr_ptr, 8 * 4 + 7);
                comma_ptr = strchr(ipaddr, ',');
                if (comma_ptr != 0)
                    *comma_ptr = '\0';
            }
        }
    }

/* this block should be removed! */
#if 1
    if (!cfg->gips) {
        if (cfg->GeoIPFilenames != NULL) {
            cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles);
            for (i = 0; i < cfg->numGeoIPFiles; i++) {
                cfg->gips[i] =
                    GeoIP_open(cfg->GeoIPFilenames[i],
                               (cfg->GeoIPFlags2[i] ==
                                GEOIP_UNKNOWN) ? cfg->GeoIPFlags
                               : cfg->GeoIPFlags2[i]);

                if (cfg->gips[i]) {
                    if (cfg->GeoIPEnableUTF8) {
                        GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
                    }
                } else {
                    ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                                 r->server,
                                 "[mod_geoip]: Error while opening data file %s",
                                 cfg->GeoIPFilenames[i]);
                    return DECLINED;
                }
            }
        } else {
            cfg->gips = malloc(sizeof(GeoIP *));
            cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
            if (!cfg->gips[0]) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0,
                             r->server,
                             "[mod_geoip]: Error while opening data file");
                return DECLINED;
            }
            cfg->numGeoIPFiles = 1;
        }
    }
#endif

    set_geoip_output(cfg, r, "GEOIP_ADDR", ipaddr);

    for (i = 0; i < cfg->numGeoIPFiles; i++) {

        /*
         * skip database handles that can not be opned for some
         * reason
         */
        if (cfg->gips[i] == NULL)
            continue;

        databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1;        /* -1 is "magic value"
                                                                                         * in case file not
                                                                                         * found */
        switch (databaseType) {
        case GEOIP_NETSPEED_EDITION_REV1:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_NETSPEED", orgorisp);
            break;

        case GEOIP_NETSPEED_EDITION:
            netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr);
            if (netspeed == GEOIP_UNKNOWN_SPEED) {
                netspeedstring = "unknown";
            } else if (netspeed == GEOIP_DIALUP_SPEED) {
                netspeedstring = "dialup";
            } else if (netspeed == GEOIP_CABLEDSL_SPEED) {
                netspeedstring = "cabledsl";
            } else if (netspeed == GEOIP_CORPORATE_SPEED) {
                netspeedstring = "corporate";
            }
            setn_geoip_output(cfg, r, "GEOIP_NETSPEED", netspeedstring);
            break;
        case GEOIP_COUNTRY_EDITION_V6:
            /* Get the Country ID */
            country_id = GeoIP_id_by_addr_v6(cfg->gips[i], ipaddr);

            if (country_id > 0) {
                /* Lookup the Code and the Name with the ID */
                continent_code = GeoIP_country_continent[country_id];
                country_code = GeoIP_country_code[country_id];
                country_name = GeoIP_country_name[country_id];

                if (cfg->numGeoIPFiles == 0) {
                    cfg->numGeoIPFiles = 0;
                }
                if (cfg->GeoIPFilenames == 0) {
                    cfg->GeoIPFilenames = 0;
                }
                /* Set it for our user */
                setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6",
                                  continent_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6",
                                  country_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6",
                                  country_name);
            }
            break;
        case GEOIP_COUNTRY_EDITION:
            /* Get the Country ID */
            country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr);

            if (country_id > 0) {
                /* Lookup the Code and the Name with the ID */
                continent_code = GeoIP_country_continent[country_id];
                country_code = GeoIP_country_code[country_id];
                country_name = GeoIP_country_name[country_id];

                if (cfg->numGeoIPFiles == 0) {
                    cfg->numGeoIPFiles = 0;
                }
                if (cfg->GeoIPFilenames == 0) {
                    cfg->GeoIPFilenames = 0;
                }
                /* Set it for our user */
                setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                  continent_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE", country_code);
                setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME", country_name);
            }

            break;
        case GEOIP_REGION_EDITION_REV0:
        case GEOIP_REGION_EDITION_REV1:
            giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr);
            if (giregion != NULL) {
                region_name = NULL;
                if (giregion->country_code[0]) {
                    region_name =
                        GeoIP_region_name_by_code
                        (giregion->country_code, giregion->region);
                    set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE",
                                      giregion->country_code);
                    country_id = GeoIP_id_by_code(giregion->country_code);
                    setn_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME",
                                      GeoIP_country_name[country_id]);
                    setn_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                      GeoIP_country_continent[country_id]);
                }
                if (giregion->region[0]) {
                    set_geoip_output(cfg, r, "GEOIP_REGION", giregion->region);
                }
                if (region_name != NULL) {
                    set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name);
                }
                GeoIPRegion_delete(giregion);
            }
            break;
        case GEOIP_CITY_EDITION_REV0_V6:
        case GEOIP_CITY_EDITION_REV1_V6:
            gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr);
            if (gir != NULL) {
                if (gir->country_code != NULL) {
                    region_name =
                        GeoIP_region_name_by_code(gir->country_code,
                                                  gir->region);
                }
                sprintf(metrocodestr, "%d", gir->dma_code);
                sprintf(areacodestr, "%d", gir->area_code);
                set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE_V6",
                                  gir->continent_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE_V6",
                                  gir->country_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME_V6",
                                  gir->country_name);
                set_geoip_output(cfg, r, "GEOIP_REGION_V6", gir->region);
                set_geoip_output(cfg, r, "GEOIP_REGION_NAME_V6", region_name);
                set_geoip_output(cfg, r, "GEOIP_CITY_V6", gir->city);
                set_geoip_output(cfg, r, "GEOIP_DMA_CODE_V6", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_METRO_CODE_V6", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_AREA_CODE_V6", areacodestr);
                sprintf(latstr, "%f", gir->latitude);
                sprintf(lonstr, "%f", gir->longitude);
                set_geoip_output(cfg, r, "GEOIP_LATITUDE_V6", latstr);
                set_geoip_output(cfg, r, "GEOIP_LONGITUDE_V6", lonstr);

                set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE_V6",
                                  gir->postal_code);
                GeoIPRecord_delete(gir);
            }

            break;
        case GEOIP_CITY_EDITION_REV0:
        case GEOIP_CITY_EDITION_REV1:
            gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr);
            if (gir != NULL) {
                if (gir->country_code != NULL) {
                    region_name =
                        GeoIP_region_name_by_code(gir->country_code,
                                                  gir->region);
                }
                sprintf(metrocodestr, "%d", gir->dma_code);
                sprintf(areacodestr, "%d", gir->area_code);
                set_geoip_output(cfg, r, "GEOIP_CONTINENT_CODE",
                                  gir->continent_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_CODE",
                                  gir->country_code);
                set_geoip_output(cfg, r, "GEOIP_COUNTRY_NAME",
                                  gir->country_name);
                set_geoip_output(cfg, r, "GEOIP_REGION", gir->region);
                set_geoip_output(cfg, r, "GEOIP_REGION_NAME", region_name);
                set_geoip_output(cfg, r, "GEOIP_CITY", gir->city);
                set_geoip_output(cfg, r, "GEOIP_DMA_CODE", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_METRO_CODE", metrocodestr);
                set_geoip_output(cfg, r, "GEOIP_AREA_CODE", areacodestr);
                sprintf(latstr, "%f", gir->latitude);
                sprintf(lonstr, "%f", gir->longitude);
                set_geoip_output(cfg, r, "GEOIP_LATITUDE", latstr);
                set_geoip_output(cfg, r, "GEOIP_LONGITUDE", lonstr);
                set_geoip_output(cfg, r, "GEOIP_POSTAL_CODE",
                                  gir->postal_code);
                GeoIPRecord_delete(gir);
            }

            break;
        case GEOIP_ORG_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_ORGANIZATION", orgorisp);
            break;
        case GEOIP_ISP_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_ISP", orgorisp);
            break;
        case GEOIP_DOMAIN_EDITION:
            orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
            setn_geoip_output(cfg, r, "GEOIP_DOMAIN", orgorisp);
            break;
        }
    }

    if (free_me)
        free(free_me);
    return OK;
}
Exemple #9
0
int main(int argc, char *argv[])
{
    char * hostname = NULL;
    char * db_info;
    GeoIP * gi;
    int i;
    char *custom_directory = NULL;
    char *custom_file = NULL;
    int version_flag = 0;

    if (argc < 2) {
        usage();
        exit(1);
    }
    i = 1;
    while (i < argc) {
        if (strcmp(argv[i], "-v") == 0) {
            version_flag = 1;
        } else if (strcmp(argv[i], "-h") == 0
                   || strcmp(argv[i], "-?") == 0) {
            usage();
            exit(0);
        } else if (strcmp(argv[i], "-f") == 0) {
            if ((i + 1) < argc) {
                i++;
                custom_file = argv[i];
            }
        } else if (strcmp(argv[i], "-d") == 0) {
            if ((i + 1) < argc) {
                i++;
                custom_directory = argv[i];
            }
        } else {
            hostname = argv[i];
        }
        i++;
    }
    if (hostname == NULL) {
        usage();
        exit(1);
    }

    if (custom_directory != NULL) {
        GeoIP_setup_custom_directory(custom_directory);
    }
    _GeoIP_setup_dbfilename();

    if (custom_file != NULL) {
        gi = GeoIP_open(custom_file, GEOIP_STANDARD);
        if (NULL == gi) {
            printf("%s not available, skipping...\n", custom_file);
        } else {
            i = GeoIP_database_edition(gi);
            if (version_flag == 1) {
                db_info = GeoIP_database_info(gi);
                printf("%s: %s\n", GeoIPDBDescription[i],
                       db_info == NULL ? "" : db_info );
                free(db_info);
            } else {
                geoiplookup(gi, hostname, i);
            }
        }
        GeoIP_delete(gi);
    } else {
        /* iterate through different database types */
        for (i = 0; i < NUM_DB_TYPES; ++i) {
            if (GeoIP_db_avail(i)) {
                gi = GeoIP_open_type(i, GEOIP_STANDARD);
                if (NULL == gi) {
                    /* Ignore these errors. It's possible
                     * to use the same database name for
                     * different databases.
                     */
                    ;
                } else {
                    if (version_flag == 1) {
                        db_info = GeoIP_database_info(gi);
                        printf("%s: %s\n", GeoIPDBDescription[i], db_info);
                        free(db_info);
                    } else {
                        geoiplookup(gi, hostname, i);
                    }
                }
                GeoIP_delete(gi);
            }
        }
    }
    return 0;
}
int IpToGeo::setGeoIpDbFile(const char *pFile, const char *cacheMode)
{
    GeoIP *pGip;
    int flag = GEOIP_MEMORY_CACHE;
    if (!pFile)
        return LS_FAIL;
    if (cacheMode)
    {
        if (strcasecmp(cacheMode, "Standard") == 0)
            flag = GEOIP_STANDARD;
        else if (strcasecmp(cacheMode, "MemoryCache") == 0)
            flag = GEOIP_MEMORY_CACHE;
        else if (strcasecmp(cacheMode, "CheckCache") == 0)
            flag = GEOIP_CHECK_CACHE;
        else if (strcasecmp(cacheMode, "IndexCache") == 0)
            flag = GEOIP_INDEX_CACHE;
    }
    pGip = GeoIP_open(pFile, flag);
    if (!pGip)
    {
        LS_ERROR("Failed to open GeoIP DB file: %s", pFile);
        return LS_FAIL;
    }
    int fd = fileno(pGip->GeoIPDatabase);
    if (fd != -1)
        ::fcntl(fd, F_SETFD, FD_CLOEXEC);

    flag = GeoIP_database_edition(pGip);
    switch (flag)
    {
    case GEOIP_COUNTRY_EDITION:
    case GEOIP_REGION_EDITION_REV0:
    case GEOIP_REGION_EDITION_REV1:
    case GEOIP_CITY_EDITION_REV0:
    case GEOIP_CITY_EDITION_REV1:
        if (m_pLocation)
            GeoIP_delete(m_pLocation);
        m_pLocation = pGip;
        m_locDbType = flag;
        break;

    case GEOIP_ORG_EDITION:
        if (m_pOrg)
            GeoIP_delete(m_pOrg);
        m_pOrg = pGip;
        break;

    case GEOIP_ISP_EDITION:
        if (m_pIsp)
            GeoIP_delete(m_pIsp);
        m_pIsp = pGip;
        break;

    case GEOIP_NETSPEED_EDITION:
        if (m_pNetspeed)
            GeoIP_delete(m_pNetspeed);
        m_pNetspeed = pGip;
        break;

    default:
        GeoIP_delete(pGip);
        return LS_FAIL;
    }
    return 0;
}
static int 
geoip_header_parser(request_rec * r)
{
	char           *orgorisp;
	char           *ipaddr;
	short int       country_id;
	GeoIP          *gip;
	const char     *continent_code;
	const char     *country_code;
	const char     *country_name;
	const char     *region_name;

	geoip_server_config_rec *cfg;

	unsigned char   databaseType;
	GeoIPRecord    *gir;
	GeoIPRegion    *giregion;
	int             i;
	int             netspeed;
	/* For splitting proxy headers */
	char           *ipaddr_ptr = 0;
	char           *comma_ptr;
	char           *found_ip;
	apr_sockaddr_t *sa;
	char           *hostname = 0;

	cfg = ap_get_module_config(r->server->module_config, &geoip_module);

	if (!cfg)
		return DECLINED;

	if (!cfg->scanProxyHeaders) {
		ipaddr = r->connection->remote_ip;
	}
	else {
		ap_add_common_vars(r);
		if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) {
			ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP");
		}
		else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) {
			ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR");
		}
		else if (apr_table_get(r->headers_in, "X-Forwarded-For")) {
			ipaddr_ptr = (char *) apr_table_get(r->headers_in, "X-Forwarded-For");
		}
		else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) {
			ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR");
		}
		if (!ipaddr_ptr) {
			ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR.");
			ipaddr = r->connection->remote_ip;
		}
		else {
			ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr);

			if (cfg->use_left_public_x_forwarded_for_ip) {
				// find the first public IP address in a potentially comma-separated list,
				// fall back to remote_ip if we can't find one
				ipaddr = first_public_ip_in_list(ipaddr_ptr, r->connection->remote_ip);
			} else {
				// leaving some of the following inconsistent indenting intact for easier diff to original maxmind src

                       /*
                        * Check to ensure that the HTTP_CLIENT_IP or
                        * X-Forwarded-For header is not a comma separated
                        * list of addresses, which would cause mod_geoip to
                        * return no country code. If the header is a comma
                        * separated list, return the first IP address in the
                        * list, which is (hopefully!) the real client IP.
                        */
                        ipaddr = (char *) calloc(8*4+7+1, sizeof(char));

                        if (cfg->use_last_x_forwarded_for_ip ){
                                comma_ptr = strrchr(ipaddr_ptr, ',');
                                if ( comma_ptr ) {
                                        /* skip over whitespace */
                                        ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t");
                                }
                        }

                        strncpy(ipaddr, ipaddr_ptr, 8*4+7);
                        comma_ptr = strchr(ipaddr, ',');
                        if (comma_ptr != 0)
                                *comma_ptr = '\0';
			}
 		}
	}

/* this block should be removed! */
#if 1
	if (!cfg->gips) {
		if (cfg->GeoIPFilenames != NULL) {
			cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles);
			for (i = 0; i < cfg->numGeoIPFiles; i++) {
				cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]);

				if (cfg->gips[i]) {
					if (cfg->GeoIPEnableUTF8) {
						GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8);
					}
				}
				else {
					ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]);
					return DECLINED;
				}
			}
		}
		else {
			cfg->gips = malloc(sizeof(GeoIP *));
			cfg->gips[0] = GeoIP_new(GEOIP_STANDARD);
			if (!cfg->gips[0]) {
				ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file");
				return DECLINED;
			}
			cfg->numGeoIPFiles = 1;
		}
	}
#endif

	if (cfg->GeoIPEnableHostnameLookups
			&& apr_sockaddr_info_get(&sa, ipaddr, APR_INET, 0, 0, r->pool) == APR_SUCCESS
			&& apr_getnameinfo(&hostname, sa, 0) == APR_SUCCESS) {
		ap_str_tolower(hostname);
	}

	if (!hostname)
		hostname = ipaddr;

	if (cfg->GeoIPOutput & GEOIP_NOTES) {
		apr_table_setn(r->notes, "GEOIP_ADDR", ipaddr);
		apr_table_setn(r->notes, "GEOIP_HOST", hostname);
	}
	if (cfg->GeoIPOutput & GEOIP_ENV) {
		apr_table_setn(r->subprocess_env, "GEOIP_ADDR", ipaddr);
		apr_table_setn(r->subprocess_env, "GEOIP_HOST", hostname);
	}

	for (i = 0; i < cfg->numGeoIPFiles; i++) {

		/*
		 * skip database handles that can not be opned for some
		 * reason
		 */
		if (cfg->gips[i] == NULL)
			continue;

		databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1;	/* -1 is "magic value"
												 * in case file not
												 * found */
		switch (databaseType) {
                case GEOIP_NETSPEED_EDITION_REV1:
                  orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
                  if (orgorisp != NULL) {
   	            if (cfg->GeoIPOutput & GEOIP_NOTES) {
	              apr_table_setn(r->notes, "GEOIP_NETSPEED", orgorisp);
	            }
	            if (cfg->GeoIPOutput & GEOIP_ENV) {
	              apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", orgorisp);
	            }
                  }
                break;
 
		case GEOIP_NETSPEED_EDITION:
			netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr);
			if (netspeed == GEOIP_UNKNOWN_SPEED) {
				netspeedstring = "unknown";
			}
			else if (netspeed == GEOIP_DIALUP_SPEED) {
				netspeedstring = "dialup";
			}
			else if (netspeed == GEOIP_CABLEDSL_SPEED) {
				netspeedstring = "cabledsl";
			}
			else if (netspeed == GEOIP_CORPORATE_SPEED) {
				netspeedstring = "corporate";
			}
			if (cfg->GeoIPOutput & GEOIP_NOTES) {
				apr_table_setn(r->notes, "GEOIP_NETSPEED", netspeedstring);
			}
			if (cfg->GeoIPOutput & GEOIP_ENV) {
				apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", netspeedstring);
			}
			break;
		case GEOIP_COUNTRY_EDITION_V6:
			/* Get the Country ID */
			country_id = GeoIP_country_id_by_addr_v6(cfg->gips[i], ipaddr);

      if ( country_id > 0 ) {
			  /* Lookup the Code and the Name with the ID */
			  continent_code = GeoIP_country_continent[country_id];
			  country_code = GeoIP_country_code[country_id];
			  country_name = GeoIP_country_name[country_id];

			  if (cfg->numGeoIPFiles == 0) {
				  cfg->numGeoIPFiles = 0;
			  }
			  if (cfg->GeoIPFilenames == 0) {
				  cfg->GeoIPFilenames = 0;
			  }
			  /* Set it for our user */
			  if (cfg->GeoIPOutput & GEOIP_NOTES) {
				  apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", continent_code);
		  		apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", country_code);
			  	apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", country_name);
			  }
			  if (cfg->GeoIPOutput & GEOIP_ENV) {
				  apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", continent_code);
				  apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", country_code);
				  apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", country_name);
			  }
			}
			break;
		case GEOIP_COUNTRY_EDITION:
			/* Get the Country ID */
			country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr);

      if ( country_id > 0 ) {
			  /* Lookup the Code and the Name with the ID */
			  continent_code = GeoIP_country_continent[country_id];
			  country_code = GeoIP_country_code[country_id];
			  country_name = GeoIP_country_name[country_id];

			  if (cfg->numGeoIPFiles == 0) {
				  cfg->numGeoIPFiles = 0;
			  }
			  if (cfg->GeoIPFilenames == 0) {
				  cfg->GeoIPFilenames = 0;
			  }
			  /* Set it for our user */
			  if (cfg->GeoIPOutput & GEOIP_NOTES) {
				  apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", continent_code);
		  		apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", country_code);
			  	apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", country_name);
			  }
			  if (cfg->GeoIPOutput & GEOIP_ENV) {
				  apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", continent_code);
				  apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", country_code);
				  apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", country_name);
			  }
			}
			break;
		case GEOIP_REGION_EDITION_REV0:
		case GEOIP_REGION_EDITION_REV1:
			giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr);
			if (giregion != NULL) {
			  if ( giregion->country_code[0] ) {
			    region_name = GeoIP_region_name_by_code(giregion->country_code, giregion->region);
			  }
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					if ( giregion->country_code[0] ){
						apr_table_set(r->notes, "GEOIP_COUNTRY_CODE", giregion->country_code);
					}
					if (giregion->region[0]) {
						apr_table_set(r->notes, "GEOIP_REGION", giregion->region);
					}
					if ( region_name != NULL ){
					  apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name);
					}
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					if ( giregion->country_code[0] ){
						apr_table_set(r->subprocess_env, "GEOIP_COUNTRY_CODE", giregion->country_code);
					}
					if (giregion->region[0]) {
					      apr_table_set(r->subprocess_env, "GEOIP_REGION", giregion->region);
					}
					if ( region_name != NULL ){
					  apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name);
					}
				}
				GeoIPRegion_delete(giregion);
			}
			break;
		case GEOIP_CITY_EDITION_REV0_V6:
		case GEOIP_CITY_EDITION_REV1_V6:
			gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr);
			if (gir != NULL) {
			        if ( gir->country_code != NULL ) {
				  region_name = GeoIP_region_name_by_code(gir->country_code, gir->region);
				}
				sprintf(metrocodestr, "%d", gir->dma_code);
				sprintf(areacodestr, "%d", gir->area_code);
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", gir->continent_code);
					apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", gir->country_code);
					apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", gir->country_name);
					if (gir->region != NULL) {
						apr_table_set(r->notes, "GEOIP_REGION_V6", gir->region);
						if ( region_name != NULL ){
						  apr_table_set(r->notes, "GEOIP_REGION_NAME_V6", region_name);
						}
					}
					if (gir->city != NULL) {
						apr_table_set(r->notes, "GEOIP_CITY_V6", gir->city);
					}
					apr_table_setn(r->notes, "GEOIP_DMA_CODE_V6", metrocodestr);
					apr_table_setn(r->notes, "GEOIP_METRO_CODE_V6", metrocodestr);
					apr_table_setn(r->notes, "GEOIP_AREA_CODE_V6", areacodestr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", gir->continent_code);
					apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", gir->country_code);
					apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", gir->country_name);
					if (gir->region != NULL) {
						apr_table_set(r->subprocess_env, "GEOIP_REGION_V6", gir->region);
						if ( region_name != NULL ){
						  apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME_V6", region_name);
						}
					}
					if (gir->city != NULL) {
						apr_table_set(r->subprocess_env, "GEOIP_CITY_V6", gir->city);
					}
					apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE_V6", metrocodestr);
					apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE_V6", metrocodestr);
					apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE_V6", areacodestr);
				}
				sprintf(latstr, "%f", gir->latitude);
				sprintf(lonstr, "%f", gir->longitude);
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_LATITUDE_V6", latstr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE_V6", latstr);
				}
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_LONGITUDE_V6", lonstr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE_V6", lonstr);
				}
				if (gir->postal_code != NULL) {
					if (cfg->GeoIPOutput & GEOIP_NOTES) {
						apr_table_set(r->notes, "GEOIP_POSTAL_CODE_V6", gir->postal_code);
					}
					if (cfg->GeoIPOutput & GEOIP_ENV) {
						apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE_V6", gir->postal_code);
					}
				}
				GeoIPRecord_delete(gir);
			}
			break;
		case GEOIP_CITY_EDITION_REV0:
		case GEOIP_CITY_EDITION_REV1:
			gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr);
			if (gir != NULL) {
			        if ( gir->country_code != NULL ) {
				  region_name = GeoIP_region_name_by_code(gir->country_code, gir->region);
				}
				sprintf(metrocodestr, "%d", gir->dma_code);
				sprintf(areacodestr, "%d", gir->area_code);
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", gir->continent_code);
					apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", gir->country_code);
					apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", gir->country_name);
					if (gir->region != NULL) {
						apr_table_set(r->notes, "GEOIP_REGION", gir->region);
						if ( region_name != NULL ){
						  apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name);
						}
					}
					if (gir->city != NULL) {
						apr_table_set(r->notes, "GEOIP_CITY", gir->city);
					}
					apr_table_setn(r->notes, "GEOIP_DMA_CODE", metrocodestr);
					apr_table_setn(r->notes, "GEOIP_METRO_CODE", metrocodestr);
					apr_table_setn(r->notes, "GEOIP_AREA_CODE", areacodestr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", gir->continent_code);
					apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", gir->country_code);
					apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", gir->country_name);
					if (gir->region != NULL) {
						apr_table_set(r->subprocess_env, "GEOIP_REGION", gir->region);
						if ( region_name != NULL ){
						  apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name);
						}
					}
					if (gir->city != NULL) {
						apr_table_set(r->subprocess_env, "GEOIP_CITY", gir->city);
					}
					apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE", metrocodestr);
					apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE", metrocodestr);
					apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE", areacodestr);
				}
				sprintf(latstr, "%f", gir->latitude);
				sprintf(lonstr, "%f", gir->longitude);
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_LATITUDE", latstr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE", latstr);
				}
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_LONGITUDE", lonstr);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE", lonstr);
				}
				if (gir->postal_code != NULL) {
					if (cfg->GeoIPOutput & GEOIP_NOTES) {
						apr_table_set(r->notes, "GEOIP_POSTAL_CODE", gir->postal_code);
					}
					if (cfg->GeoIPOutput & GEOIP_ENV) {
						apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE", gir->postal_code);
					}
				}
				GeoIPRecord_delete(gir);
			}
			break;
		case GEOIP_ORG_EDITION:
			orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
			if (orgorisp != NULL) {
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_ORGANIZATION", orgorisp);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_ORGANIZATION", orgorisp);
				}
			}
			break;
		case GEOIP_ISP_EDITION:
			orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
			if (orgorisp != NULL) {
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_ISP", orgorisp);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_ISP", orgorisp);
				}
			}
			break;
		case GEOIP_DOMAIN_EDITION:
			orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr);
			if (orgorisp != NULL) {
				if (cfg->GeoIPOutput & GEOIP_NOTES) {
					apr_table_setn(r->notes, "GEOIP_DOMAIN", orgorisp);
				}
				if (cfg->GeoIPOutput & GEOIP_ENV) {
					apr_table_setn(r->subprocess_env, "GEOIP_DOMAIN", orgorisp);
				}
			}
			break;
		}
	}

	return OK;
}
Exemple #12
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;
	size_t size;

	hostlist = GeoIP_get_host_or_proxy();

	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(GeoIPHTTPPort);
	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 server\n");
		GeoIP_printf(f, "via Host or Proxy Server: %s:%d\n", hostlist->h_name, GeoIPHTTPPort);
	}
	
	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,GeoIPHTTPRequestFilename,GeoIPProxyHTTP,GeoIPProxiedHost,data_base_type,GeoIPUpdateHost);
	if (verbose == 1) {
		GeoIP_printf(f, "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){
		GeoIP_printf(f, "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) {
    GeoIP_printf(f, NoCurrentDB, geoipfilename);
	} 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]);
    GeoIP_printf(f, MD5Info, hex_digest );
	}
	if (verbose == 1) {
		GeoIP_printf(f,"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(GeoIPHTTPPort);
		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,GeoIPHTTPRequestClientIP,GeoIPProxyHTTP,GeoIPProxiedHost,GeoIPUpdateHost);
		send(sock, request_uri, strlen(request_uri),0); /* send the request */
		if (verbose == 1) {
			GeoIP_printf(f, "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) {
			GeoIP_printf(f, "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, (byte *)license_key, 12);//add license key to the md5 sum
	md5_write (&context2, (byte *)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) {
		GeoIP_printf(f, "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(GeoIPHTTPPort);
	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,GeoIPProxyHTTP,GeoIPProxiedHost,hex_digest,hex_digest2,user_id,data_base_type);
	send(sock, request_uri, strlen(request_uri),0);
	if (verbose == 1) {
		GeoIP_printf(f, "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);
		GeoIP_printf(f, "%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");

	GeoIP_printf(f, "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) {
    GeoIP_printf(f, "%s%s", SavingGzip, file_path_gz );
	}
	comp_fh = fopen(file_path_gz, "wb");

	if(comp_fh == NULL) {
		free(file_path_gz);
		free(buf);
		return GEOIP_GZIP_IO_ERR;
	}

	size = fwrite(compr, 1, comprLen, comp_fh);
	fclose(comp_fh);
	free(buf);
        if ( size != comprLen ) {
		return GEOIP_GZIP_IO_ERR;
	}

	if (verbose == 1) {
		GeoIP_printf(f, "download data to a gz file named %s \n",file_path_gz);
		GeoIP_printf(f,"Done\n");
		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;
		}
		if ( amt != fwrite(block,1,amt,gi_fh) ){
			return GEOIP_GZIP_IO_ERR;
		}
	}
	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) {
		GeoIP_printf(f, "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;
}
Exemple #13
0
static void get_geoip_tables(array_header *geoips, int filter_flags) {
  config_rec *c;

  c = find_config(main_server->conf, CONF_PARAM, "GeoIPTable", FALSE);
  while (c) {
    GeoIP *gi;
    const char *path;
    int flags, use_utf8 = FALSE;

    pr_signals_handle();

    path = c->argv[0];
    flags = *((int *) c->argv[1]);
    use_utf8 = *((int *) c->argv[2]);

    /* Make sure we open tables that are marked with the default
     * GEOIP_STANDARD flag, which has a value of zero.
     */
    if ((flags == GEOIP_STANDARD && filter_flags != GEOIP_STANDARD) || 
        !(flags & filter_flags)) {
      c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE);
      continue;
    } 

    PRIVS_ROOT
    gi = GeoIP_open(path, flags);
    if (gi == NULL &&
        (flags & GEOIP_INDEX_CACHE)) {
      /* Per Bug#3975, a common cause of this error is the fact that some
       * of the Maxmind GeoIP Lite database files simply do not have indexes.
       * So try to open them as standard databases as a fallback.
       */
      pr_log_debug(DEBUG8, MOD_GEOIP_VERSION
        ": unable to open GeoIPTable '%s' using the IndexCache flag "
        "(database lacks index?), retrying without IndexCache flag", path);
      flags &= ~GEOIP_INDEX_CACHE;
      gi = GeoIP_open(path, flags);
    }
    PRIVS_RELINQUISH

    if (gi != NULL) {
      if (use_utf8) {
        GeoIP_set_charset(gi, GEOIP_CHARSET_UTF8); 
      }

      *((GeoIP **) push_array(geoips)) = gi;

      pr_trace_msg(trace_channel, 15, "loaded GeoIP table '%s': %s (type %d)",
        path, GeoIP_database_info(gi), GeoIP_database_edition(gi));

    } else {
      /* XXX Sigh.  Stupid libGeoIP library logs to stdout/stderr, rather
       * than providing a strerror function.  Grr!
       */

      pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
        ": warning: unable to open/use GeoIPTable '%s'", path);
    }

    c = find_config_next(c, c->next, CONF_PARAM, "GeoIPTable", FALSE);
  }

  if (geoips->nelts == 0 &&
      static_geoips->nelts == 0 &&
      ((filter_flags == GEOIP_STANDARD) ||
       (filter_flags & GEOIP_CHECK_CACHE))) {
    GeoIP *gi;

    /* Let the library use its own default database file(s), if no others
     * have been configured.
     */

    PRIVS_ROOT
    gi = GeoIP_new(GEOIP_STANDARD);
    PRIVS_RELINQUISH

    if (gi != NULL) {
      *((GeoIP **) push_array(geoips)) = gi;

      pr_trace_msg(trace_channel, 15,
        "loaded default GeoIP table: %s (type %d)",
        GeoIP_database_info(gi), GeoIP_database_edition(gi));

    } else {
      pr_log_pri(PR_LOG_WARNING, MOD_GEOIP_VERSION
        ": warning: unable to open/use default GeoIP library database file(s)");
    }
  }
Exemple #14
0
/* Error message capture code inspired by code by Wolfgang Oertl. */
int luageoip_common_open_db(
    lua_State * L,
    const luaL_reg * M,
    int default_type,
    int default_flags,
    const char * mt_name,
    unsigned int bad_flags,
    size_t num_allowed_types,
    const int * allowed_types
  )
{
  /* First argument is checked later */
  int flags = luaL_optint(L, 2, default_flags);
  int charset = luaL_optint(L, 2, GEOIP_CHARSET_UTF8);

  GeoIP * pGeoIP = NULL;
  luageoip_DB * pResult = NULL;

  int old_stderr;
  int pipefd[2];
  char buf[256];

  int error_reported = 0;

  if (bad_flags && (flags & bad_flags) == bad_flags)
  {
    /* TODO: Or is it concrete DB file problem? */
    return luaL_error(
        L,
        "%s error: can't open db with these flags",
        mt_name
      );
  }

  /* Errors are printed to stderr, capture them */
  {
    /* TODO: Handle failures */
    int result = pipe(pipefd);
    result = 0 + result; /* While we're not handling failures, shut up compiler */
    fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
    fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
    old_stderr = dup(2);
    dup2(pipefd[1], 2);
  }

  if (lua_isnoneornil(L, 1))
  {
    pGeoIP = GeoIP_open_type(default_type, flags);
  }
  else
  {
    const char * filename = luaL_checkstring(L, 1);
    pGeoIP = GeoIP_open(filename, flags);
  }

  /* Cleanup error handling */
  {
    int n = read(pipefd[0], buf, sizeof(buf));
    if (n >= 0)
    {
      buf[n] = 0;

      if (!pGeoIP) /* ?! What to do otherwise? */
      {
        lua_pushnil(L);
        lua_pushstring(L, buf);
        error_reported = 1;
      }
    }

    close(pipefd[0]);
    close(pipefd[1]);
    dup2(old_stderr, 2);
    close(old_stderr);
  }

  if (pGeoIP)
  {
    int type = GeoIP_database_edition(pGeoIP);
    int found = 0;
    size_t i = 0;

    for (i = 0; i < num_allowed_types; ++i)
    {
      if (type == allowed_types[i])
      {
        found = 1;
        break;
      }
    }

    if (!found)
    {
      lua_pushnil(L);
      lua_pushfstring(
          L,
          "%s error: unexpected db type in that file (%s)",
          mt_name,
          GeoIP_database_info(pGeoIP)
        );
      error_reported = 1;

      GeoIP_delete(pGeoIP);
      pGeoIP = NULL;
    }
  }

  if (pGeoIP == NULL)
  {
    if (!error_reported)
    {
      lua_pushnil(L);
      lua_pushfstring(
          L,
          "%s error: failed to open database file",
          mt_name
        );
      error_reported = 1;
    }

    return 2; /* nil and error message already on stack */
  }

  GeoIP_set_charset(pGeoIP, charset);

  pResult = (luageoip_DB *)lua_newuserdata(L, sizeof(luageoip_DB));
  pResult->pGeoIP = pGeoIP;

  if (luaL_newmetatable(L, mt_name))
  {
    luaL_register(L, NULL, M);
    lua_pushvalue(L, -1);
    lua_setfield(L, -2, "__index");
  }

  lua_setmetatable(L, -2);

  return 1;
}
void parse(char *country_input,
	   char *path_input,
	   char *domain_input,
	   char *ipaddress_input,
	   char *http_status_input,
	   char *referer_input,
	   char *bird,
	   char *db_path,
	   int minimum_field_count) {

	// GENERIC VARIABLES
	char *fields[MAX_FIELD_CNT];       // number of fields we expect in a single line
	int num_filters             = 0;   // total number of filters we detect from the command line
	int num_domain_filters      = 0;   // total number of domain filters
	int num_path_filters        = 0;   // total number of path filters
	int num_ipaddress_filters   = 0;   // total number of ipaddress filter
	int num_countries_filters   = 0;   // total number countries we want to restrict the filtering
	int num_http_status_filters = 0;   // total number of http status we want to restrict the filtering.
	int num_referer_filters     = 0;
	int required_hits           = 0;
	int bird_int                = 0;
	int i;

	int field_count_this_line=0;  // number of fields found in the current line

	char line[ LINE_BUF_SIZE ];
	char *ipaddr;
	char *url;
	char *http_status;
	char *referer;


	// DETERMINE NUMBER OF FILTERS
	if(params[DOMAIN_FILTER]){
		num_domain_filters = determine_num_obs(domain_input,comma_delimiter);
		required_hits+=1;
	}
	if(params[PATH_FILTER]){
		num_path_filters = determine_num_obs(path_input,comma_delimiter);
		required_hits+=1;
	}
	if(params[IP_FILTER]){
		num_ipaddress_filters = determine_num_obs(ipaddress_input, comma_delimiter);
		required_hits+=1;
	}
	if(params[GEO_FILTER]){
		if(country_input != NULL && strlen(country_input) >1){
			num_countries_filters = determine_num_obs(country_input, comma_delimiter);
			required_hits+=1;
		}
	}
	if(params[REFERER_FILTER]){
		num_referer_filters = determine_num_obs(referer_input, comma_delimiter);
		required_hits+=1;
	}
	if(params[HTTP_STATUS_FILTER]){
		if(http_status_input != NULL && strlen(http_status_input) >1){
			num_http_status_filters = determine_num_obs(http_status_input, comma_delimiter);
			required_hits+=1;
		}
	}

	num_filters = num_path_filters + num_domain_filters + num_ipaddress_filters
		+ num_countries_filters + num_http_status_filters + num_referer_filters;
	Filter filters[num_filters];

	// GEO_FILTER INITIALIZATION
	GeoIP *gi = NULL;    // initialize to suppress compiler warning
	char *countries[num_countries_filters];
	char *area;

	// FILTER INITIALIZATION
	if(params[DOMAIN_FILTER]){
		init_domains(filters, domain_input, comma_delimiter);
	} else {
		domain_input=NULL;
	}

	if(params[PATH_FILTER]){
		init_paths(filters, path_input, comma_delimiter);
	} else {
		path_input = NULL;
	}

	if(params[IP_FILTER]){
		init_ip_addresses(filters, ipaddress_input, comma_delimiter);
	} else {
		ipaddress_input = NULL;
	}

	if (params[REFERER_FILTER]){
		init_domains(filters, referer_input, comma_delimiter);
	} else {
		referer_input = NULL;
	}

	if( ! (params[GEO_FILTER] || (recode & GEO)) ) {
		country_input = NULL;
	} else {
		init_countries(countries, country_input, num_countries_filters, comma_delimiter);
		bird_int = init_bird_level(bird);
		/*
		 *  Before changing the type of cache, have a look at this benchmark:
		 *  http://www.maxmind.com/app/benchmark
		 *  and choose wisely.
		 */
		switch(bird_int){
		case COUNTRY:
			if(db_path!=NULL){
				db_country_path=db_path;
			}
			gi = GeoIP_open(db_country_path, GEOIP_MEMORY_CACHE);
			break;

		case REGION:
			if(db_path!=NULL){
				db_region_path=db_path;
			}
			gi = GeoIP_open(db_region_path, GEOIP_MEMORY_CACHE);
			break;

		case CITY:
			if(db_path!=NULL){
				db_city_path=db_path;
			}
			gi = GeoIP_open(db_city_path, GEOIP_MEMORY_CACHE);
			break;

		case LAT_LON:
			if(db_path!=NULL){
				db_city_path=db_path;
			}
			gi = GeoIP_open(db_city_path, GEOIP_MEMORY_CACHE);
			break;

		case EVERYTHING:
			if(db_path!=NULL){
				db_city_path=db_path;
			}
			gi = GeoIP_open(db_city_path, GEOIP_MEMORY_CACHE);
			break;
		}

		if (gi == NULL) {
			fprintf(stderr, "Error opening MaxMind Geo database.\n");
			fprintf(stderr, "Path used for country database:%s\n", db_country_path);
			fprintf(stderr, "Path used for region database:%s\n", db_region_path);
			fprintf(stderr, "Path used for city database:%s\n", db_city_path);
			exit(EXIT_FAILURE);
		} else {
			if(verbose_flag){
				char *db_info =GeoIP_database_info(gi);
				unsigned char db_edition = GeoIP_database_edition(gi);
				GeoIPDBTypes geodbtype = (GeoIPDBTypes)db_info;
				fprintf(stderr,"Maxmind database: %i; version: %i\n", db_edition, geodbtype);
			}
		}
	}

	if(params[HTTP_STATUS_FILTER]){
		init_http_status(filters, http_status_input, comma_delimiter);
	} else {
		http_status_input = NULL;
	}


	if (verbose_flag){
		fprintf(stderr, "num_path_filters:%d\tnum_domain_filters:%d"
			"\tnum_http_status_filters:%d\tip_address_count:%d"
			"\tcountries_count:%d\treferer_count:%d\n",
			num_path_filters, num_domain_filters, num_http_status_filters,
			num_ipaddress_filters, num_countries_filters, num_referer_filters);
	}


	// Now that we have initilaized all the filters,
	// do the actual filtering and conversion of the
	// incoming data.
	while ( true ) {
		int found =0;
		area = NULL;

		char *r;
		r=fgets(line, LINE_BUF_SIZE, stdin);
		if(!r) {
			break;
		}

		i = 0;
		char *p;
		do {
			fields[i] = r;
			//strsep(&r, ws_delimiter);
			p = strchr( r, *ws_delimiter );
			i++;
                        if ( NULL == p )
                                break;
                        *p = 0;
                        r = p + 1;
		} while (i < MAX_FIELD_CNT);

		if (i < minimum_field_count || i == MAX_FIELD_CNT){
			continue;    // ignore line since field count is outside expected range
		}


		// we found i fields in this line.
		field_count_this_line = i;

		ipaddr        = fields[4];
		http_status   = fields[5];
		url           = fields[8];
		referer       = fields[11];
		//ua            = fields[13]; // necessary for bot detection


		if (url != NULL) {

			if (params[DOMAIN_FILTER]){
				found += match_domain(url, filters, num_domain_filters,verbose_flag);
			}

			if (params[PATH_FILTER]){
				found += match_path(url, filters, num_path_filters,verbose_flag);
			}

			if (params[HTTP_STATUS_FILTER]){
				found += match_http_status(http_status, filters, num_http_status_filters,verbose_flag);
			}

			if (params[IP_FILTER]){
				found += match_ip_address(ipaddr, filters, num_ipaddress_filters,verbose_flag);
			}

			if (params[REFERER_FILTER]){
				found += match_domain(referer, filters, num_referer_filters,verbose_flag);
			}

			if (params[GEO_FILTER]){
				area = geo_lookup(gi, ipaddr, bird_int);
				found += geo_check(area, countries, num_countries_filters,verbose_flag);
				if (verbose_flag){
					fprintf(stderr, "IP address: %s was geocoded as: %s\n", ipaddr, area);
				}
			}
		}

		// required_hits will equal the number of filters
		// given.  These include ip, domain, path, status,
		// and country filtering.  If no filters were given,
		// then found will be 0 AND require_hits will be 0,
		// allowing the line to pass through.
		if (found >= required_hits) {
			// if we need to replace the IP addr
			// because recode is GEO or ANONYMIZE or both
			if (recode)
			{
				// geocode if we haven't already geocoded and
				// we'll be needing the geocoded string when
				// replacing the IP.
				if (area == NULL && (recode & GEO)) {
					area = geo_lookup(gi, ipaddr, bird_int);
				}

				// replace the ip address in fields.
				// if area is not null, it will be appended
				// to the ip address.  If (recode & ANONYMIZE) is
				// true, then the IP will be replaced.
				replace_ip_addr(fields, area, (recode & ANONYMIZE));
			}

			// print output to stdout
			for (i=0;i<field_count_this_line;++i){
				if (i!=0){
					FPUTS(ws_delimiter, stdout);
				}
				FPUTS(fields[i], stdout);
			}

		}

		if (verbose_flag) {
			fprintf(stderr, "ipaddr: '%s', url: '%s, status: %s'\n", ipaddr, url, http_status);
		}

	}
	free_memory(filters, path_input, domain_input,num_filters, gi, countries, num_countries_filters);
}
Exemple #16
0
PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh,
                 int flags,
                 int argc,
                 const char **argv)
{
    struct options *opts;
    FILE *fh;
    char *username;        /* username requesting access */
    char *rhost;           /* remote host */
    char *srv;             /* PAM service we're running as */
    char buf[LINE_LENGTH];
    int retval, action;
    int is_v6 = 0;
    struct locations *geo;
    unsigned char gi_type;

    GeoIP       *gi   = NULL;
#ifdef HAVE_GEOIP_010408
    GeoIP       *gi6  = NULL;
    int is_city6_db   = 0;
#endif
    GeoIPRecord *rec  = NULL;

    opts = malloc(sizeof(struct options));
    if (opts == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'opts': %m");
        return PAM_SERVICE_ERR;
    }
    opts->charset      = GEOIP_CHARSET_UTF8;
    opts->debug        = 0;
    opts->action       = PAM_PERM_DENIED;
    opts->system_file  = NULL;
    opts->service_file = NULL;
    opts->by_service   = 0;
    opts->geoip_db     = NULL;
#ifdef HAVE_GEOIP_010408
    opts->use_v6       = 0;
    opts->v6_first     = 0;
    opts->geoip6_db    = NULL;
#endif
    opts->is_city_db   = 0;

    geo = malloc(sizeof(struct locations));
    if (geo == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'geo': %m");
        free_opts(opts);
        return PAM_SERVICE_ERR;
    }
    geo->country = NULL;
    geo->city    = NULL;
    geo->next    = NULL;

    _parse_args(pamh, argc, argv, opts);

    if (opts->system_file == NULL)
        opts->system_file = strdup(SYSTEM_FILE);
    if (opts->system_file == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->system_file': %m");
        free_opts(opts);
        return PAM_SERVICE_ERR;
    }

    if (opts->geoip_db == NULL)
        opts->geoip_db = strdup(GEOIPDB_FILE);
    if (opts->geoip_db == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->geoip_db': %m");
        free_opts(opts);
        return PAM_SERVICE_ERR;
    }

#ifdef HAVE_GEOIP_010408
    if (opts->geoip6_db == NULL)
        opts->geoip6_db = strdup(GEOIP6DB_FILE);
    if (opts->geoip6_db == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'opts->geoip6_db': %m");
        free_opts(opts);
        return PAM_SERVICE_ERR;
    }
#endif

    retval = pam_get_item(pamh, PAM_USER, (void*) &username);
    if (username == NULL || retval != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_CRIT, "error recovering username");
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }

    retval = pam_get_item(pamh, PAM_RHOST, (void*) &rhost);
    if (retval != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_CRIT, "error fetching rhost");
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }
    if (rhost == NULL) {
        pam_syslog(pamh, LOG_INFO, "rhost is NULL, allowing");
        free_opts(opts);
        free_locations(geo);
        return PAM_SUCCESS;
    }

    retval = pam_get_item(pamh, PAM_SERVICE, (void*) &srv);
    if (srv == NULL || retval != PAM_SUCCESS ) {
        pam_syslog(pamh, LOG_CRIT, "error requesting service name");
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }

    opts->service_file = malloc(PATH_MAX);
    if (opts->service_file == NULL) {
        pam_syslog(pamh, LOG_CRIT, "malloc error 'service_file': %m");
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }
    if (snprintf(opts->service_file, PATH_MAX-1, SERVICE_FILE, srv) < 0) {
        pam_syslog(pamh, LOG_CRIT, "snprintf error 'service_file'");
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }

    gi = GeoIP_open(opts->geoip_db, GEOIP_INDEX_CACHE);
    if (gi == NULL) {
        pam_syslog(pamh, LOG_CRIT,
                   "failed to open geoip db (%s): %m", opts->geoip_db);
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }
    gi_type = GeoIP_database_edition(gi);
    if (opts->debug)
        pam_syslog(pamh, LOG_DEBUG, "GeoIP edition: %d", gi_type);
    switch (gi_type) {
    case GEOIP_COUNTRY_EDITION:
        if (opts->debug)
            pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: country");
        opts->is_city_db = 0;
        break;
    case GEOIP_CITY_EDITION_REV0:
        if (opts->debug)
            pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: city rev0");
        opts->is_city_db = 1;
        break;
    case GEOIP_CITY_EDITION_REV1:
        if (opts->debug)
            pam_syslog(pamh, LOG_DEBUG, "GeoIP v4 edition: city rev1");
        opts->is_city_db = 1;
        break;
    default:
        pam_syslog(pamh, LOG_CRIT, "invalid GeoIP DB type `%d' found", gi_type);
        GeoIP_delete(gi);
        free_opts(opts);
        free_locations(geo);
        return PAM_SERVICE_ERR;
    }
    GeoIP_set_charset(gi, opts->charset);
    if (opts->debug)
        pam_syslog(pamh, LOG_DEBUG, "GeoIP DB is City: %s",
                   opts->is_city_db ? "yes" : "no");

#ifdef HAVE_GEOIP_010408
    if (opts->use_v6 != 0) {
        gi6 = GeoIP_open(opts->geoip6_db, GEOIP_INDEX_CACHE);
        if (gi6 == NULL) {
            pam_syslog(pamh, LOG_CRIT,
                       "failed to open geoip6 db (%s): %m", opts->geoip6_db);
            GeoIP_delete(gi);
            free_opts(opts);
            free_locations(geo);
            return PAM_SERVICE_ERR;
        }
        gi_type = GeoIP_database_edition(gi6);

        switch (gi_type) {
        case GEOIP_COUNTRY_EDITION_V6:
            if (opts->debug)
                pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: country");
            is_city6_db = 0;
            break;
        case GEOIP_CITY_EDITION_REV0_V6:
            if (opts->debug)
                pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: city rev0");
            is_city6_db = 1;
            break;
        case GEOIP_CITY_EDITION_REV1_V6:
            if (opts->debug)
                pam_syslog(pamh, LOG_DEBUG, "GeoIP v6 edition: city rev1");
            is_city6_db = 1;
            break;
        default:
            pam_syslog(pamh, LOG_CRIT, "invalid GeoIP DB type `%d' found", gi_type);
            GeoIP_delete(gi);
            GeoIP_delete(gi6);
            free_opts(opts);
            free_locations(geo);
            return PAM_SERVICE_ERR;
        }
        if (opts->debug)
            pam_syslog(pamh, LOG_DEBUG, "GeoIP DB is City v6: %s",
                       is_city6_db ? "yes" : "no");
        GeoIP_set_charset(gi6, opts->charset);

        if (opts->is_city_db != is_city6_db) {
            pam_syslog(pamh, LOG_CRIT, "IPv4 DB type is not the same as IPv6 (not both Country edition or both City edition)");
            GeoIP_delete(gi);
            GeoIP_delete(gi6);
            free_opts(opts);
            free_locations(geo);
            return PAM_SERVICE_ERR;
        }

        if (opts->v6_first != 0) {
            rec = GeoIP_record_by_name_v6(gi6, rhost);
            if (rec == NULL) {
                if (opts->debug)
                    pam_syslog(pamh, LOG_DEBUG, "no IPv6 record for %s, trying IPv4", rhost);
                rec = GeoIP_record_by_name(gi, rhost);
            }
            else
                is_v6 = 1;
        }
        else {
            rec = GeoIP_record_by_name(gi, rhost);
            if (rec == NULL) {
                if (opts->debug)
                    pam_syslog(pamh, LOG_DEBUG, "no IPv4 record for %s, trying IPv6", rhost);
                rec = GeoIP_record_by_name_v6(gi6, rhost);
                if (rec != NULL)
                    is_v6 = 1;
            }
        }
    }
    else
#endif /* HAVE_GEOIP_010408 */
        rec = GeoIP_record_by_name(gi, rhost);

    if (rec == NULL) {
        pam_syslog(pamh, LOG_INFO, "no record for %s, setting GeoIP to 'UNKNOWN,*'", rhost);

        geo->city    = strdup("*");
        geo->country = strdup("UNKNOWN");

        if (geo->city == NULL || geo->country == NULL) {
            pam_syslog(pamh, LOG_CRIT, "malloc error 'geo->{city,country}': %m");
            GeoIP_delete(gi);
#ifdef HAVE_GEOIP_010408
            GeoIP_delete(gi6);
#endif
            free_opts(opts);
            free_locations(geo);
            return PAM_SERVICE_ERR;
        }
    }
    else {
        if (rec->city == NULL || opts->is_city_db == 0)
            geo->city = strdup("*");
        else
            geo->city = strdup(rec->city);

        if (rec->country_code == NULL)
            geo->country = strdup("UNKNOWN");
        else
            geo->country = strdup(rec->country_code);

        if (geo->city == NULL || geo->country == NULL) {
            pam_syslog(pamh, LOG_CRIT, "malloc error 'geo->{city,country}': %m");
            GeoIP_delete(gi);
#ifdef HAVE_GEOIP_010408
            GeoIP_delete(gi6);
#endif
            free_opts(opts);
            free_locations(geo);
            return PAM_SERVICE_ERR;
        }

        if (opts->is_city_db) {
            geo->latitude  = rec->latitude;
            geo->longitude = rec->longitude;
        }
    }

    if (opts->debug)
        pam_syslog(pamh, LOG_DEBUG, "GeoIP record for %s: %s,%s",
                   rhost, geo->country, geo->city);

    if (opts->debug && strcmp(geo->country, "UNKNOWN") != 0 && opts->is_city_db)
        pam_syslog(pamh, LOG_DEBUG, "GeoIP coordinates for %s: %f,%f",
                   rhost, geo->latitude, geo->longitude);

    if ((fh = fopen(opts->service_file, "r")) != NULL) {
        opts->by_service = 1;
        if (opts->debug)
            pam_syslog(pamh, LOG_DEBUG, "using services file %s",
                       opts->service_file);
    }
    else {
        if ((fh = fopen(opts->system_file, "r")) == NULL) {
            pam_syslog(pamh, LOG_CRIT, "error opening %s: %m", opts->system_file);

#ifdef HAVE_GEOIP_010408
            if (gi6) GeoIP_delete(gi6);
#endif
            if (gi) GeoIP_delete(gi);
            if (rec) GeoIPRecord_delete(rec);
            free_opts(opts);
            return PAM_SERVICE_ERR;
        }
    }

    action = opts->action;
    char location[LINE_LENGTH];
    while (fgets(buf, LINE_LENGTH, fh) != NULL) {
        char *line, *ptr;
        char domain[LINE_LENGTH],
             service[LINE_LENGTH];

        action = opts->action;
        line   = buf;
        /* skip the leading white space */
        while (*line && isspace(*line))
            line++;

        /* Rip off the comments */
        ptr = strchr(line,'#');
        if (ptr)
            *ptr = '\0';
        /* Rip off the newline char */
        ptr = strchr(line,'\n');
        if (ptr)
            *ptr = '\0';
        /* Anything left ? */
        if (!strlen(line))
            continue;

        if (opts->by_service)
            action = parse_line_srv(pamh, line, domain, location);
        else
            action = parse_line_sys(pamh, line, domain, service, location);
        if (action < 0) { /* parsing failed */
            action = opts->action;
            continue;
        }

        if (!opts->by_service) {
            if (!check_service(pamh, service, srv))
                continue;
        }

        if ((strcmp(domain, "*") == 0) || (strcmp(username, domain) == 0)) {
            if (check_location(pamh, opts, location, geo))
                break;
        }
        else if (domain[0] == '@') {
            if (pam_modutil_user_in_group_nam_nam(pamh, username, domain+1)) {
                if (check_location(pamh, opts, location, geo))
                    break;
            }
        }
    }

    fclose(fh);
    if (gi) GeoIP_delete(gi);
#ifdef HAVE_GEOIP_010408
    if (gi6) GeoIP_delete(gi6);
#endif
    if (rec) GeoIPRecord_delete(rec);
    free_locations(geo);

    switch (action) {
    case PAM_SUCCESS:
        pam_syslog(pamh, LOG_DEBUG, "location %s allowed for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4);
        break;
    case PAM_PERM_DENIED:
        pam_syslog(pamh, LOG_DEBUG, "location %s denied for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4);
        break;
    case PAM_IGNORE:
        pam_syslog(pamh, LOG_DEBUG, "location %s ignored for user %s from %s (IPv%d)", location, username, rhost, is_v6 ? 6 : 4);
        break;
    default: /* should not happen */
        pam_syslog(pamh, LOG_DEBUG, "location status: %d, IPv%d", action, is_v6 ? 6 : 4);
        break;
    };
    free_opts(opts);
    return action;
}