aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2020-11-04 22:11:57 +0100
committerMarvin Borner2020-11-04 22:11:57 +0100
commit916fca2161e76de67a5106b90baf00a57f2a0512 (patch)
tree5aa47b4d37718d44fd54565ea345cd6248d8a8d6 /kernel
parent5951024ab35e6cdd1ed6b97d76e28f1a253f6593 (diff)
Further TCP work
Can now send ACKs with correct checksum
Diffstat (limited to 'kernel')
-rw-r--r--kernel/features/net.c93
-rw-r--r--kernel/inc/net.h8
2 files changed, 91 insertions, 10 deletions
diff --git a/kernel/features/net.c b/kernel/features/net.c
index 2b4fbb5..f9b9d12 100644
--- a/kernel/features/net.c
+++ b/kernel/features/net.c
@@ -160,10 +160,12 @@ void ip_send_packet(u32 dst, void *data, int len, int prot)
packet->protocol = prot;
packet->src = ip_addr;
packet->dst = dst;
- memcpy(packet->data, data, len);
packet->length = htons(sizeof(*packet) + len);
packet->checksum = htons(ip_calculate_checksum(packet));
+ if (data)
+ memcpy(packet->data, data, len);
+
u8 dst_mac[6];
int arp_sent = 3;
@@ -190,17 +192,58 @@ void udp_send_packet(u32 dst, u16 src_port, u16 dst_port, void *data, int len)
print("UDP send packet\n");
int length = sizeof(struct udp_packet) + len;
struct udp_packet *packet = malloc(length);
- memset(packet, 0, sizeof(struct udp_packet));
+ memset(packet, 0, sizeof(*packet));
packet->src_port = htons(src_port);
packet->dst_port = htons(dst_port);
packet->length = htons(length);
packet->checksum = 0; // Optional
- memcpy(packet->data, data, len);
+ if (data)
+ memcpy(packet->data, data, len);
+
ip_send_packet(dst, packet, length, IP_PROT_UDP);
free(packet);
}
+u32 seq_no, ack_no = 0; // TODO: Per socket
+void tcp_send_packet(u32 dst, u16 src_port, u16 dst_port, u16 flags, void *data, int len)
+{
+ print("TCP send packet\n");
+ int length = sizeof(struct tcp_packet) + len;
+ struct tcp_packet *packet = malloc(length);
+ memset(packet, 0, sizeof(*packet));
+ packet->src_port = htons(src_port);
+ packet->dst_port = htons(dst_port);
+ packet->seq_number = htonl(seq_no);
+ packet->ack_number = flags & TCP_FLAG_ACK ? htonl(ack_no) : 0;
+ packet->flags = htons(0x5000 ^ (flags & 0xff));
+ packet->window_size = htons(1548 - 54);
+ packet->urgent = 0;
+ packet->checksum = 0; // Later
+
+ if ((flags & 0xff) == TCP_FLAG_SYN)
+ seq_no++;
+ else
+ seq_no += len;
+
+ if (data)
+ memcpy(packet->data, data, len);
+
+ struct tcp_pseudo_header checksum_hd = {
+ .src = ip_addr,
+ .dst = dst,
+ .zeros = 0,
+ .protocol = 6,
+ .tcp_len = htons(length),
+ };
+ u16 checksum = tcp_calculate_checksum(packet, &checksum_hd, data,
+ length - (htons(packet->flags) >> 12) * 4);
+ packet->checksum = htons(checksum);
+
+ ip_send_packet(dst, packet, length, IP_PROT_TCP);
+ free(packet);
+}
+
void dhcp_make_packet(struct dhcp_packet *packet, u8 msg_type);
void dhcp_request()
{
@@ -233,7 +276,7 @@ void icmp_handle_packet(struct icmp_packet *request_packet, u32 dst)
void dhcp_handle_packet(struct dhcp_packet *packet)
{
print("DHCP!\n");
- if (packet->op == DHCP_REPLY) {
+ if (packet->op == DHCP_REPLY && htonl(packet->xid) == DHCP_TRANSACTION_IDENTIFIER) {
u8 *type = dhcp_get_options(packet, 53);
if (*type == 2) { // Offer
print("DHCP offer\n");
@@ -246,11 +289,49 @@ void dhcp_handle_packet(struct dhcp_packet *packet)
}
}
-void tcp_handle_packet(struct tcp_packet *packet)
+void tcp_handle_packet(struct tcp_packet *packet, u32 dst, int len)
{
printf("TCP Port: %d\n", ntohs(packet->dst_port));
+ int data_length = len - (htons(packet->flags) >> 12) * 4;
u16 flags = ntohs(packet->flags);
printf("%b\n", flags);
+
+ if (seq_no != ntohl(packet->ack_number)) {
+ printf("Dropping packet seq_no: %d\n", seq_no);
+ return;
+ }
+
+ if ((htons(packet->flags) & TCP_FLAG_SYN) && (htons(packet->flags) & TCP_FLAG_ACK)) {
+ ack_no = ntohl(packet->seq_number) + data_length + 1;
+ tcp_send_packet(dst, packet->dst_port, packet->src_port, TCP_FLAG_ACK, NULL, 0);
+ } else if (htons(packet->flags) & TCP_FLAG_RES) {
+ print("Socket reset!\n");
+ return;
+ } else if (data_length == 0) {
+ if (htons(packet->flags) & TCP_FLAG_FIN) {
+ print("Finished, closing socket\n");
+ ack_no = ntohl(packet->seq_number) + data_length + 1;
+ tcp_send_packet(dst, packet->dst_port, packet->src_port,
+ TCP_FLAG_ACK | TCP_FLAG_FIN, NULL, 0);
+ }
+ return;
+ }
+
+ ack_no = ntohl(packet->seq_number) + data_length;
+ if ((htons(packet->flags) & TCP_FLAG_SYN) && (htons(packet->flags) & TCP_FLAG_ACK) &&
+ data_length == 0)
+ ack_no++;
+ ack_no = ntohl(packet->seq_number) + data_length;
+
+ tcp_send_packet(dst, packet->dst_port, packet->src_port, TCP_FLAG_ACK, NULL, 0);
+
+ // TODO: Look at the spec again
+ if (htons(packet->flags) & TCP_FLAG_FIN) {
+ print("Finished, closing socket\n");
+ ack_no = ntohl(packet->seq_number) + data_length + 1;
+ tcp_send_packet(dst, packet->dst_port, packet->src_port,
+ TCP_FLAG_ACK | TCP_FLAG_FIN, NULL, 0);
+ }
}
void udp_handle_packet(struct udp_packet *packet)
@@ -272,7 +353,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);
+ tcp_handle_packet((struct tcp_packet *)packet->data, packet->src, len);
break;
case IP_PROT_UDP:
print("UDP Packet!\n");
diff --git a/kernel/inc/net.h b/kernel/inc/net.h
index f2fbb20..81754d8 100644
--- a/kernel/inc/net.h
+++ b/kernel/inc/net.h
@@ -35,7 +35,7 @@
#define DHCP_REQUEST 1
#define DHCP_REPLY 2
-#define DHCP_TRANSACTION_IDENTIFIER 0x55555555
+#define DHCP_TRANSACTION_IDENTIFIER 0x18122002
#define HARDWARE_TYPE_ETHERNET 0x01
@@ -114,12 +114,12 @@ struct tcp_packet {
} __attribute__((packed));
struct tcp_pseudo_header {
- u32 source;
- u32 destination;
+ u32 src;
+ u32 dst;
u8 zeros;
u8 protocol;
u16 tcp_len;
- u8 tcp_header[];
+ u8 tcp_packet[];
};
struct icmp_packet {