-module(ls_iprange). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -endif. -export([ create/8, delete/1, get/1, release/2, claim/1, list/2, list/3, stream/3 ]). -export([ name/2, uuid/2, network/2, netmask/2, gateway/2, set_metadata/2, tag/2, vlan/2 ]). -export([ip_to_bin/1, ip_to_int/1]). %%%=================================================================== %%% Iprange Functions %%%=================================================================== %%-------------------------------------------------------------------- %% @doc Creates a new IP range on the server. All ips are passed as %% integer or binary. %% @end %%-------------------------------------------------------------------- -spec create(Iprange::binary(), Network::integer() | binary(), Gateway::integer() | binary(), Netmask::integer() | binary(), First::integer() | binary(), Last::integer() | binary(), Tag::binary(), Vlan::pos_integer()) -> {ok, UUID::fifo:iprange_id()} | duplicate | {'error', 'no_servers'}. create(Iprange, Network, Gateway, Netmask, First, Last, Tag, Vlan) when is_binary(Iprange), is_binary(Tag), is_integer(Network), %is_integer(Gateway), Network =:= (Gateway band Netmask), is_integer(Netmask), is_integer(First), % Network =:= (First band Netmask), is_integer(Last), % Network =:= (Last band Netmask), is_integer(Vlan), Vlan >= 0 -> send({iprange, create, Iprange, Network, Gateway, Netmask, First, Last, Tag, Vlan}); create(Iprange, Network, Gateway, Netmask, First, Last, Tag, Vlan) when is_binary(Iprange), is_binary(Tag), is_integer(Vlan), Vlan >= 0, is_binary(Network), is_binary(Gateway), is_binary(Netmask), is_binary(First), is_binary(Last) -> create(Iprange, ip_to_int(Network), ip_to_int(Gateway), ip_to_int(Netmask), ip_to_int(First), ip_to_int(Last), Tag, Vlan). %%-------------------------------------------------------------------- %% @doc Deletes a iprange from the server. %% @end %%-------------------------------------------------------------------- -spec delete(Iprange::binary()) -> ok | not_found | {'error', 'no_servers'}. delete(Iprange) -> send({iprange, delete, Iprange}). %%-------------------------------------------------------------------- %% @doc Reads all the info of a iprange from the server. %% @end %%-------------------------------------------------------------------- -spec get(Iprange::binary()) -> not_found | {ok, fifo:iprange()} | {'error', 'no_servers'}. get(Iprange) -> send({iprange, get, Iprange}). %%-------------------------------------------------------------------- %% @doc Tries to release a claimed ip address from a range. %% @end %%-------------------------------------------------------------------- -spec release(Iprange::fifo:iprange_id(), Ip::integer()) -> ok | not_found | {'error', 'no_servers'}. release(Iprange, Ip) when is_binary(Iprange), is_integer(Ip) -> send({iprange, release, Iprange, ip_to_int(Ip)}); release(Iprange, Ip) when is_binary(Iprange) -> release(Iprange, ip_to_int(Ip)). %%-------------------------------------------------------------------- %% @doc Claims a ipaddress and returns the address and the relevant %% network information. %% @end %%-------------------------------------------------------------------- -spec claim(Iprange::fifo:iprange_id()) -> not_found | {ok, {Tag::binary(), IP::pos_integer(), Netmask::pos_integer(), Gateway::pos_integer(), VLan::non_neg_integer()}} | {error, failed} | {'error', 'no_servers'}. claim(Iprange) -> send({iprange, claim, Iprange}). -define(HS(F), F(DTRace, Val) -> send({iprange, F, DTRace, Val})). ?HS(name). ?HS(uuid). ?HS(network). ?HS(netmask). ?HS(gateway). ?HS(set_metadata). ?HS(tag). ?HS(vlan). %%-------------------------------------------------------------------- %% @doc Lists all ip ranges known to the system filtered by %% given matchers. %% @end %%-------------------------------------------------------------------- -spec list(Reqs::[fifo:matcher()], boolean()) -> {ok, [{Ranking::integer(), ID::fifo:iprange_id()}]} | {ok, [{Ranking::integer(), ID::fifo:iprange()}]} | {'error', 'no_servers'}. list(Reqs, Full) -> list(mdns, Reqs, Full). list(Sniffle, Reqs, Full) -> send(Sniffle, {iprange, list, Reqs, Full}). %%-------------------------------------------------------------------- %% @doc Streams the IPRANGE's in chunks. %% @end %%-------------------------------------------------------------------- -spec stream(Reqs::[fifo:matcher()], mdns_client_lib:stream_fun(), term()) -> {ok, [{Ranking::integer(), fifo:iprange_id()}]} | {ok, [{Ranking::integer(), fifo:iprange()}]} | {'error', 'no_servers'}. stream(Reqs, StreamFn, Acc0) -> case libsniffle_server:stream({iprange, stream, Reqs}, StreamFn, Acc0) of {reply, Reply} -> Reply; noreply -> ok; E -> E end. %%%=================================================================== %%% Utility functions %%%=================================================================== %%-------------------------------------------------------------------- %% @doc This function convers an integer to the human readable ip %% format as
AAA.BBB.CCC.DDD. %% @end %%-------------------------------------------------------------------- -spec ip_to_bin(integer()) -> binary(). ip_to_bin(IP) -> <> = <
AAA.BBB.CCC.DDDto an integer. %% @end %%-------------------------------------------------------------------- -spec ip_to_int(integer()|string()|binary()) -> integer(). ip_to_int(IP) when is_integer(IP) -> IP; ip_to_int(IP) -> [As, Bs, Cs, Ds] = re:split(IP, "\\.", [{return, list}]), {A, _} = string:to_integer(As), {B, _} = string:to_integer(Bs), {C, _} = string:to_integer(Cs), {D, _} = string:to_integer(Ds), <