2012-02-28 98 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所以檢查內存時/直接字節,你會看到在「相反的順序」字節。