diff options
author | href <href@random.sh> | 2021-09-08 15:39:01 +0200 |
---|---|---|
committer | href <href@random.sh> | 2021-09-08 15:39:01 +0200 |
commit | f7c3f34ad3cd63e92c2952a3ce6c34bd98ce2175 (patch) | |
tree | 335ae98acc40d17be143fc9fbfd32854e548bc1f /lib/lsg | |
parent | assets: build (diff) |
;o custom subnets
Diffstat (limited to '')
-rw-r--r-- | lib/lsg/application.ex | 1 | ||||
-rw-r--r-- | lib/lsg/subnet.ex | 84 |
2 files changed, 85 insertions, 0 deletions
diff --git a/lib/lsg/application.ex b/lib/lsg/application.ex index 5b62dcd..0d29668 100644 --- a/lib/lsg/application.ex +++ b/lib/lsg/application.ex @@ -20,6 +20,7 @@ defmodule LSG.Application do worker(LSG.IcecastAgent, []), worker(LSG.Token, []), worker(LSG.AuthToken, []), + LSG.Subnet, {GenMagic.Pool, [name: LSG.GenMagic, pool_size: 2]}, #worker(LSG.Icecast, []), ] ++ LSG.IRC.application_childs diff --git a/lib/lsg/subnet.ex b/lib/lsg/subnet.ex new file mode 100644 index 0000000..81bd862 --- /dev/null +++ b/lib/lsg/subnet.ex @@ -0,0 +1,84 @@ +defmodule LSG.Subnet do + use Agent + + def start_link(_) do + Agent.start_link(&setup/0, name: __MODULE__) + end + + def assignations() do + :dets.select(dets(), [{{:"$1", :"$2"}, [is_binary: :"$2"], [{{:"$1", :"$2"}}]}]) + end + + def find_subnet_for(binary) when is_binary(binary) do + case :dets.select(dets(), [{{:"$1", :"$2"}, [{:==, :"$2", binary}], [{{:"$1", :"$2"}}]}]) do + [{subnet, _}] -> subnet + _ -> nil + end + end + + def assign(binary) when is_binary(binary) do + result = if subnet = find_subnet_for(binary) do + {:ok, subnet} + else + Agent.get_and_update(__MODULE__, fn(dets) -> + {subnet, _} = available_select(dets) + :dets.insert(dets, {subnet, binary}) + :dets.sync(dets) + {{:new, subnet}, dets} + end) + end + + case result do + {:new, subnet} -> + ip = Pfx.host(subnet, 1) + set_reverse(binary, ip) + subnet + {:ok, subnet} -> + subnet + end + end + + def set_reverse(name, ip, value \\ nil) + + def set_reverse(name, ip, nil) do + set_reverse(name, ip, "#{name}.users.goulag.org") + end + + def set_reverse(_, ip, value) do + ptr_zone = "3.0.0.2.d.f.0.a.2.ip6.arpa" + ip_fqdn = Pfx.dns_ptr(ip) + ip_local = String.replace(ip_fqdn, ".#{ptr_zone}", "") + rev? = String.ends_with?(value, ".users.goulag.org") + if rev? do + {:ok, rev_zone} = PowerDNSex.show_zone("users.goulag.org") + rev_update? = Enum.any?(rev_zone.rrsets, fn(rr) -> rr.name == "#{ip_fqdn}." end) + record = %{name: "#{value}.", type: "AAAA", ttl: 8600, records: [%{content: ip, disabled: false}]} + if(rev_update?, do: PowerDNSex.update_record(rev_zone, record), else: PowerDNSex.create_record(rev_zone, record)) + end + {:ok, zone} = PowerDNSex.show_zone(ptr_zone) + update? = Enum.any?(zone.rrsets, fn(rr) -> rr.name == "#{ip_fqdn}." end) + record = %{name: "#{ip_fqdn}.", type: "PTR", ttl: 3600, records: [%{content: "#{value}.", disabled: false}]} + pdns = if(update?, do: PowerDNSex.update_record(zone, record), else: PowerDNSex.create_record(zone, record)) + :ok + end + + @doc false + def dets() do + (LSG.data_path() <> "/subnets.dets") |> String.to_charlist() + end + + @doc false + def setup() do + {:ok, dets} = :dets.open_file(dets(), []) + dets + end + + defp available_select(dets) do + spec = [{{:"$1", :"$2"}, [is_integer: :"$2"], [{{:"$1", :"$2"}}]}] + {subnets, _} = :dets.select(dets, spec, 20) + subnet = subnets + |> Enum.sort_by(fn({_, last}) -> last end) + |> List.first() + end + +end |