将IP列表到主机/网络地址列表
问题描述:
我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(和某种这里子网掩码)
任何帮助是巨大的。
答
#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));
}
答
的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上IP & 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所以检查内存时/直接字节,你会看到在“相反的顺序”字节。
你能否将IP表示为'unsigned int'(长度为32b)?比它会:'if((ip&mask)== subnet)':) – Vyktor 2012-02-28 17:53:55
我appoligize也许这可能是我缺乏C + +知识,但没有给出的掩码。 (ip&mask)是否假设你有面具? – SP3CH8TR 2012-02-28 17:57:24
@ SP3CH8TR是的。请注意,您可以轻松地将/ 16或/ 8或/任何内容转换为掩码,因为它只是说明设置了多少个前导位。例如/ 16是掩码0xFFFF0000。如果你不知道它是一个/ 16或一个/ 8或一个/ 31等,但你有一个问题。 – nos 2012-02-28 18:02:08