2012-02-28 77 views
3

我appoligize,但是新来C++。在我们的组织,我们收到每日黑名单(更大,因为这仅仅是一个片断)的格式如下:将IP列表到主机/网络地址列表

172.44.12.0

198.168.1.5

10.10.0.0

192.168 .78.6

192.168.22.22

111.111.0.0

222.222.0.0

12.12.12.12

当运行该程序的代码编译后我得到:

我使用C++在Linux/Unix环境。

到目前为止,我只是吐出来确保我的格式正确。请善良,我确信这被认为是草率的编程,我是一个noob。

该文件的名称是blacklist.txt,其中包含目前上面列出的IP。我只使用cout来确保我的变量被正确定义。

#include <iostream> 
#include <vector> 
#include <fstream> 
#include <string> 
#include <netinet/in.h> 
#include <stdint.h> 
#include <arpa/inet.h> 

using namespace std; 

bool is_match(std::string &hay_stack, std::string &srcip) { 
in_addr_t _ip = inet_addr(hay_stack.c_str()); 
in_addr_t _IP = inet_addr(srcip.c_str()); 
_ip = ntohl(_ip); 
_IP = ntohl(_IP); 
uint32_t mask=(_ip & 0x00ffffff == 0) ? 0xff000000 : 
(_ip & 0x0000ffff == 0 ? 0xffff0000 : 0); 
return ((_ip & mask) == (_IP & mask)); 
} 

int main() 
{ 
vector<std::string> lines; 
lines.reserve(5000); //Assuming that the file to read can have max 5K lines 

string fileName("blacklist.txt"); 

ifstream file; 
file.open(fileName.c_str()); 

if(!file.is_open()) 
{ 
cerr<<"Error opening file : "<<fileName.c_str()<<endl; 
return -1; 
} 

//Read the lines and store it in the vector 
string line; 
while(getline(file,line)) 
{ 
lines.push_back(line); 
} 

file.close(); 


//Dump all the lines in output 
for(unsigned int i = 0; i < lines.size(); i++) 
{ 
string h = lines[i]; 
string mi = "10.10.10.10"; 
cout<<is_match(h,mi)<<endl; 
} 

return 0; 
} 

我期待的输出为10.10.10.10 10.10.0.0(和某种这里子网掩码)

任何帮助是巨大的。

+1

你能否将IP表示为'unsigned int'(长度为32b)?比它会:'if((ip&mask)== subnet)':) – Vyktor 2012-02-28 17:53:55

+0

我appoligize也许这可能是我缺乏C + +知识,但没有给出的掩码。 (ip&mask)是否假设你有面具? – SP3CH8TR 2012-02-28 17:57:24

+0

@ SP3CH8TR是的。请注意,您可以轻松地将/ 16或/ 8或/任何内容转换为掩码,因为它只是说明设置了多少个前导位。例如/ 16是掩码0xFFFF0000。如果你不知道它是一个/ 16或一个/ 8或一个/ 31等,但你有一个问题。 – nos 2012-02-28 18:02:08

回答

1
#include <netinet/in.h> 
#include <stdint.h> 
#include <string> 
#include <arpa/inet.h> 

bool is_match(std::string &hay_ip, std::string &needle_ip) { 
    in_addr_t _ip = inet_addr(hay_ip.c_str()); 
    in_addr_t _IP = inet_addr(needle_ip.c_str()); 
    _ip = ntohl(_ip); 
    _IP = ntohl(_IP); 
    uint32_t mask=(_ip & 0x0000ffff == 0) ? 0xffff0000 : 
       (_ip & 0x000000ff == 0 ? 0xffffff00 : 0xffffffff); 
    return ((_ip & mask) == (_IP & mask)); 
} 
+0

因此,我会先将文件读入内存,然后为每种语句执行一个语句,将每个ip放入一个向量中,并与某个变量的IP进行某种比较(我相信IP是一个字符串变量现在)看看是否有匹配? – SP3CH8TR 2012-02-28 18:56:00

+0

@ SP3CH8TR,更新了答案。处理前不需要读取所有地址。 – perreal 2012-02-28 19:08:40

+0

我在编辑帖子以包含示例代码。我理解你的例子中发生了什么,现在我想看看我适合在哪里。 – SP3CH8TR 2012-02-28 20:06:00

3

的IPv4] 1由4个字节,因此它可以(并且通常是)表示为unsigned int或相当Uint32(32位长数/ 4字节),例如:

decimal:  172.16.254.1 
hexadecimal: ac 10 fe 01 
binary:  10101100 0001000 11111110 00000001 

子网掩模在/XX形式指定从开始多少比特(二进制的)应该有在掩模,例如:

/24: 11111111 11111111 11111111 00000000 > 0xffffff00 
/16: 11111111 11111111 00000000 00000000 > 0xffff0000 

ñ嗷嗷您将使用binary ANDIP & Mask(用C/C++ &表示),它会给你这样的输出:

IP:  172.16.254.1 | 0xac10fe01 | 10101100 0001000 11111110 00000001 & 
Mask: 255.255.255.0 | 0xffffff00 | 11111111 1111111 11111111 00000000 = 
Result: 172.16.254.0 | 0xac10fe00 | 10101100 0001000 11111110 00000000 

,你现在可以表示为Uint32子网比较,一开始你会产生面膜:

uint32 get_mask(const int mask_length = 24){ // for /24 mask notation 
    if(mask_length > 31){ 
     return 0xffffffff; 
    } 
    return (1 << (mask_length + 1)) - 1; 
    // << 25 will shift 1 to 25th place, -1 will than generate 24 ones in row 
    // this wouldn't work with 32 because you would shift 1 outside 32b int 
} 

,然后只需用&==

if((ip&get_mask(24)) == subnet){ 
// if((ip&0xffffff00) == subnet){ 
// if((ip&get_mask(subnet.mask.length)) == subnet){ 
    // match 
} 

注意,x86体系结构使用little-endian所以检查内存时/直接字节,你会看到在“相反的顺序”字节。