aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2020-11-03 21:09:34 +0100
committerMarvin Borner2020-11-03 21:09:34 +0100
commit5951024ab35e6cdd1ed6b97d76e28f1a253f6593 (patch)
tree52670f12af4a1274f9ce6e8a642ad055658255ed /kernel
parent36bd8f09d359d176a2a1ca59864838269e887c4b (diff)
Started TCP implementation
Diffstat (limited to 'kernel')
-rw-r--r--kernel/features/net.c64
-rw-r--r--kernel/inc/net.h31
2 files changed, 91 insertions, 4 deletions
diff --git a/kernel/features/net.c b/kernel/features/net.c
index 01cbb47..2b4fbb5 100644
--- a/kernel/features/net.c
+++ b/kernel/features/net.c
@@ -19,7 +19,7 @@ static u8 gateway_mac[6] = { 0 };
u16 ip_calculate_checksum(struct ip_packet *packet)
{
- int array_size = sizeof(struct ip_packet) / 2;
+ int array_size = sizeof(*packet) / 2;
u16 *array = (u16 *)packet;
u32 sum = 0;
for (int i = 0; i < array_size; i++) {
@@ -32,6 +32,55 @@ u16 ip_calculate_checksum(struct ip_packet *packet)
return ret;
}
+u16 tcp_calculate_checksum(struct tcp_packet *packet, struct tcp_pseudo_header *header, void *data,
+ u32 len)
+{
+ u32 sum = 0;
+ u16 *s = (u16 *)header;
+
+ // TODO: Checksums for options?
+ for (int i = 0; i < 6; ++i) {
+ sum += ntohs(s[i]);
+ if (sum > 0xffff) {
+ sum = (sum >> 16) + (sum & 0xffff);
+ }
+ }
+
+ s = (u16 *)packet;
+ for (int i = 0; i < 10; ++i) {
+ sum += ntohs(s[i]);
+ if (sum > 0xffff) {
+ sum = (sum >> 16) + (sum & 0xffff);
+ }
+ }
+
+ u16 d_words = len / 2;
+
+ s = (u16 *)data;
+ for (unsigned int i = 0; i < d_words; ++i) {
+ sum += ntohs(s[i]);
+ if (sum > 0xffff) {
+ sum = (sum >> 16) + (sum & 0xffff);
+ }
+ }
+
+ if (d_words * 2 != len) {
+ u8 *t = (u8 *)data;
+ u8 tmp[2];
+ tmp[0] = t[d_words * sizeof(u16)];
+ tmp[1] = 0;
+
+ u16 *f = (u16 *)tmp;
+
+ sum += ntohs(f[0]);
+ if (sum > 0xffff) {
+ sum = (sum >> 16) + (sum & 0xffff);
+ }
+ }
+
+ return ~(sum & 0xffff) & 0xffff;
+}
+
u16 icmp_calculate_checksum(struct icmp_packet *packet)
{
u32 sum = 0;
@@ -40,8 +89,8 @@ u16 icmp_calculate_checksum(struct icmp_packet *packet)
for (int i = 0; i < 5; i++)
sum += s[i];
- if (sum > 0xFFFF)
- sum = (sum >> 16) + (sum & 0xFFFF);
+ if (sum > 0xffff)
+ sum = (sum >> 16) + (sum & 0xffff);
return ~sum;
}
@@ -197,6 +246,13 @@ void dhcp_handle_packet(struct dhcp_packet *packet)
}
}
+void tcp_handle_packet(struct tcp_packet *packet)
+{
+ printf("TCP Port: %d\n", ntohs(packet->dst_port));
+ u16 flags = ntohs(packet->flags);
+ printf("%b\n", flags);
+}
+
void udp_handle_packet(struct udp_packet *packet)
{
printf("UDP Port: %d\n", ntohs(packet->dst_port));
@@ -204,7 +260,6 @@ void udp_handle_packet(struct udp_packet *packet)
if (ntohs(packet->dst_port) == 68)
dhcp_handle_packet(data_ptr);
- return;
}
void ip_handle_packet(struct ip_packet *packet, int len)
@@ -217,6 +272,7 @@ void ip_handle_packet(struct ip_packet *packet, int len)
break;
case IP_PROT_TCP:
print("TCP Packet!\n");
+ tcp_handle_packet((struct tcp_packet *)packet->data);
break;
case IP_PROT_UDP:
print("UDP Packet!\n");
diff --git a/kernel/inc/net.h b/kernel/inc/net.h
index 78aed51..f2fbb20 100644
--- a/kernel/inc/net.h
+++ b/kernel/inc/net.h
@@ -20,6 +20,16 @@
#define IP_PROT_TCP 0x06
#define IP_PROT_UDP 0x11
+#define TCP_FLAG_FIN (1 << 0)
+#define TCP_FLAG_SYN (1 << 1)
+#define TCP_FLAG_RES (1 << 2)
+#define TCP_FLAG_PSH (1 << 3)
+#define TCP_FLAG_ACK (1 << 4)
+#define TCP_FLAG_URG (1 << 5)
+#define TCP_FLAG_ECE (1 << 6)
+#define TCP_FLAG_CWR (1 << 7)
+#define TCP_FLAG_NS (1 << 8)
+
#define ARP_REQUEST 1
#define ARP_REPLY 2
@@ -91,6 +101,27 @@ struct udp_packet {
u8 data[];
} __attribute__((packed));
+struct tcp_packet {
+ u16 src_port;
+ u16 dst_port;
+ u32 seq_number;
+ u32 ack_number;
+ u16 flags;
+ u16 window_size;
+ u16 checksum;
+ u16 urgent;
+ u8 data[];
+} __attribute__((packed));
+
+struct tcp_pseudo_header {
+ u32 source;
+ u32 destination;
+ u8 zeros;
+ u8 protocol;
+ u16 tcp_len;
+ u8 tcp_header[];
+};
+
struct icmp_packet {
u8 type;
u8 version;