SayoriOS 0.3.3

ipv4.c
1 //
2 // Created by ndraey on 01.11.23.
3 //
4
5 #include "net/ipv4.h"
6 #include "net/ethernet.h"
7 #include "net/endianess.h"
8 #include "io/ports.h"
9 #include "debug/hexview.h"
10 #include "lib/stdlib.h"
11 #include "mem/vmm.h"
12 #include "net/arp.h"
13 #include "net/udp.h"
14 #include "net/icmp.h"
15 #include "net/tcp.h"
16
17 void ipv4_handle_packet(netcard_entry_t *card, char *packet, size_t packet_size) {
18 ETH_IPv4_PKG* ipv4_pkt = (ETH_IPv4_PKG*)packet;
19
20 ipv4_pkt->TotalLength = ntohs(ipv4_pkt->TotalLength);
21
22 qemu_warn("IPV4");
23 qemu_log(" |--- Version: %x", ipv4_pkt->Version);
24 qemu_log(" |--- DSF: %x", ipv4_pkt->DSF);
25 qemu_log(" |--- TotalLength: %x", ipv4_pkt->TotalLength);
26 qemu_log(" |--- ID: %x", ipv4_pkt->ID);
27 qemu_log(" |--- Flags: %x", ipv4_pkt->Flags);
28 qemu_log(" |--- TimeLife: %x", ipv4_pkt->TimeLife);
29 qemu_log(" |--- Protocol: %x", ipv4_pkt->Protocol);
30 qemu_log(" |--- Checksum: %x", ipv4_pkt->Checksum);
31 qemu_log(" |--- Source: %d.%d.%d.%d", ipv4_pkt->Source[0], ipv4_pkt->Source[1], ipv4_pkt->Source[2], ipv4_pkt->Source[3]);
32 qemu_log(" |--- Destination: %d.%d.%d.%d", ipv4_pkt->Destination[0], ipv4_pkt->Destination[1], ipv4_pkt->Destination[2], ipv4_pkt->Destination[3]);
33
34
35 ethernet_frame_t* eth_frame = (packet - sizeof(ethernet_frame_t));
36 qemu_log(" |--- Phys source: %x:%x:%x:%x:%x:%x",
37 eth_frame->src_mac[0],
38 eth_frame->src_mac[1],
39 eth_frame->src_mac[2],
40 eth_frame->src_mac[3],
41 eth_frame->src_mac[4],
42 eth_frame->src_mac[5]);
43
44 // EXPERIMENTAL!
45 arp_lookup_add(eth_frame->src_mac, ipv4_pkt->Source);
46
47 if (ipv4_pkt->Protocol == ETH_IPv4_HEAD_UDP) {
48 udp_handle_packet(card, (udp_packet_t *) (packet + sizeof(ETH_IPv4_PKG)));
49 } else if(ipv4_pkt->Protocol == ETH_IPv4_HEAD_ICMPv4) {
50 qemu_err("ICMP not implemented!");
51
52 icmp_handle_packet(card, packet + sizeof(ETH_IPv4_PKG));
53 } else if(ipv4_pkt->Protocol == ETH_IPv4_HEAD_TCP) {
54 qemu_note("HANDLING TCP!");
55
56 tcp_handle_packet(card, (tcp_packet_t*)(packet + sizeof(ETH_IPv4_PKG)));
57 } else {
58 qemu_log(" | |--- Header: [%x] %s", ipv4_pkt->Protocol, "Unknown");
59 qemu_log(" | |--- RAW: %d bytes", packet_size - sizeof(ETH_IPv4_PKG));
60 qemu_log(" | |");
61 }
62 }
63
64 uint16_t ipv4_checksum(ETH_IPv4_PKG* packet) {
65 // Treat the packet header as a 2-byte-integer array
66 // Sum all integers up and flip all bits
67 size_t array_size = sizeof(ETH_IPv4_PKG) / 2;
68 uint16_t* array = (uint16_t*)packet;
69 uint32_t sum = 0;
70
71 for(int i = 0; i < array_size; i++) {
72 sum += bit_flip_short(array[i]);
73 }
74
75 uint32_t carry = sum >> 16;
76 sum = sum & 0x0000ffff;
77 sum = sum + carry;
78
79 return ~sum;
80 }
81
82 void ipv4_send_packet(netcard_entry_t *card, uint8_t dest_ip[4], const void *data, size_t size, uint8_t protocol) {
83 ETH_IPv4_PKG* ipv4_pkt = kcalloc(1, sizeof(ETH_IPv4_PKG) + size);
84 char* pkt_data = (char*)ipv4_pkt + sizeof(ETH_IPv4_PKG);
85
86 qemu_log("IP send: %d bytes", size);
87
88 ipv4_pkt->Version = 4;
89 ipv4_pkt->HeaderLength = 5;
90 memcpy(ipv4_pkt->Destination, dest_ip, 4);
91 memcpy(ipv4_pkt->Source, card->ipv4_addr, 4);
92 ipv4_pkt->Flags = 0; // No fragment
93 ipv4_pkt->TimeLife = 64;
94 ipv4_pkt->TotalLength = htons(sizeof(ETH_IPv4_PKG) + size);
95 ipv4_pkt->Protocol = protocol;
96 ipv4_pkt->Checksum = 0;
97 ipv4_pkt->ID = 0;
98
99 ipv4_pkt->Checksum = htons(ipv4_checksum(ipv4_pkt));
100
101 memcpy(pkt_data, data, size);
102
103 uint8_t dest_mac[6] = {0};
104 uint8_t arp_zero[6] = {0};
105
106 size_t spin = 10;
107
108 while(!arp_lookup(dest_mac, dest_ip) && --spin) {
109 arp_send_packet(card, arp_zero, dest_ip);
110 }
111
112 if(spin == 0) {
113 qemu_err("%u.%u.%u.%u is unreachable", dest_ip[0], dest_ip[1], dest_ip[2], dest_ip[3]);
114
115 goto end;
116 }
117
118 qemu_log("Total IP packet size: %d", sizeof(ETH_IPv4_PKG) + size);
119
120 ethernet_send_packet(card, dest_mac, (uint8_t *) ipv4_pkt, sizeof(ETH_IPv4_PKG) + size, ETHERNET_TYPE_IPV4);
121
122 end:
123
124 kfree(ipv4_pkt);
125 }
memcpy
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
array
Definition: minesweeper.c:29
netcard_entry_t
Definition: cards.h:5
tcp_packet_t
Definition: tcp.h:10