/********************************************** * IP Search client for QQWry.Dat * * by taopku@gmail.com * *********************************************/
//#include
//#include
//#include
#include <iostream> #include <string> #include "IPFinder.h"
/* function definitions */ unsigned long get_long_addr3(unsigned char *buf); char* get_string_by_addr(long addr, FILE *fp); char* get_area(unsigned char* buffer, FILE *fp);
/* implementation */ static unsigned long ip_str2dec(char *ip_in) { char *ip = strdup(ip_in); unsigned long ip_dec = 0;
char *p; int i; for(i=0; i<3; i++) { p = strrchr(ip, '.'); ip_dec |= atoi(p+1) << (8*i); *p = '\0'; } ip_dec |= atoi(ip) << (8*i); free(ip); return ip_dec; }
/* static unsigned long ip_arr2dec(char **ip_arr) { unsigned long ip_dec = 0; int i; for(i=0; i<4; i++) { ip_dec |= atoi(ip_arr[i]) << (8*(3-i)); } return ip_dec; } */
static unsigned long ip_arr2dec_r(unsigned char *ip_arr) { unsigned long ip_dec = 0; int i; for(i=0; i<4; i++) { ip_dec |= ip_arr[i] << (8*i); } return ip_dec; }
unsigned long get_long_addr3(unsigned char *buf) { unsigned long addr = 0; /* addr = buf[0] + buf[1]*256 + buf[2]*65536; */ addr = buf[0] | buf[1] << 8 | buf[2] << 16; return addr; }
char* get_string_by_addr(long addr, FILE *fp) { unsigned char buffer[1024]; fseek(fp, addr, SEEK_SET); fread(buffer, 1024, 1, fp); return strdup((char*)buffer); }
IP_INFO *get_ip_by_index(unsigned long index_addr, FILE *fp) { IP_INFO *ipinfo = (IP_INFO *)malloc(sizeof(IP_INFO));
unsigned char ip[4]; unsigned char addr[3]; unsigned long record_addr = 0;
fseek(fp, index_addr, SEEK_SET); fread(ip, 4, 1, fp); fread(addr, 3, 1, fp); record_addr = get_long_addr3(addr); sprintf(ipinfo->start_ip, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
unsigned char buffer[1024]; unsigned long country_addr;
fseek(fp, record_addr, SEEK_SET); fread(ip, 4, 1, fp); fread(buffer, 1024, 1, fp); sprintf(ipinfo->end_ip, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
if (buffer[0] == 1) { country_addr = get_long_addr3(buffer + 1); fseek(fp, country_addr, SEEK_SET); fread(buffer, 1024, 1, fp);
if (buffer[0] == 2) { ipinfo->country = get_string_by_addr(get_long_addr3(buffer + 1), fp); ipinfo->area = get_area(buffer + 4, fp); ipinfo->mode = "1 + 2"; } else { ipinfo->country = get_string_by_addr(country_addr, fp); ipinfo->area = get_area(buffer + strlen(ipinfo->country) + 1, fp); ipinfo->mode = "1 + D"; }
} else if (buffer[0] == 2) { ipinfo->country = get_string_by_addr(get_long_addr3(buffer + 1), fp); ipinfo->area = get_area(buffer + 4, fp); ipinfo->mode = "2 + D";
} else { ipinfo->country = strdup((char*)buffer); ipinfo->area = get_area(buffer + strlen(ipinfo->country) + 1, fp); ipinfo->mode = "D + D"; } return ipinfo; }
char* get_area(unsigned char* buffer, FILE *fp) { if (buffer[0] == 1 || buffer[0] == 2) { return get_string_by_addr(get_long_addr3(buffer + 1), fp); } else { return strdup((char*)buffer); } }
void print_iptable(FILE *fp) { unsigned long index_start, index_end; fseek(fp, 0, SEEK_SET); fread(&index_start, 4, 1, fp); fread(&index_end, 4, 1, fp); /* printf("%lu %lu\n", index_start, index_end); */
unsigned long i; IP_INFO *ipinfo;
for(i=index_start; i<=index_end; i+=7) { ipinfo = get_ip_by_index(i, fp); printf("%s - %s\n%s, %s\n", ipinfo->start_ip, ipinfo->end_ip, ipinfo->country, ipinfo->area);
free(ipinfo); } }
unsigned long search_ip(char *ip_in, FILE *fp) { unsigned long index_start, index_end, lo, hi, i, ip_i, ip_dest; unsigned char ip_arr[4];
fseek(fp, 0, SEEK_SET); fread(&index_start, 4, 1, fp); fread(&index_end, 4, 1, fp);
lo = 0; hi = (index_end - index_start) / 7; ip_dest = ip_str2dec(ip_in);
while(lo <= hi) { i = (lo + hi) / 2;
fseek(fp, index_start + i * 7, SEEK_SET); fread(ip_arr, 4, 1, fp); ip_i = ip_arr2dec_r(ip_arr); if (ip_i == ip_dest) return index_start + i * 7; else if (ip_i < ip_dest) lo = i + 1; else hi = i - 1; }
return index_start + hi * 7; }
#ifdef _TEST int main(int argc, char **argv) { FILE *fp; int index = 0; IP_INFO *ipinfo = NULL;
if (argc < 3) { printf("usage: %s path_to_QQWry.Dat ip_list\n", argv[0]); return -1; }
fp = fopen(argv[1], "r"); if (fp == NULL) return -1;
/*print_iptable(fp);*/
for (index = 0; index < argc-2; index++) { ipinfo = get_ip_by_index(search_ip(argv[index+2], fp), fp); printf("%s: %s, %s\n", argv[index+2], ipinfo->country, ipinfo->area); free(ipinfo); }
fclose(fp); return EXIT_SUCCESS; } #endif
|