Nothing to see here, move along
1#![no_std]
2#![no_main]
3
4mod device;
5mod stack;
6
7use device::PacketDevice;
8use lancer_core::dns::{
9 DNS_TYPE_A, DNS_TYPE_PTR, build_mdns_a_response, build_mdns_ptr_response, dns_name_eq,
10 dns_skip_name,
11};
12use lancer_core::net_config::NetConfig;
13use lancer_core::packet_ring::{PacketRingReader, PacketRingWriter};
14use lancer_core::sync_unsafe::SyncUnsafe;
15use lancer_user::syscall;
16use smoltcp::socket::{dhcpv4, dns, icmp, udp};
17use smoltcp::time::Duration;
18use smoltcp::time::Instant;
19use smoltcp::wire::{DnsQueryType, IpAddress, IpCidr, IpListenEndpoint, Ipv4Address, Ipv6Address};
20use stack::{MAX_SHELL_SOCKETS, MAX_UDP_SOCKETS};
21
22const PACKET_RING_BASE_SLOT: u64 = 64;
23const PACKET_RING_FRAME_COUNT: u64 = 16;
24const NOTIF_SLOT: u64 = 3;
25const DRIVER_NOTIF_SLOT: u64 = 4;
26const SHELL_RING_BASE_SLOT: u64 = 96;
27const SHELL_RING_FRAME_COUNT: u64 = 4;
28const SHELL_NOTIF_SLOT: u64 = 6;
29const INIT_RING_BASE_SLOT: u64 = 128;
30const INIT_RING_FRAME_COUNT: u64 = 2;
31const INIT_NOTIF_SLOT: u64 = 8;
32
33const RING_BASE_VADDR: u64 = 0x4000_0000;
34const RING_HALF_SIZE: usize = 32768;
35
36const SHELL_RING_BASE: u64 = 0x5000_0000;
37const SHELL_RING_HALF: usize = 8192;
38
39const INIT_RING_BASE: u64 = 0x6000_0000;
40const INIT_RING_HALF: usize = 4096;
41
42const ECHO_PORT: u16 = 7;
43const SHELL_PORT: u16 = 22;
44
45const MAC: [u8; 6] = [0x52, 0x54, 0x00, 0x12, 0x34, 0x56];
46
47const NOTIFY_BIT_RX: u64 = 1;
48const NOTIFY_BIT_TX: u64 = 2;
49
50const MSG_DATA: u8 = 0;
51const MSG_CONNECT: u8 = 1;
52const MSG_DISCONNECT: u8 = 2;
53const MSG_DNS_QUERY: u8 = 3;
54const MSG_DNS_RESULT: u8 = 4;
55const MSG_PING_REQUEST: u8 = 5;
56const MSG_PING_RESULT: u8 = 6;
57const MSG_PING_DONE: u8 = 7;
58const MSG_UDP_BIND: u8 = 8;
59const MSG_UDP_SEND: u8 = 9;
60const MSG_UDP_RECV: u8 = 10;
61const MSG_UDP_CLOSE: u8 = 11;
62const MSG_UDP_BOUND: u8 = 12;
63const MSG_DNS_QUERY6: u8 = 13;
64const MSG_DNS_RESULT6: u8 = 14;
65const MSG_PING_REQUEST6: u8 = 15;
66const MSG_IFCONFIG_REQUEST: u8 = 16;
67const MSG_IFCONFIG_RESULT: u8 = 17;
68const MSG_ARP_REQUEST: u8 = 18;
69const MSG_ARP_ENTRY: u8 = 19;
70const MSG_ARP_DONE: u8 = 20;
71const MSG_NETSTAT_REQUEST: u8 = 21;
72const MSG_NETSTAT_ENTRY: u8 = 22;
73const MSG_NETSTAT_ENTRY_UDP: u8 = 23;
74const MSG_NETSTAT_DONE: u8 = 24;
75const MSG_MCAST_JOIN: u8 = 25;
76const MSG_MCAST_LEAVE: u8 = 26;
77const MSG_MCAST_RESULT: u8 = 27;
78
79const MAX_PENDING_DNS: usize = 4;
80const MAX_PINGS: usize = 8;
81const PING_IDENT: u16 = 0x4C41;
82const PING_TIMEOUT_MS: i64 = 2000;
83const PING_INTERVAL_MS: i64 = 1000;
84
85#[derive(Clone, Copy, PartialEq, Eq)]
86enum RingSource {
87 Shell,
88 Init,
89}
90
91struct PendingPing {
92 conn_id: u8,
93 target: IpAddress,
94 total: u8,
95 sent: u8,
96 received: u8,
97 next_send_ms: i64,
98 send_times: [i64; MAX_PINGS],
99 replied_mask: u8,
100 timeout_mask: u8,
101 send_failures: u8,
102 ring_source: RingSource,
103}
104
105static mut PENDING_PING: Option<PendingPing> = None;
106
107struct PendingDns {
108 conn_id: u8,
109 handle: dns::QueryHandle,
110 is_v6: bool,
111 ring_source: RingSource,
112}
113
114static mut PENDING_DNS: [Option<PendingDns>; MAX_PENDING_DNS] = [const { None }; MAX_PENDING_DNS];
115static mut UDP_RING_SOURCE: [RingSource; MAX_UDP_SOCKETS] = [RingSource::Shell; MAX_UDP_SOCKETS];
116
117fn log_ip(prefix: &str, a: u8, b: u8, c: u8, d: u8) {
118 lancer_user::show!(net, "{}{}.{}.{}.{}", prefix, a, b, c, d);
119}
120
121fn send_router_solicitation(tx: &PacketRingWriter, mac: &[u8; 6]) {
122 let mut frame = [0u8; 70];
123
124 frame[0..6].copy_from_slice(&[0x33, 0x33, 0x00, 0x00, 0x00, 0x02]);
125 frame[6..12].copy_from_slice(mac);
126 frame[12] = 0x86;
127 frame[13] = 0xDD;
128
129 frame[14] = 0x60;
130 let payload_len: u16 = 16;
131 frame[18] = (payload_len >> 8) as u8;
132 frame[19] = payload_len as u8;
133 frame[20] = 58;
134 frame[21] = 255;
135
136 let src_addr = stack::eui64_link_local_bytes(mac);
137 frame[22..38].copy_from_slice(&src_addr);
138 frame[38..54].copy_from_slice(&[0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x02]);
139
140 frame[54] = 133;
141 frame[55] = 0;
142 frame[56] = 0;
143 frame[57] = 0;
144 frame[58..62].copy_from_slice(&[0; 4]);
145
146 frame[62] = 1;
147 frame[63] = 1;
148 frame[64..70].copy_from_slice(mac);
149
150 let cksum = icmpv6_checksum(&frame[22..38], &frame[38..54], &frame[54..70]);
151 frame[56] = (cksum >> 8) as u8;
152 frame[57] = cksum as u8;
153
154 tx.try_push(&frame[..70]);
155 lancer_user::show!(net, "sent router solicitation");
156}
157
158fn icmpv6_checksum(src: &[u8], dst: &[u8], icmpv6: &[u8]) -> u16 {
159 let mut sum = 0u32;
160
161 let add_u16 = |sum: &mut u32, hi: u8, lo: u8| {
162 *sum += ((hi as u32) << 8) | lo as u32;
163 };
164
165 (0..8).for_each(|i| {
166 add_u16(&mut sum, src[i * 2], src[i * 2 + 1]);
167 add_u16(&mut sum, dst[i * 2], dst[i * 2 + 1]);
168 });
169
170 let upper_len = icmpv6.len() as u32;
171 sum += upper_len;
172 sum += 58u32;
173
174 let mut i = 0usize;
175 core::iter::from_fn(|| match i + 1 < icmpv6.len() {
176 true => {
177 add_u16(&mut sum, icmpv6[i], icmpv6[i + 1]);
178 i += 2;
179 Some(())
180 }
181 false => None,
182 })
183 .count();
184 if i < icmpv6.len() {
185 add_u16(&mut sum, icmpv6[i], 0);
186 }
187
188 sum = (sum >> 16) + (sum & 0xFFFF);
189 sum += sum >> 16;
190 !(sum as u16)
191}
192
193static mut SLAAC_CONFIGURED: bool = false;
194static NET_CONFIG: SyncUnsafe<NetConfig> = SyncUnsafe::new(NetConfig::empty());
195
196fn configure_slaac(net: &mut stack::NetStack, slaac: &device::SlaacInfo) {
197 let already = unsafe { (&raw const SLAAC_CONFIGURED).read() };
198 if already {
199 return;
200 }
201
202 let iid = eui64_interface_id(&MAC);
203
204 let mut addr_bytes = [0u8; 16];
205 addr_bytes.copy_from_slice(&slaac.prefix);
206 let prefix_bits = slaac.prefix_len as usize;
207 (prefix_bits / 8..16).for_each(|i| {
208 let bit_start = match i == prefix_bits / 8 {
209 true => prefix_bits % 8,
210 false => 0,
211 };
212 match bit_start == 0 {
213 true => addr_bytes[i] = iid[i],
214 false => {
215 let host_mask = 0xFFu8 >> bit_start;
216 addr_bytes[i] = (addr_bytes[i] & !host_mask) | (iid[i] & host_mask);
217 }
218 }
219 });
220
221 let ipv6_addr = Ipv6Address::from_octets(addr_bytes);
222 net.iface.update_ip_addrs(|addrs| {
223 let has_global = addrs.iter().any(|a| match a {
224 IpCidr::Ipv6(cidr) => !cidr.address().is_unicast_link_local(),
225 _ => false,
226 });
227 match has_global {
228 true => {}
229 false => {
230 let _ = addrs.push(IpCidr::Ipv6(smoltcp::wire::Ipv6Cidr::new(
231 ipv6_addr,
232 slaac.prefix_len,
233 )));
234 }
235 }
236 });
237
238 let router = Ipv6Address::from_octets(slaac.router);
239 let _ = net.iface.routes_mut().add_default_ipv6_route(router);
240
241 unsafe { (&raw mut SLAAC_CONFIGURED).write(true) };
242 let cfg = unsafe { NET_CONFIG.as_mut_unchecked() };
243 cfg.set_ipv6_global(addr_bytes, slaac.prefix_len);
244 lancer_user::show!(net, "slaac global ipv6 configured");
245}
246
247fn eui64_interface_id(mac: &[u8; 6]) -> [u8; 16] {
248 let mut iid = [0u8; 16];
249 iid[8] = mac[0] ^ 0x02;
250 iid[9] = mac[1];
251 iid[10] = mac[2];
252 iid[11] = 0xFF;
253 iid[12] = 0xFE;
254 iid[13] = mac[3];
255 iid[14] = mac[4];
256 iid[15] = mac[5];
257 iid
258}
259
260fn handle_dhcp_event(net: &mut stack::NetStack, ever_configured: &mut bool) {
261 let event = {
262 let dhcp = net.sockets.get_mut::<dhcpv4::Socket>(net.dhcp_handle);
263 dhcp.poll()
264 };
265
266 match event {
267 Some(dhcpv4::Event::Configured(config)) => {
268 *ever_configured = true;
269 let addr = config.address;
270 net.iface.update_ip_addrs(|addrs| {
271 match addrs.iter_mut().find(|a| matches!(a, IpCidr::Ipv4(_))) {
272 Some(slot) => *slot = IpCidr::Ipv4(addr),
273 None => {
274 let _ = addrs.push(IpCidr::Ipv4(addr));
275 }
276 }
277 });
278
279 if let Some(router) = config.router {
280 let _ = net.iface.routes_mut().add_default_ipv4_route(router);
281 let octets = router.octets();
282 log_ip("DHCP: gateway ", octets[0], octets[1], octets[2], octets[3]);
283 }
284
285 let octets = addr.address().octets();
286 log_ip(
287 "DHCP: acquired ",
288 octets[0],
289 octets[1],
290 octets[2],
291 octets[3],
292 );
293
294 let mut dns_addrs: [IpAddress; 3] = [IpAddress::v4(0, 0, 0, 0); 3];
295 let dns_count = config.dns_servers.len().min(3);
296 let mut dns_octets = [[0u8; 4]; 3];
297 (0..dns_count).for_each(|i| {
298 dns_addrs[i] = IpAddress::Ipv4(config.dns_servers[i]);
299 dns_octets[i] = config.dns_servers[i].octets();
300 let o = dns_octets[i];
301 log_ip("DHCP: dns ", o[0], o[1], o[2], o[3]);
302 });
303
304 let gw_octets = config.router.map(|r| r.octets());
305
306 let dns = net.sockets.get_mut::<dns::Socket>(net.dns_handle);
307 dns.update_servers(&dns_addrs[..dns_count]);
308
309 let cfg = unsafe { NET_CONFIG.as_mut_unchecked() };
310 cfg.set_ipv4(octets, addr.prefix_len());
311 if let Some(gw) = gw_octets {
312 cfg.set_gateway(gw);
313 }
314 cfg.set_dns(&dns_octets, dns_count as u8);
315 }
316 Some(dhcpv4::Event::Deconfigured) if *ever_configured => {
317 lancer_user::show!(net, "dhcp lease lost");
318 net.iface.update_ip_addrs(|addrs| {
319 if let Some(idx) = (0..addrs.len()).find(|&i| matches!(addrs[i], IpCidr::Ipv4(_))) {
320 addrs.swap_remove(idx);
321 }
322 });
323 net.iface.routes_mut().remove_default_ipv4_route();
324 let cfg = unsafe { NET_CONFIG.as_mut_unchecked() };
325 cfg.clear_ipv4();
326 }
327 _ => {}
328 }
329}
330
331fn tx_for_source<'a>(
332 source: RingSource,
333 shell_tx: &'a PacketRingWriter,
334 init_tx: Option<&'a PacketRingWriter>,
335) -> &'a PacketRingWriter {
336 match source {
337 RingSource::Shell => shell_tx,
338 RingSource::Init => init_tx.expect("init ring required for Init-sourced request"),
339 }
340}
341
342#[allow(clippy::deref_addrof)]
343fn poll_pending_dns(
344 net: &mut stack::NetStack,
345 shell_tx: &PacketRingWriter,
346 init_tx: Option<&PacketRingWriter>,
347) -> (bool, bool) {
348 let pending: &mut [Option<PendingDns>; MAX_PENDING_DNS] =
349 unsafe { &mut *(&raw mut PENDING_DNS) };
350 let mut any_shell = false;
351 let mut any_init = false;
352
353 pending.iter_mut().for_each(|slot| {
354 let should_clear = match slot {
355 Some(pd) => {
356 let tx = tx_for_source(pd.ring_source, shell_tx, init_tx);
357 let dns = net.sockets.get_mut::<dns::Socket>(net.dns_handle);
358 match dns.get_query_result(pd.handle) {
359 Ok(addrs) => {
360 match pd.is_v6 {
361 false => {
362 let v4 = addrs.iter().find_map(|a| match a {
363 IpAddress::Ipv4(v4) => Some(v4.octets()),
364 _ => None,
365 });
366 let mut msg = [0u8; 8];
367 msg[0] = pd.conn_id;
368 msg[1] = MSG_DNS_RESULT;
369 match v4 {
370 Some(octets) => {
371 msg[2] = 0;
372 msg[3] = octets[0];
373 msg[4] = octets[1];
374 msg[5] = octets[2];
375 msg[6] = octets[3];
376 let _ = tx.try_push(&msg[..7]);
377 }
378 None => {
379 msg[2] = 2;
380 let _ = tx.try_push(&msg[..3]);
381 }
382 }
383 }
384 true => {
385 let v6 = addrs.iter().find_map(|a| match a {
386 IpAddress::Ipv6(v6) => Some(v6.octets()),
387 _ => None,
388 });
389 let mut msg = [0u8; 20];
390 msg[0] = pd.conn_id;
391 msg[1] = MSG_DNS_RESULT6;
392 match v6 {
393 Some(octets) => {
394 msg[2] = 0;
395 msg[3..19].copy_from_slice(&octets);
396 let _ = tx.try_push(&msg[..19]);
397 }
398 None => {
399 msg[2] = 2;
400 let _ = tx.try_push(&msg[..3]);
401 }
402 }
403 }
404 }
405 match pd.ring_source {
406 RingSource::Shell => any_shell = true,
407 RingSource::Init => any_init = true,
408 }
409 true
410 }
411 Err(dns::GetQueryResultError::Pending) => false,
412 Err(dns::GetQueryResultError::Failed) => {
413 let result_type = match pd.is_v6 {
414 true => MSG_DNS_RESULT6,
415 false => MSG_DNS_RESULT,
416 };
417 let msg = [pd.conn_id, result_type, 2];
418 let _ = tx.try_push(&msg);
419 match pd.ring_source {
420 RingSource::Shell => any_shell = true,
421 RingSource::Init => any_init = true,
422 }
423 true
424 }
425 }
426 }
427 None => false,
428 };
429 if should_clear {
430 *slot = None;
431 }
432 });
433
434 (any_shell, any_init)
435}
436
437#[allow(clippy::deref_addrof)]
438fn handle_dns_query(
439 net: &mut stack::NetStack,
440 tx: &PacketRingWriter,
441 conn_id: u8,
442 hostname_bytes: &[u8],
443 is_v6: bool,
444 source: RingSource,
445) {
446 let result_type = match is_v6 {
447 false => MSG_DNS_RESULT,
448 true => MSG_DNS_RESULT6,
449 };
450 let name = match core::str::from_utf8(hostname_bytes) {
451 Ok(s) => s,
452 Err(_) => {
453 let msg = [conn_id, result_type, 2];
454 let _ = tx.try_push(&msg);
455 return;
456 }
457 };
458
459 let query_type = match is_v6 {
460 false => DnsQueryType::A,
461 true => DnsQueryType::Aaaa,
462 };
463 let dns = net.sockets.get_mut::<dns::Socket>(net.dns_handle);
464 match dns.start_query(net.iface.context(), name, query_type) {
465 Ok(handle) => {
466 let pending: &mut [Option<PendingDns>; MAX_PENDING_DNS] =
467 unsafe { &mut *(&raw mut PENDING_DNS) };
468 match pending.iter_mut().find(|s| s.is_none()) {
469 Some(slot) => {
470 *slot = Some(PendingDns {
471 conn_id,
472 handle,
473 is_v6,
474 ring_source: source,
475 });
476 }
477 None => {
478 dns.cancel_query(handle);
479 let msg = [conn_id, result_type, 2];
480 let _ = tx.try_push(&msg);
481 }
482 }
483 }
484 Err(_) => {
485 let msg = [conn_id, result_type, 2];
486 let _ = tx.try_push(&msg);
487 }
488 }
489}
490
491fn icmp_checksum(data: &[u8]) -> u16 {
492 let mut sum = 0u32;
493 let mut i = 0usize;
494 core::iter::from_fn(|| match i + 1 < data.len() {
495 true => {
496 sum += ((data[i] as u32) << 8) | (data[i + 1] as u32);
497 i += 2;
498 Some(())
499 }
500 false => None,
501 })
502 .count();
503 if i < data.len() {
504 sum += (data[i] as u32) << 8;
505 }
506 sum = (sum >> 16) + (sum & 0xFFFF);
507 sum += sum >> 16;
508 !(sum as u16)
509}
510
511#[allow(clippy::deref_addrof)]
512fn ping_send(net: &mut stack::NetStack, now_ms: i64) {
513 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
514 let pp = match pending.as_mut() {
515 Some(pp) => pp,
516 None => return,
517 };
518
519 if pp.sent >= pp.total || now_ms < pp.next_send_ms {
520 return;
521 }
522
523 let seq = pp.sent as u16;
524 let icmp_type = match pp.target {
525 IpAddress::Ipv4(_) => 8u8,
526 IpAddress::Ipv6(_) => 128u8,
527 };
528
529 let mut packet = [0u8; 12];
530 packet[0] = icmp_type;
531 packet[1] = 0;
532 packet[4] = (PING_IDENT >> 8) as u8;
533 packet[5] = PING_IDENT as u8;
534 packet[6] = (seq >> 8) as u8;
535 packet[7] = seq as u8;
536 let ts = now_ms as u32;
537 packet[8] = (ts >> 24) as u8;
538 packet[9] = (ts >> 16) as u8;
539 packet[10] = (ts >> 8) as u8;
540 packet[11] = ts as u8;
541
542 match pp.target {
543 IpAddress::Ipv4(_) => {
544 let cksum = icmp_checksum(&packet);
545 packet[2] = (cksum >> 8) as u8;
546 packet[3] = cksum as u8;
547 }
548 IpAddress::Ipv6(_) => {}
549 }
550
551 let socket = net.sockets.get_mut::<icmp::Socket>(net.icmp_handle);
552 match socket.send_slice(&packet, pp.target) {
553 Ok(()) => {
554 pp.send_failures = 0;
555 pp.send_times[pp.sent as usize] = now_ms;
556 pp.sent += 1;
557 pp.next_send_ms = now_ms + PING_INTERVAL_MS;
558 }
559 Err(_) => {
560 pp.send_failures += 1;
561 match pp.send_failures >= 4 {
562 true => {
563 pp.send_failures = 0;
564 pp.send_times[pp.sent as usize] = 0;
565 pp.sent += 1;
566 pp.next_send_ms = now_ms + PING_INTERVAL_MS;
567 }
568 false => {
569 pp.next_send_ms = now_ms + 200;
570 }
571 }
572 }
573 }
574}
575
576#[allow(clippy::deref_addrof)]
577fn ping_recv(
578 net: &mut stack::NetStack,
579 shell_tx: &PacketRingWriter,
580 init_tx: Option<&PacketRingWriter>,
581 now_ms: i64,
582) -> (bool, bool) {
583 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
584 let pp = match pending.as_mut() {
585 Some(pp) => pp,
586 None => return (false, false),
587 };
588
589 let tx = tx_for_source(pp.ring_source, shell_tx, init_tx);
590 let socket = net.sockets.get_mut::<icmp::Socket>(net.icmp_handle);
591 let mut buf = [0u8; 64];
592 let mut any_result = false;
593
594 core::iter::from_fn(|| match socket.recv_slice(&mut buf) {
595 Ok((len, _addr)) if len >= 8 => {
596 let typ = buf[0];
597 let ident = ((buf[4] as u16) << 8) | buf[5] as u16;
598 let seq = ((buf[6] as u16) << 8) | buf[7] as u16;
599
600 let reply_type = match pp.target {
601 IpAddress::Ipv4(_) => 0u8,
602 IpAddress::Ipv6(_) => 129u8,
603 };
604 if typ == reply_type && ident == PING_IDENT && seq < pp.sent as u16 {
605 let seq_idx = seq as u8;
606 if pp.replied_mask & (1 << seq_idx) == 0 {
607 pp.replied_mask |= 1 << seq_idx;
608 pp.received += 1;
609 let rtt = (now_ms - pp.send_times[seq_idx as usize]).max(0) as u16;
610 let msg = [
611 pp.conn_id,
612 MSG_PING_RESULT,
613 seq_idx,
614 0,
615 (rtt >> 8) as u8,
616 rtt as u8,
617 ];
618 let _ = tx.try_push(&msg);
619 any_result = true;
620 }
621 }
622 Some(())
623 }
624 _ => None,
625 })
626 .take(4)
627 .count();
628
629 match any_result {
630 true => match pp.ring_source {
631 RingSource::Shell => (true, false),
632 RingSource::Init => (false, true),
633 },
634 false => (false, false),
635 }
636}
637
638#[allow(clippy::deref_addrof)]
639fn ping_timeout(
640 shell_tx: &PacketRingWriter,
641 init_tx: Option<&PacketRingWriter>,
642 now_ms: i64,
643) -> (bool, bool) {
644 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
645 let pp = match pending.as_mut() {
646 Some(pp) => pp,
647 None => return (false, false),
648 };
649
650 let tx = tx_for_source(pp.ring_source, shell_tx, init_tx);
651 let mut any_timeout = false;
652 (0..pp.sent).for_each(|seq| {
653 let mask = 1u8 << seq;
654 if pp.replied_mask & mask != 0 || pp.timeout_mask & mask != 0 {
655 return;
656 }
657 if now_ms - pp.send_times[seq as usize] > PING_TIMEOUT_MS {
658 pp.timeout_mask |= mask;
659 let msg = [pp.conn_id, MSG_PING_RESULT, seq, 1, 0, 0];
660 let _ = tx.try_push(&msg);
661 any_timeout = true;
662 }
663 });
664
665 match any_timeout {
666 true => match pp.ring_source {
667 RingSource::Shell => (true, false),
668 RingSource::Init => (false, true),
669 },
670 false => (false, false),
671 }
672}
673
674#[allow(clippy::deref_addrof)]
675fn ping_check_done(
676 shell_tx: &PacketRingWriter,
677 init_tx: Option<&PacketRingWriter>,
678) -> (bool, bool) {
679 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
680 let pp = match pending.as_ref() {
681 Some(pp) => pp,
682 None => return (false, false),
683 };
684
685 let all_accounted = pp.sent == pp.total
686 && (pp.replied_mask | pp.timeout_mask) == ((1u16 << pp.total) - 1) as u8;
687
688 match all_accounted {
689 true => {
690 let source = pp.ring_source;
691 let tx = tx_for_source(source, shell_tx, init_tx);
692 let msg = [pp.conn_id, MSG_PING_DONE, pp.received, pp.total];
693 let _ = tx.try_push(&msg);
694 *pending = None;
695 match source {
696 RingSource::Shell => (true, false),
697 RingSource::Init => (false, true),
698 }
699 }
700 false => (false, false),
701 }
702}
703
704#[allow(clippy::deref_addrof)]
705fn handle_ping_request(
706 tx: &PacketRingWriter,
707 conn_id: u8,
708 data: &[u8],
709 now_ms: i64,
710 source: RingSource,
711) {
712 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
713 if pending.is_some() {
714 let msg = [conn_id, MSG_PING_DONE, 0, 0];
715 let _ = tx.try_push(&msg);
716 return;
717 }
718
719 if data.len() < 5 {
720 let msg = [conn_id, MSG_PING_DONE, 0, 0];
721 let _ = tx.try_push(&msg);
722 return;
723 }
724
725 let target = IpAddress::Ipv4(Ipv4Address::new(data[0], data[1], data[2], data[3]));
726 let count = data[4].clamp(1, MAX_PINGS as u8);
727
728 *pending = Some(PendingPing {
729 conn_id,
730 target,
731 total: count,
732 sent: 0,
733 received: 0,
734 next_send_ms: now_ms,
735 send_times: [0i64; MAX_PINGS],
736 replied_mask: 0,
737 timeout_mask: 0,
738 send_failures: 0,
739 ring_source: source,
740 });
741}
742
743#[allow(clippy::deref_addrof)]
744fn handle_ping_request6(
745 tx: &PacketRingWriter,
746 conn_id: u8,
747 data: &[u8],
748 now_ms: i64,
749 source: RingSource,
750) {
751 let pending: &mut Option<PendingPing> = unsafe { &mut *(&raw mut PENDING_PING) };
752 if pending.is_some() {
753 let msg = [conn_id, MSG_PING_DONE, 0, 0];
754 let _ = tx.try_push(&msg);
755 return;
756 }
757
758 if data.len() < 17 {
759 let msg = [conn_id, MSG_PING_DONE, 0, 0];
760 let _ = tx.try_push(&msg);
761 return;
762 }
763
764 let mut addr_bytes = [0u8; 16];
765 addr_bytes.copy_from_slice(&data[..16]);
766 let target = IpAddress::Ipv6(Ipv6Address::from_octets(addr_bytes));
767 let count = data[16].clamp(1, MAX_PINGS as u8);
768
769 *pending = Some(PendingPing {
770 conn_id,
771 target,
772 total: count,
773 sent: 0,
774 received: 0,
775 next_send_ms: now_ms,
776 send_times: [0i64; MAX_PINGS],
777 replied_mask: 0,
778 timeout_mask: 0,
779 send_failures: 0,
780 ring_source: source,
781 });
782}
783
784#[allow(clippy::deref_addrof)]
785fn handle_udp_bind(
786 net: &mut stack::NetStack,
787 tx: &PacketRingWriter,
788 conn_id: u8,
789 data: &[u8],
790 source: RingSource,
791) {
792 if data.len() < 2 || (conn_id as usize) >= MAX_UDP_SOCKETS {
793 let msg = [conn_id, MSG_UDP_BOUND, 1];
794 let _ = tx.try_push(&msg);
795 return;
796 }
797
798 let udp_sources: &mut [RingSource; MAX_UDP_SOCKETS] =
799 unsafe { &mut *(&raw mut UDP_RING_SOURCE) };
800 udp_sources[conn_id as usize] = source;
801
802 let port = ((data[0] as u16) << 8) | data[1] as u16;
803 let socket = net
804 .sockets
805 .get_mut::<udp::Socket>(net.udp_handles[conn_id as usize]);
806 socket.close();
807 match socket.bind(IpListenEndpoint { addr: None, port }) {
808 Ok(()) => {
809 lancer_user::show!(net, "udp bind ok");
810 let msg = [conn_id, MSG_UDP_BOUND, 0];
811 let _ = tx.try_push(&msg);
812 }
813 Err(_) => {
814 let msg = [conn_id, MSG_UDP_BOUND, 1];
815 let _ = tx.try_push(&msg);
816 }
817 }
818}
819
820#[allow(clippy::deref_addrof)]
821fn handle_udp_send(net: &mut stack::NetStack, conn_id: u8, data: &[u8], source: RingSource) {
822 if data.len() < 7 || (conn_id as usize) >= MAX_UDP_SOCKETS {
823 return;
824 }
825
826 let udp_sources: &mut [RingSource; MAX_UDP_SOCKETS] =
827 unsafe { &mut *(&raw mut UDP_RING_SOURCE) };
828 udp_sources[conn_id as usize] = source;
829
830 let ip = Ipv4Address::new(data[0], data[1], data[2], data[3]);
831 let port = ((data[4] as u16) << 8) | data[5] as u16;
832 let payload = &data[6..];
833
834 let socket = net
835 .sockets
836 .get_mut::<udp::Socket>(net.udp_handles[conn_id as usize]);
837 if !socket.is_open() {
838 let ephemeral = 49152 + conn_id as u16;
839 let _ = socket.bind(IpListenEndpoint {
840 addr: None,
841 port: ephemeral,
842 });
843 }
844 let _ = socket.send_slice(payload, (IpAddress::Ipv4(ip), port));
845}
846
847fn handle_udp_close(net: &mut stack::NetStack, conn_id: u8) {
848 if (conn_id as usize) >= MAX_UDP_SOCKETS {
849 return;
850 }
851 let socket = net
852 .sockets
853 .get_mut::<udp::Socket>(net.udp_handles[conn_id as usize]);
854 socket.close();
855}
856
857#[allow(clippy::deref_addrof)]
858fn poll_udp_recv(
859 net: &mut stack::NetStack,
860 shell_tx: &PacketRingWriter,
861 init_tx: Option<&PacketRingWriter>,
862) -> (bool, bool) {
863 let udp_sources: &[RingSource; MAX_UDP_SOCKETS] = unsafe { &*(&raw const UDP_RING_SOURCE) };
864 let mut any_shell = false;
865 let mut any_init = false;
866 (0..MAX_UDP_SOCKETS).for_each(|i| {
867 let socket = net.sockets.get_mut::<udp::Socket>(net.udp_handles[i]);
868 if socket.is_open() && socket.can_recv() {
869 lancer_user::show!(net, "udp socket has data");
870 }
871 let tx = tx_for_source(udp_sources[i], shell_tx, init_tx);
872 let source = udp_sources[i];
873 let mut buf = [0u8; 128];
874 core::iter::from_fn(|| match socket.can_recv() {
875 true => match socket.recv_slice(&mut buf[8..126]) {
876 Ok((len, endpoint)) => {
877 match endpoint.endpoint.addr {
878 IpAddress::Ipv4(ip) => {
879 let o = ip.octets();
880 let port = endpoint.endpoint.port;
881 buf[0] = i as u8;
882 buf[1] = MSG_UDP_RECV;
883 buf[2] = o[0];
884 buf[3] = o[1];
885 buf[4] = o[2];
886 buf[5] = o[3];
887 buf[6] = (port >> 8) as u8;
888 buf[7] = port as u8;
889 let _ = tx.try_push(&buf[..8 + len]);
890 match source {
891 RingSource::Shell => any_shell = true,
892 RingSource::Init => any_init = true,
893 }
894 }
895 IpAddress::Ipv6(_) => {}
896 }
897 Some(())
898 }
899 Err(_) => None,
900 },
901 false => None,
902 })
903 .take(4)
904 .count();
905 });
906 (any_shell, any_init)
907}
908
909fn handle_ifconfig_request(tx: &PacketRingWriter, conn_id: u8) {
910 let cfg: &NetConfig = unsafe { NET_CONFIG.as_ref_unchecked() };
911 let mut msg = [0u8; 64];
912 msg[0] = conn_id;
913 msg[1] = MSG_IFCONFIG_RESULT;
914 let n = cfg.serialize(&mut msg[2..]);
915 let _ = tx.try_push(&msg[..2 + n]);
916}
917
918fn handle_arp_request(tx: &PacketRingWriter, conn_id: u8, now_ms: i64) {
919 let table = device::arp_table();
920 table.iter().filter(|e| e.valid).for_each(|entry| {
921 let age_secs = ((now_ms - entry.timestamp_ms) / 1000).max(0) as u16;
922 let mut msg = [0u8; 14];
923 msg[0] = conn_id;
924 msg[1] = MSG_ARP_ENTRY;
925 msg[2..6].copy_from_slice(&entry.ip);
926 msg[6..12].copy_from_slice(&entry.mac);
927 msg[12] = (age_secs >> 8) as u8;
928 msg[13] = age_secs as u8;
929 let _ = tx.try_push(&msg);
930 });
931 let done = [conn_id, MSG_ARP_DONE];
932 let _ = tx.try_push(&done);
933}
934
935fn handle_netstat_request(net: &mut stack::NetStack, tx: &PacketRingWriter, conn_id: u8) {
936 let encode_tcp =
937 |socket: &smoltcp::socket::tcp::Socket, msg: &mut [u8; 20], conn: u8| -> usize {
938 msg[0] = conn;
939 msg[1] = MSG_NETSTAT_ENTRY;
940 msg[2] = 6;
941 msg[3] = match socket.state() {
942 smoltcp::socket::tcp::State::Closed => 0,
943 smoltcp::socket::tcp::State::Listen => 1,
944 smoltcp::socket::tcp::State::SynSent => 2,
945 smoltcp::socket::tcp::State::SynReceived => 3,
946 smoltcp::socket::tcp::State::Established => 4,
947 smoltcp::socket::tcp::State::FinWait1 => 5,
948 smoltcp::socket::tcp::State::FinWait2 => 6,
949 smoltcp::socket::tcp::State::CloseWait => 7,
950 smoltcp::socket::tcp::State::Closing => 8,
951 smoltcp::socket::tcp::State::LastAck => 9,
952 smoltcp::socket::tcp::State::TimeWait => 10,
953 };
954 let (lip, lport) = match socket.local_endpoint() {
955 Some(ep) => {
956 let ip = match ep.addr {
957 IpAddress::Ipv4(a) => a.octets(),
958 _ => [0; 4],
959 };
960 (ip, ep.port)
961 }
962 None => {
963 let listen = socket.listen_endpoint();
964 let ip = match listen.addr {
965 Some(IpAddress::Ipv4(a)) => a.octets(),
966 _ => [0; 4],
967 };
968 (ip, listen.port)
969 }
970 };
971 msg[4..8].copy_from_slice(&lip);
972 msg[8] = (lport >> 8) as u8;
973 msg[9] = lport as u8;
974 let remote = socket.remote_endpoint();
975 let rip = match remote {
976 Some(ep) => match ep.addr {
977 IpAddress::Ipv4(a) => a.octets(),
978 _ => [0; 4],
979 },
980 None => [0; 4],
981 };
982 let rport = remote.map_or(0u16, |ep| ep.port);
983 msg[10..14].copy_from_slice(&rip);
984 msg[14] = (rport >> 8) as u8;
985 msg[15] = rport as u8;
986 let sq = socket.send_queue() as u16;
987 let rq = socket.recv_queue() as u16;
988 msg[16] = (sq >> 8) as u8;
989 msg[17] = sq as u8;
990 msg[18] = (rq >> 8) as u8;
991 msg[19] = rq as u8;
992 20
993 };
994
995 let mut msg = [0u8; 20];
996
997 let echo_sock = net
998 .sockets
999 .get_mut::<smoltcp::socket::tcp::Socket>(net.tcp_handle);
1000 let len = encode_tcp(echo_sock, &mut msg, conn_id);
1001 let _ = tx.try_push(&msg[..len]);
1002
1003 net.shell_handles.iter().for_each(|&h| {
1004 let sock = net.sockets.get_mut::<smoltcp::socket::tcp::Socket>(h);
1005 let len = encode_tcp(sock, &mut msg, conn_id);
1006 let _ = tx.try_push(&msg[..len]);
1007 });
1008
1009 net.udp_handles.iter().for_each(|&h| {
1010 let sock = net.sockets.get_mut::<udp::Socket>(h);
1011 let port = sock.endpoint().port;
1012 if port != 0 {
1013 let rq = sock.payload_recv_capacity() as u16;
1014 let mut umsg = [0u8; 6];
1015 umsg[0] = conn_id;
1016 umsg[1] = MSG_NETSTAT_ENTRY_UDP;
1017 umsg[2] = (port >> 8) as u8;
1018 umsg[3] = port as u8;
1019 umsg[4] = (rq >> 8) as u8;
1020 umsg[5] = rq as u8;
1021 let _ = tx.try_push(&umsg);
1022 }
1023 });
1024
1025 let done = [conn_id, MSG_NETSTAT_DONE];
1026 let _ = tx.try_push(&done);
1027}
1028
1029fn is_multicast_addr(octet: u8) -> bool {
1030 (224..=239).contains(&octet)
1031}
1032
1033fn handle_mcast_join(net: &mut stack::NetStack, tx: &PacketRingWriter, conn_id: u8, data: &[u8]) {
1034 let status = match data.len() >= 4 && is_multicast_addr(data[0]) {
1035 true => {
1036 let addr = Ipv4Address::new(data[0], data[1], data[2], data[3]);
1037 match net.iface.join_multicast_group(addr) {
1038 Ok(()) => 0u8,
1039 Err(_) => 1u8,
1040 }
1041 }
1042 false => 1u8,
1043 };
1044 let msg = [conn_id, MSG_MCAST_RESULT, status];
1045 let _ = tx.try_push(&msg);
1046}
1047
1048fn handle_mcast_leave(net: &mut stack::NetStack, tx: &PacketRingWriter, conn_id: u8, data: &[u8]) {
1049 let status = match data.len() >= 4 && is_multicast_addr(data[0]) {
1050 true => {
1051 let addr = Ipv4Address::new(data[0], data[1], data[2], data[3]);
1052 match net.iface.leave_multicast_group(addr) {
1053 Ok(()) => 0u8,
1054 Err(_) => 1u8,
1055 }
1056 }
1057 false => 1u8,
1058 };
1059 let msg = [conn_id, MSG_MCAST_RESULT, status];
1060 let _ = tx.try_push(&msg);
1061}
1062
1063#[derive(Clone, Copy, PartialEq, Eq)]
1064enum MdnsName {
1065 LancerLocal,
1066 LancerTcpLocal,
1067 Unknown,
1068}
1069
1070const MDNS_MULTICAST_DEST: (IpAddress, u16) =
1071 (IpAddress::Ipv4(Ipv4Address::new(224, 0, 0, 251)), 5353);
1072
1073fn poll_mdns(net: &mut stack::NetStack) {
1074 let cfg: &NetConfig = unsafe { NET_CONFIG.as_ref_unchecked() };
1075 let ip = cfg.ipv4;
1076 if ip == [0, 0, 0, 0] {
1077 return;
1078 }
1079
1080 let mdns_handle = net.mdns_handle;
1081 let socket = net.sockets.get_mut::<udp::Socket>(mdns_handle);
1082 let mut recv_buf = [0u8; 1500];
1083 let mut resp_buf = [0u8; 1500];
1084
1085 core::iter::from_fn(|| match socket.can_recv() {
1086 true => match socket.recv_slice(&mut recv_buf) {
1087 Ok((len, endpoint)) if len >= 12 => {
1088 let flags = ((recv_buf[2] as u16) << 8) | recv_buf[3] as u16;
1089 let is_query = flags & 0x8000 == 0;
1090 let qdcount = ((recv_buf[4] as u16) << 8) | recv_buf[5] as u16;
1091
1092 if is_query && qdcount >= 1 {
1093 let mut qpos = 12usize;
1094 let wire = &recv_buf[..len];
1095 (0..qdcount.min(16)).for_each(|_| {
1096 if qpos >= len {
1097 return;
1098 }
1099 let lancer_local: &[&[u8]] = &[b"lancer", b"local"];
1100 let svc_local: &[&[u8]] = &[b"_lancer", b"_tcp", b"local"];
1101
1102 let (name, after_name) = match dns_name_eq(wire, qpos, lancer_local) {
1103 Some(end) => (MdnsName::LancerLocal, end),
1104 None => match dns_name_eq(wire, qpos, svc_local) {
1105 Some(end) => (MdnsName::LancerTcpLocal, end),
1106 None => match dns_skip_name(wire, qpos) {
1107 Some(end) => (MdnsName::Unknown, end),
1108 None => {
1109 qpos = len;
1110 return;
1111 }
1112 },
1113 },
1114 };
1115
1116 match after_name + 4 <= len {
1117 true => {
1118 let qtype = ((recv_buf[after_name] as u16) << 8)
1119 | recv_buf[after_name + 1] as u16;
1120 let qclass = ((recv_buf[after_name + 2] as u16) << 8)
1121 | recv_buf[after_name + 3] as u16;
1122 let qu_bit = qclass & 0x8000 != 0;
1123 qpos = after_name + 4;
1124
1125 let resp_len = match (name, qtype) {
1126 (MdnsName::LancerLocal, DNS_TYPE_A)
1127 | (MdnsName::LancerLocal, 255) => {
1128 build_mdns_a_response(&mut resp_buf, ip).unwrap_or(0)
1129 }
1130 (MdnsName::LancerTcpLocal, DNS_TYPE_PTR)
1131 | (MdnsName::LancerTcpLocal, 255) => {
1132 build_mdns_ptr_response(&mut resp_buf, ip, SHELL_PORT)
1133 .unwrap_or(0)
1134 }
1135 _ => 0,
1136 };
1137
1138 if resp_len > 0 {
1139 let dest = match qu_bit {
1140 true => (endpoint.endpoint.addr, endpoint.endpoint.port),
1141 false => MDNS_MULTICAST_DEST,
1142 };
1143 let _ = socket.send_slice(&resp_buf[..resp_len], dest);
1144 }
1145 }
1146 false => {
1147 qpos = len;
1148 }
1149 }
1150 });
1151 }
1152 Some(())
1153 }
1154 _ => None,
1155 },
1156 false => None,
1157 })
1158 .take(4)
1159 .count();
1160}
1161
1162#[unsafe(no_mangle)]
1163pub extern "C" fn lancer_main() -> ! {
1164 lancer_user::show!(net, "starting");
1165
1166 if !(0..PACKET_RING_FRAME_COUNT).all(|i| syscall::frame_map(PACKET_RING_BASE_SLOT + i, RING_BASE_VADDR + i * 4096, 1) >= 0) {
1167 lancer_user::show!(net, error, "packet ring frame_map failed");
1168 syscall::exit();
1169 }
1170
1171 let rx_ring_base = RING_BASE_VADDR as *mut u8;
1172 let tx_ring_base = (RING_BASE_VADDR + RING_HALF_SIZE as u64) as *mut u8;
1173
1174 let rx_reader = unsafe { PacketRingReader::attach(rx_ring_base, RING_HALF_SIZE) };
1175 let tx_writer = unsafe { PacketRingWriter::init(tx_ring_base, RING_HALF_SIZE, 2048) };
1176
1177 let mut dev = PacketDevice {
1178 rx: rx_reader,
1179 tx: tx_writer,
1180 };
1181
1182 if !(0..SHELL_RING_FRAME_COUNT).all(|i| syscall::frame_map(SHELL_RING_BASE_SLOT + i, SHELL_RING_BASE + i * 4096, 1) >= 0) {
1183 lancer_user::show!(net, error, "shell ring frame_map failed");
1184 syscall::exit();
1185 }
1186
1187 let shell_tx_base = SHELL_RING_BASE as *mut u8;
1188 let shell_rx_base = (SHELL_RING_BASE + SHELL_RING_HALF as u64) as *mut u8;
1189
1190 let shell_tx = unsafe { PacketRingWriter::init(shell_tx_base, SHELL_RING_HALF, 128) };
1191 let _ = unsafe { PacketRingWriter::init(shell_rx_base, SHELL_RING_HALF, 128) };
1192 let shell_rx = unsafe { PacketRingReader::attach(shell_rx_base, SHELL_RING_HALF) };
1193
1194 lancer_user::show!(net, "shell ring mapped");
1195
1196 let has_init_ring = (0..INIT_RING_FRAME_COUNT).all(|i| syscall::frame_map(INIT_RING_BASE_SLOT + i, INIT_RING_BASE + i * 4096, 1) >= 0);
1197 let (init_tx, init_rx) = match has_init_ring {
1198 true => {
1199 let itx_base = INIT_RING_BASE as *mut u8;
1200 let irx_base = (INIT_RING_BASE + INIT_RING_HALF as u64) as *mut u8;
1201 let itx = unsafe { PacketRingWriter::init(itx_base, INIT_RING_HALF, 128) };
1202 let _ = unsafe { PacketRingWriter::init(irx_base, INIT_RING_HALF, 128) };
1203 let irx = unsafe { PacketRingReader::attach(irx_base, INIT_RING_HALF) };
1204 lancer_user::show!(net, "init ring mapped");
1205 (Some(itx), Some(irx))
1206 }
1207 false => {
1208 lancer_user::show!(net, "init ring not available");
1209 (None, None)
1210 }
1211 };
1212
1213 let now_ms = match syscall::clock_monotonic_ms() {
1214 ms if ms >= 0 => ms,
1215 _ => 0,
1216 };
1217 let now = Instant::from_millis(now_ms);
1218
1219 let mut net = stack::create(&mut dev, MAC, now);
1220
1221 if stack::MDNS_JOIN_FAILED.load(core::sync::atomic::Ordering::Relaxed) {
1222 lancer_user::show!(net, warn, "failed to join mdns multicast group");
1223 }
1224
1225 let cfg = unsafe { NET_CONFIG.as_mut_unchecked() };
1226 cfg.set_mac(MAC);
1227 cfg.set_ipv6_link_local(stack::eui64_link_local_bytes(&MAC));
1228
1229 lancer_user::show!(net, "interface up, ipv6 link-local + awaiting dhcpv4");
1230
1231 send_router_solicitation(&dev.tx, &MAC);
1232
1233 {
1234 let socket = net
1235 .sockets
1236 .get_mut::<smoltcp::socket::tcp::Socket>(net.tcp_handle);
1237 match socket.listen(ECHO_PORT) {
1238 Ok(()) => {}
1239 Err(_) => {
1240 lancer_user::show!(net, warn, "echo listen failed");
1241 }
1242 }
1243 }
1244 lancer_user::show!(net, "tcp echo listening on :7");
1245
1246 let shell_handles = net.shell_handles;
1247 {
1248 let socket = net
1249 .sockets
1250 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[0]);
1251 match socket.listen(SHELL_PORT) {
1252 Ok(()) => {}
1253 Err(_) => {
1254 lancer_user::show!(net, warn, "shell listen failed");
1255 }
1256 }
1257 }
1258 lancer_user::show!(net, "tcp shell listening on :22");
1259
1260 let mut echo_buf = [0u8; 1024];
1261 let mut shell_ring_buf = [0u8; 128];
1262 let mut init_ring_buf = [0u8; 128];
1263 let mut pkt_buf = [0u8; 128];
1264 let mut shell_connected = [false; MAX_SHELL_SOCKETS];
1265 let mut dhcp_configured = false;
1266 let init_tx_ref = init_tx.as_ref();
1267
1268 loop {
1269 let now_ms = syscall::clock_monotonic_ms().max(0);
1270 let now = Instant::from_millis(now_ms);
1271
1272 net.iface.poll(now, &mut dev, &mut net.sockets);
1273
1274 handle_dhcp_event(&mut net, &mut dhcp_configured);
1275
1276 if let Some(slaac) = device::take_slaac_prefix() {
1277 configure_slaac(&mut net, &slaac);
1278 }
1279
1280 poll_mdns(&mut net);
1281
1282 let (dns_shell, dns_init) = poll_pending_dns(&mut net, &shell_tx, init_tx_ref);
1283
1284 ping_send(&mut net, now_ms);
1285 let (pr_shell, pr_init) = ping_recv(&mut net, &shell_tx, init_tx_ref, now_ms);
1286 let (pt_shell, pt_init) = ping_timeout(&shell_tx, init_tx_ref, now_ms);
1287 let (pd_shell, pd_init) = ping_check_done(&shell_tx, init_tx_ref);
1288 let (ur_shell, ur_init) = poll_udp_recv(&mut net, &shell_tx, init_tx_ref);
1289
1290 {
1291 let socket = net
1292 .sockets
1293 .get_mut::<smoltcp::socket::tcp::Socket>(net.tcp_handle);
1294
1295 if socket.may_recv() && socket.may_send() {
1296 match socket.recv_slice(&mut echo_buf) {
1297 Ok(n) if n > 0 => {
1298 let _ = socket.send_slice(&echo_buf[..n]);
1299 }
1300 _ => {}
1301 }
1302 }
1303
1304 let needs_relisten = match socket.state() {
1305 smoltcp::socket::tcp::State::CloseWait => {
1306 socket.close();
1307 false
1308 }
1309 smoltcp::socket::tcp::State::TimeWait
1310 | smoltcp::socket::tcp::State::LastAck
1311 | smoltcp::socket::tcp::State::Closing
1312 | smoltcp::socket::tcp::State::FinWait1
1313 | smoltcp::socket::tcp::State::FinWait2
1314 | smoltcp::socket::tcp::State::Closed => true,
1315 _ => false,
1316 };
1317
1318 if needs_relisten {
1319 socket.abort();
1320 let _ = socket.listen(ECHO_PORT);
1321 }
1322 }
1323
1324 let mut any_shell_notify = dns_shell || pr_shell || pt_shell || pd_shell || ur_shell;
1325 let mut any_init_notify = dns_init || pr_init || pt_init || pd_init || ur_init;
1326
1327 (0..MAX_SHELL_SOCKETS).for_each(|i| {
1328 let socket = net
1329 .sockets
1330 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1331
1332 let fully_open = socket.may_send() && socket.may_recv();
1333
1334 if fully_open && !shell_connected[i] {
1335 shell_connected[i] = true;
1336 let ctrl = [i as u8, MSG_CONNECT];
1337 if shell_tx.try_push(&ctrl) {
1338 any_shell_notify = true;
1339 }
1340 }
1341
1342 if !fully_open && shell_connected[i] {
1343 shell_connected[i] = false;
1344 let ctrl = [i as u8, MSG_DISCONNECT];
1345 if shell_tx.try_push(&ctrl) {
1346 any_shell_notify = true;
1347 }
1348 }
1349
1350 if socket.state() == smoltcp::socket::tcp::State::CloseWait {
1351 socket.close();
1352 }
1353
1354 if shell_connected[i] && socket.may_recv() {
1355 let pushed =
1356 core::iter::from_fn(|| match shell_tx.has_space() && socket.may_recv() {
1357 true => match socket.recv_slice(&mut pkt_buf[2..126]) {
1358 Ok(n) if n > 0 => {
1359 pkt_buf[0] = i as u8;
1360 pkt_buf[1] = MSG_DATA;
1361 shell_tx.try_push(&pkt_buf[..2 + n]).then_some(())
1362 }
1363 _ => None,
1364 },
1365 false => None,
1366 })
1367 .take(8)
1368 .count();
1369 if pushed > 0 {
1370 any_shell_notify = true;
1371 }
1372 }
1373 });
1374
1375 let any_listening = (0..MAX_SHELL_SOCKETS).any(|i| {
1376 net.sockets
1377 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i])
1378 .is_listening()
1379 });
1380
1381 if !any_listening
1382 && let Some(i) = (0..MAX_SHELL_SOCKETS).find(|&i| {
1383 let s = net
1384 .sockets
1385 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1386 !s.is_open() && !s.is_listening()
1387 })
1388 {
1389 let s = net
1390 .sockets
1391 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1392 s.abort();
1393 s.set_nagle_enabled(false);
1394 s.set_ack_delay(None);
1395 s.set_keep_alive(Some(Duration::from_secs(30)));
1396 let _ = s.listen(SHELL_PORT);
1397 }
1398
1399 core::iter::from_fn(|| match shell_rx.try_pop(&mut shell_ring_buf) {
1400 Some(n) if n >= 2 => {
1401 let conn_id = shell_ring_buf[0] as usize;
1402 let msg_type = shell_ring_buf[1];
1403 match msg_type {
1404 MSG_DNS_QUERY if n > 2 => {
1405 handle_dns_query(
1406 &mut net,
1407 &shell_tx,
1408 conn_id as u8,
1409 &shell_ring_buf[2..n],
1410 false,
1411 RingSource::Shell,
1412 );
1413 any_shell_notify = true;
1414 }
1415 MSG_DNS_QUERY6 if n > 2 => {
1416 handle_dns_query(
1417 &mut net,
1418 &shell_tx,
1419 conn_id as u8,
1420 &shell_ring_buf[2..n],
1421 true,
1422 RingSource::Shell,
1423 );
1424 any_shell_notify = true;
1425 }
1426 MSG_PING_REQUEST if n >= 7 => {
1427 handle_ping_request(
1428 &shell_tx,
1429 conn_id as u8,
1430 &shell_ring_buf[2..n],
1431 now_ms,
1432 RingSource::Shell,
1433 );
1434 any_shell_notify = true;
1435 }
1436 MSG_PING_REQUEST6 if n >= 19 => {
1437 handle_ping_request6(
1438 &shell_tx,
1439 conn_id as u8,
1440 &shell_ring_buf[2..n],
1441 now_ms,
1442 RingSource::Shell,
1443 );
1444 any_shell_notify = true;
1445 }
1446 MSG_UDP_BIND if n >= 4 => {
1447 handle_udp_bind(
1448 &mut net,
1449 &shell_tx,
1450 conn_id as u8,
1451 &shell_ring_buf[2..n],
1452 RingSource::Shell,
1453 );
1454 any_shell_notify = true;
1455 }
1456 MSG_UDP_SEND if n > 8 => {
1457 handle_udp_send(
1458 &mut net,
1459 conn_id as u8,
1460 &shell_ring_buf[2..n],
1461 RingSource::Shell,
1462 );
1463 }
1464 MSG_UDP_CLOSE => {
1465 handle_udp_close(&mut net, conn_id as u8);
1466 }
1467 MSG_IFCONFIG_REQUEST => {
1468 handle_ifconfig_request(&shell_tx, conn_id as u8);
1469 any_shell_notify = true;
1470 }
1471 MSG_ARP_REQUEST => {
1472 handle_arp_request(&shell_tx, conn_id as u8, now_ms);
1473 any_shell_notify = true;
1474 }
1475 MSG_NETSTAT_REQUEST => {
1476 handle_netstat_request(&mut net, &shell_tx, conn_id as u8);
1477 any_shell_notify = true;
1478 }
1479 MSG_MCAST_JOIN if n >= 6 => {
1480 handle_mcast_join(
1481 &mut net,
1482 &shell_tx,
1483 conn_id as u8,
1484 &shell_ring_buf[2..n],
1485 );
1486 any_shell_notify = true;
1487 }
1488 MSG_MCAST_LEAVE if n >= 6 => {
1489 handle_mcast_leave(
1490 &mut net,
1491 &shell_tx,
1492 conn_id as u8,
1493 &shell_ring_buf[2..n],
1494 );
1495 any_shell_notify = true;
1496 }
1497 _ if conn_id < MAX_SHELL_SOCKETS => {
1498 let socket = net
1499 .sockets
1500 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[conn_id]);
1501 match msg_type {
1502 MSG_DATA if n > 2 && socket.may_send() => {
1503 let _ = socket.send_slice(&shell_ring_buf[2..n]);
1504 }
1505 MSG_DISCONNECT => {
1506 socket.close();
1507 shell_connected[conn_id] = false;
1508 handle_udp_close(&mut net, conn_id as u8);
1509 }
1510 _ => {}
1511 }
1512 }
1513 _ => {}
1514 }
1515 Some(())
1516 }
1517 _ => None,
1518 })
1519 .take(64)
1520 .count();
1521
1522 if let Some(irx) = &init_rx
1523 && let Some(itx) = &init_tx
1524 {
1525 core::iter::from_fn(|| match irx.try_pop(&mut init_ring_buf) {
1526 Some(n) if n >= 2 => {
1527 let conn_id = init_ring_buf[0];
1528 let msg_type = init_ring_buf[1];
1529 match msg_type {
1530 MSG_DNS_QUERY if n > 2 => {
1531 handle_dns_query(
1532 &mut net,
1533 itx,
1534 conn_id,
1535 &init_ring_buf[2..n],
1536 false,
1537 RingSource::Init,
1538 );
1539 any_init_notify = true;
1540 }
1541 MSG_DNS_QUERY6 if n > 2 => {
1542 handle_dns_query(
1543 &mut net,
1544 itx,
1545 conn_id,
1546 &init_ring_buf[2..n],
1547 true,
1548 RingSource::Init,
1549 );
1550 any_init_notify = true;
1551 }
1552 MSG_PING_REQUEST if n >= 7 => {
1553 handle_ping_request(
1554 itx,
1555 conn_id,
1556 &init_ring_buf[2..n],
1557 now_ms,
1558 RingSource::Init,
1559 );
1560 any_init_notify = true;
1561 }
1562 MSG_PING_REQUEST6 if n >= 19 => {
1563 handle_ping_request6(
1564 itx,
1565 conn_id,
1566 &init_ring_buf[2..n],
1567 now_ms,
1568 RingSource::Init,
1569 );
1570 any_init_notify = true;
1571 }
1572 MSG_UDP_BIND if n >= 4 => {
1573 handle_udp_bind(
1574 &mut net,
1575 itx,
1576 conn_id,
1577 &init_ring_buf[2..n],
1578 RingSource::Init,
1579 );
1580 any_init_notify = true;
1581 }
1582 MSG_UDP_SEND if n > 8 => {
1583 handle_udp_send(
1584 &mut net,
1585 conn_id,
1586 &init_ring_buf[2..n],
1587 RingSource::Init,
1588 );
1589 }
1590 MSG_UDP_CLOSE => {
1591 handle_udp_close(&mut net, conn_id);
1592 }
1593 MSG_IFCONFIG_REQUEST => {
1594 handle_ifconfig_request(itx, conn_id);
1595 any_init_notify = true;
1596 }
1597 MSG_ARP_REQUEST => {
1598 handle_arp_request(itx, conn_id, now_ms);
1599 any_init_notify = true;
1600 }
1601 MSG_NETSTAT_REQUEST => {
1602 handle_netstat_request(&mut net, itx, conn_id);
1603 any_init_notify = true;
1604 }
1605 MSG_MCAST_JOIN if n >= 6 => {
1606 handle_mcast_join(&mut net, itx, conn_id, &init_ring_buf[2..n]);
1607 any_init_notify = true;
1608 }
1609 MSG_MCAST_LEAVE if n >= 6 => {
1610 handle_mcast_leave(&mut net, itx, conn_id, &init_ring_buf[2..n]);
1611 any_init_notify = true;
1612 }
1613 _ => {}
1614 }
1615 Some(())
1616 }
1617 _ => None,
1618 })
1619 .take(64)
1620 .count();
1621 }
1622
1623 if any_shell_notify {
1624 syscall::notify_signal(SHELL_NOTIF_SLOT, NOTIFY_BIT_RX);
1625 }
1626
1627 if any_init_notify {
1628 syscall::notify_signal(INIT_NOTIF_SLOT, NOTIFY_BIT_TX);
1629 }
1630
1631 core::iter::from_fn(|| {
1632 let now = Instant::from_millis(syscall::clock_monotonic_ms());
1633 matches!(
1634 net.iface.poll(now, &mut dev, &mut net.sockets),
1635 smoltcp::iface::PollResult::SocketStateChanged
1636 )
1637 .then_some(())
1638 })
1639 .take(16)
1640 .count();
1641
1642 syscall::notify_signal(DRIVER_NOTIF_SLOT, NOTIFY_BIT_TX);
1643
1644 let post_ms = syscall::clock_monotonic_ms().max(0);
1645 let post_now = Instant::from_millis(post_ms);
1646 let delay = net.iface.poll_delay(post_now, &net.sockets);
1647
1648 let ping_active = unsafe { (&raw const PENDING_PING).read().is_some() };
1649 let max_sleep = match ping_active {
1650 true => 100i64,
1651 false => 200i64,
1652 };
1653
1654 match delay {
1655 Some(d) if d == Duration::ZERO => {
1656 syscall::sched_yield();
1657 }
1658 Some(d) => {
1659 let deadline = post_ms + (d.total_millis() as i64).min(max_sleep);
1660 core::iter::from_fn(|| {
1661 syscall::sched_yield();
1662 let (status, _) = syscall::notify_poll(NOTIF_SLOT);
1663 match status >= 0 {
1664 true => None,
1665 false => (syscall::clock_monotonic_ms() < deadline).then_some(()),
1666 }
1667 })
1668 .take(100)
1669 .count();
1670 }
1671 None => {
1672 syscall::notify_wait(NOTIF_SLOT);
1673 }
1674 }
1675 }
1676}