2012-03-02 265 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