Hi all,
i want to flag if a given ip is an ip broadcast/multicast or not:
there are some built-in functions able to recognize an ip broadcast in
Bro?
Thanks,
Vito
This sounds like something the Hosts module in scriptland does. If not, you could define subnets of multicast/broadcast addresses in a script and check on new_connection if id.orig_h or id.resp_h is in those subnets.
-AK
One way would be to check the packet destination against the IP multicast range:
global mcast = 224.0.0.0/4;
global bcast = 255.255.255.255;
event new_packet(c:connection,p:pkt_hdr) {
if (c$id$resp_h in mcast || c$id$resp_h == bcast)
print "mutlicast or broadcast found";
}
You wouldn't want to use the new_packet event of course.
Hi,
thanks for your reply.
What i'm trying to do is to create a flag if an ip broadcast is found.
For example, in networks.cfg i've written this subnet
172.20.1.0/24
It's broadcast address is 172.20.1.255.
I can read all subnets written in networks.cfg with the variable
Site::local_nets_table: to calculate the ip broadcast i can use this
method
https://en.wikipedia.org/wiki/Broadcast_address
What i'm not able to do is to transform a subnet variable (in this
case 172.20.1.0/24) into an ip variable (172.20.1.0) plus a count
(24).
Any suggestion?
Thanks
Vito
Oh I see what you’re saying. What you’d like is a function that takes a subnet as input and returns the broadcast address, correct?
-AK
Correct!
Any suggestion?
The following code feels like it should work, but the last print statement breaks it.
local my_subnet: subnet = 1.1.1.1/8;
print fmt("%s", my_subnet);
print fmt("%s", |my_subnet|);
print fmt("%s", my_subnet[ |my_subnet| ]);
I don’t believe there is currently a built in way to do what you want. Is there a way to convert a subnet to a vector of addr?
-AK
I’m looking to write a bif which does this. How can I access a subnet’s prefix as an int? Here’s what I have so far.
function get_broadcast%(snet: subnet%): addr
%{
return new AddrVal( snet->Prefix() + (snet->Width() - 1) );
%}
-AK
snet->Prefix() yields an IPAddr. You don't easily get that as an int,
but it has a method for getting it as a sequence of bytes:
int GetBytes(const uint32_t** bytes)
That works for both IPv4 and v6.
That said, I think you can solve this more easily by combining some
other methods that IPAddr offers as well:
/**
* Masks out lower bits of the address.
[...]
*/
void Mask(int top_bits_to_keep);
/**
* Masks out top bits of the address.
[...]
*/
void ReverseMask(int top_bits_to_chop);
/**
* Bitwise OR operator returns the IP address resulting from the bitwise
* OR operation on the raw bytes of this address with another.
*/
IPAddr operator|(const IPAddr& other)
You'd mask out the lower bits of the prefix, mask out the upper bits
of 255.255.255.255 (for IPv4), and then "or" the two together.
Robin
I believe I have some logic that solves this. I created an xor (^)
operator for IPAddr types similar to the inclusive or (|) and am
making use of it to calculate the broadcast address of a subnet. My
BiF follows:
function subnet_end%(snet: subnet%): addr
%{
IPAddr broadcast;
if (snet->Prefix().GetFamily() == IPv4) //ipv4
{
broadcast = (IPAddr(string("255.255.255.255")) ^
snet->Mask()) | snet->Prefix();
}
else if (snet->Prefix().GetFamily() == IPv6) //ipv6
{
broadcast =
(IPAddr(string("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) ^
snet->Mask()) | snet->Prefix();
}
else
{
reporter->InternalError("Unsupported address size. Not
IPv4 or IPv6.");
}
return new AddrVal(broadcast);
%}
When calling this from scriptland, v6 addresses work properly.
However, v4 addresses are represented as v6 addresses still. I am
missing some concept around how IPAddrs can be either v4 or v6 and how
scriptland knows the difference. How might I properly indicate the
IPAddr in the returned AddrVal is meant to represent a v4 address
instead of a v6 address?
Thanks!
-AK
Here is a simpler implementation of this function (no other
changes to Bro are needed):
function subnet_end%(s: subnet%): addr
%{
IPAddr mask;
int offset = 0;
if ( s->Prefix().GetFamily() == IPv4 )
{
mask = IPAddr("255.255.255.255");
offset = 96;
}
else
{
mask = IPAddr("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
}
mask.ReverseMask(offset + s->Width());
return new AddrVal(mask | s->Prefix());
%}
That’s much cleaner and doesn’t have the v4/v6 issue I introduced. Thanks Daniel. I understand now why Robin suggested using those methods.
-AK