defmodule GSMLG.MAC.Compiler do
@moduledoc "Compiles wireshark to the internally used lookup table format."
alias GSMLG.MAC.Parser
def count_entries(table) do
table
|> Enum.reduce(0, fn
{_, {_, map}}, acc -> acc + Enum.count(map)
_, acc -> acc + 1
end)
end
def build_lookup_table(mac_database_file) do
mac_database_file
|> Parser.parse_file()
|> Enum.reduce(%{}, fn
# the prefix is only 24 bits (min) long - standard key
{bit_mac, vendor}, acc when bit_size(bit_mac) == 24 ->
acc
|> Map.update(bit_mac, vendor, fn
sub_match when not is_list(sub_match) ->
IO.puts(
"Discovered shorter key for existing entry at #{inspect(bit_mac)} for <#{Enum.join(vendor, "\t")}> - dropping."
)
sub_match
_ ->
vendor
end)
# the prefix is longer, so add it into a list associated with the first 24 bits
{<<key::bits-size(24), _::bits>> = bit_mac, vendor} = tuple, acc ->
key_bitsize = bit_size(bit_mac)
acc
|> Map.update(key, {key_bitsize, %{bit_mac => vendor}}, fn
sub_match when not is_list(sub_match) -> update_sub_match_map(sub_match, tuple)
_ -> {key_bitsize, %{bit_mac => vendor}}
end)
end)
end
def update_sub_match_map({key_bitsize, map}, {bit_mac, vendor})
when bit_size(bit_mac) == key_bitsize do
{key_bitsize, map |> Map.put(bit_mac, vendor)}
end
def update_sub_match_map({key_bitsize, _} = given, {bit_mac, vendor})
when bit_size(bit_mac) < key_bitsize do
IO.puts(
"Discovered inconsistent bit-size at #{inspect(bit_mac)} for <#{Enum.join(vendor, "\t")}>: expected #{key_bitsize} but got #{bit_size(bit_mac)} - dropping"
)
given
end
# silently drop more precise keys (b/c its well-known addresses only)
def update_sub_match_map(given, _), do: given
end