mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Add new functions for calculating geographic distance
Added a new BIF haversine_distance that computes distance between two geographic locations. Added a new Bro script function haversine_distance_ip that does the same but takes two IP addresses instead of latitude/longitude. This function requires that Bro be built with libgeoip.
This commit is contained in:
parent
58dea28504
commit
91496543ad
5 changed files with 93 additions and 0 deletions
|
@ -12,6 +12,7 @@
|
||||||
@load base/utils/directions-and-hosts
|
@load base/utils/directions-and-hosts
|
||||||
@load base/utils/exec
|
@load base/utils/exec
|
||||||
@load base/utils/files
|
@load base/utils/files
|
||||||
|
@load base/utils/geoip-distance
|
||||||
@load base/utils/numbers
|
@load base/utils/numbers
|
||||||
@load base/utils/paths
|
@load base/utils/paths
|
||||||
@load base/utils/patterns
|
@load base/utils/patterns
|
||||||
|
|
26
scripts/base/utils/geoip-distance.bro
Normal file
26
scripts/base/utils/geoip-distance.bro
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
##! Functions to calculate distance between two locations, based on GeoIP data.
|
||||||
|
|
||||||
|
## Returns the distance between two IP addresses using the haversine formula,
|
||||||
|
## based on GeoIP database locations. Requires Bro to be built with libgeoip.
|
||||||
|
##
|
||||||
|
## a1: First IP address.
|
||||||
|
##
|
||||||
|
## a2: Second IP address.
|
||||||
|
##
|
||||||
|
## Returns: The distance between *a1* and *a2* in miles, or -1.0 if GeoIP data
|
||||||
|
## is not available for either of the IP addresses.
|
||||||
|
##
|
||||||
|
## .. bro:see:: haversine_distance lookup_location
|
||||||
|
function haversine_distance_ip(a1: addr, a2: addr): double
|
||||||
|
{
|
||||||
|
local loc1 = lookup_location(a1);
|
||||||
|
local loc2 = lookup_location(a2);
|
||||||
|
local miles: double;
|
||||||
|
|
||||||
|
if (loc1?$latitude && loc1?$longitude && loc2?$latitude && loc2?$longitude)
|
||||||
|
miles = haversine_distance(loc1$latitude, loc1$longitude, loc2$latitude, loc2$longitude);
|
||||||
|
else
|
||||||
|
miles = -1.0;
|
||||||
|
|
||||||
|
return miles;
|
||||||
|
}
|
29
src/bro.bif
29
src/bro.bif
|
@ -3787,6 +3787,35 @@ function lookup_asn%(a: addr%) : count
|
||||||
return new Val(0, TYPE_COUNT);
|
return new Val(0, TYPE_COUNT);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
## Calculates distance between two geographic locations using the haversine
|
||||||
|
## formula. Latitudes and longitudes must be given in degrees, where southern
|
||||||
|
## hemispere latitudes are negative and western hemisphere longitudes are
|
||||||
|
## negative.
|
||||||
|
##
|
||||||
|
## lat1: Latitude (in degrees) of location 1.
|
||||||
|
##
|
||||||
|
## long1: Longitude (in degrees) of location 1.
|
||||||
|
##
|
||||||
|
## lat2: Latitude (in degrees) of location 2.
|
||||||
|
##
|
||||||
|
## long2: Longitude (in degrees) of location 2.
|
||||||
|
##
|
||||||
|
## Returns: Distance in miles.
|
||||||
|
##
|
||||||
|
## .. bro:see:: haversine_distance_ip
|
||||||
|
function haversine_distance%(lat1: double, long1: double, lat2: double, long2: double%): double
|
||||||
|
%{
|
||||||
|
const double PI = 3.14159;
|
||||||
|
const double RADIUS = 3958.8; // Earth's radius in miles.
|
||||||
|
|
||||||
|
double s1 = sin((lat2 - lat1) * PI/360);
|
||||||
|
double s2 = sin((long2 - long1) * PI/360);
|
||||||
|
double a = s1 * s1 + cos(lat1 * PI/180) * cos(lat2 * PI/180) * s2 * s2;
|
||||||
|
double distance = 2 * RADIUS * asin(sqrt(a));
|
||||||
|
|
||||||
|
return new Val(distance, TYPE_DOUBLE);
|
||||||
|
%}
|
||||||
|
|
||||||
## Converts UNIX file permissions given by a mode to an ASCII string.
|
## Converts UNIX file permissions given by a mode to an ASCII string.
|
||||||
##
|
##
|
||||||
## mode: The permissions (an octal number like 0644 converted to decimal).
|
## mode: The permissions (an octal number like 0644 converted to decimal).
|
||||||
|
|
7
testing/btest/Baseline/bifs.haversine_distance/out
Normal file
7
testing/btest/Baseline/bifs.haversine_distance/out
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
5.8481e+03
|
||||||
|
5.8481e+03
|
||||||
|
1.9193e-02
|
||||||
|
1.5136e-02
|
||||||
|
9.2419e-01
|
||||||
|
1.2437e+04
|
||||||
|
1.2437e+04
|
30
testing/btest/bifs/haversine_distance.bro
Normal file
30
testing/btest/bifs/haversine_distance.bro
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
function test(la1: double, lo1: double, la2: double, lo2: double)
|
||||||
|
{
|
||||||
|
print fmt("%.4e", haversine_distance(la1, lo1, la2, lo2));
|
||||||
|
}
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
# Test two arbitrary locations.
|
||||||
|
test(37.866798, -122.253601, 48.25, 11.65);
|
||||||
|
# Swap the order of locations to verify the distance doesn't change.
|
||||||
|
test(48.25, 11.65, 37.866798, -122.253601);
|
||||||
|
|
||||||
|
# Distance of one second of latitude (crossing the equator).
|
||||||
|
test(.0001388889, 0, -.0001388889, 0);
|
||||||
|
|
||||||
|
# Distance of one second of longitude (crossing the prime meridian).
|
||||||
|
test(38, 0.000138999, 38, -0.000138999);
|
||||||
|
|
||||||
|
# Distance of one minute of longitude (test extreme longitude values).
|
||||||
|
test(38, 180, 38, -179.98333);
|
||||||
|
|
||||||
|
# Two locations on opposite ends of the Earth.
|
||||||
|
test(45, -90, -45, 90);
|
||||||
|
# Same, but verify that extreme latitude values work.
|
||||||
|
test(90, 0, -90, 0);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue