Nothing to see here, move along
at main 183 lines 4.7 kB view raw
1#![no_std] 2#![no_main] 3 4use lancer_user::net; 5use lancer_user::syscall; 6 7const STATE_NAMES: [&[u8]; 11] = [ 8 b"Closed", 9 b"Listen", 10 b"SynSent", 11 b"SynRecv", 12 b"Established", 13 b"FinWait1", 14 b"FinWait2", 15 b"CloseWait", 16 b"Closing", 17 b"LastAck", 18 b"TimeWait", 19]; 20 21#[unsafe(no_mangle)] 22pub extern "C" fn lancer_main() -> ! { 23 let (rx, tx) = match net::init() { 24 Some(pair) => pair, 25 None => { 26 lancer_user::show!(net, error, "netsock init failed"); 27 syscall::exit(); 28 } 29 }; 30 31 if !net::has_relay() { 32 lancer_user::io::write_bytes(b"networking not available (use SSH)\n"); 33 syscall::exit(); 34 } 35 36 let mut args_buf = [0u8; 64]; 37 let _ = net::recv_args(&rx, &mut args_buf); 38 39 lancer_user::io::write_bytes( 40 b"Proto Local Remote State SndQ RcvQ\n", 41 ); 42 43 net::send_request(&tx, &[net::MSG_NETSTAT_REQUEST]); 44 45 let mut resp = [0u8; 64]; 46 let mut done = false; 47 core::iter::from_fn(|| match done { 48 true => None, 49 false => { 50 let n = net::recv_response_blocking(&rx, &mut resp); 51 match n < 1 { 52 true => None, 53 false => match resp[0] { 54 net::MSG_NETSTAT_DONE => { 55 done = true; 56 None 57 } 58 net::MSG_NETSTAT_ENTRY if n >= 18 => { 59 format_tcp_entry(&resp[1..n]); 60 Some(()) 61 } 62 net::MSG_NETSTAT_ENTRY_UDP if n >= 4 => { 63 format_udp_entry(&resp[1..n]); 64 Some(()) 65 } 66 _ => Some(()), 67 }, 68 } 69 } 70 }) 71 .take(32) 72 .count(); 73 74 syscall::exit() 75} 76 77fn format_tcp_entry(data: &[u8]) { 78 let state_idx = data[1] as usize; 79 let local_ip = &data[2..6]; 80 let local_port = ((data[6] as u16) << 8) | data[7] as u16; 81 let remote_ip = &data[8..12]; 82 let remote_port = ((data[12] as u16) << 8) | data[13] as u16; 83 let send_q = ((data[14] as u16) << 8) | data[15] as u16; 84 let recv_q = ((data[16] as u16) << 8) | data[17] as u16; 85 86 let mut out = [b' '; 128]; 87 let mut pos = 0usize; 88 89 pos = append(&mut out, pos, b"tcp "); 90 91 let ip_len = net::write_ip_decimal(&mut out[pos..], local_ip); 92 pos += ip_len; 93 out[pos] = b':'; 94 pos += 1; 95 let port_len = net::write_u16_decimal(&mut out[pos..], local_port); 96 pos += port_len; 97 98 pad_to(&mut out, &mut pos, 25); 99 100 let has_remote = remote_ip.iter().any(|&b| b != 0) || remote_port != 0; 101 match has_remote { 102 true => { 103 let rip_len = net::write_ip_decimal(&mut out[pos..], remote_ip); 104 pos += rip_len; 105 out[pos] = b':'; 106 pos += 1; 107 let rport_len = net::write_u16_decimal(&mut out[pos..], remote_port); 108 pos += rport_len; 109 } 110 false => { 111 out[pos] = b'-'; 112 pos += 1; 113 } 114 } 115 116 pad_to(&mut out, &mut pos, 43); 117 118 let state_name = match state_idx < STATE_NAMES.len() { 119 true => STATE_NAMES[state_idx], 120 false => b"?", 121 }; 122 pos = append(&mut out, pos, state_name); 123 124 pad_to(&mut out, &mut pos, 57); 125 126 let sq_len = net::write_u16_decimal(&mut out[pos..], send_q); 127 pos += sq_len; 128 129 pad_to(&mut out, &mut pos, 63); 130 131 let rq_len = net::write_u16_decimal(&mut out[pos..], recv_q); 132 pos += rq_len; 133 134 out[pos] = b'\n'; 135 pos += 1; 136 137 lancer_user::io::write_bytes(&out[..pos]); 138} 139 140fn format_udp_entry(data: &[u8]) { 141 let local_port = ((data[0] as u16) << 8) | data[1] as u16; 142 let recv_q = ((data[2] as u16) << 8) | data[3] as u16; 143 144 let mut out = [b' '; 128]; 145 let mut pos = 0usize; 146 147 pos = append(&mut out, pos, b"udp 0.0.0.0:"); 148 let port_len = net::write_u16_decimal(&mut out[pos..], local_port); 149 pos += port_len; 150 151 pad_to(&mut out, &mut pos, 25); 152 153 out[pos] = b'-'; 154 pos += 1; 155 156 pad_to(&mut out, &mut pos, 43); 157 158 out[pos] = b'-'; 159 pos += 1; 160 161 pad_to(&mut out, &mut pos, 63); 162 163 let rq_len = net::write_u16_decimal(&mut out[pos..], recv_q); 164 pos += rq_len; 165 166 out[pos] = b'\n'; 167 pos += 1; 168 169 lancer_user::io::write_bytes(&out[..pos]); 170} 171 172fn append(buf: &mut [u8], pos: usize, data: &[u8]) -> usize { 173 let n = data.len().min(buf.len() - pos); 174 buf[pos..pos + n].copy_from_slice(&data[..n]); 175 pos + n 176} 177 178fn pad_to(buf: &mut [u8], pos: &mut usize, target: usize) { 179 (*pos..target).for_each(|i| { 180 buf[i] = b' '; 181 }); 182 *pos = (*pos).max(target); 183}