将IP与主机/网络地址列表进行比较

时间:2012-02-28 17:50:03

标签: c++

我是appoligize但不熟悉C ++。在我们的组织中,我们按以下格式收到每日黑名单(更大,因为这只是一个片段):

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

当我收到代码编译后运行程序时:

1

1

1

1

1

1

1

1

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

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

该文件的名称为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(以及某种子网掩码)

任何帮助都很棒。

2 个答案:

答案 0 :(得分: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 AND(在C / C ++中用IP & Mask表示),这将为您提供此输出:

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,因此在直接检查内存/字节时,您将看到&#34; 相反顺序&#34;中的字节。

答案 1 :(得分: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) );
}