telize

High performance JSON IP and GeoIP REST API (IP Geolocation)
Log | Files | Refs | README | LICENSE

utils.c (2684B)


      1 /*
      2  * Telize 2.0.0
      3  * Copyright (c) 2013-2020, Frederic Cambus
      4  * https://www.telize.com
      5  *
      6  * Created:      2013-08-15
      7  * Last Updated: 2019-03-13
      8  *
      9  * Telize is released under the BSD 2-Clause license.
     10  * See LICENSE file for details.
     11  */
     12 
     13 #include "telize.h"
     14 
     15 #define GEOIP2DIR "/var/db/GeoIP/"
     16 
     17 MMDB_s telize_asn;
     18 MMDB_s telize_city;
     19 
     20 int
     21 telize_init(int state)
     22 {
     23 	if (state == KORE_MODULE_UNLOAD) {
     24 		MMDB_close(&telize_city);
     25 		MMDB_close(&telize_asn);
     26 		return (KORE_RESULT_OK);
     27 	}
     28 
     29 	if (MMDB_open(GEOIP2DIR "GeoLite2-City.mmdb",
     30 	    MMDB_MODE_MMAP, &telize_city) != MMDB_SUCCESS)
     31 		fatalx("can't open GeoLite2 City database: %s", errno_s);
     32 
     33 	if (MMDB_open(GEOIP2DIR "GeoLite2-ASN.mmdb",
     34 	    MMDB_MODE_MMAP, &telize_asn) != MMDB_SUCCESS)
     35 		fatalx("can't open GeoLite2 ASN database: %s", errno_s);
     36 
     37 	return (KORE_RESULT_OK);
     38 }
     39 
     40 void
     41 telize_getdata(struct kore_buf *json, MMDB_lookup_result_s *lookup,
     42     MMDB_entry_data_s *entry_data, char *field, int type, ...)
     43 {
     44 	va_list keys;
     45 	va_start(keys, type);
     46 
     47 	MMDB_vget_value(&lookup->entry, entry_data, keys);
     48 
     49 	if (entry_data->has_data) {
     50 		switch(type) {
     51 		case ENTRY_TYPE_UINT32:
     52 			kore_buf_appendf(json, ",\"%s\":%d",
     53 			    field, entry_data->uint32);
     54 			break;
     55 		case ENTRY_TYPE_STRING:
     56 			kore_buf_appendf(json, ",\"%s\":\"%.*s\"",
     57 			    field, entry_data->data_size,
     58 			    entry_data->utf8_string);
     59 			break;
     60 		case ENTRY_TYPE_DOUBLE:
     61 			kore_buf_appendf(json, ",\"%s\":%.4f",
     62 			    field, entry_data->double_value);
     63 			break;
     64 		}
     65 	}
     66 
     67 	va_end(keys);
     68 }
     69 
     70 int
     71 telize_request_ip(struct http_request *req, char *buf, size_t len)
     72 {
     73 	char		*ptr;
     74 	void		*addr;
     75 	size_t		hdr_len;
     76 	const char	*hdr_ip;
     77 
     78 	switch (req->owner->family) {
     79 	case AF_INET:
     80 		addr = &req->owner->addr.ipv4.sin_addr;
     81 		break;
     82 	case AF_INET6:
     83 		addr = &req->owner->addr.ipv6.sin6_addr;
     84 		break;
     85 	default:
     86 		kore_log(LOG_ERR, "unsupported family %d", req->owner->family);
     87 		return (KORE_RESULT_ERROR);
     88 	}
     89 
     90 	if (inet_ntop(req->owner->family, addr, buf, len) == NULL) {
     91 		kore_log(LOG_ERR, "inet_ntop failed (%s)", errno_s);
     92 		return (KORE_RESULT_ERROR);
     93 	}
     94 
     95 	if (!http_request_header(req, "x-forwarded-for", &hdr_ip))
     96 		return (KORE_RESULT_OK);
     97 
     98 	if ((ptr = strchr(hdr_ip, ',')) != NULL) {
     99 		hdr_len = ptr - hdr_ip;
    100 	} else {
    101 		hdr_len = strlen(hdr_ip);
    102 	}
    103 
    104 	if (hdr_len > len - 1) {
    105 		kore_log(LOG_ERR, "IP in X-Forwarded-For too large");
    106 		return (KORE_RESULT_ERROR);
    107 	}
    108 
    109 	memcpy(buf, hdr_ip, hdr_len);
    110 	buf[hdr_len] = '\0';
    111 
    112 	if (inet_pton(AF_INET, buf, addr) == -1) {
    113 		if (inet_pton(AF_INET6, buf, &req->owner->addr) == -1) {
    114 			kore_log(LOG_ERR, "Malformed IP in X-Forwarded-For");
    115 			return (KORE_RESULT_ERROR);
    116 		}
    117 	}
    118 
    119 	return (KORE_RESULT_OK);
    120 }