#include #include #include #include #include #include #include #include "ip_to_geo.h" #include "ip_data.c" static const uint8_t* ip_to_geo_rec(uint32_t ipv4, unsigned level, const ip_level* root) { unsigned cur_average; const ip_level* cur_ip = root; unsigned cur_addr = (ipv4 >> (level*8)) & 0xFF; // Optimistic search if (cur_addr && level != 2) { cur_average = cur_addr >> root->average; while (cur_average-- && cur_ip->next) cur_ip = cur_ip->next; } #define IP_TEST \ do { \ if (cur_addr >= cur_ip->start && cur_addr <= cur_ip->end) \ { \ if (cur_ip->childs) \ return ip_to_geo_rec(ipv4, level-1, cur_ip->childs); \ else \ return &cur_ip->code; \ } \ } while (0) if (cur_addr < cur_ip->start) { for (cur_ip = cur_ip->prev; cur_ip; cur_ip = cur_ip->prev) IP_TEST; } else if (cur_addr > cur_ip->end) { for (cur_ip = cur_ip->next; cur_ip; cur_ip = cur_ip->next) IP_TEST; } else IP_TEST; return NULL; } const uint8_t* ip_to_geo(uint32_t ipv4) { const ip_level* first_level = s_root_ip[ipv4 >> 24]; if (!first_level) return NULL; return ip_to_geo_rec(ipv4, 2, first_level); } const uint8_t* get_country_code(const uint8_t* idx) { if (!idx || *idx >= sizeof(country_codes)/sizeof(country_codes[0])) return NULL; return country_codes[*idx]; } /* int strip_to_int(char* strip_, uint32_t* ip) */ /* { */ /* char* saveptr = NULL; */ /* char* cur; */ /* int i; */ /* char* strip = strdup(strip_); */ /* *ip = 0; */ /* for(i=3; i>=0; i--) */ /* { */ /* cur = strtok_r(strip, ".", &saveptr); */ /* if (!cur) goto end; */ /* *ip += atoi(cur) << (8*i); */ /* strip = NULL; */ /* } */ /* cur = strtok_r(strip, ".", &saveptr); */ /* end: */ /* free(strip); */ /* return (cur)?-1:0; */ /* } */ int interactive(struct gengetopt_args_info* params) { const uint8_t* cc; int ret; ret = inet_addr(params->ip_arg); if (ret == INADDR_NONE) { if (!params->quiet_flag) fprintf(stderr, "Invalid IP %s\n", params->ip_arg); return -1; } cc = ip_to_geo((uint32_t)ret); if (params->quiet_flag) printf("%s\n", (cc)?(char*)get_country_code(cc):""); else printf("IP %s : %s\n", params->ip_arg, (cc)?(char*)get_country_code(cc):""); return 0; } int main(int argc, char** argv) { int ret; struct gengetopt_args_info params; ret = cmdline_parser (argc, argv, ¶ms); if (ret) return ret; //self_test(); if (params.ip_given) return interactive(¶ms); else if (params.daemon_flag) return daemonize(¶ms); else cmdline_parser_print_help(); return 0; }