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 }
void * memcpy(void *restrict destination, const void *restrict source, size_t n)
Копирование непересекающихся массивов используя SSE.
Definition: string.c:173
Definition: cards.h:5