diff --git a/src/client.c b/src/client.c index 10c3cde..a75c183 100644 --- a/src/client.c +++ b/src/client.c @@ -751,51 +751,9 @@ int client_connection_handler(client_ctx_t *ctx, sock *client, unsigned long cli ctx->host[0] = 0; } - long str_off = 0; - for (int i = 0; i < MAX_MMDB && mmdbs[i].filename != NULL; i++) { - int gai_error, mmdb_res; - MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[i], ctx->addr, &gai_error, &mmdb_res); - if (mmdb_res != MMDB_SUCCESS) { - error("Unable to lookup geoip info: %s", MMDB_strerror(mmdb_res)); - continue; - } else if (gai_error != 0) { - error("Unable to lookup geoip info"); - continue; - } else if (!result.found_entry) { - continue; - } - - MMDB_entry_data_list_s *list; - mmdb_res = MMDB_get_entry_data_list(&result.entry, &list); - if (mmdb_res != MMDB_SUCCESS) { - error("Unable to lookup geoip info: %s", MMDB_strerror(mmdb_res)); - continue; - } - - long prev = str_off; - if (str_off != 0) { - str_off--; - } - mmdb_json(list, ctx->geoip, &str_off, GEOIP_MAX_SIZE); - if (prev != 0) { - ctx->geoip[prev - 1] = ','; - } - - MMDB_free_entry_data_list(list); - } - ctx->cc[0] = 0; - if (str_off == 0) { - ctx->geoip[0] = 0; - } else { - const char *pos = ctx->geoip; - pos = strstr(pos, "\"country\":"); - if (pos != NULL) { - pos = strstr(pos, "\"iso_code\":"); - pos += 12; - snprintf(ctx->cc, sizeof(ctx->cc), "%s", pos); - } - } + ctx->geoip[0] = 0; + geoip_lookup_country((struct sockaddr *) &client->addr, ctx->cc); info("Connection accepted from %s %s%s%s[%s]", ctx->addr, ctx->host[0] != 0 ? "(" : "", ctx->host[0] != 0 ? ctx->host : "", ctx->host[0] != 0 ? ") " : "", @@ -849,7 +807,7 @@ int client_connection_handler(client_ctx_t *ctx, sock *client, unsigned long cli return 0; } -int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *client_addr) { +int client_handler(sock *client, unsigned long client_num) { struct sockaddr_in6 *server_addr; struct sockaddr_storage server_addr_storage; @@ -861,7 +819,7 @@ int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 * signal(SIGINT, client_terminate); signal(SIGTERM, client_terminate); - inet_ntop(client_addr->sin6_family, (void *) &client_addr->sin6_addr, ctx._c_addr, sizeof(ctx._c_addr)); + inet_ntop(client->addr.sin6_family, (void *) &client->addr.sin6_addr, ctx._c_addr, sizeof(ctx._c_addr)); if (strncmp(ctx._c_addr, "::ffff:", 7) == 0) { ctx.addr = ctx._c_addr + 7; } else { @@ -880,7 +838,7 @@ int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 * sprintf(log_client_prefix, "[%s%4i%s]%s[%*s][%5i]%s", (int) client->enc ? HTTPS_STR : HTTP_STR, ntohs(server_addr->sin6_port), CLR_STR, color_table[client_num % 6], INET6_ADDRSTRLEN, ctx.addr, - ntohs(client_addr->sin6_port), CLR_STR); + ntohs(client->addr.sin6_port), CLR_STR); sprintf(log_conn_prefix, "[%6i][%*s]%s", getpid(), INET6_ADDRSTRLEN, ctx.s_addr, log_client_prefix); logger_set_prefix(log_conn_prefix); diff --git a/src/client.h b/src/client.h index a533fc1..b585282 100644 --- a/src/client.h +++ b/src/client.h @@ -20,13 +20,13 @@ typedef struct { char *s_addr; char cc[3]; char host[256]; - char geoip[GEOIP_MAX_SIZE + 1]; + char geoip[GEOIP_MAX_JSON_SIZE + 1]; char _c_addr[INET6_ADDRSTRLEN + 1]; char _s_addr[INET6_ADDRSTRLEN + 1]; } client_ctx_t; host_config *get_host_config(const char *host); -int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *client_addr); +int client_handler(sock *client, unsigned long client_num); #endif //SESIMOS_CLIENT_H diff --git a/src/lib/geoip.c b/src/lib/geoip.c index 6cab0a1..58b509e 100644 --- a/src/lib/geoip.c +++ b/src/lib/geoip.c @@ -7,9 +7,14 @@ */ #include "geoip.h" +#include "../logger.h" +#include +#include -MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) { +static MMDB_s mmdbs[GEOIP_MAX_MMDB]; + +static MMDB_entry_data_list_s *geoip_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) { switch (list->entry_data.type) { case MMDB_DATA_TYPE_MAP: *str_off += sprintf(str + *str_off, "{"); @@ -33,7 +38,7 @@ MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off += sprintf(str + *str_off, "%llu", (unsigned long long) list->entry_data.uint128); break; case MMDB_DATA_TYPE_INT32: - *str_off += sprintf(str + *str_off, "%i", list->entry_data.uint32); + *str_off += sprintf(str + *str_off, "%i", list->entry_data.int32); break; case MMDB_DATA_TYPE_BOOLEAN: *str_off += sprintf(str + *str_off, "%s", list->entry_data.boolean ? "true" : "false"); @@ -45,13 +50,14 @@ MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off += sprintf(str + *str_off, "%f", list->entry_data.double_value); break; } - if (list->entry_data.type != MMDB_DATA_TYPE_MAP && list->entry_data.type != MMDB_DATA_TYPE_ARRAY) { + + if (list->entry_data.type != MMDB_DATA_TYPE_MAP && list->entry_data.type != MMDB_DATA_TYPE_ARRAY) return list->next; - } + MMDB_entry_data_list_s *next = list->next; int stat = 0; for (int i = 0; i < list->entry_data.data_size; i++) { - next = mmdb_json(next, str, str_off, str_len); + next = geoip_json(next, str, str_off, str_len); if (list->entry_data.type == MMDB_DATA_TYPE_MAP) { stat = !stat; if (stat) { @@ -60,12 +66,127 @@ MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long continue; } } - if (i != list->entry_data.data_size - 1) *str_off += sprintf(str + *str_off, ","); - } - if (list->entry_data.type == MMDB_DATA_TYPE_MAP) { - *str_off += sprintf(str + *str_off, "}"); - } else { - *str_off += sprintf(str + *str_off, "]"); + if (i != list->entry_data.data_size - 1) + *str_off += sprintf(str + *str_off, ","); } + + *str_off += sprintf(str + *str_off, (list->entry_data.type == MMDB_DATA_TYPE_MAP) ? "}" : "]"); + return next; } + +int geoip_init(const char *directory) { + char buf[512]; + + memset(mmdbs, 0, sizeof(mmdbs)); + + if (directory[0] == 0) + return 0; + + DIR *geoip_dir; + if ((geoip_dir = opendir(directory)) == NULL) + return -1; + + struct dirent *entry; + int i = 0, status; + while ((entry = readdir(geoip_dir)) != NULL) { + if (strcmp(entry->d_name + strlen(entry->d_name) - 5, ".mmdb") != 0) + continue; + + if (i >= GEOIP_MAX_MMDB) { + critical("Unable to initialize geoip: Too many .mmdb files"); + closedir(geoip_dir); + return 1; + } + + sprintf(buf, "%s/%s", directory, entry->d_name); + if ((status = MMDB_open(buf, 0, &mmdbs[i])) != MMDB_SUCCESS) { + critical("Unable to initialize geoip: Unable to open .mmdb file: %s", MMDB_strerror(status)); + closedir(geoip_dir); + return 1; + } + i++; + } + + closedir(geoip_dir); + + if (i == 0) { + critical("Unable to initialize geoip: No .mmdb files found in %s", directory); + return 1; + } + + return 0; +} + +void geoip_free() { + for (int i = 0; i < GEOIP_MAX_MMDB && mmdbs[i].file_content != NULL; i++) { + MMDB_close(&mmdbs[i]); + } +} + +int geoip_lookup_country(struct sockaddr *addr, char *str) { + for (int i = 0; i < GEOIP_MAX_MMDB && mmdbs[i].file_content != NULL; i++) { + // lookup + int mmdb_res; + MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&mmdbs[i], addr, &mmdb_res); + if (mmdb_res != MMDB_SUCCESS) { + return -1; + } else if (!result.found_entry) { + continue; + } + + // get country iso code + MMDB_entry_data_s data; + int status; + if ((status = MMDB_get_value(&result.entry, &data, "country", "iso_code", NULL)) != MMDB_SUCCESS) { + if (status == MMDB_IO_ERROR) { + + } + return -1; + } + + // no, or invalid data + if (!data.has_data || data.type != MMDB_DATA_TYPE_UTF8_STRING) + continue; + + // return country code + sprintf(str, "%.2s", data.utf8_string); + return 0; + } + + // not found + return 1; +} + +int geoip_lookup_json(struct sockaddr *addr, char *json, long len) { + long str_off = 0; + for (int i = 0; i < GEOIP_MAX_MMDB && mmdbs[i].filename != NULL; i++) { + int mmdb_res; + MMDB_lookup_result_s result = MMDB_lookup_sockaddr(&mmdbs[i], addr, &mmdb_res); + if (mmdb_res != MMDB_SUCCESS) { + error("Unable to lookup geoip info: %s", MMDB_strerror(mmdb_res)); + continue; + } else if (!result.found_entry) { + continue; + } + + MMDB_entry_data_list_s *list; + if ((mmdb_res = MMDB_get_entry_data_list(&result.entry, &list)) != MMDB_SUCCESS) { + error("Unable to lookup geoip info: %s", MMDB_strerror(mmdb_res)); + continue; + } + + long prev = str_off; + if (str_off != 0) { + str_off--; + } + geoip_json(list, json, &str_off, len); + if (prev != 0) { + json[prev - 1] = ','; + } + + MMDB_free_entry_data_list(list); + } + + return 0; +} diff --git a/src/lib/geoip.h b/src/lib/geoip.h index 463dc5a..81eccaa 100644 --- a/src/lib/geoip.h +++ b/src/lib/geoip.h @@ -12,8 +12,13 @@ #include -#define GEOIP_MAX_SIZE 8192 +#define GEOIP_MAX_JSON_SIZE 8192 +#define GEOIP_MAX_MMDB 3 -MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len); +int geoip_init(const char *directory); + +void geoip_free(); + +int geoip_lookup_country(struct sockaddr *addr, char *str); #endif //SESIMOS_GEOIP_H diff --git a/src/lib/sock.h b/src/lib/sock.h index 40cb236..6ce0a01 100644 --- a/src/lib/sock.h +++ b/src/lib/sock.h @@ -11,10 +11,12 @@ #include #include +#include typedef struct { unsigned int enc:1; int socket; + struct sockaddr_in6 addr; SSL_CTX *ctx; SSL *ssl; long _last_ret; diff --git a/src/server.c b/src/server.c index 90275cd..347bed0 100644 --- a/src/server.c +++ b/src/server.c @@ -32,14 +32,12 @@ #include #include #include -#include volatile sig_atomic_t active = 1; const char *config_file; int sockets[NUM_SOCKETS]; pid_t children[MAX_CHILDREN]; -MMDB_s mmdbs[MAX_MMDB]; SSL_CTX *contexts[CONFIG_MAX_CERT_CONFIG]; static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { @@ -150,17 +148,13 @@ int main(int argc, const char *argv[]) { struct pollfd poll_fds[NUM_SOCKETS]; int ready_sockets_num; long client_num = 0; - char buf[1024]; int ret; int client_fd; sock client; - struct sockaddr_in6 client_addr; - unsigned int client_addr_len = sizeof(client_addr); memset(sockets, 0, sizeof(sockets)); memset(children, 0, sizeof(children)); - memset(mmdbs, 0, sizeof(mmdbs)); const struct sockaddr_in6 addresses[2] = { {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)}, @@ -240,37 +234,12 @@ int main(int argc, const char *argv[]) { signal(SIGINT, terminate); signal(SIGTERM, terminate); - if (geoip_dir[0] != 0) { - DIR *geoip = opendir(geoip_dir); - if (geoip == NULL) { - critical("Unable to open GeoIP dir"); - config_unload(); - return 1; + if ((ret = geoip_init(geoip_dir)) != 0) { + if (ret == -1) { + critical("Unable to initialize geoip"); } - struct dirent *dir; - int i = 0; - while ((dir = readdir(geoip)) != NULL) { - if (strcmp(dir->d_name + strlen(dir->d_name) - 5, ".mmdb") != 0) continue; - if (i >= MAX_MMDB) { - critical("Too many .mmdb files"); - config_unload(); - return 1; - } - sprintf(buf, "%s/%s", geoip_dir, dir->d_name); - ret = MMDB_open(buf, 0, &mmdbs[i]); - if (ret != MMDB_SUCCESS) { - critical("Unable to open .mmdb file: %s", MMDB_strerror(ret)); - config_unload(); - return 1; - } - i++; - } - if (i == 0) { - critical("No .mmdb files found in %s", geoip_dir); - config_unload(); - return 1; - } - closedir(geoip); + config_unload(); + return 1; } ret = cache_init(); @@ -343,7 +312,8 @@ int main(int argc, const char *argv[]) { for (int i = 0; i < NUM_SOCKETS; i++) { if (poll_fds[i].revents & POLLIN) { - client_fd = accept(sockets[i], (struct sockaddr *) &client_addr, &client_addr_len); + socklen_t addr_len = sizeof(client.addr); + client_fd = accept(sockets[i], (struct sockaddr *) &client.addr, &addr_len); if (client_fd < 0) { critical("Unable to accept connection"); continue; @@ -357,7 +327,7 @@ int main(int argc, const char *argv[]) { client.socket = client_fd; client.enc = (i == 1); - return client_handler(&client, client_num, &client_addr); + return client_handler(&client, client_num); } else if (pid > 0) { // parent client_num++; diff --git a/src/server.h b/src/server.h index 373a1ff..59d592f 100644 --- a/src/server.h +++ b/src/server.h @@ -15,7 +15,6 @@ #define NUM_SOCKETS 2 #define MAX_CHILDREN 1024 -#define MAX_MMDB 3 #define LISTEN_BACKLOG 16 #define REQ_PER_CONNECTION 200 #define CLIENT_TIMEOUT 3600 @@ -24,7 +23,6 @@ extern int sockets[NUM_SOCKETS]; extern pid_t children[MAX_CHILDREN]; -extern MMDB_s mmdbs[MAX_MMDB]; extern volatile sig_atomic_t server_keep_alive; extern struct timeval client_timeout;