读取纯真IP数据库 showip [zt]

关于 纯真IP数据库格式,详细见下面帖子:

纯真IP数据库格式详解 zt

程序说明:能够根据输入的IP,在 纯真IP数据库 中,搜索并且读取对应的 物理地址,还可以导出所有的IP段地址信息

函数部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#include “stdio.h”
#include “string.h”
#define QQWRY “QQWry.dat”
#define REDIRECT_MODE_1 0×01
#define REDIRECT_MODE_2 0×02
#define MAXBUF 255

/*unsigned long getValue( 获取文件中指定的16进制串的值,并返回
FILE *fp, 指定文件指针
unsigned long start, 指定文件偏移量
int length) 获取的16进制字符个数/长度
*/
unsigned long getValue(FILE *fp, unsigned long start, int length)
{
unsigned long variable=0;
long val[length],i;

fseek(fp,start,SEEK_SET);
for(i=0;i {
/*过滤高位,一次读取一个字符*/
val[i]=fgetc(fp)&0x000000FF;
}
for(i=length-1;i>=0;i–)
{
/*因为读取多个16进制字符,叠加*/
variable=variable*0×100+val[i];
}
return variable;
};

/*int getString( 获取文件中指定的字符串,返回字符串长度
FILE *fp, 指定文件指针
unsigned long start, 指定文件偏移量
char **string) 用来存放将读取字符串的字符串空间的首地址
*/
int getString(FILE *fp, unsigned long start, char **string)
{
unsigned long i=0;
char val;
fseek(fp,start,SEEK_SET);
/*读取字符串,直到遇到0×00为止*/
do
{
val=fgetc(fp);
/*依次放入用来存储的字符串空间中*/
*(*string+i)=val;
i++;
}while(val!=0×00);
/*返回字符串长度*/
return i;
};

/*void getAddress( 读取指定IP的国家位置和地域位置
FILE *fp, 指定文件指针
unsigned long start, 指定IP在索引中的文件偏移量
char **country, 用来存放国家位置的字符串空间的首地址
char **location) 用来存放地域位置的字符串空间的首地址
*/
void getAddress(FILE *fp, unsigned long start, char **country, char **location)
{
unsigned long redirect_address,counrty_address,location_address;
char val;

start+=4;
fseek(fp,start,SEEK_SET);
/*读取首地址的值*/
val=(fgetc(fp)&0x000000FF);

if(val==REDIRECT_MODE_1)
{
/*重定向1类型的*/
redirect_address=getValue(fp,start+1,3);
fseek(fp,redirect_address,SEEK_SET);
/*混合类型,重定向1类型进入后遇到重定向2类型
读取重定向后的内容,并设置地域位置的文件偏移量*/
if((fgetc(fp)&0x000000FF)==REDIRECT_MODE_2)
{
counrty_address=getValue(fp,redirect_address+1,3);
location_address=redirect_address+4;
getString(fp,counrty_address,country);
}
/*读取重定向1后的内容,并设置地域位置的文件偏移量*/
else
{
counrty_address=redirect_address;
location_address=redirect_address+getString(fp,counrty_address,country);
}
}
/*重定向2类型的*/
else if(val==REDIRECT_MODE_2)
{
counrty_address=getValue(fp,start+1,3);
location_address=start+4;
getString(fp,counrty_address,country);
}
else
{
counrty_address=start;
location_address=counrty_address+getString(fp,counrty_address,country);
}

/*读取地域位置*/
fseek(fp,location_address,SEEK_SET);
if((fgetc(fp)&0x000000FF)==REDIRECT_MODE_2||(fgetc(fp)&0x000000FF)==REDIRECT_MODE_1)
{
location_address=getValue(fp,location_address+1,3);
}
getString(fp,location_address,location);

return;
};

/*void getHead( 读取索引部分的范围(在文件头中,最先的2个8位16进制)
FILE *fp, 指定文件指针
unsigned long *start, 文件偏移量,索引的起止位置
unsigned long *end) 文件偏移量,索引的结束位置
*/
void getHead(FILE *fp,unsigned long *start,unsigned long *end)
{
/*索引的起止位置的文件偏移量,存储在文件头中的前8个16进制中
设置偏移量为0,读取4个字符*/
*start=getValue(fp,0L,4);
/*索引的结束位置的文件偏移量,存储在文件头中的第8个到第15个的16进制中
设置偏移量为4个字符,再读取4个字符*/
*end=getValue(fp,4L,4);
};

/*unsigned long searchIP( 搜索指定IP在索引区的位置,采用二分查找法;
返回IP在索引区域的文件偏移量
一条索引记录的结果是,前4个16进制表示起始IP地址
后面3个16进制,表示该起始IP在IP信息段中的位置,文件偏移量
FILE *fp,
unsigned long index_start, 索引起始位置的文件偏移量
unsigned long index_end, 索引结束位置的文件偏移量
unsigned long ip) 关键字,要索引的IP
*/
unsigned long searchIP(FILE *fp, unsigned long index_start,

unsigned long index_end, unsigned long ip)
{
unsigned long index_current,index_top,index_bottom;
unsigned long record;
index_bottom=index_start;
index_top=index_end;
/*此处的7,是因为一条索引记录的长度是7*/
index_current=((index_top-index_bottom)/7/2)*7+index_bottom;
/*二分查找法*/
do{
record=getValue(fp,index_current,4);
if(record>ip)
{
index_top=index_current;
index_current=((index_top-index_bottom)/14)*7+index_bottom;
}
else
{
index_bottom=index_current;
index_current=((index_top-index_bottom)/14)*7+index_bottom;
}
}while(index_bottom /*返回关键字IP在索引区域的文件偏移量*/
return index_current;
};

/*unsigned long putAll( 导出所有IP信息到文件文件中,函数返回导出总条数
FILE *fp,
FILE *out, 导出的文件指针,必须拥有写权限
unsigned long index_start, 索引区域的起始文件偏移量
unsigned long index_end) 索引区域的结束文件偏移量
*/
unsigned long putAll(FILE *fp, FILE *out, unsigned long index_start, unsigned long index_end)
{
unsigned long i,count=0;
unsigned long start_ip,end_ip;
char *country;
char *location;

country=(char*)malloc(255);
location=(char*)malloc(255);

/*此处的7,是因为一条索引记录的长度是7*/
for(i=index_start;i {
/*获取IP段的起始IP和结束IP,

起始IP为索引部分的前4位16进制
结束IP在IP信息部分的前4位16进制中,靠索引部分指定的偏移量找寻*/
start_ip=getValue(fp,i,4);
end_ip=getValue(fp,getValue(fp,i+4,3),4);
/*导出IP信息,格式是
起始IPt结束IPt国家位置t地域位置n*/
fprintf(out,”%d.%d.%d.%d”,(start_ip&0xFF000000)>>0×18,

(start_ip&0x00FF0000)>>0×10,(start_ip&0x0000FF00)>>0×8,start_ip&0x000000FF);
fprintf(out,”t”);
fprintf(out,”%d.%d.%d.%d”,(end_ip&0xFF000000)>>0×18,

(end_ip&0x00FF0000)>>0×10,(end_ip&0x0000FF00)>>0×8,end_ip&0x000000FF);
getAddress(fp,getValue(fp,i+4,3),&country,&location);
fprintf(out,”t%st%sn”,country,location);
count++;
}
/*返回导出总条数*/
return count;
};

/*判断一个字符是否为数字字符,
如果是,返回0
如果不是,返回1*/
int beNumber(char c)
{
if(c>=’0′&&c< ='9')
return 0;
else
return 1;
};

/*函数的参数是一个存储着IP地址的字符串首地址
返回该IP的16进制代码
如果输入的IP地址有错误,函数将返回0*/
unsigned long getIP(char *ip_addr)
{
unsigned long ip=0;
int i,j=0;
/*依次读取字符串中的各个字符*/
for(i=0;i {
/*如果是IP地址间隔的‘.’符号
把当前读取到的IP字段的值,存入ip变量中
(注意,ip为叠加时,乘以16进制的0×100)
并清除临时变量的值*/
if(*(ip_addr+i)==’.')
{
ip=ip*0×100+j;
j=0;
}
/*往临时变量中写入当前读取到的IP字段中的字符值
叠加乘以10,因为输入的IP地址是10进制*/
else
{
/*判断,如果输入的IP地址不规范,不是10进制字符
函数将返回0*/
if(beNumber(*(ip_addr+i))==0)
j=j*10+*(ip_addr+i)-’0′;
else
return 0;
}
}
/*IP字段有4个,但是‘.’只有3个,叠加第四个字段值*/
ip=ip*0×100+j;
return ip;
};

/*显示logo信息*/
void logo(void)
{
printf(“=============================================================================n”);
printf(“— Get the IP info.s from QQWry.dat v0.1 by dorainm dorainm@gmail.com —n”);
printf(“=============================================================================n”);

};

/*显示程序语法*/
void usage(char *app_name)
{
printf(“nUsage : %s [options]n”,app_name);
printf(“options:n”);
printf(” -a
Search and display the Informations by Location Address.(*)n”);
printf(” -i Search and display the Informations by IP Address.n”);
printf(” -o Output all the informations to a text file.n”);
printf(” -local Display the localhost IP’s informations.(*)n”);
printf(” -updata Update the QQWry.dat from the Internet.(*)nn”);
printf(“ps: the optionss marked (*) are incompleted.n”);
};
/*显示结束信息*/
void showend(void)
{
printf(“nnThe command completed successfully.nn”);
};

main函数部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/*主函数*/
int main(int argc, char *argv[])
{
FILE *fp; /*打开QQWry.dat的文件指针*/
unsigned long index_start,index_end,current; /*索引部分的起始位置的文件偏移量
索引部分的结束位置的文件偏移量
待搜索IP地址的索引条目的文件偏移量*/
char *country; /*国家位置*/
char *location; /*地域位置*/
country=(char*)malloc(MAXBUF);
location=(char*)malloc(MAXBUF);
logo();
if(argc<3)
{
usage(argv[0]);
showend();
return 1;
}

/*打开QQWry.dat文件*/
if((fp=fopen(QQWRY,”rb”))==NULL)
{
printf(“[-] Error : Can not open the file %s.n”,QQWRY);
showend();
return 2;
}
else
printf(“[+] Open the file [ %s ] successfully.n”,QQWRY);

/*显示QQWry.dat文件信息*/
getHead(fp,&index_start,&index_end);
getAddress(fp,getValue(fp,index_end+4,3),&country,&location);
printf(“[+] Version of QQWry.dat : [ %s %s ]n”,country,location);
printf(“[+] Index Location [ 0x%X - 0x%X ].n”,index_start,index_end);

/*判断第一个参数的值*/
if((strncmp(argv[1],”-i”,2)==0)||(strncmp(argv[1],”-I”,2)==0))
{
/*-i参数,搜索IP*/
unsigned long ip;

ip=getIP(argv[2]);
if(ip==0)
{
printf(“[-] Error : the IP Address inputed.n”);
showend();
return 3;
}

/*搜索IP在索引区域的条目的偏移量*/
current=searchIP(fp,index_start,index_end,ip);
printf(“[+] Address of index for [ %X ] is %Xn”,ip,current);

/*获取该IP对因的国家地址和地域地址*/
getAddress(fp,getValue(fp,current+4,3),&country,&location);
printf(“[+] Get the location for the IP address.n”);
printf(“[+] [ IP Address ] %d.%d.%d.%dn”,(ip&0xFF000000)>>0×18,(ip&0x00FF0000)>>0×10,(ip&0x0000FF00)>>0×8,ip&0x000000FF);
printf(“[+] [ Location ] %s %sn”,country,location);
}
else if((strncmp(argv[1],”-o”,2)==0)||(strncmp(argv[1],”-O”,2)==0))
{
/*-o参数,解压缩数据库,导出IP信息到文本文件*/
FILE *out;
unsigned long num;
if((out=fopen(argv[2],”w”))==NULL)
{
printf(“[-] Error create the output text file [ %s ].n”,”out.txt”);
showend();
}
else
{
printf(“[+] Create the output text file [ %s ] successfully.n”,”out.txt”);
}

/*导出IP条目信息*/
printf(“[+] Outputing the informations …”);
num=putAll(fp,out,index_start,index_end);
printf(“Finished.n”);
fclose(out);
/*显示导出条目的数量*/
printf(“[+] The Total items number is [ %d ].”,num);
}
/*关闭文件指针,释放变量空间,结束程序*/
fclose(fp);
free(country);
free(location);
showend();
return 0;
}

使用语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
==============
========================================================================
--- Get the IP info.s from QQWry.dat v0.1 by dorainm dorainm@gmail.com ---
========================================================================

Usage : showip [options]
options:
-a <address> Search and display the Informations by Location Address.(*)
-i <IP> Search and display the Informations by IP Address.
-o <FILE> Output all the informations to a text file.
-local Display the localhost IP's informations.(*)
-updata Update the QQWry.dat from the Internet.(*)

ps: the optionss marked (*) are incompleted.

The command completed successfully.

搜索IP:

showip -i 222.19.211.254

========================================================================
--- Get the IP info.s from QQWry.dat v0.1 by dorainm dorainm@gmail.com ---
========================================================================
[+] Open the file [ QQWry.dat ] successfully.
[+] Version of QQWry.dat : [ 纯真网络 2006年3月5日IP数据 ]
[+] Index Location [ 0x37A265 - 0x535EB1 ].
[+] Address of index for [ DE13D3FE ] is 51BB44
[+] Get the location for the IP address.
[+] [ IP Address ] 222.19.211.254
[+] [ Location ] 云南大学 国家示范性软件学院

The command completed successfully.

导出所有IP信息,语法是 showip -o out.txt

其余功能有待完成

程序在 gcc3.3.1 中编译通过

如果移植到 microsoft windows 下,使用 VC 编译器,

可能需要把main函数中所有的变量申明语句移动到main函数的 logo(); 语句前面

(遥远记得以前,我在win2000下用VC++6.0,好像需要先申请再执行语句
不然编译没法通过…)

注:使用malloc要包含必要的头文件stdlib.h,在gcc4下编译出现warning: incompatible implicit declaration of built-in function ‘malloc’