/
dnsd_config.ex
128 lines (103 loc) · 3.2 KB
/
dnsd_config.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
defmodule VintageNet.IP.DnsdConfig do
@moduledoc """
This is a helper module for VintageNet.Technology implementations that use
the Busybox DNS server.
DNS functionality is only supported for IPv4 configurations using static IP
addresses.
DNS server parameters are:
* `:port` - The port to use (defaults to 53)
* `:ttl` - DNS record TTL in seconds (defaults to 120)
* `:records` - DNS A records (required)
The `:records` option is a list of name/IP address tuples. For example:
```
[{"example.com", {1, 2, 3, 4}}]
```
Only IPv4 addresses are supported. Addresses may be specified as strings or
tuples, but will be normalized to tuple form before being applied.
"""
alias VintageNet.{Command, IP}
alias VintageNet.Interface.RawConfig
@doc """
Normalize the DNSD parameters in a configuration.
"""
@spec normalize(map()) :: map()
def normalize(%{ipv4: %{method: :static}, dnsd: dnsd} = config) do
# Normalize IP addresses
new_dnsd =
dnsd
|> Map.update(:records, [], &normalize_records/1)
|> Map.take([
:records,
:port,
:ttl
])
%{config | dnsd: new_dnsd}
end
def normalize(%{dnsd: _something_else} = config) do
# DNSD won't be started if not an IPv4 static configuration
Map.drop(config, [:dnsd])
end
def normalize(config), do: config
defp normalize_records(records) do
Enum.map(records, &normalize_record/1)
end
defp normalize_record({name, ipa}) do
{name, IP.ip_to_tuple!(ipa)}
end
@doc """
Add dnsd configuration commands for running a DNSD server
"""
@spec add_config(RawConfig.t(), map(), keyword()) :: RawConfig.t()
def add_config(
%RawConfig{
ifname: ifname,
files: files,
child_specs: child_specs
} = raw_config,
%{ipv4: %{method: :static, address: address}, dnsd: dnsd_config},
opts
) do
tmpdir = Keyword.fetch!(opts, :tmpdir)
dnsd_conf_path = Path.join(tmpdir, "dnsd.conf.#{ifname}")
new_files = [{dnsd_conf_path, dnsd_contents(dnsd_config)} | files]
dnsd_args =
[
"-c",
dnsd_conf_path,
"-i",
IP.ip_to_string(address)
]
|> add_port(dnsd_config)
|> add_ttl(dnsd_config)
new_child_specs =
child_specs ++
[
Supervisor.child_spec(
{MuonTrap.Daemon,
[
"dnsd",
dnsd_args,
Command.add_muon_options(stderr_to_stdout: true, log_output: :debug)
]},
id: :dnsd
)
]
%RawConfig{raw_config | files: new_files, child_specs: new_child_specs}
end
def add_config(raw_config, _config_without_dhcpd, _opts), do: raw_config
defp dnsd_contents(%{records: records}) do
Enum.map(records, &record_to_string/1)
|> IO.chardata_to_string()
end
defp record_to_string({name, ipa}) do
"#{name} #{IP.ip_to_string(ipa)}\n"
end
defp add_port(dnsd_args, %{port: port}) do
["-p", to_string(port) | dnsd_args]
end
defp add_port(dnsd_args, _dnsd_config), do: dnsd_args
defp add_ttl(dnsd_args, %{ttl: ttl}) do
["-t", to_string(ttl) | dnsd_args]
end
defp add_ttl(dnsd_args, _dnsd_config), do: dnsd_args
end