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)
1167 .all(|i| syscall::frame_map(PACKET_RING_BASE_SLOT + i, RING_BASE_VADDR + i * 4096, 1) >= 0)
1168 {
1169 lancer_user::show!(net, error, "packet ring frame_map failed");
1170 syscall::exit();
1171 }
1172
1173 let rx_ring_base = RING_BASE_VADDR as *mut u8;
1174 let tx_ring_base = (RING_BASE_VADDR + RING_HALF_SIZE as u64) as *mut u8;
1175
1176 let rx_reader = unsafe { PacketRingReader::attach(rx_ring_base, RING_HALF_SIZE) };
1177 let tx_writer = unsafe { PacketRingWriter::init(tx_ring_base, RING_HALF_SIZE, 2048) };
1178
1179 let mut dev = PacketDevice {
1180 rx: rx_reader,
1181 tx: tx_writer,
1182 };
1183
1184 let shell_ring_ok = core::iter::repeat_n((), 5)
1185 .position(|()| {
1186 let ok = (0..SHELL_RING_FRAME_COUNT).all(|i| {
1187 syscall::frame_map(SHELL_RING_BASE_SLOT + i, SHELL_RING_BASE + i * 4096, 1) >= 0
1188 });
1189 match ok {
1190 true => true,
1191 false => {
1192 (0..SHELL_RING_FRAME_COUNT).for_each(|i| {
1193 syscall::frame_unmap(SHELL_RING_BASE_SLOT + i, SHELL_RING_BASE + i * 4096);
1194 });
1195 syscall::sched_yield();
1196 false
1197 }
1198 }
1199 })
1200 .is_some();
1201
1202 if !shell_ring_ok {
1203 lancer_user::show!(net, error, "shell ring frame_map failed after retries");
1204 syscall::exit();
1205 }
1206
1207 let shell_tx_base = SHELL_RING_BASE as *mut u8;
1208 let shell_rx_base = (SHELL_RING_BASE + SHELL_RING_HALF as u64) as *mut u8;
1209
1210 let shell_tx = unsafe { PacketRingWriter::init(shell_tx_base, SHELL_RING_HALF, 128) };
1211 let _ = unsafe { PacketRingWriter::init(shell_rx_base, SHELL_RING_HALF, 128) };
1212 let shell_rx = unsafe { PacketRingReader::attach(shell_rx_base, SHELL_RING_HALF) };
1213
1214 lancer_user::show!(net, "shell ring mapped");
1215
1216 let has_init_ring = (0..INIT_RING_FRAME_COUNT)
1217 .all(|i| syscall::frame_map(INIT_RING_BASE_SLOT + i, INIT_RING_BASE + i * 4096, 1) >= 0);
1218 let (init_tx, init_rx) = match has_init_ring {
1219 true => {
1220 let itx_base = INIT_RING_BASE as *mut u8;
1221 let irx_base = (INIT_RING_BASE + INIT_RING_HALF as u64) as *mut u8;
1222 let itx = unsafe { PacketRingWriter::init(itx_base, INIT_RING_HALF, 128) };
1223 let _ = unsafe { PacketRingWriter::init(irx_base, INIT_RING_HALF, 128) };
1224 let irx = unsafe { PacketRingReader::attach(irx_base, INIT_RING_HALF) };
1225 lancer_user::show!(net, "init ring mapped");
1226 (Some(itx), Some(irx))
1227 }
1228 false => {
1229 lancer_user::show!(net, "init ring not available");
1230 (None, None)
1231 }
1232 };
1233
1234 let now_ms = match syscall::clock_monotonic_ms() {
1235 ms if ms >= 0 => ms,
1236 _ => 0,
1237 };
1238 let now = Instant::from_millis(now_ms);
1239
1240 let mut net = stack::create(&mut dev, MAC, now);
1241
1242 if stack::MDNS_JOIN_FAILED.load(core::sync::atomic::Ordering::Relaxed) {
1243 lancer_user::show!(net, warn, "failed to join mdns multicast group");
1244 }
1245
1246 let cfg = unsafe { NET_CONFIG.as_mut_unchecked() };
1247 cfg.set_mac(MAC);
1248 cfg.set_ipv6_link_local(stack::eui64_link_local_bytes(&MAC));
1249
1250 lancer_user::show!(net, "interface up, ipv6 link-local + awaiting dhcpv4");
1251
1252 send_router_solicitation(&dev.tx, &MAC);
1253
1254 {
1255 let socket = net
1256 .sockets
1257 .get_mut::<smoltcp::socket::tcp::Socket>(net.tcp_handle);
1258 match socket.listen(ECHO_PORT) {
1259 Ok(()) => {}
1260 Err(_) => {
1261 lancer_user::show!(net, warn, "echo listen failed");
1262 }
1263 }
1264 }
1265 lancer_user::show!(net, "tcp echo listening on :7");
1266
1267 let shell_handles = net.shell_handles;
1268 {
1269 let socket = net
1270 .sockets
1271 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[0]);
1272 match socket.listen(SHELL_PORT) {
1273 Ok(()) => {}
1274 Err(_) => {
1275 lancer_user::show!(net, warn, "shell listen failed");
1276 }
1277 }
1278 }
1279 lancer_user::show!(net, "tcp shell listening on :22");
1280
1281 let mut echo_buf = [0u8; 1024];
1282 let mut shell_ring_buf = [0u8; 128];
1283 let mut init_ring_buf = [0u8; 128];
1284 let mut pkt_buf = [0u8; 128];
1285 let mut shell_connected = [false; MAX_SHELL_SOCKETS];
1286 let mut dhcp_configured = false;
1287 let init_tx_ref = init_tx.as_ref();
1288
1289 loop {
1290 let now_ms = syscall::clock_monotonic_ms().max(0);
1291 let now = Instant::from_millis(now_ms);
1292
1293 let _poll_result = net.iface.poll(now, &mut dev, &mut net.sockets);
1294
1295 handle_dhcp_event(&mut net, &mut dhcp_configured);
1296
1297 if let Some(slaac) = device::take_slaac_prefix() {
1298 configure_slaac(&mut net, &slaac);
1299 }
1300
1301 poll_mdns(&mut net);
1302
1303 let (dns_shell, dns_init) = poll_pending_dns(&mut net, &shell_tx, init_tx_ref);
1304
1305 ping_send(&mut net, now_ms);
1306 let (pr_shell, pr_init) = ping_recv(&mut net, &shell_tx, init_tx_ref, now_ms);
1307 let (pt_shell, pt_init) = ping_timeout(&shell_tx, init_tx_ref, now_ms);
1308 let (pd_shell, pd_init) = ping_check_done(&shell_tx, init_tx_ref);
1309 let (ur_shell, ur_init) = poll_udp_recv(&mut net, &shell_tx, init_tx_ref);
1310
1311 {
1312 let socket = net
1313 .sockets
1314 .get_mut::<smoltcp::socket::tcp::Socket>(net.tcp_handle);
1315
1316 if socket.may_recv() && socket.may_send() {
1317 match socket.recv_slice(&mut echo_buf) {
1318 Ok(n) if n > 0 => {
1319 let _ = socket.send_slice(&echo_buf[..n]);
1320 }
1321 _ => {}
1322 }
1323 }
1324
1325 let needs_relisten = match socket.state() {
1326 smoltcp::socket::tcp::State::CloseWait => {
1327 socket.close();
1328 false
1329 }
1330 smoltcp::socket::tcp::State::TimeWait
1331 | smoltcp::socket::tcp::State::LastAck
1332 | smoltcp::socket::tcp::State::Closing
1333 | smoltcp::socket::tcp::State::FinWait1
1334 | smoltcp::socket::tcp::State::FinWait2
1335 | smoltcp::socket::tcp::State::Closed => true,
1336 _ => false,
1337 };
1338
1339 if needs_relisten {
1340 socket.abort();
1341 let _ = socket.listen(ECHO_PORT);
1342 }
1343 }
1344
1345 let mut any_shell_notify = dns_shell || pr_shell || pt_shell || pd_shell || ur_shell;
1346 let mut any_init_notify = dns_init || pr_init || pt_init || pd_init || ur_init;
1347
1348 (0..MAX_SHELL_SOCKETS).for_each(|i| {
1349 let socket = net
1350 .sockets
1351 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1352
1353 let fully_open = socket.may_send() && socket.may_recv();
1354
1355 if fully_open && !shell_connected[i] {
1356 shell_connected[i] = true;
1357 let ctrl = [i as u8, MSG_CONNECT];
1358 if shell_tx.try_push(&ctrl) {
1359 any_shell_notify = true;
1360 }
1361 }
1362
1363 if !fully_open && shell_connected[i] {
1364 shell_connected[i] = false;
1365 let ctrl = [i as u8, MSG_DISCONNECT];
1366 if shell_tx.try_push(&ctrl) {
1367 any_shell_notify = true;
1368 }
1369 }
1370
1371 if socket.state() == smoltcp::socket::tcp::State::CloseWait {
1372 socket.close();
1373 }
1374
1375 if shell_connected[i] && socket.may_recv() {
1376 let pushed =
1377 core::iter::from_fn(|| match shell_tx.has_space() && socket.may_recv() {
1378 true => match socket.recv_slice(&mut pkt_buf[2..126]) {
1379 Ok(n) if n > 0 => {
1380 pkt_buf[0] = i as u8;
1381 pkt_buf[1] = MSG_DATA;
1382 shell_tx.try_push(&pkt_buf[..2 + n]).then_some(())
1383 }
1384 _ => None,
1385 },
1386 false => None,
1387 })
1388 .take(8)
1389 .count();
1390 if pushed > 0 {
1391 any_shell_notify = true;
1392 }
1393 }
1394 });
1395
1396 let any_listening = (0..MAX_SHELL_SOCKETS).any(|i| {
1397 net.sockets
1398 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i])
1399 .is_listening()
1400 });
1401
1402 if !any_listening
1403 && let Some(i) = (0..MAX_SHELL_SOCKETS).find(|&i| {
1404 let s = net
1405 .sockets
1406 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1407 !s.is_open() && !s.is_listening()
1408 })
1409 {
1410 let s = net
1411 .sockets
1412 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[i]);
1413 s.abort();
1414 s.set_nagle_enabled(false);
1415 s.set_ack_delay(None);
1416 s.set_keep_alive(Some(Duration::from_secs(30)));
1417 let _ = s.listen(SHELL_PORT);
1418 }
1419
1420 core::iter::from_fn(|| match shell_rx.try_pop(&mut shell_ring_buf) {
1421 Some(n) if n >= 2 => {
1422 let conn_id = shell_ring_buf[0] as usize;
1423 let msg_type = shell_ring_buf[1];
1424 match msg_type {
1425 MSG_DNS_QUERY if n > 2 => {
1426 handle_dns_query(
1427 &mut net,
1428 &shell_tx,
1429 conn_id as u8,
1430 &shell_ring_buf[2..n],
1431 false,
1432 RingSource::Shell,
1433 );
1434 any_shell_notify = true;
1435 }
1436 MSG_DNS_QUERY6 if n > 2 => {
1437 handle_dns_query(
1438 &mut net,
1439 &shell_tx,
1440 conn_id as u8,
1441 &shell_ring_buf[2..n],
1442 true,
1443 RingSource::Shell,
1444 );
1445 any_shell_notify = true;
1446 }
1447 MSG_PING_REQUEST if n >= 7 => {
1448 handle_ping_request(
1449 &shell_tx,
1450 conn_id as u8,
1451 &shell_ring_buf[2..n],
1452 now_ms,
1453 RingSource::Shell,
1454 );
1455 any_shell_notify = true;
1456 }
1457 MSG_PING_REQUEST6 if n >= 19 => {
1458 handle_ping_request6(
1459 &shell_tx,
1460 conn_id as u8,
1461 &shell_ring_buf[2..n],
1462 now_ms,
1463 RingSource::Shell,
1464 );
1465 any_shell_notify = true;
1466 }
1467 MSG_UDP_BIND if n >= 4 => {
1468 handle_udp_bind(
1469 &mut net,
1470 &shell_tx,
1471 conn_id as u8,
1472 &shell_ring_buf[2..n],
1473 RingSource::Shell,
1474 );
1475 any_shell_notify = true;
1476 }
1477 MSG_UDP_SEND if n > 8 => {
1478 handle_udp_send(
1479 &mut net,
1480 conn_id as u8,
1481 &shell_ring_buf[2..n],
1482 RingSource::Shell,
1483 );
1484 }
1485 MSG_UDP_CLOSE => {
1486 handle_udp_close(&mut net, conn_id as u8);
1487 }
1488 MSG_IFCONFIG_REQUEST => {
1489 handle_ifconfig_request(&shell_tx, conn_id as u8);
1490 any_shell_notify = true;
1491 }
1492 MSG_ARP_REQUEST => {
1493 handle_arp_request(&shell_tx, conn_id as u8, now_ms);
1494 any_shell_notify = true;
1495 }
1496 MSG_NETSTAT_REQUEST => {
1497 handle_netstat_request(&mut net, &shell_tx, conn_id as u8);
1498 any_shell_notify = true;
1499 }
1500 MSG_MCAST_JOIN if n >= 6 => {
1501 handle_mcast_join(
1502 &mut net,
1503 &shell_tx,
1504 conn_id as u8,
1505 &shell_ring_buf[2..n],
1506 );
1507 any_shell_notify = true;
1508 }
1509 MSG_MCAST_LEAVE if n >= 6 => {
1510 handle_mcast_leave(
1511 &mut net,
1512 &shell_tx,
1513 conn_id as u8,
1514 &shell_ring_buf[2..n],
1515 );
1516 any_shell_notify = true;
1517 }
1518 _ if conn_id < MAX_SHELL_SOCKETS => {
1519 let socket = net
1520 .sockets
1521 .get_mut::<smoltcp::socket::tcp::Socket>(shell_handles[conn_id]);
1522 match msg_type {
1523 MSG_DATA if n > 2 && socket.may_send() => {
1524 let _ = socket.send_slice(&shell_ring_buf[2..n]);
1525 }
1526 MSG_DISCONNECT => {
1527 socket.close();
1528 shell_connected[conn_id] = false;
1529 handle_udp_close(&mut net, conn_id as u8);
1530 }
1531 _ => {}
1532 }
1533 }
1534 _ => {}
1535 }
1536 Some(())
1537 }
1538 _ => None,
1539 })
1540 .take(64)
1541 .count();
1542
1543 if let Some(irx) = &init_rx
1544 && let Some(itx) = &init_tx
1545 {
1546 core::iter::from_fn(|| match irx.try_pop(&mut init_ring_buf) {
1547 Some(n) if n >= 2 => {
1548 let conn_id = init_ring_buf[0];
1549 let msg_type = init_ring_buf[1];
1550 match msg_type {
1551 MSG_DNS_QUERY if n > 2 => {
1552 handle_dns_query(
1553 &mut net,
1554 itx,
1555 conn_id,
1556 &init_ring_buf[2..n],
1557 false,
1558 RingSource::Init,
1559 );
1560 any_init_notify = true;
1561 }
1562 MSG_DNS_QUERY6 if n > 2 => {
1563 handle_dns_query(
1564 &mut net,
1565 itx,
1566 conn_id,
1567 &init_ring_buf[2..n],
1568 true,
1569 RingSource::Init,
1570 );
1571 any_init_notify = true;
1572 }
1573 MSG_PING_REQUEST if n >= 7 => {
1574 handle_ping_request(
1575 itx,
1576 conn_id,
1577 &init_ring_buf[2..n],
1578 now_ms,
1579 RingSource::Init,
1580 );
1581 any_init_notify = true;
1582 }
1583 MSG_PING_REQUEST6 if n >= 19 => {
1584 handle_ping_request6(
1585 itx,
1586 conn_id,
1587 &init_ring_buf[2..n],
1588 now_ms,
1589 RingSource::Init,
1590 );
1591 any_init_notify = true;
1592 }
1593 MSG_UDP_BIND if n >= 4 => {
1594 handle_udp_bind(
1595 &mut net,
1596 itx,
1597 conn_id,
1598 &init_ring_buf[2..n],
1599 RingSource::Init,
1600 );
1601 any_init_notify = true;
1602 }
1603 MSG_UDP_SEND if n > 8 => {
1604 handle_udp_send(
1605 &mut net,
1606 conn_id,
1607 &init_ring_buf[2..n],
1608 RingSource::Init,
1609 );
1610 }
1611 MSG_UDP_CLOSE => {
1612 handle_udp_close(&mut net, conn_id);
1613 }
1614 MSG_IFCONFIG_REQUEST => {
1615 handle_ifconfig_request(itx, conn_id);
1616 any_init_notify = true;
1617 }
1618 MSG_ARP_REQUEST => {
1619 handle_arp_request(itx, conn_id, now_ms);
1620 any_init_notify = true;
1621 }
1622 MSG_NETSTAT_REQUEST => {
1623 handle_netstat_request(&mut net, itx, conn_id);
1624 any_init_notify = true;
1625 }
1626 MSG_MCAST_JOIN if n >= 6 => {
1627 handle_mcast_join(&mut net, itx, conn_id, &init_ring_buf[2..n]);
1628 any_init_notify = true;
1629 }
1630 MSG_MCAST_LEAVE if n >= 6 => {
1631 handle_mcast_leave(&mut net, itx, conn_id, &init_ring_buf[2..n]);
1632 any_init_notify = true;
1633 }
1634 _ => {}
1635 }
1636 Some(())
1637 }
1638 _ => None,
1639 })
1640 .take(64)
1641 .count();
1642 }
1643
1644 if any_shell_notify {
1645 syscall::notify_signal(SHELL_NOTIF_SLOT, NOTIFY_BIT_RX);
1646 }
1647
1648 if any_init_notify {
1649 syscall::notify_signal(INIT_NOTIF_SLOT, NOTIFY_BIT_TX);
1650 }
1651
1652 core::iter::from_fn(|| {
1653 let now = Instant::from_millis(syscall::clock_monotonic_ms());
1654 matches!(
1655 net.iface.poll(now, &mut dev, &mut net.sockets),
1656 smoltcp::iface::PollResult::SocketStateChanged
1657 )
1658 .then_some(())
1659 })
1660 .take(16)
1661 .count();
1662
1663 syscall::notify_signal(DRIVER_NOTIF_SLOT, NOTIFY_BIT_TX);
1664
1665 let post_ms = syscall::clock_monotonic_ms().max(0);
1666 let post_now = Instant::from_millis(post_ms);
1667 let delay = net.iface.poll_delay(post_now, &net.sockets);
1668
1669 let ping_active = unsafe { (&raw const PENDING_PING).read().is_some() };
1670 let max_sleep = match ping_active {
1671 true => 100i64,
1672 false => 200i64,
1673 };
1674
1675 match delay {
1676 Some(d) if d == Duration::ZERO => {
1677 syscall::sched_yield();
1678 }
1679 Some(d) => {
1680 let deadline = post_ms + (d.total_millis() as i64).min(max_sleep);
1681 core::iter::from_fn(|| {
1682 syscall::sched_yield();
1683 let (status, _) = syscall::notify_poll(NOTIF_SLOT);
1684 match status >= 0 {
1685 true => None,
1686 false => (syscall::clock_monotonic_ms() < deadline).then_some(()),
1687 }
1688 })
1689 .take(100)
1690 .count();
1691 }
1692 None => {
1693 syscall::notify_wait(NOTIF_SLOT);
1694 }
1695 }
1696 }
1697}