strate_net_silo/
config.rs1use smoltcp::{
2 socket::{dhcpv4, dns},
3 wire::{DnsQueryType, IpAddress, IpCidr, Ipv4Address, Ipv6Address, Ipv6Cidr},
4};
5use strate_net::syscalls::clock_gettime_ns;
6
7use crate::{
8 ip::{
9 broadcast_from_host_prefix, mask_from_prefix, parse_ipv4, parse_ipv6, IpConfig, Ipv6Config,
10 },
11 now_instant, sleep_micros,
12 state::NetworkStrate,
13};
14
15impl NetworkStrate {
16 pub(crate) fn process_dhcp(&mut self) {
17 if !self.dhcp_enabled {
18 return;
19 }
20
21 let event = self
22 .sockets
23 .get_mut::<dhcpv4::Socket>(self.dhcp_handle)
24 .poll();
25
26 match event {
27 Some(dhcpv4::Event::Configured(config)) => {
28 crate::log("[strate-net] DHCP: address acquired\n");
29
30 self.interface.update_ip_addrs(|addrs| {
31 let cidr = IpCidr::new(
32 IpAddress::Ipv4(config.address.address()),
33 config.address.prefix_len(),
34 );
35 for addr in addrs.iter_mut() {
36 if matches!(addr, IpCidr::Ipv4(_)) {
37 *addr = cidr;
38 return;
39 }
40 }
41 let _ = addrs.push(cidr);
42 });
43
44 let _ = self.interface.routes_mut().remove_default_ipv4_route();
45 if let Some(gw) = config.router {
46 self.interface.routes_mut().add_default_ipv4_route(gw).ok();
47 }
48
49 let mut dns = [None::<Ipv4Address>; 3];
50 self.dns_servers = [None; 3];
51 for ((slot_v4, slot_any), &server) in dns
52 .iter_mut()
53 .zip(self.dns_servers.iter_mut())
54 .zip(config.dns_servers.iter())
55 {
56 *slot_v4 = Some(server);
57 *slot_any = Some(IpAddress::Ipv4(server));
58 }
59 self.dns_from_dhcp = true;
60
61 let host = config.address.address();
62 let prefix_len = config.address.prefix_len();
63 let netmask = mask_from_prefix(prefix_len);
64 let broadcast = broadcast_from_host_prefix(host, prefix_len);
65 self.ip_config = Some(IpConfig {
66 address: config.address,
67 host,
68 prefix_len,
69 netmask,
70 broadcast,
71 gateway: config.router,
72 dns,
73 });
74 self.refresh_dns_servers();
75 }
76 Some(dhcpv4::Event::Deconfigured) => {
77 crate::log("[strate-net] DHCP: deconfigured (lease expired?)\n");
78 if self.dns_from_dhcp {
79 self.dns_servers = [None; 3];
80 self.dns_from_dhcp = false;
81 }
82 self.clear_ipv4_runtime_config();
83 }
84 None => {}
85 }
86 }
87
88 pub(crate) fn refresh_dns_servers(&mut self) {
89 let mut servers = [IpAddress::Ipv4(Ipv4Address::new(0, 0, 0, 0)); 3];
90 let mut count = 0usize;
91
92 for server in self.dns_servers.iter().flatten() {
93 if count < servers.len() {
94 servers[count] = *server;
95 count += 1;
96 }
97 }
98
99 if count == 0 {
100 if let Some(ref cfg) = self.ip_config {
101 if let Some(gw) = cfg.gateway {
102 servers[0] = IpAddress::Ipv4(gw);
103 count = 1;
104 }
105 }
106 }
107
108 if count == 0 {
109 if let Some(ref cfg) = self.ipv6_config {
110 if let Some(gw) = cfg.gateway {
111 servers[0] = IpAddress::Ipv6(gw);
112 count = 1;
113 }
114 }
115 }
116
117 let socket = self.sockets.get_mut::<dns::Socket>(self.dns_handle);
118 socket.update_servers(&servers[..count]);
119 }
120
121 pub(crate) fn apply_ipv4_config(
122 &mut self,
123 address: smoltcp::wire::Ipv4Cidr,
124 gateway: Option<Ipv4Address>,
125 ) {
126 let host = address.address();
127 let prefix_len = address.prefix_len();
128 let netmask = mask_from_prefix(prefix_len);
129 let broadcast = broadcast_from_host_prefix(host, prefix_len);
130
131 self.interface.update_ip_addrs(|addrs| {
132 let cidr = IpCidr::new(IpAddress::Ipv4(host), prefix_len);
133 for addr in addrs.iter_mut() {
134 if matches!(addr, IpCidr::Ipv4(_)) {
135 *addr = cidr;
136 return;
137 }
138 }
139 let _ = addrs.push(cidr);
140 });
141
142 let _ = self.interface.routes_mut().remove_default_ipv4_route();
143 if let Some(gw) = gateway {
144 let _ = self.interface.routes_mut().add_default_ipv4_route(gw);
145 }
146
147 let mut dns = [None; 3];
148 for (slot, server) in dns.iter_mut().zip(self.dns_servers.iter()) {
149 if let Some(IpAddress::Ipv4(addr)) = server {
150 *slot = Some(*addr);
151 }
152 }
153
154 self.ip_config = Some(IpConfig {
155 address,
156 host,
157 prefix_len,
158 netmask,
159 broadcast,
160 gateway,
161 dns,
162 });
163 self.dns_from_dhcp = false;
164 self.refresh_dns_servers();
165 }
166
167 pub(crate) fn apply_ipv6_config(&mut self, address: Ipv6Cidr, gateway: Option<Ipv6Address>) {
168 self.interface.update_ip_addrs(|addrs| {
169 let cidr = IpCidr::new(IpAddress::Ipv6(address.address()), address.prefix_len());
170 for addr in addrs.iter_mut() {
171 if let IpCidr::Ipv6(current) = addr {
172 if !current.address().is_unicast_link_local() {
173 *addr = cidr;
174 return;
175 }
176 }
177 }
178 let _ = addrs.push(cidr);
179 });
180 if let Some(gw) = gateway {
181 let _ = self.interface.routes_mut().add_default_ipv6_route(gw);
182 }
183 self.ipv6_config = Some(Ipv6Config { address, gateway });
184 self.refresh_dns_servers();
185 }
186
187 pub(crate) fn resolve_hostname_query(
188 &mut self,
189 name: &str,
190 q_type: DnsQueryType,
191 ) -> core::result::Result<IpAddress, i32> {
192 let query = {
193 let cx = self.interface.context();
194 let socket = self.sockets.get_mut::<dns::Socket>(self.dns_handle);
195 match socket.start_query(cx, name, q_type) {
196 Ok(query) => query,
197 Err(_) => return Err(-22),
198 }
199 };
200
201 let deadline_ns = clock_gettime_ns()
202 .unwrap_or(0)
203 .saturating_add(3_000_000_000);
204 loop {
205 let now = now_instant();
206 let _ = self
207 .interface
208 .poll(now, &mut self.device, &mut self.sockets);
209 self.process_dhcp();
210 self.process_ipv6_slaac();
211 self.process_icmp();
212
213 let res = self
214 .sockets
215 .get_mut::<dns::Socket>(self.dns_handle)
216 .get_query_result(query);
217 match res {
218 Ok(addrs) => {
219 if let Some(addr) = addrs.into_iter().next() {
220 return Ok(addr);
221 }
222 return Err(-2);
223 }
224 Err(dns::GetQueryResultError::Failed) => return Err(-2),
225 Err(dns::GetQueryResultError::Pending) => {
226 if clock_gettime_ns().unwrap_or(0) >= deadline_ns {
227 return Err(-110);
228 }
229 sleep_micros(10_000);
230 }
231 }
232 }
233 }
234
235 pub(crate) fn resolve_hostname_blocking(
236 &mut self,
237 name: &str,
238 ) -> core::result::Result<IpAddress, i32> {
239 if let Some(ip) = parse_ipv4(name) {
240 return Ok(IpAddress::Ipv4(ip));
241 }
242 if let Some(ip) = parse_ipv6(name) {
243 return Ok(IpAddress::Ipv6(ip));
244 }
245 if self.ip_config.is_none() && self.ipv6_config.is_none() {
246 return Err(-11);
247 }
248
249 let mut last_err = -2;
250 if self.ipv6_config.is_some() {
251 match self.resolve_hostname_query(name, DnsQueryType::Aaaa) {
252 Ok(addr) => return Ok(addr),
253 Err(-2) => {}
254 Err(err) => last_err = err,
255 }
256 }
257 if self.ip_config.is_some() {
258 match self.resolve_hostname_query(name, DnsQueryType::A) {
259 Ok(addr) => return Ok(addr),
260 Err(err) => last_err = err,
261 }
262 }
263 Err(last_err)
264 }
265
266 pub(crate) fn process_ipv6_slaac(&mut self) {
267 let mut global_addr: Option<Ipv6Cidr> = None;
268 self.interface.update_ip_addrs(|addrs| {
269 for addr in addrs.iter() {
270 if let IpCidr::Ipv6(cidr) = addr {
271 if !cidr.address().is_unicast_link_local() && global_addr.is_none() {
272 global_addr = Some(*cidr);
273 }
274 }
275 }
276 });
277
278 let mut gateway: Option<Ipv6Address> = None;
279 self.interface.routes_mut().update(|table| {
280 for route in table.iter() {
281 if let (IpCidr::Ipv6(cidr), IpAddress::Ipv6(via)) = (route.cidr, route.via_router) {
282 if cidr.prefix_len() == 0 {
283 gateway = Some(via);
284 break;
285 }
286 }
287 }
288 });
289
290 match (global_addr, &mut self.ipv6_config) {
291 (Some(addr), Some(cfg)) => {
292 cfg.address = addr;
293 cfg.gateway = gateway;
294 }
295 (Some(addr), cfg @ None) => {
296 *cfg = Some(Ipv6Config {
297 address: addr,
298 gateway,
299 });
300 }
301 (None, _) => {
302 self.ipv6_config = None;
303 }
304 }
305 }
306}