Skip to main content

os/net/
mod.rs

1pub mod port_table;
2pub mod socket;
3pub mod tcp;
4pub mod udp;
5
6pub use lose_net_stack::IPv4;
7
8use alloc::{sync::Arc, vec};
9use lose_net_stack::{LoseStack, MacAddress, TcpFlags, results::Packet};
10
11use crate::{
12    drivers::NET_DEVICE,
13    net::socket::{get_socket, push_data},
14    sync::UPIntrFreeCell,
15};
16
17use self::{port_table::check_accept, socket::set_s_a_by_index};
18
19pub struct NetStack(UPIntrFreeCell<LoseStack>);
20
21impl NetStack {
22    pub fn new() -> Self {
23        unsafe {
24            NetStack(UPIntrFreeCell::new(LoseStack::new(
25                IPv4::new(10, 0, 2, 15),
26                MacAddress::new([0x52, 0x54, 0x00, 0x12, 0x34, 0x56]),
27            )))
28        }
29    }
30}
31
32lazy_static::lazy_static! {
33    static ref LOSE_NET_STACK: Arc<NetStack> = Arc::new(NetStack::new());
34}
35
36pub fn net_interrupt_handler() {
37    let mut recv_buf = vec![0u8; 1024];
38
39    let len = NET_DEVICE.receive(&mut recv_buf);
40
41    let packet = LOSE_NET_STACK
42        .0
43        .exclusive_access()
44        .analysis(&recv_buf[..len]);
45
46    // println!("[kernel] receive a packet");
47    // hexdump(&recv_buf[..len]);
48
49    match packet {
50        Packet::ARP(arp_packet) => {
51            let lose_stack = LOSE_NET_STACK.0.exclusive_access();
52            let reply_packet = arp_packet
53                .reply_packet(lose_stack.ip, lose_stack.mac)
54                .expect("can't build reply");
55            let reply_data = reply_packet.build_data();
56            NET_DEVICE.transmit(&reply_data)
57        }
58
59        Packet::UDP(udp_packet) => {
60            let target = udp_packet.source_ip;
61            let lport = udp_packet.dest_port;
62            let rport = udp_packet.source_port;
63
64            if let Some(socket_index) = get_socket(target, lport, rport) {
65                push_data(socket_index, udp_packet.data.to_vec());
66            }
67        }
68
69        Packet::TCP(tcp_packet) => {
70            let target = tcp_packet.source_ip;
71            let lport = tcp_packet.dest_port;
72            let rport = tcp_packet.source_port;
73            let flags = tcp_packet.flags;
74
75            if flags.contains(TcpFlags::S) {
76                // if it has a port to accept, then response the request
77                if check_accept(lport, &tcp_packet).is_some() {
78                    let mut reply_packet = tcp_packet.ack();
79                    reply_packet.flags = TcpFlags::S | TcpFlags::A;
80                    NET_DEVICE.transmit(&reply_packet.build_data());
81                }
82                return;
83            } else if tcp_packet.flags.contains(TcpFlags::F) {
84                // tcp disconnected
85                let reply_packet = tcp_packet.ack();
86                NET_DEVICE.transmit(&reply_packet.build_data());
87
88                let mut end_packet = reply_packet.ack();
89                end_packet.flags |= TcpFlags::F;
90                NET_DEVICE.transmit(&end_packet.build_data());
91            } else if tcp_packet.flags.contains(TcpFlags::A) && tcp_packet.data_len == 0 {
92                return;
93            }
94
95            if let Some(socket_index) = get_socket(target, lport, rport) {
96                push_data(socket_index, tcp_packet.data.to_vec());
97                set_s_a_by_index(socket_index, tcp_packet.seq, tcp_packet.ack);
98            }
99        }
100        _ => {}
101    }
102}
103
104#[allow(unused)]
105pub fn hexdump(data: &[u8]) {
106    const PRELAND_WIDTH: usize = 70;
107    println!("[kernel] {:-^1$}", " hexdump ", PRELAND_WIDTH);
108    for offset in (0..data.len()).step_by(16) {
109        print!("[kernel] ");
110        for i in 0..16 {
111            if offset + i < data.len() {
112                print!("{:02x} ", data[offset + i]);
113            } else {
114                print!("{:02} ", "");
115            }
116        }
117
118        print!("{:>6}", ' ');
119
120        for i in 0..16 {
121            if offset + i < data.len() {
122                let c = data[offset + i];
123                if c >= 0x20 && c <= 0x7e {
124                    print!("{}", c as char);
125                } else {
126                    print!(".");
127                }
128            } else {
129                print!("{:02} ", "");
130            }
131        }
132
133        println!("");
134    }
135    println!("[kernel] {:-^1$}", " hexdump end ", PRELAND_WIDTH);
136}