mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-08-09 09:51:49 +08:00
* Import system headers as `#include <...>`. * Import local headers as `#include "..."`. * Use consistent header guards (starting with `OC_`). Signed-off-by: Dimitri Papadopoulos <3350651-DimitriPapadopoulos@users.noreply.gitlab.com>
238 lines
5.3 KiB
C
238 lines
5.3 KiB
C
/*
|
|
* Copyright (c) 2015-2017 Red Hat, Inc. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License, version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Authors:
|
|
* Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <stdarg.h>
|
|
|
|
#ifdef HAVE_GEOIP
|
|
|
|
#include <GeoIP.h>
|
|
#include <GeoIPCity.h>
|
|
|
|
extern void _GeoIP_setup_dbfilename(void);
|
|
#define p_GeoIP_setup_dbfilename _GeoIP_setup_dbfilename
|
|
#define pGeoIP_open_type GeoIP_open_type
|
|
#define pGeoIP_country_name_by_id GeoIP_country_name_by_id
|
|
#define pGeoIP_delete GeoIP_delete
|
|
#define pGeoIP_record_by_ipnum GeoIP_record_by_ipnum
|
|
#define pGeoIP_id_by_ipnum GeoIP_id_by_ipnum
|
|
#define pGeoIP_id_by_ipnum_v6 GeoIP_id_by_ipnum_v6
|
|
#define pGeoIP_record_by_ipnum_v6 GeoIP_record_by_ipnum_v6
|
|
#define pGeoIP_code_by_id GeoIP_code_by_id
|
|
|
|
int geo_setup(void)
|
|
{
|
|
static unsigned int init;
|
|
|
|
if (init == 0) {
|
|
p_GeoIP_setup_dbfilename();
|
|
init = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void geo_ipv4_lookup(struct in_addr ip, char **country, char **city,
|
|
char **coord)
|
|
{
|
|
GeoIP *gi;
|
|
GeoIPRecord *gir;
|
|
int country_id;
|
|
const char *p;
|
|
|
|
if (geo_setup() != 0)
|
|
return;
|
|
|
|
ip.s_addr = ntohl(ip.s_addr);
|
|
|
|
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
country_id = pGeoIP_id_by_ipnum(gi, ip.s_addr);
|
|
if (country_id < 0) {
|
|
return;
|
|
}
|
|
p = pGeoIP_country_name_by_id(gi, country_id);
|
|
if (p)
|
|
*country = strdup(p);
|
|
|
|
pGeoIP_delete(gi);
|
|
}
|
|
|
|
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
gir = pGeoIP_record_by_ipnum(gi, ip.s_addr);
|
|
|
|
if (gir && gir->city)
|
|
*city = strdup(gir->city);
|
|
|
|
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
|
if (asprintf(coord, "%f,%f", gir->latitude,
|
|
gir->longitude) < 0)
|
|
*coord = NULL;
|
|
|
|
pGeoIP_delete(gi);
|
|
} else {
|
|
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
gir = pGeoIP_record_by_ipnum(gi, ip.s_addr);
|
|
|
|
if (gir && gir->city)
|
|
*city = strdup(gir->city);
|
|
|
|
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
|
if (asprintf(coord, "%f,%f", gir->latitude,
|
|
gir->longitude) < 0)
|
|
*coord = NULL;
|
|
|
|
pGeoIP_delete(gi);
|
|
}
|
|
}
|
|
}
|
|
|
|
void geo_ipv6_lookup(struct in6_addr *ip, char **country, char **city,
|
|
char **coord)
|
|
{
|
|
GeoIP *gi;
|
|
GeoIPRecord *gir;
|
|
int country_id;
|
|
const char *p;
|
|
|
|
if (geo_setup() != 0)
|
|
return;
|
|
|
|
gi = pGeoIP_open_type(GEOIP_COUNTRY_EDITION_V6,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
country_id = pGeoIP_id_by_ipnum_v6(gi, (geoipv6_t)*ip);
|
|
if (country_id < 0) {
|
|
return;
|
|
}
|
|
p = pGeoIP_country_name_by_id(gi, country_id);
|
|
if (p)
|
|
*country = strdup(p);
|
|
|
|
pGeoIP_delete(gi);
|
|
}
|
|
|
|
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV1_V6,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
gir = pGeoIP_record_by_ipnum_v6(gi, (geoipv6_t)*ip);
|
|
|
|
if (gir && gir->city)
|
|
*city = strdup(gir->city);
|
|
|
|
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
|
if (asprintf(coord, "%f,%f", gir->latitude,
|
|
gir->longitude) < 0)
|
|
*coord = NULL;
|
|
|
|
pGeoIP_delete(gi);
|
|
} else {
|
|
gi = pGeoIP_open_type(GEOIP_CITY_EDITION_REV0_V6,
|
|
GEOIP_STANDARD | GEOIP_SILENCE);
|
|
if (gi != NULL) {
|
|
gi->charset = GEOIP_CHARSET_UTF8;
|
|
|
|
gir = pGeoIP_record_by_ipnum_v6(gi, (geoipv6_t)*ip);
|
|
|
|
if (gir && gir->city)
|
|
*city = strdup(gir->city);
|
|
|
|
if (gir && gir->longitude != 0 && gir->longitude != 0)
|
|
if (asprintf(coord, "%f,%f", gir->latitude,
|
|
gir->longitude) < 0)
|
|
*coord = NULL;
|
|
|
|
pGeoIP_delete(gi);
|
|
}
|
|
}
|
|
}
|
|
|
|
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size)
|
|
{
|
|
char *country = NULL;
|
|
char *city = NULL;
|
|
char *coord = NULL;
|
|
|
|
if (strchr(ip, ':') != NULL) {
|
|
struct in6_addr addr;
|
|
|
|
if (inet_pton(AF_INET6, ip, &addr) == 0)
|
|
goto fail;
|
|
geo_ipv6_lookup(&addr, &country, &city, &coord);
|
|
} else { /*ipv4*/
|
|
struct in_addr addr;
|
|
|
|
if (inet_pton(AF_INET, ip, &addr) == 0)
|
|
goto fail;
|
|
geo_ipv4_lookup(addr, &country, &city, &coord);
|
|
}
|
|
|
|
if (country && city && coord) {
|
|
snprintf(buf, buf_size, "%s, %s (%s)", city, country, coord);
|
|
} else if (country && city) {
|
|
snprintf(buf, buf_size, "%s, %s", city, country);
|
|
} else if (country) {
|
|
snprintf(buf, buf_size, "%s", country);
|
|
} else
|
|
goto fail;
|
|
|
|
free(country);
|
|
free(city);
|
|
free(coord);
|
|
|
|
return buf;
|
|
|
|
fail:
|
|
free(country);
|
|
free(city);
|
|
free(coord);
|
|
|
|
return "unknown";
|
|
}
|
|
|
|
#else
|
|
char *geo_lookup(const char *ip, char *buf, unsigned int buf_size)
|
|
{
|
|
return "unknown";
|
|
}
|
|
#endif
|