/*
* Copyright 2008,2009 Surf Chen <http://www.surfchen.org>
*
*
* This source code is under the terms of the
* GNU Lesser General Public License.
* see <http://www.gnu.org/licenses/lgpl.txt>
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#define BE_32(x) ((((uint8_t*)(x))[0]<<24) |/
(((uint8_t*)(x))[1]<<16) |/
(((uint8_t*)(x))[2]<<8) |/
((uint8_t*)(x))[3])
#define LE_32(x) ((((uint8_t*)(x))[3]<<24) |/
(((uint8_t*)(x))[2]<<16) |/
(((uint8_t*)(x))[1]<<8) |/
((uint8_t*)(x))[0])
#define LE_24(x) ((((uint8_t*)(x))[2]<<16) |/
(((uint8_t*)(x))[1]<<8) |/
((uint8_t*)(x))[0])
#define REDIRECT_TYPE_1 0x01
#define REDIRECT_TYPE_2 0x02
static uint32_t ip2long(const char *ip) {
uint32_t ip_long=0;
uint8_t ip_len=strlen(ip);
uint32_t ip_sec=0;
int8_t ip_level=3;
uint8_t i,n;
for (i=0;i<=ip_len;i++) {
if (i!=ip_len && ip[i]!='.' && ip[i]<48 || ip[i]>57) {
continue;
}
if (ip[i]=='.' || i==ip_len) {
/*too many .*/
if (ip_level==-1) {
return 0;
}
for (n=0;n<ip_level;n++) {
ip_sec*=256;
}
ip_long+=ip_sec;
if (i==ip_len) {
break;
}
ip_level--;
ip_sec=0;
} else {
/*char '0' == int 48*/
ip_sec=ip_sec*10+(ip[i]-48);
}
}
return ip_long;
}
static uint32_t search_index(const uint32_t ip,FILE *qqwry_file) {
uint32_t index_ip;
unsigned char head[8];
unsigned char index_bytes[7];
fread(head,8,1,qqwry_file);
uint32_t index_start,index_end,index_mid;
index_start = (uint32_t)LE_32(&head[0]);
index_end = (uint32_t)LE_32(&head[4]);
while (1) {
if ((index_end-index_start)==7) {
break;
}
//printf("index:%u:%u/n",index_start,index_end);
index_mid=index_end/7 - index_start/7;
if (index_mid%2==0) {
index_mid=index_mid/2;
} else {
index_mid=(index_mid+1)/2;
}
index_mid=index_start+index_mid*7;
fseek(qqwry_file,index_mid,SEEK_SET);
fread(index_bytes,7,1,qqwry_file);
index_ip=(uint32_t)LE_32(&index_bytes[0]);
if (index_ip==ip) {
break;
} else if (index_ip<ip) {
index_start=index_mid;
} else {
index_end=index_mid;
}
}
if (index_ip>ip) {
fseek(qqwry_file,index_start,SEEK_SET);
fread(index_bytes,7,1,qqwry_file);
}
return (uint32_t)LE_24(&index_bytes[4]);
}
static int readOrJumpRead(char *location,FILE *qqwry_file,const uint32_t data_index) {
unsigned char c;
unsigned char data_index_bytes[3];
uint32_t jump_data_index=0;
if (data_index) {
fseek(qqwry_file,data_index,SEEK_SET);
}
c=fgetc(qqwry_file);
switch (c) {
case REDIRECT_TYPE_2:
case REDIRECT_TYPE_1:
fread(data_index_bytes,3,1,qqwry_file);
jump_data_index=LE_24(&data_index_bytes[0]);
fseek(qqwry_file,jump_data_index,SEEK_SET);
break;
default:
location[strlen(location)]=c;
}
if (c) {
while (c=fgetc(qqwry_file)) {
location[strlen(location)]=c;
}
}
return 1;
}
static int is_cz88(const char *str) {
int i;
int l=strlen(str)-7;
for (i=0;i<l;i++) {
if (str[i]=='C'
&& str[i+1]=='Z'
&& str[i+2]=='8'
&& str[i+3]=='8'
&& str[i+4]=='.'
&& str[i+5]=='N'
&& str[i+6]=='E'
&& str[i+7]=='T'
) {
return 1;
}
}
return 0;
}
int qqwry_get_location_by_long(char *addr1,char *addr2,const uint32_t ip,FILE *qqwry_file) {
//printf("%u",ip);
unsigned char data_index_bytes[3];
uint32_t data_index;
uint32_t addr2_offset;
unsigned char c;
if (!qqwry_file) {
return 0;
}
fseek(qqwry_file,0,SEEK_SET);
data_index = search_index(ip,qqwry_file);
//fprintf(stderr,"index:%u:%u/n",ftell(qqwry_file),data_index);
/*ip 4 + mode byte 1*/
fseek(qqwry_file,data_index+4,SEEK_SET);
c=fgetc(qqwry_file);
if (c==REDIRECT_TYPE_1) {
fread(data_index_bytes,3,1,qqwry_file);
data_index=LE_24(&data_index_bytes[0]);
fseek(qqwry_file,data_index,SEEK_SET);
c=fgetc(qqwry_file);
/*制造一个假的4bytes位移,抵充ip*/
data_index-=4;
}
if (c==REDIRECT_TYPE_2) {
/*
* ip 4 + mode byte 1 + addr1 offset 3
* 这里ip的4个bytes不一定是真的,有可能是上一条注释里提到的情况
*/
addr2_offset=data_index+8;
fread(data_index_bytes,3,1,qqwry_file);
data_index=LE_24(&data_index_bytes[0]);
fseek(qqwry_file,data_index,SEEK_SET);
while (c=fgetc(qqwry_file)) {
addr1[strlen(addr1)]=c;
}
readOrJumpRead(addr2,qqwry_file,addr2_offset);
} else {
addr1[strlen(addr1)]=c;
while (c=fgetc(qqwry_file)) {
addr1[strlen(addr1)]=c;
}
readOrJumpRead(addr2,qqwry_file,0);
}
if (is_cz88(addr1)) {
addr1[0]='/0';
}
if (is_cz88(addr2)) {
addr2[0]='/0';
}
return 1;
}
int qqwry_get_location(char *addr1,char *addr2,const char *ip,FILE *qqwry_file) {
return qqwry_get_location_by_long(addr1,addr2,ip2long(ip),qqwry_file);
}
int main()
{
FILE *fp;
fp = fopen("qqwry.dat", "r");
if(!fp)
{
printf("open error/n");
}
char a1[256];
char a2[256];
qqwry_get_location(a1,a2,"61.152.108.1",fp);
printf("%s %s/n",a1,a2);
fclose(fp);
return 0;
}
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "/usr/local/mysql/include/mysql.h"
#include "sql.h"
#include "uni.h"
int in_aton(const char *str)
{
unsigned long l;
unsigned int val;
int i;
l = 0;
for (i = 0; i < 4; i++) {
l <<= 8;
if (*str != '/0') {
val = 0;
while (*str != '/0' && *str != '.') {
val *= 10;
val += *str - '0';
str++;
}
l |= val;
if (*str != '/0')
str++;
}
}
return l;
// return(htonl(l));
}
unsigned long ip_str2dec(char *ip_in) {
char *ip = strdup(ip_in);
unsigned long ip_dec = 0;
return in_aton(char *ip_in);
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;
}
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;
}
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;
}
/*****************************************/
typedef struct ip_info {
char ip[16];
char *country;
char *area;
char start_ip[16]; // For debug
char end_ip[16]; // For debug
char *mode; // For debug
} IP_INFO;
unsigned long get_long_addr3(unsigned char *buf);
char* get_string_by_addr(long addr, FILE *fp);
IP_INFO *get_ip_by_index(unsigned long index_addr, FILE *fp);
char* get_area(unsigned char* buffer, FILE *fp);
void print_iptable(FILE *fp);
unsigned long search_ip(char *ip_in, FILE *fp);
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(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(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(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;
char query[1024]={0};
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);
/*
if(strstr(ipinfo->area,"CZ88"))
{
ipinfo->area="0";
}
*/
sprintf(query,"insert into IpArea(ia_from,ia_to,ia_from1,ia_to1,ia_country,ia_area)values('%s','%s',%d,%d,'%s','%s')",ipinfo->start_ip, ipinfo->end_ip,in_aton(ipinfo->start_ip),in_aton(ipinfo->end_ip), ipinfo->country, ipinfo->area);
//printf("%s/n",query);
//if(!strstr(ipinfo->area,"CZ88")&&!strstr(ipinfo->area,"CZ88")&&!strstr(ipinfo->area,"美国"))
if(strstr(ipinfo->country,"市"))
while(AddSql(query,strlen(query))==0)
{
sleep(30);
printf("is full/n");
}
/*
mysql_query( mysql,"set names gbk");
mysql_query( mysql ,query);
*/
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;
}
/* hi return index_start + hi * 7;*/
}
int main(int argc, char **argv)
{
/*
int ret;
int i;
pthread_t thread[1000];
for(i=0;i<40;i++)
{
ret=pthread_create(&thread[i],NULL,(void*)cmdpool,NULL);
if(ret!=0)
{
printf("Create cmdpool thread Failed/n ");
}
sleep(2);
}
*/
FILE *fp;
fp = fopen("qqwry.dat", "r");
if(!fp)
{
printf("open error/n");
}
//print_iptable(fp);
printf("%s/n",argv[1]);
IP_INFO *ipinfo = get_ip_by_index(search_ip(argv[1], fp), fp);
printf("%s, %s/n", ipinfo->country, ipinfo->area);
free(ipinfo);
/* print_iptable(fp); */
fclose(fp);
//while(1) sleep(1);
return 0;
}