2012-03-02 204 views
3

在我們的組織,我們收到每日黑名單(更大,因爲這僅僅是一個片斷)的格式如下:意外的結果

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環境。

到目前爲止,我只是吐出來確保我的格式正確。

該文件的名稱是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(和某種這裏子網掩碼)

+0

我猜「面具」始終評估爲零。 – 2012-03-02 20:23:53

+0

您有特定的問題嗎?或者我們應該爲您解決這個問題? – PlasmaHH 2012-03-02 20:24:12

+0

即使你沒有提供任何問題,我還是會爲+1做準備:提供一個完整的程序(http://sscce.org),並使用正確的方式讀取輸入的行。 – 2012-03-02 20:28:52

回答

4

這是你的問題是:

uint32_t mask=(_ip & 0x00ffffff == 0) ? 0xff000000 : 
(_ip & 0x0000ffff == 0 ? 0xffff0000 : 0); 
return ((_ip & mask) == (_IP & mask)); 

如果_ip是形式x.0.0.0,它只有在_IP, 比較X和如果_ip是形式xy0.0,它只在_IP中比較x和y, 這很好。

但是,如果_ip不是這兩種格式之一,則將掩碼設置爲0 < - 這是問題所在。 (_IP & 0),結果始終爲0。 這意味着您始終在a.b.c.d,c!= 0或d!= 0的地址上返回true。

而是使默認掩碼等於0xffffffff以檢查完整匹配。

但事實證明,這不是大問題。最大的問題是,==比&更高的運算符優先級,讓你的代碼實際上是這樣工作:

uint32_t mask=(_ip & (0x00ffffff == 0)) ? 0xff000000 : 
    (_ip & (0x0000ffff == 0) ? 0xffff0000 : 0); 
return ((_ip & mask) == (_IP & mask)); 

其結果是,你將永遠的面具得到了0。你需要應用parens來解決這個問題。

所以在最後,你的代碼應該改變看起來像這樣:

uint32_t mask=((_ip & 0x00ffffff) == 0) ? 0xff000000 : 
    ((_ip & 0x0000ffff) == 0 ? 0xffff0000 : 0xffffffff); 
return ((_ip & mask) == (_IP & mask)); 
+0

非常感謝編程,我基本上只花了幾個小時學習C++到目前爲止。 – SP3CH8TR 2012-03-02 22:08:10

+0

非常感謝我編程新手,現在我只接收全零。我應該沒有爲比賽返回不同的值(10.10.10.10駐留在10.10.0.0子網內),所以我期望得到與blacklist.txt文件中包含的其他值不同的結果? – SP3CH8TR 2012-03-02 22:19:00

+0

事實證明,有一個更微妙的操作優先問題。我已經更新了我的答案來解釋它。 – 2012-03-03 00:12:59

3

迴應隱含的問題,「爲什麼我的程序沒有按照我所期望的方式工作嗎?「

我期待的輸出爲10.10.10.10(某種這裏主機的子網)10.10.0.0(和某種這裏子網掩碼)

我不知道你爲什麼正在期待這一點。您的代碼(如果該文件順利打開)只中有一個print語句:

cout<<is_match(h,mi)<<endl; 

功能is_match總是返回一個布爾值,要麼truefalse。打印時,它總是分別爲10。程序中沒有任何代碼可以打印IP地址或網絡掩碼。

+0

而且由於該布爾值總是真的......無論他在'is_match()'...中嘗試做什麼都不起作用。 – 2012-03-02 20:28:55

+0

我正在嘗試10.10.10.10並查看它是否與blacklist.txt中的任何內容匹配。由於作爲網絡範圍的條目不包含子網掩碼,因此我假設我必須爲這些地址分配一個掩碼並查看我的主機是否屬於該範圍。 – SP3CH8TR 2012-03-02 20:36:31

+0

我想我剛剛得到它。將==更改爲<=。 – SP3CH8TR 2012-03-02 22:44:30