strate_net_silo/
content.rs1use alloc::{string::String, vec, vec::Vec};
2use core::fmt::Write;
3
4use smoltcp::socket::tcp;
5use strate_net::syscalls::call;
6
7use crate::state::NetworkStrate;
8
9impl NetworkStrate {
10 pub(crate) fn generate_content(
11 &mut self,
12 _file_id: u64,
13 path: &str,
14 ) -> core::result::Result<Vec<u8>, i32> {
15 match path {
16 "" => Ok(b"ip\naddress\nprefix\nnetmask\nbroadcast\ngateway\nroute\nroutes\ndns\ndhcp\nresolve\nping\ntcp\nudp\nip6\nip6/address\nip6/gateway\n".to_vec()),
17 "ip" => Ok(if let Some(ref cfg) = self.ip_config {
18 alloc::format!("{}\n", cfg.address).into_bytes()
19 } else {
20 b"0.0.0.0/0\n".to_vec()
21 }),
22 "address" => Ok(if let Some(ref cfg) = self.ip_config {
23 alloc::format!("{}\n", cfg.host).into_bytes()
24 } else {
25 b"0.0.0.0\n".to_vec()
26 }),
27 "prefix" => Ok(if let Some(ref cfg) = self.ip_config {
28 alloc::format!("{}\n", cfg.prefix_len).into_bytes()
29 } else {
30 b"0\n".to_vec()
31 }),
32 "netmask" => Ok(if let Some(ref cfg) = self.ip_config {
33 alloc::format!("{}\n", cfg.netmask).into_bytes()
34 } else {
35 b"0.0.0.0\n".to_vec()
36 }),
37 "broadcast" => Ok(if let Some(ref cfg) = self.ip_config {
38 alloc::format!("{}\n", cfg.broadcast).into_bytes()
39 } else {
40 b"0.0.0.0\n".to_vec()
41 }),
42 "gateway" => Ok(if let Some(ref cfg) = self.ip_config {
43 if let Some(gw) = cfg.gateway {
44 alloc::format!("{}\n", gw).into_bytes()
45 } else {
46 b"0.0.0.0\n".to_vec()
47 }
48 } else {
49 b"0.0.0.0\n".to_vec()
50 }),
51 "dns" => {
52 let mut out = String::new();
53 let mut wrote = false;
54 for server in self.dns_servers.iter().flatten() {
55 let _ = writeln!(out, "{}", server);
56 wrote = true;
57 }
58 if !wrote {
59 out.push_str("0.0.0.0\n");
60 }
61 Ok(out.into_bytes())
62 }
63 "dhcp" => Ok(if self.dhcp_enabled {
64 b"on\n".to_vec()
65 } else {
66 b"off\n".to_vec()
67 }),
68 "ip6" | "ip6/address" => {
69 let addr = if let Some(ref cfg) = self.ipv6_config {
70 cfg.address.address()
71 } else {
72 self.link_local_addr
73 };
74 Ok(alloc::format!("{}\n", addr).into_bytes())
75 }
76 "ip6/gateway" => Ok(if let Some(ref cfg) = self.ipv6_config {
77 if let Some(gw) = cfg.gateway {
78 alloc::format!("{}\n", gw).into_bytes()
79 } else {
80 b"::\n".to_vec()
81 }
82 } else {
83 b"::\n".to_vec()
84 }),
85 "route" => Ok(if let Some(ref cfg) = self.ip_config {
86 if let Some(gw) = cfg.gateway {
87 alloc::format!("default via {}\n", gw).into_bytes()
88 } else if let Some(ref cfg6) = self.ipv6_config {
89 if let Some(gw) = cfg6.gateway {
90 alloc::format!("default via {}\n", gw).into_bytes()
91 } else {
92 b"none\n".to_vec()
93 }
94 } else {
95 b"none\n".to_vec()
96 }
97 } else if let Some(ref cfg6) = self.ipv6_config {
98 if let Some(gw) = cfg6.gateway {
99 alloc::format!("default via {}\n", gw).into_bytes()
100 } else {
101 b"none\n".to_vec()
102 }
103 } else {
104 b"none\n".to_vec()
105 }),
106 "routes" => {
107 let mut content = Vec::new();
108 self.interface.routes_mut().update(|table| {
109 for route in table.iter() {
110 let line = alloc::format!("{} via {}\n", route.cidr, route.via_router);
111 content.extend_from_slice(line.as_bytes());
112 }
113 });
114 if content.is_empty() {
115 content.extend_from_slice(b"none\n");
116 }
117 Ok(content)
118 }
119 "resolve" => Ok(b"use /net/resolve/<hostname>\n".to_vec()),
120 "tcp" => Ok(b"use /net/tcp/listen/<port>, /net/tcp/listen-once/<port>, /net/tcp/connect/<ip>/<port>[/<local_port>], /net/tcp/listeners, /net/tcp/connections, /net/tcp/stats\n".to_vec()),
121 "tcp/listeners" => {
122 let mut content = Vec::new();
123 if self.tcp_listeners.is_empty() {
124 content.extend_from_slice(b"none\n");
125 } else {
126 for (fid, listener) in self.tcp_listeners.iter() {
127 let socket = self.sockets.get::<tcp::Socket>(listener.socket);
128 let mode = if listener.auto_relisten { "auto" } else { "once" };
129 let line = alloc::format!(
130 "fid={} port={} state={} mode={}\n",
131 fid,
132 listener.port,
133 Self::tcp_state_name(socket.state()),
134 mode
135 );
136 content.extend_from_slice(line.as_bytes());
137 }
138 }
139 Ok(content)
140 }
141 "tcp/connections" => {
142 let mut content = Vec::new();
143 if self.tcp_connections.is_empty() {
144 content.extend_from_slice(b"none\n");
145 } else {
146 for (fid, conn) in self.tcp_connections.iter() {
147 let socket = self.sockets.get::<tcp::Socket>(conn.socket);
148 let local = socket.local_endpoint();
149 let remote = socket.remote_endpoint();
150 let line = match (local, remote) {
151 (Some(local), Some(remote)) => alloc::format!(
152 "fid={} local={} remote={} state={}\n",
153 fid,
154 local,
155 remote,
156 Self::tcp_state_name(socket.state())
157 ),
158 _ => alloc::format!(
159 "fid={} local_port={} remote={} state={}\n",
160 fid,
161 conn.local_port,
162 conn.remote,
163 Self::tcp_state_name(socket.state())
164 ),
165 };
166 content.extend_from_slice(line.as_bytes());
167 }
168 }
169 Ok(content)
170 }
171 "tcp/stats" => {
172 let listeners = self.tcp_listeners.len();
173 let connections = self.tcp_connections.len();
174 let mut established = 0usize;
175 let mut connecting = 0usize;
176 let mut closing = 0usize;
177 for conn in self.tcp_connections.values() {
178 let socket = self.sockets.get::<tcp::Socket>(conn.socket);
179 match socket.state() {
180 tcp::State::Established => established += 1,
181 tcp::State::SynSent | tcp::State::SynReceived => connecting += 1,
182 tcp::State::Closed => {}
183 _ => closing += 1,
184 }
185 }
186 Ok(alloc::format!(
187 "listeners={}\nconnections={}\nestablished={}\nconnecting={}\nclosing={}\n",
188 listeners,
189 connections,
190 established,
191 connecting,
192 closing
193 )
194 .into_bytes())
195 }
196 "udp" => Ok(b"use /net/udp/bind/<port>, /net/udp/connect/<ip>/<port> or /net/udp/send/<ip>/<port>\n".to_vec()),
197 path if path.starts_with("resolve/") => {
198 let name = &path[8..];
199 self.resolve_hostname_blocking(name)
200 .map(|addr| alloc::format!("{}\n", addr).into_bytes())
201 }
202 path if path.starts_with("ping/") || path.starts_with("ping6/") => {
203 if let Some((seq, rtt_us)) = self.ping_replies.first().copied() {
204 self.ping_replies.remove(0);
205 let _ = call::debug_log(b"[ping] read returning seq=");
206 let _ = call::debug_log(&[(seq >> 8) as u8, seq as u8]);
207 let _ = call::debug_log(b" rtt=");
208 let _ = call::debug_log(&[(rtt_us / 1000) as u8]);
209 let _ = call::debug_log(b"ms\n");
210 let mut buf = vec![0u8; 10];
211 buf[0..2].copy_from_slice(&seq.to_le_bytes());
212 buf[2..10].copy_from_slice(&rtt_us.to_le_bytes());
213 Ok(buf)
214 } else {
215 let _ = call::debug_log(b"[ping] read: no replies waiting\n");
216 Ok(Vec::new())
217 }
218 }
219 _ => Err(-9),
220 }
221 }
222}