telize

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

utils.c (2648B)


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