At our organization we recieve a daily blacklist (much bigger as this is just a snippet) in the following format:
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
When I run the program after the code compiles I receive:
1
1
1
1
1
1
1
1
I am using C++ in a Linux/Unix environment.
So far, I am just spitting it out to make sure I have it formatted correctly.
The name of the file is blacklist.txt which contains the IP's listed above for now. I am only using cout to make sure my variable are defined correctly.
#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;
}
I am expecting the output to be 10.10.10.10 (some sort of host subnet here) 10.10.0.0 (and some sort of subnet mask here)
This is where your problem is:
uint32_t mask=(_ip & 0x00ffffff == 0) ? 0xff000000 :
(_ip & 0x0000ffff == 0 ? 0xffff0000 : 0);
return ( (_ip & mask) == (_IP & mask) );
If _ip is in the form x.0.0.0, it only compares x in _IP,
and if _ip is in the form x.y.0.0, it only compares x and y in _IP,
which is fine.
But if _ip isn't in either format you set the mask to 0 <- this is the problem.
When you take (_ip & 0) the result is always 0, likewise with (_IP & 0).
This means you always return true on addresses with a.b.c.d, c != 0 or d != 0.
Instead, make the default mask equal 0xffffffff to check for a complete match.
But it turns out that's not the big problem. The big problem is that == has a higher operator precedence than &, so your code is actually working like this:
uint32_t mask=(_ip & (0x00ffffff == 0)) ? 0xff000000 :
(_ip & (0x0000ffff == 0) ? 0xffff0000 : 0);
return ( (_ip & mask) == (_IP & mask) );
As a result, you will always get the 0 for a mask. You need to apply parens to fix this.
So in conclusion, your code should change to look like this:
uint32_t mask=( (_ip & 0x00ffffff) == 0) ? 0xff000000 :
( (_ip & 0x0000ffff) == 0 ? 0xffff0000 : 0xffffffff);
return ( (_ip & mask) == (_IP & mask) );
Responding to the implicit question, "Why doesn't my program work the way I expect?"
I am expecting the output to be 10.10.10.10 (some sort of host subnet here) 10.10.0.0 (and some sort of subnet mask here)
I don't know why you are expecting that. Your code (if the file opens successfully) only has one print statement in it:
cout<<is_match(h,mi)<<endl;
The function is_match always return a bool, either true or false. When printed, it will always be either 1 or 0, respectively. There simply isn't any code in your program which could print an IP address or netmask.
Related
I am creating an IP address class wrapper, and I want to differentiate the address types according to RFC 5735 Section 4 - Special Use IPv4 Addresses.
I want to
be able to test whether an address is within one of the blocks.
expand a block, so I get an array of IPAddress objects when returning.
If someone can help me by small sample code, or point me to existing code, I'd appreciate that. Sadly I find my brain can't wrap itself around the intricacy of this topic, that's why I am specifically asking for sample code. I know it's not polite to ask for source code like this, and I apologize.
When coming up with a unified IP address representation, it is important to realize that IPv4 addresses occupy 4 bytes and IPv6 addresses require 16 bytes. A naive wrapper implementation would use a union plus an enum discriminator to indicate the address type. Fortunately, this is not necessary because there exists an unambiguous representation of an IPv4 address within an IPv6 address. Keeping this in mind, your IP address wrapper class could look like this:
class address
{
/// Top 96 bits of v4-mapped-addr.
static std::array<uint8_t, 12> const v4_mapped_prefix =
{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }};
public:
address() = default;
bool is_v4() const
{
return std::memcmp(&bytes_, &v4_mapped_prefix, 12) == 0;
}
private:
std::array<uint8_t, 16> bytes_;
};
Now to check whether you have a certain class of addresses, you can add member functions ad libitum. Here are examples for loopback, broadcast, and multicast:
bool is_loopback() const
{
if (is_v4())
return bytes_[12] == 127;
else
return ((bytes_[0] == 0) && (bytes_[1] == 0) &&
(bytes_[2] == 0) && (bytes_[3] == 0) &&
(bytes_[4] == 0) && (bytes_[5] == 0) &&
(bytes_[6] == 0) && (bytes_[7] == 0) &&
(bytes_[8] == 0) && (bytes_[9] == 0) &&
(bytes_[10] == 0) && (bytes_[11] == 0) &&
(bytes_[12] == 0) && (bytes_[13] == 0) &&
(bytes_[14] == 0) && (bytes_[15] == 1));
}
bool is_broadcast() const
{
return is_v4() &&
bytes_[12] == 0xff && bytes_[13] == 0xff &&
bytes_[14] == 0xff && bytes_[15] == 0xff;
}
bool is_multicast() const
{
return is_v4() ? bytes_[12] == 224 : bytes_[0] == 0xff;
}
I do debug this code:
result = conn_process(conn, 1, 0);
if (result == CG_ERR_OK) continue;
if (result == CG_ERR_TIMEOUT)
{
break; // i'm here!
}
As in debugger i'm at break; I assume that result == CG_ERR_TIMEOUT is true. In Locals I do see:
result 131075 unsigned int
In Watch I do see:
CG_ERR_TIMEOUT error: identifier 'CG_ERR_TIMEOUT' out of scope
Going to definition shows me such code:
enum {
CG_ERR_OK = 0,
CG_ERR_INTERNAL = CG_RANGE_BEGIN,
CG_ERR_INVALIDARGUMENT,
CG_ERR_UNSUPPORTED,
CG_ERR_TIMEOUT,
CG_ERR_MORE,
CG_ERR_INCORRECTSTATE,
CG_ERR_DUPLICATEID,
CG_ERR_BUFFERTOOSMALL,
CG_ERR_OVERFLOW,
CG_ERR_UNDERFLOW,
CG_RANGE_END
};
So I just wonder why CG_ERR_TIMEOUT == 131075. What a strange magic number?
Because CG_RANGE_BEGIN is 131072 (which is 0x20000).
enum {
CG_ERR_OK = 0,
CG_ERR_INTERNAL = CG_RANGE_BEGIN, // == 131072
From now on every enum value is the previous one plus 1:
CG_ERR_INVALIDARGUMENT, // == 131072 + 1 = 131073
CG_ERR_UNSUPPORTED, // == 131073 + 1 = 131074
CG_ERR_TIMEOUT, // == 131074 + 1 = 131075
CG_ERR_MORE, // etc.
CG_ERR_INCORRECTSTATE,
CG_ERR_DUPLICATEID,
CG_ERR_BUFFERTOOSMALL,
CG_ERR_OVERFLOW,
CG_ERR_UNDERFLOW,
CG_RANGE_END
};
I am new to the win32 api and need help trying to understand how the GetLogicalDrives() function works. I am trying to populate a cbs_dropdownlist with all the available drives that are not in use. here is what I have so far. I would appreciate any help.
void FillListBox(HWND hWndDropMenu)
{
DWORD drives = GetLogicalDrives();
for (int i=0; i<26; i++)
{
SendMessage(hWndDropMenu, CB_ADDSTRING, 0, (LPARAM)drives);
}
}
The function GetLogicalDrives returns a bitmask of the logical drives available. Here is how you would do it:
DWORD drives = GetLogicalDrives();
for (int i=0; i<26; i++)
{
if( !( drives & ( 1 << i ) ) )
{
TCHAR driveName[] = { TEXT('A') + i, TEXT(':'), TEXT('\\'), TEXT('\0') };
SendMessage(hWndDropMenu, CB_ADDSTRING, 0, (LPARAM)driveName);
}
}
The code checks whether the i-th bit in the bitmask is not set to 1 or true.
GetLogicalDrives returns a bitmask and to inspect it you need to use bitwise operators. To see if drive A is in use:
GetLogicalDrives() & 1 == 1
If drive A is unavailable, GetLogicalDrives() & 1 would yield 0 and the condition would fail.
To check the next drive you'll need to use the next multiple of 2, GetLogicalDrives() & 2, GetLogicalDrives() & 4 and so on.
You could use GetLogicalDriveStrings but this returns the inverse of what you want, all the used logical drives.
I would build a table instead, and index into that:
const char *drive_names[] =
{
"A:",
"B:",
...
"Z:"
};
Then your loop could be:
DWORD drives_bitmask = GetLogicalDrives();
for (DWORD i < 0; i < 32; i++)
{
// Shift 1 to a multiple of 2. 1 << 0 = 1 (0000 0001), 1 << 1 = 2 etc.
DWORD mask_index = 1 << i;
if (drives_bitmask & i == 0)
{
// Drive unavailable, add it to list.
const char *name = drive_names[i];
// ... do GUI work.
}
}
I have a DWORD variable & I want to test if specific bits are set in it. I have my code below but I am not sure if I am transferring the bits from the win32 data type KBDLLHOOKSTRUCT to my lparam datatype correctly?
See MSDN that documents the DWORD flag variable: http://msdn.microsoft.com/en-us/library/ms644967(v=vs.85).aspx
union KeyState
{
LPARAM lparam;
struct
{
unsigned nRepeatCount : 16;
unsigned nScanCode : 8;
unsigned nExtended : 1;
unsigned nReserved : 4;
unsigned nContext : 1;
unsigned nPrev : 1;
unsigned nTrans : 1;
};
};
KBDLLHOOKSTRUCT keyInfo = *((KBDLLHOOKSTRUCT*)lParam);
KeyState myParam;
myParam.nRepeatCount = 1;
myParam.nScanCode = keyInfo.scanCode;
myParam.nExtended = keyInfo.flags && LLKHF_EXTENDED; // maybe it should be keyInfo.flags & LLKHF_EXTENDED or keyInfo.flags >> LLKHF_EXTENDED
myParam.nReserved = 0;
myParam.nContext = keyInfo.flags && LLKHF_ALTDOWN;
myParam.nPrev = 0; // can store the last key pressed as virtual key/code, then check against this one, if its the same then set this to 1 else do 0
myParam.nTrans = keyInfo.flags && LLKHF_UP;
// Or maybe I shd do this to transfer bits...
myParam.nRepeatCount = 1;
myParam.nScanCode = keyInfo.scanCode;
myParam.nExtended = keyInfo.flags & 0x01;
myParam.nReserved = (keyInfo.flags >> 0x01) & (1<<3)-1;
myParam.nContext = keyInfo.flags & 0x05;
myParam.nPrev = 0; // can store the last key pressed as virtual key/code, then check against this one, if its the same then set this to 1 else do 0
myParam.nTrans = keyInfo.flags & 0x07;
Rather than
myParam.nExtended = keyInfo.flags && LLKHF_EXTENDED
you need
myParam.nExtended = (keyInfo.flags & LLKHF_EXTENDED) != 0;
It's & not && because you want a bitwise and not a logical and. And the !=0 ensures the answer is either 0 or 1 (rather than 0 or some-other-nonzero-value) so it can be represented in your one-bit bitfield.
CheckBits(DWORD var, DWORD mask)
{
DWORD setbits=var&mask; //Find all bits are set
DWORD diffbits=setbits^mask; //Find all set bits that differ from mask
return diffbits!=0; //Retrun True if all specific bits in variable are set
}
If you want to merge two bits, you would use | (bitwise OR) operator:
myParam.nExtended = keyInfo.flags | LLKHF_EXTENDED;
myParam.nExtended = keyInfo.flags | 0x01;
To check if bit was set, you would use & (bitwise AND) operator:
if(myParam.nExtended & LLKHF_EXTENDED) ...
How could I make a function with flags like how Windows' CreateWindow(...style | style,...), for example, a createnum function:
int CreateNum(flag flags) //???
{
int num = 0;
if(flags == GREATER_THAN_TEN)
num = 11;
if(flags == EVEN && ((num % 2) == 1)
num++;
else if(flags == ODD && ((num % 2) == 0)
num++;
return num;
}
//called like this
int Number = CreateNum(GREATER_THAN_TEN | EVEN);
Is this possible, and if so, how?
You can define an enum specifying "single bit" values (note that the enclosing struct is acting here only as a naming context, so that you can write e.g. MyFlags::EVEN):
struct MyFlags{
enum Value{
EVEN = 0x01,
ODD = 0x02,
ANOTHER_FLAG = 0x04,
YET_ANOTHER_FLAG = 0x08,
SOMETHING_ELSE = 0x10,
SOMETHING_COMPLETELY_DIFFERENT = 0x20
};
};
and then use it like this:
int CreateNum(MyFlags::Value flags){
if (flags & MyFlags::EVEN){
// do something...
}
}
void main(){
CreateNum((MyFlags::Value)(MyFlags::EVEN | MyFlags::ODD));
}
or simply like this:
int CreateNum(int flags){
if (flags & MyFlags::EVEN){
// do something...
}
}
void main(){
CreateNum(MyFlags::EVEN | MyFlags::ODD);
}
You could also simply declare integer constants, but the enum is clearer in my opinion.
Note: I updated the post to take some comments into account, thanks!
I upvoted orsogufo's answer, but I always liked doing the following for defining the values:
enum Value{
EVEN = (1<<0),
ODD = (1<<2),
ANOTHER_FLAG = (1<<3),
YET_ANOTHER_FLAG = (1<<4),
SOMETHING_ELSE = (1<<5),
SOMETHING_COMPLETELY_DIFFERENT = (1<<6),
ANOTHER_EVEN = EVEN|ANOTHER_FLAG
};
<< is the shift operator. Incrementing the right side lets you generate sequential bit masks by moving the 1 over, one bit at a time. This has the same values for the bare flags, but reads easier to my eyes and makes it obvious if you skip or duplicate a value.
I also like combining some common flag combinations when appropriate.
You can use const int like this:
const int FLAG1 = 0x0001;
const int FLAG2 = 0x0010;
const int FLAG3 = 0x0100;
// ...
And when you use it:
int CreateNum(int flags)
{
if( flags & FLAG1 )
// FLAG1 is present
if( flags & FLAG2 )
// FLAG2 is present
// ...
}
Of course you can put one or more flag in your flags using the | operator.
Use powers of two as the individual constants, like
enum Flags { EVEN = 0x1, ODD = 0x2, GREATER_TEN = 0x4 };
and you use the logical and operator '&' for testing, like
if( flags & GREATER_THAN_TEN)
num = 11;
if( (flags & EVEN) && (num % 2) == 1 )
num++;
else if ( (flags & ODD) && (num % 2) == 0 )
num++;
return num;
You've got your tests wrong. What you want is something like (flags & EVEN), where EVEN is an integer with a single bit set (1, 2, 4, 8, 16 - some power of 2). (The integer can be an int or an enum. You could have a macro, but that's generally not a good idea.)
You can use the notation you listed, by overloading flags::operator==(flagvalue f), but it's a bad idea.
enum flags {
EVEN = 0x0100,
ODD = 0x0200,
BELOW_TEN = 0x0400,
ABOVETEN = 0x0800,
HUNDRED = 0x1000,
MASK = 0xff00
};
void some_func(int id_and_flags)
{
int the_id = id_and_flags & ~MASK;
int flags = id_and_flags & MASK;
if ((flags & EVEN) && (the_id % 2) == 1)
++the_id;
if ((flags & ODD) && (the_id % 2) == 0)
++the_id;
// etc
}
Illustrates masking of bit fields too which can be useful when you just need to bolt on a simplistic bit of extra functionality without adding any extra data structure.