diff --git a/build.py b/build.py index 487bf0f..5dde6ae 100644 --- a/build.py +++ b/build.py @@ -71,6 +71,15 @@ def build_sysapp(): # 构建内置系统应用 return 0 +def build_network(): # 构建网络系统 + print("Building network source code...") + for file in os.listdir(cd + '\\network'): + cmd = cd + gcc + " " + "network\\" + file + " -o " + "target\\" + file.split(".")[0] + ".o" + e = os.system(cmd) + if e != 0: + return -1 + return 0 + def linker(): # 交叉编译链接 print("Linking object files...") source_file = "" @@ -94,6 +103,9 @@ a = build_data() if a != 0: exit(-1) a = build_sysapp() +if a != 0: + exit(-1) +a = build_network() if a != 0: exit(-1) a = linker() diff --git a/driver/vdisk.c b/driver/vdisk.c index 9cf4ed2..af0ff4b 100644 --- a/driver/vdisk.c +++ b/driver/vdisk.c @@ -5,6 +5,8 @@ #include "../include/vdisk.h" #include "../include/printf.h" +#include "../include/fifo.h" +#include "../include/task.h" int getReadyDisk(); @@ -111,3 +113,52 @@ void Disk_Write(unsigned int lba, unsigned int number, void *buffer, } } } + +static unsigned char *drive_name[16] = {NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL}; +static struct FIFO8 drive_fifo[16]; +static unsigned char drive_buf[16][256]; + +bool SetDrive(unsigned char *name) { + for (int i = 0; i != 16; i++) { + if (drive_name[i] == NULL) { + drive_name[i] = name; + fifo8_init(&drive_fifo[i], 256, drive_buf[i]); + return 1; + } + } + return 0; +} + +unsigned int GetDriveCode(unsigned char *name) { + for (int i = 0; i != 16; i++) { + if (strcmp((char *)drive_name[i], (char *)name) == 0) { + return i; + } + } + return 16; +} + +bool DriveSemaphoreTake(unsigned int drive_code) { + if (drive_code >= 16) { + return 1; + } + fifo8_put(&drive_fifo[drive_code], get_current()->pid); + // printk("FIFO: %d PUT: %d STATUS: %d\n", drive_code, Get_Tid(current_task()), + // fifo8_status(&drive_fifo[drive_code])); + while (drive_buf[drive_code][drive_fifo[drive_code].q] != + get_current()->pid) { + // printk("Waiting....\n"); + } + return 1; +} +void DriveSemaphoreGive(unsigned int drive_code) { + if (drive_code >= 16) { + return; + } + if (drive_buf[drive_code][drive_fifo[drive_code].q] != get_current()->pid) { + return; + } + fifo8_get(&drive_fifo[drive_code]); +} diff --git a/include/arp.h b/include/arp.h new file mode 100644 index 0000000..d8d24f4 --- /dev/null +++ b/include/arp.h @@ -0,0 +1,26 @@ +#ifndef CRASHPOWEROS_ARP_H +#define CRASHPOWEROS_ARP_H + +#define ARP_PROTOCOL 0x0806 +#define MAX_ARP_TABLE 256 +#define ARP_WAITTIME 1 + +#include + +struct ARPMessage { + uint16_t hardwareType; + uint16_t protocol; + uint8_t hardwareAddressSize; + uint8_t protocolAddressSize; + uint16_t command; + uint8_t src_mac[6]; + uint32_t src_ip; + uint8_t dest_mac[6]; + uint32_t dest_ip; +} __attribute__((packed)); + +uint64_t IPParseMAC(uint32_t dstIP); +uint8_t *ARP_Packet(uint64_t dest_mac, uint32_t dest_ip, uint64_t src_mac, + uint32_t src_ip, uint16_t command); + +#endif diff --git a/include/common.h b/include/common.h index 1c37c81..d9b3c2e 100644 --- a/include/common.h +++ b/include/common.h @@ -7,6 +7,11 @@ #define LONG_MAX 9223372036854775807L #define LONG_MIN -9223372036854775808L +#define swap32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) +#define swap16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) + #include #include #include diff --git a/include/dhcp.h b/include/dhcp.h new file mode 100644 index 0000000..b03723a --- /dev/null +++ b/include/dhcp.h @@ -0,0 +1,59 @@ +#ifndef CRASHPOWEROS_DHCP_H +#define CRASHPOWEROS_DHCP_H + +#define DHCP_CHADDR_LEN 16 +#define DHCP_SNAME_LEN 64 +#define DHCP_FILE_LEN 128 + +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +#define DHCP_HARDWARE_TYPE_10_EHTHERNET 1 + +#define MESSAGE_TYPE_PAD 0 +#define MESSAGE_TYPE_REQ_SUBNET_MASK 1 +#define MESSAGE_TYPE_ROUTER 3 +#define MESSAGE_TYPE_DNS 6 +#define MESSAGE_TYPE_DOMAIN_NAME 15 +#define MESSAGE_TYPE_REQ_IP 50 +#define MESSAGE_TYPE_DHCP 53 +#define MESSAGE_TYPE_PARAMETER_REQ_LIST 55 +#define MESSAGE_TYPE_END 255 + +#define DHCP_OPTION_DISCOVER 1 +#define DHCP_OPTION_OFFER 2 +#define DHCP_OPTION_REQUEST 3 +#define DHCP_OPTION_PACK 4 + +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 + +#define DHCP_MAGIC_COOKIE 0x63825363 + +#include + +struct DHCPMessage { + uint8_t opcode; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[DHCP_CHADDR_LEN]; + char bp_sname[DHCP_SNAME_LEN]; + char bp_file[DHCP_FILE_LEN]; + uint32_t magic_cookie; + uint8_t bp_options[0]; +} __attribute__((packed)); + + + +int dhcp_discovery(uint8_t *mac); +void dhcp_handler(void *base); + +#endif diff --git a/include/dns.h b/include/dns.h new file mode 100644 index 0000000..87d6492 --- /dev/null +++ b/include/dns.h @@ -0,0 +1,69 @@ +#ifndef CRASHPOWEROS_DNS_H +#define CRASHPOWEROS_DNS_H + +#define DNS_Header_ID 0x2115 + +#define DNS_TYPE_A 1 +#define DNS_TYPE_NS 2 +#define DNS_TYPE_MD 3 +#define DNS_TYPE_MF 4 +#define DNS_TYPE_CNAME 5 +#define DNS_TYPE_SOA 6 +#define DNS_TYPE_MB 7 +#define DNS_TYPE_MG 8 +#define DNS_TYPE_MR 9 +#define DNS_TYPE_NULL 10 +#define DNS_TYPE_WKS 11 +#define DNS_TYPE_PTR 12 +#define DNS_TYPE_HINFO 13 +#define DNS_TYPE_MINFO 14 +#define DNS_TYPE_MX 15 +#define DNS_TYPE_TXT 16 +#define DNS_TYPE_ANY 255 + +#define DNS_CLASS_INET 1 +#define DNS_CLASS_CSNET 2 +#define DNS_CLASS_CHAOS 3 +#define DNS_CLASS_HESIOD 4 +#define DNS_CLASS_ANY 255 + +#define DNS_PORT 53 +#define DNS_SERVER_IP 0x08080808 + +#include + +struct DNS_Header { + uint16_t ID; + uint8_t RD : 1; + uint8_t AA : 1; + uint8_t Opcode : 4; + uint8_t QR : 1; + uint8_t RCODE : 4; + uint8_t Z : 3; + uint8_t RA : 1; + uint8_t TC : 1; + uint16_t QDcount; + uint16_t ANcount; + uint16_t NScount; + uint16_t ARcount; + uint8_t reserved; +} __attribute__((packed)); + +struct DNS_Question { + uint16_t type; + uint16_t Class; +} __attribute__((packed)); + +struct DNS_Answer { + uint32_t name : 24; + uint16_t type; + uint16_t Class; + uint32_t TTL; + uint16_t RDlength; + uint8_t reserved; + uint8_t RData[0]; +} __attribute__((packed)); + +void dns_handler(void *base); + +#endif diff --git a/include/etherframe.h b/include/etherframe.h new file mode 100644 index 0000000..d1c6ac5 --- /dev/null +++ b/include/etherframe.h @@ -0,0 +1,19 @@ +#ifndef CRASHPOWEROS_ETHERFRAME_H +#define CRASHPOWEROS_ETHERFRAME_H + +#include + +struct EthernetFrame_head { + uint8_t dest_mac[6]; + uint8_t src_mac[6]; + uint16_t type; +} __attribute__((packed)); + +struct EthernetFrame_tail { + uint32_t CRC; // 这里可以填写为0,网卡会自动计算 +}; + +void ether_frame_provider_send(uint64_t dest_mac, uint16_t type, uint8_t *buffer, + uint32_t size); + +#endif diff --git a/include/fifo.h b/include/fifo.h new file mode 100644 index 0000000..60c89ac --- /dev/null +++ b/include/fifo.h @@ -0,0 +1,15 @@ +#ifndef CRASHPOWEROS_FIFO_H +#define CRASHPOWEROS_FIFO_H + +#define FLAGS_OVERRUN 0x0001 + +struct FIFO8 { + unsigned char *buf; + int p, q, size, free, flags; +}; + +int fifo8_put(struct FIFO8* fifo, unsigned char data); +int fifo8_get(struct FIFO8* fifo); +void fifo8_init(struct FIFO8* fifo, int size, unsigned char* buf); + +#endif diff --git a/include/ipv4.h b/include/ipv4.h new file mode 100644 index 0000000..5299ef4 --- /dev/null +++ b/include/ipv4.h @@ -0,0 +1,31 @@ +#ifndef CRASHPOWEROS_IPV4_H +#define CRASHPOWEROS_IPV4_H + +#define IP_PROTOCOL 0x0800 +#define MTU 1500 +#define IP_MF 13 +#define IP_DF 14 +#define IP_OFFSET 0 + +#include + +struct IPV4Message { + uint8_t headerLength : 4; + uint8_t version : 4; + uint8_t tos; + uint16_t totalLength; + uint16_t ident; + uint16_t flagsAndOffset; + uint8_t timeToLive; + uint8_t protocol; + uint16_t checkSum; + uint32_t srcIP; + uint32_t dstIP; +} __attribute__((packed)); + +void IPV4ProviderSend(uint8_t protocol, uint64_t dest_mac, uint32_t dest_ip, + uint32_t src_ip, uint8_t *data, uint32_t size); +uint16_t CheckSum(uint16_t *data, uint32_t size); +uint32_t IP2UINT32_T(uint8_t *ip); + +#endif diff --git a/include/net.h b/include/net.h new file mode 100644 index 0000000..58ef110 --- /dev/null +++ b/include/net.h @@ -0,0 +1,17 @@ +#ifndef CRASHPOWEROS_NET_H +#define CRASHPOWEROS_NET_H + +#include "../include/common.h" + +typedef struct { + bool (*find)(); + void (*init)(); + void (*Send)(unsigned char* buffer, unsigned int size); + char card_name[50]; + int use; // 正在使用 + int flag; +} network_card; + +void netcard_send(unsigned char* buffer, unsigned int size); + +#endif diff --git a/include/socket.h b/include/socket.h new file mode 100644 index 0000000..7ce9be4 --- /dev/null +++ b/include/socket.h @@ -0,0 +1,37 @@ +#ifndef CRASHPOWEROS_SOCKET_H +#define CRASHPOWEROS_SOCKET_H + +#define MAX_SOCKET_NUM 256 +#define SOCKET_ALLOC -1 +#define SOCKET_FREE 0 + +#include + +struct Socket { + // 函数格式 + int (*Connect)(struct Socket *socket); // TCP + void (*Disconnect)(struct Socket *socket); // TCP + void (*Listen)(struct Socket *socket); // TCP + void (*Send)(struct Socket *socket, uint8_t *data, uint32_t size); // TCP/UDP + void (*Handler)(struct Socket *socket, void *base); // TCP/UDP + // TCP/UDP + uint32_t remoteIP; + uint16_t remotePort; + uint32_t localIP; + uint16_t localPort; + uint8_t state; + uint8_t protocol; + // TCP + uint32_t seqNum; + uint32_t ackNum; + uint16_t MSS; + int flag; // 1 有包 0 没包 + int size; + char *buf; +} __attribute__((packed)); + +void socket_init(); +struct Socket *Socket_Find(uint32_t dstIP, uint16_t dstPort, uint32_t srcIP, + uint16_t srcPort, uint8_t protocol); + +#endif diff --git a/include/tcp.h b/include/tcp.h new file mode 100644 index 0000000..c3e32f7 --- /dev/null +++ b/include/tcp.h @@ -0,0 +1,59 @@ +#ifndef CRASHPOWEROS_TCP_H +#define CRASHPOWEROS_TCP_H + +#define TCP_PROTOCOL 6 +#define TCP_CONNECT_WAITTIME 10000 +#define MSS_Default 1460 +#define TCP_SEG_WAITTIME 100 + +#define SOCKET_TCP_CLOSED 1 +#define SOCKET_TCP_LISTEN 2 +#define SOCKET_TCP_SYN_SENT 3 +#define SOCKET_TCP_SYN_RECEIVED 4 +#define SOCKET_TCP_ESTABLISHED 5 +#define SOCKET_TCP_FIN_WAIT1 6 +#define SOCKET_TCP_FIN_WAIT2 7 +#define SOCKET_TCP_CLOSING 8 +#define SOCKET_TCP_TIME_WAIT 9 +#define SOCKET_TCP_CLOSE_WAIT 10 +#define SOCKET_TCP_LAST_ACK 11 + +#include + +#include "common.h" + +struct TCPPesudoHeader { + uint32_t srcIP; + uint32_t dstIP; + uint16_t protocol; + uint16_t totalLength; +} __attribute__((packed)); + +struct TCPMessage { + uint16_t srcPort; + uint16_t dstPort; + uint32_t seqNum; + uint32_t ackNum; + uint8_t reserved : 4; + uint8_t headerLength : 4; + uint8_t FIN : 1; + uint8_t SYN : 1; + uint8_t RST : 1; + uint8_t PSH : 1; + uint8_t ACK : 1; + uint8_t URG : 1; + uint8_t ECE : 1; + uint8_t CWR : 1; + uint16_t window; + uint16_t checkSum; + uint16_t pointer; + uint32_t options[0]; +} __attribute__((packed)); + +void tcp_provider_send(uint32_t dstIP, uint32_t srcIP, uint16_t dstPort, + uint16_t srcPort, uint32_t Sequence, uint32_t ackNum, + bool URG, bool ACK, bool PSH, bool RST, bool SYN, bool FIN, + bool ECE, bool CWR, uint8_t *data, uint32_t size); +void tcp_handler(void *base); + +#endif diff --git a/include/udp.h b/include/udp.h new file mode 100644 index 0000000..f0a02bb --- /dev/null +++ b/include/udp.h @@ -0,0 +1,20 @@ +#ifndef CRASHPOWEROS_UDP_H +#define CRASHPOWEROS_UDP_H + +#define UDP_PROTOCOL 17 + +#include + +struct UDPMessage { + uint16_t srcPort; + uint16_t dstPort; + uint16_t length; + uint16_t checkSum; +} __attribute__((packed)); + +uint8_t *UDP_Packet(uint16_t dest_port, uint16_t src_port, uint8_t *data, uint32_t size); +void udp_provider_send(uint32_t destip, uint32_t srcip, uint16_t dest_port, + uint16_t src_port, uint8_t *data, uint32_t size); +void udp_handler(void *base); + +#endif diff --git a/include/vdisk.h b/include/vdisk.h index 2cd17cc..0f7cf01 100644 --- a/include/vdisk.h +++ b/include/vdisk.h @@ -3,6 +3,8 @@ #define SECTORS_ONCE 8 +#include "../include/common.h" + typedef struct { void (*Read)(char drive, unsigned char *buffer, unsigned int number, unsigned int lba); @@ -42,5 +44,9 @@ int disk_Size(char drive); int DiskReady(char drive); void Disk_Write(unsigned int lba, unsigned int number, void *buffer, char drive); +unsigned int GetDriveCode(unsigned char *name); +bool SetDrive(unsigned char *name); +void DriveSemaphoreGive(unsigned int drive_code); +bool DriveSemaphoreTake(unsigned int drive_code); #endif diff --git a/kernel/fifo.c b/kernel/fifo.c new file mode 100644 index 0000000..fcac12e --- /dev/null +++ b/kernel/fifo.c @@ -0,0 +1,41 @@ +#include "../include/fifo.h" + +void fifo8_init(struct FIFO8* fifo, int size, unsigned char* buf) { + fifo->size = size; + fifo->buf = buf; + fifo->free = size; /* 缓冲区大小 */ + fifo->flags = 0; + fifo->p = 0; /* 下一个数据写入位置 */ + fifo->q = 0; /* 下一个数据读出位置 */ + return; +} + +int fifo8_put(struct FIFO8* fifo, unsigned char data) { + if (fifo->free == 0) { + /* 没有空间了,溢出 */ + fifo->flags |= FLAGS_OVERRUN; + return -1; + } + fifo->buf[fifo->p] = data; + fifo->p++; + if (fifo->p == fifo->size) { + fifo->p = 0; + } + fifo->free--; + return 0; +} + +int fifo8_get(struct FIFO8* fifo) { + int data; + if (fifo->free == fifo->size) { + /* 如果缓冲区为空则返回-1 */ + return -1; + } + data = fifo->buf[fifo->q]; + fifo->q++; + if (fifo->q == fifo->size) { + fifo->q = 0; + } + fifo->free++; + return data; +} \ No newline at end of file diff --git a/network/arp.c b/network/arp.c new file mode 100644 index 0000000..9f883c5 --- /dev/null +++ b/network/arp.c @@ -0,0 +1,72 @@ +#include "../include/arp.h" +#include "../include/etherframe.h" +#include "../include/memory.h" + +uint8_t ARP_flags = 1; +uint64_t ARP_mac_address[MAX_ARP_TABLE]; +uint32_t ARP_ip_address[MAX_ARP_TABLE]; +uint32_t ARP_write_pointer = 0; + +uint8_t *ARP_Packet(uint64_t dest_mac, uint32_t dest_ip, uint64_t src_mac, + uint32_t src_ip, uint16_t command) { + struct ARPMessage *res = + (struct ARPMessage *)kmalloc(sizeof(struct ARPMessage)); + res->hardwareType = 0x0100; + res->protocol = 0x0008; + res->hardwareAddressSize = 6; + res->protocolAddressSize = 4; + res->command = ((command & 0xff00) >> 8) | ((command & 0x00ff) << 8); + res->dest_mac[0] = (uint8_t)dest_mac; + res->dest_mac[1] = (uint8_t)(dest_mac >> 8); + res->dest_mac[2] = (uint8_t)(dest_mac >> 16); + res->dest_mac[3] = (uint8_t)(dest_mac >> 24); + res->dest_mac[4] = (uint8_t)(dest_mac >> 32); + res->dest_mac[5] = (uint8_t)(dest_mac >> 40); + res->dest_ip = ((dest_ip << 24) & 0xff000000) | + ((dest_ip << 8) & 0x00ff0000) | ((dest_ip >> 8) & 0xff00) | + ((dest_ip >> 24) & 0xff); + res->src_mac[0] = (uint8_t)src_mac; + res->src_mac[1] = (uint8_t)(src_mac >> 8); + res->src_mac[2] = (uint8_t)(src_mac >> 16); + res->src_mac[3] = (uint8_t)(src_mac >> 24); + res->src_mac[4] = (uint8_t)(src_mac >> 32); + res->src_mac[5] = (uint8_t)(src_mac >> 40); + res->src_ip = ((src_ip << 24) & 0xff000000) | ((src_ip << 8) & 0x00ff0000) | + ((src_ip >> 8) & 0xff00) | ((src_ip >> 24) & 0xff); + return (uint8_t *)res; +} + +uint64_t IPParseMAC(uint32_t dstIP) { + extern uint8_t ARP_flags; + extern uint32_t ARP_write_pointer; + extern uint64_t ARP_mac_address[MAX_ARP_TABLE]; + extern uint32_t ARP_ip_address[MAX_ARP_TABLE]; + extern uint32_t ip; + extern uint8_t mac0; + extern uint32_t gateway; + //extern struct TIMERCTL timerctl; + if ((dstIP & 0xffffff00) != (ip & 0xffffff00)) { + dstIP = gateway; + } + for (int i = 0; i != ARP_write_pointer; i++) { + if (dstIP == ARP_ip_address[i]) { + return ARP_mac_address[i]; + } + } + ARP_flags = 1; + //printk("send\n"); + ether_frame_provider_send( + 0xffffffffffff, 0x0806, + ARP_Packet(0xffffffffffff, dstIP, *(uint64_t *)&mac0, ip, 1), + sizeof(struct ARPMessage)); + //printk("ok\n"); + /* + uint32_t time = timerctl.count; + while (ARP_flags) { + if (timerctl.count - time > ARP_WAITTIME) { + return -1; + } + } + */ + return ARP_mac_address[ARP_write_pointer - 1]; +} diff --git a/network/dhcp.c b/network/dhcp.c new file mode 100644 index 0000000..baf6144 --- /dev/null +++ b/network/dhcp.c @@ -0,0 +1,110 @@ +#include "../include/dhcp.h" +#include "../include/memory.h" +#include "../include/common.h" +#include "../include/udp.h" +#include "../include/ipv4.h" +#include "../include/etherframe.h" + +uint32_t gateway, submask, dns, ip, dhcp_ip; + +static int fill_dhcp_option(uint8_t *packet, uint8_t code, uint8_t *data, + uint8_t len) { + packet[0] = code; + packet[1] = len; + memcpy(&packet[2], data, len); + + return len + (sizeof(uint8_t) * 2); +} + +static int fill_dhcp_discovery_options(struct DHCPMessage *dhcp) { + int len = 0; + uint32_t req_ip; + uint8_t parameter_req_list[] = {MESSAGE_TYPE_REQ_SUBNET_MASK, + MESSAGE_TYPE_ROUTER, MESSAGE_TYPE_DNS, + MESSAGE_TYPE_DOMAIN_NAME}; + uint8_t option; + + option = DHCP_OPTION_DISCOVER; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_DHCP, &option, + sizeof(option)); + req_ip = swap32(0xffffffff); + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_REQ_IP, + (uint8_t *)&req_ip, sizeof(req_ip)); + len += fill_dhcp_option( + &dhcp->bp_options[len], MESSAGE_TYPE_PARAMETER_REQ_LIST, + (uint8_t *)¶meter_req_list, sizeof(parameter_req_list)); + option = 0; + len += fill_dhcp_option(&dhcp->bp_options[len], MESSAGE_TYPE_END, &option, + sizeof(option)); + + return len; +} + +static void dhcp_output(struct DHCPMessage *dhcp, uint8_t *mac, int *len) { + *len += sizeof(struct DHCPMessage); + memset(dhcp, 0, sizeof(struct DHCPMessage)); + + dhcp->opcode = DHCP_BOOTREQUEST; + dhcp->htype = DHCP_HARDWARE_TYPE_10_EHTHERNET; + dhcp->hlen = 6; + memcpy(dhcp->chaddr, mac, DHCP_CHADDR_LEN); + + dhcp->magic_cookie = swap32(DHCP_MAGIC_COOKIE); +} + +int dhcp_discovery(uint8_t *mac) { + int len = 0; + struct DHCPMessage *dhcp = + (struct DHCPMessage *)kmalloc(sizeof(struct DHCPMessage)); + + len = fill_dhcp_discovery_options(dhcp); + dhcp_output(dhcp, mac, &len); + udp_provider_send(0xffffffff, 0x0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, + (uint8_t *)dhcp, len); + return 0; +} + +void dhcp_handler(void *base) { + struct IPV4Message *ipv4 = + (struct IPV4Message *)(base + sizeof(struct EthernetFrame_head)); + struct UDPMessage *udp = + (struct UDPMessage *)(base + sizeof(struct EthernetFrame_head) + + sizeof(struct IPV4Message)); + struct DHCPMessage *dhcp = + (struct DHCPMessage *)(base + sizeof(struct EthernetFrame_head) + + sizeof(struct IPV4Message) + + sizeof(struct UDPMessage)); + if (dhcp->bp_options[0] == 53 && dhcp->bp_options[1] == 1 && + dhcp->bp_options[2] == DHCP_OPTION_OFFER) { + // printk("DHCP Offer\n"); + ip = dhcp->yiaddr; + uint8_t nip1 = ip; + uint8_t nip2 = ip >> 8; + uint8_t nip3 = ip >> 16; + uint8_t nip4 = ip >> 24; + // printk("DHCP: %d.%d.%d.%d\n", (uint8_t)(ipv4->srcIP), + // (uint8_t)(ipv4->srcIP >> 8), (uint8_t)(ipv4->srcIP >> 16), + // (uint8_t)(ipv4->srcIP >> 24)); + dhcp_ip = swap32(ipv4->srcIP); + //printk("IP: %d.%d.%d.%d\n", nip1, nip2, nip3, nip4); + ip = swap32(ip); + + unsigned char *options = &dhcp->bp_options[0]; + while (options[0] != 0xff) { + if (options[0] == MESSAGE_TYPE_DNS) { + // printk("DNS: %d.%d.%d.%d\n", options[2], options[3], options[4], + // options[5]); + dns = swap32(*(uint32_t *)&options[2]); + } else if (options[0] == MESSAGE_TYPE_REQ_SUBNET_MASK) { + // printk("Subnet Mask: %d.%d.%d.%d\n", options[2], options[3], options[4], + // options[5]); + submask = swap32(*(uint32_t *)&options[2]); + } else if (options[0] == MESSAGE_TYPE_ROUTER) { + // printk("Gateway: %d.%d.%d.%d\n", options[2], options[3], options[4], + // options[5]); + gateway = swap32(*(uint32_t *)&options[2]); + } + options += options[1] + 2; + } + } +} diff --git a/network/dns.c b/network/dns.c new file mode 100644 index 0000000..e7cc2d2 --- /dev/null +++ b/network/dns.c @@ -0,0 +1,20 @@ +#include "../include/dns.h" +#include "../include/common.h" +#include "../include/udp.h" +#include "../include/ipv4.h" +#include "../include/etherframe.h" + +uint32_t dns_parse_ip_result = 0; + +void dns_handler(void *base) { + struct DNS_Header *dns_header = + (struct DNS_Header *)(base + sizeof(struct EthernetFrame_head) + + sizeof(struct IPV4Message) + + sizeof(struct UDPMessage)); + if (swap16(dns_header->ID) == DNS_Header_ID) { + uint8_t *p = (uint8_t *)(dns_header) + sizeof(struct DNS_Header); + p += strlen(p) + sizeof(struct DNS_Question) - 1; + struct DNS_Answer *dns_answer = (struct DNS_Answer *)p; + dns_parse_ip_result = swap32(*(uint32_t *)&dns_answer->RData[0]); + } +} diff --git a/network/etherframe.c b/network/etherframe.c new file mode 100644 index 0000000..172c765 --- /dev/null +++ b/network/etherframe.c @@ -0,0 +1,37 @@ +#include "../include/etherframe.h" +#include "../include/memory.h" +#include "../include/net.h" + +extern uint8_t mac0, mac1, mac2, mac3, mac4, mac5; +// 以太网帧 +void ether_frame_provider_send(uint64_t dest_mac, uint16_t type, uint8_t *buffer, + uint32_t size) { + uint8_t *buffer2 = + (uint8_t *)kmalloc(sizeof(struct EthernetFrame_head) + size + + sizeof(struct EthernetFrame_tail)); + struct EthernetFrame_head *header = (struct EthernetFrame_head *)buffer2; + struct EthernetFrame_tail *tailer = + (struct EthernetFrame_tail *)(buffer2 + + sizeof(struct EthernetFrame_head) + size); + header->dest_mac[0] = (uint8_t)dest_mac; + header->dest_mac[1] = (uint8_t)(dest_mac >> 8); + header->dest_mac[2] = (uint8_t)(dest_mac >> 16); + header->dest_mac[3] = (uint8_t)(dest_mac >> 24); + header->dest_mac[4] = (uint8_t)(dest_mac >> 32); + header->dest_mac[5] = (uint8_t)(dest_mac >> 40); + header->src_mac[0] = mac0; + header->src_mac[1] = mac1; + header->src_mac[2] = mac2; + header->src_mac[3] = mac3; + header->src_mac[4] = mac4; + header->src_mac[5] = mac5; + header->type = (type << 8) | ((type & 0xff00) >> 8); + tailer->CRC = 0; + uint8_t *src = buffer; + uint8_t *dst = buffer2 + sizeof(struct EthernetFrame_head); + for (uint32_t i = 0; i < size; i++) + dst[i] = src[i]; + netcard_send(buffer2, sizeof(struct EthernetFrame_head) + size + + sizeof(struct EthernetFrame_tail)); + kfree(buffer2); +} diff --git a/network/ipv4.c b/network/ipv4.c new file mode 100644 index 0000000..5bf042f --- /dev/null +++ b/network/ipv4.c @@ -0,0 +1,110 @@ +#include "../include/ipv4.h" +#include "../include/memory.h" +#include "../include/common.h" + +static uint16_t ident = 0; + +void IPV4ProviderSend(uint8_t protocol, uint64_t dest_mac, uint32_t dest_ip, + uint32_t src_ip, uint8_t *data, uint32_t size) { + struct IPV4Message *res = + (struct IPV4Message *)kmalloc(sizeof(struct IPV4Message) + size); + uint8_t *dat = (uint8_t *)res; + memcpy(dat + sizeof(struct IPV4Message), data, size); + res->version = 4; + res->headerLength = sizeof(struct IPV4Message) / 4; + res->tos = 0; + res->ident = ident; + res->timeToLive = 64; + res->protocol = protocol; + res->dstIP = ((dest_ip << 24) & 0xff000000) | ((dest_ip << 8) & 0x00ff0000) | + ((dest_ip >> 8) & 0xff00) | ((dest_ip >> 24) & 0xff); + res->srcIP = ((src_ip << 24) & 0xff000000) | ((src_ip << 8) & 0x00ff0000) | + ((src_ip >> 8) & 0xff00) | ((src_ip >> 24) & 0xff); + if (sizeof(struct IPV4Message) + size <= MTU) { + res->totalLength = swap16(sizeof(struct IPV4Message) + size); + res->flagsAndOffset = 0; + res->checkSum = 0; + res->checkSum = CheckSum((uint16_t *)dat, sizeof(struct IPV4Message)); + ether_frame_provider_send(dest_mac, 0x0800, dat, + sizeof(struct IPV4Message) + size); + } else { + int offset = 0; + uint8_t *dat1 = (uint8_t *)kmalloc(MTU); + for (int i = 0; i * (MTU - sizeof(struct IPV4Message)) <= size; i++) { + if (i * (MTU - sizeof(struct IPV4Message)) >= + size - (MTU - sizeof(struct IPV4Message))) { + res->totalLength = + swap16(size - i * (MTU - sizeof(struct IPV4Message)) + + sizeof(struct IPV4Message)); + res->flagsAndOffset = offset << IP_OFFSET; + res->flagsAndOffset = swap16(res->flagsAndOffset); + res->checkSum = 0; + res->checkSum = CheckSum((uint16_t *)dat, sizeof(struct IPV4Message)); + memcpy((void *)dat1, (void *)res, sizeof(struct IPV4Message)); + memcpy((void *)(dat1 + sizeof(struct IPV4Message)), + (void *)(data + i * (MTU - sizeof(struct IPV4Message))), + size - i * (MTU - sizeof(struct IPV4Message))); + // printk("ip:%08x,%08x + // size:%d\nMF:0\noffset:%d\n",swap32(res->srcIP),swap32(res->dstIP),swap16(res->totalLength),(swap16(res->flagsAndOffset) + // >> 3)); + ether_frame_provider_send(dest_mac, 0x0800, dat1, + size - i * (MTU - sizeof(struct IPV4Message)) + + sizeof(struct IPV4Message)); + } else { + res->totalLength = swap16(MTU); + res->flagsAndOffset = (offset << IP_OFFSET) | (1 << IP_MF); + res->flagsAndOffset = swap16(res->flagsAndOffset); + res->checkSum = 0; + res->checkSum = CheckSum((uint16_t *)dat, sizeof(struct IPV4Message)); + memcpy((void *)dat1, (void *)res, sizeof(struct IPV4Message)); + memcpy((void *)(dat1 + sizeof(struct IPV4Message)), + (void *)(data + i * (MTU - sizeof(struct IPV4Message))), + MTU - sizeof(struct IPV4Message)); + // printk("ip:%08x,%08x + // size:%d\nMF:1\noffset:%d\n",swap32(res->srcIP),swap32(res->dstIP),swap16(res->totalLength),(swap16(res->flagsAndOffset) + // >> 3)); + ether_frame_provider_send(dest_mac, 0x0800, dat1, MTU); + } + offset += (MTU - sizeof(struct IPV4Message)) / 8; + } + kfree((void *)dat1); + } + + kfree(dat); + ident++; + return; +} +uint16_t CheckSum(uint16_t *data, uint32_t size) { + uint32_t tmp = 0; + for (int i = 0; i < size / 2; i++) { + tmp += ((data[i] & 0xff00) >> 8) | ((data[i] & 0x00ff) << 8); + } + if (size % 2) + tmp += ((uint16_t)((char *)data)[size - 1]) << 8; + while (tmp & 0xffff0000) + tmp = (tmp & 0xffff) + (tmp >> 16); + return ((~tmp & 0xff00) >> 8) | ((~tmp & 0x00ff) << 8); +} +uint32_t IP2UINT32_T(uint8_t *ip) { + uint8_t ip0, ip1, ip2, ip3; + ip0 = strtol(ip, '.', 10); + uint8_t t = ip0; + while (t >= 10) { + t /= 10; + ip++; + } + ip1 = strtol(ip + 2, '.', 10); + t = ip1; + while (t >= 10) { + t /= 10; + ip++; + } + ip2 = strtol(ip + 4, '.', 10); + t = ip2; + while (t >= 10) { + t /= 10; + ip++; + } + ip3 = strtol(ip + 6, NULL, 10); + return (uint32_t)((ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3); +} diff --git a/network/net.c b/network/net.c new file mode 100644 index 0000000..74570ec --- /dev/null +++ b/network/net.c @@ -0,0 +1,23 @@ +#include "../include/net.h" +#include "../include/vdisk.h" +#include "../include/etherframe.h" + +network_card network_card_CTL[25]; +static uint8_t* IP_Packet_Base[16] = {NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL}; + +void netcard_send(unsigned char* buffer, unsigned int size) { + for (int i = 0; i < 25; i++) { + if (network_card_CTL[i].use) { + if (DriveSemaphoreTake(GetDriveCode("NETCARD_DRIVE"))) { + // printk("Send....%s %d + // %d\n",network_card_CTL[i].card_name,network_card_CTL[i].use,i); + network_card_CTL[i].Send(buffer, size); + DriveSemaphoreGive(GetDriveCode("NETCARD_DRIVE")); + break; + } + } + } +} + diff --git a/driver/pcnet.c b/network/pcnet.c similarity index 94% rename from driver/pcnet.c rename to network/pcnet.c index 3d93780..ca2677b 100644 --- a/driver/pcnet.c +++ b/network/pcnet.c @@ -10,6 +10,8 @@ uint8_t bus = 255, dev = 255, func = 255; extern unsigned int PCI_ADDR_BASE; extern idt_ptr_t idt_ptr; +extern uint32_t gateway, submask, dns, ip, dhcp_ip; + static int io_base = 0; static uint8_t sendBufferDescMemory[2048 + 15]; static uint8_t sendBuffers[8][2048 + 15]; @@ -66,31 +68,23 @@ void Activate() { } int pcnet_find_card() { - //printk("pcnet_find:"); PCI_GET_DEVICE(CARD_VENDOR_ID, CARD_DEVICE_ID, &bus, &dev, &func); if (bus == 255) { - //printk("false\n"); return 0; } - //printk("true"); return 1; } -/* + static void init_Card_all() { currentSendBuffer = 0; currentRecvBuffer = 0; - // 获取MAC地址并保存 mac0 = io_in8(io_base + APROM0); mac1 = io_in8(io_base + APROM1); mac2 = io_in8(io_base + APROM2); mac3 = io_in8(io_base + APROM3); mac4 = io_in8(io_base + APROM4); mac5 = io_in8(io_base + APROM5); - // printk("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", mac0, mac1, mac2, - // mac3, - // mac4, mac5); - // 这里约等于 into_16bitsRW(); reset_card(); clock_sleep(1); @@ -99,9 +93,6 @@ static void init_Card_all() { io_out16(io_base + RAP16, CSR0); io_out16(io_base + RDP16, 0x0004); // 暂时停止所有传输(用于初始化PCNET网卡 - // initBlock传输初始化(CSR1=IB地址低16位,CSR2=IB地址高16位) - // & - // Send/Recv环形缓冲区的初始化 initBlock.mode = 0; initBlock.reserved1numSendBuffers = (0 << 4) | 3; // 高4位是reserved1 低4位是numSendBuffers @@ -165,7 +156,7 @@ static void init_Card_all() { // "来自Powerint DOS 386的消息:我是周志昊!!!", strlen("来自Powerint DOS // 386的消息:我是周志昊!!!")); } -*/ + void init_pcnet_card() { printf("[\035kernel\036]: Loading pcnet driver.\n"); // 允许PCNET网卡产生中断 @@ -177,7 +168,7 @@ void init_pcnet_card() { conf |= 0x7; // 设置第0~2位(允许PCNET网卡产生中断 pci_write_command_status(bus, dev, func, conf); io_base = pci_get_port_base(bus, dev, func); - //init_Card_all(); + init_Card_all(); } void PCNET_IRQ(registers_t *reg) { diff --git a/driver/rtl8139.c b/network/rtl8139.c similarity index 100% rename from driver/rtl8139.c rename to network/rtl8139.c diff --git a/network/socket.c b/network/socket.c new file mode 100644 index 0000000..cb3c7c6 --- /dev/null +++ b/network/socket.c @@ -0,0 +1,44 @@ +#include "../include/socket.h" +#include "../include/udp.h" +#include "../include/tcp.h" + +static struct Socket sockets[MAX_SOCKET_NUM]; + +static void socket_udp_send(struct Socket *socket, uint8_t *data, + uint32_t size) { + udp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, data, size); +} + +static void socket_tcp_send(struct Socket *socket, uint8_t *data, + uint32_t size) { + while(socket->state != SOCKET_TCP_ESTABLISHED); + uint32_t s = size; + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, 0, + 0, 0, 0, 0, 0, data, s); + socket->seqNum += s; + //io_delay(); +} + +void socket_init() { + for (int i = 0; i < MAX_SOCKET_NUM; i++) { + sockets->state = SOCKET_FREE; + } +} + +struct Socket *Socket_Find(uint32_t dstIP, uint16_t dstPort, uint32_t srcIP, + uint16_t srcPort, uint8_t protocol) { + for (int i = 0; i != MAX_SOCKET_NUM; i++) { + if (srcIP == sockets[i].localIP && dstIP == sockets[i].remoteIP && + srcPort == sockets[i].localPort && dstPort == sockets[i].remotePort && + protocol == sockets[i].protocol && sockets[i].state != SOCKET_FREE) { + return (struct Socket *)&sockets[i]; + } else if (srcIP == sockets[i].localIP && srcPort == sockets[i].localPort && + protocol == sockets[i].protocol && + sockets[i].state == SOCKET_TCP_LISTEN) { + return (struct Socket *)&sockets[i]; + } + } + return -1; +} diff --git a/network/tcp.c b/network/tcp.c new file mode 100644 index 0000000..e74799a --- /dev/null +++ b/network/tcp.c @@ -0,0 +1,167 @@ +#include "../include/tcp.h" +#include "../include/memory.h" +#include "../include/ipv4.h" +#include "../include/dhcp.h" +#include "../include/socket.h" +#include "../include/printf.h" +#include "../include/etherframe.h" + +static uint16_t ident = 0; + +void tcp_provider_send(uint32_t dstIP, uint32_t srcIP, uint16_t dstPort, + uint16_t srcPort, uint32_t Sequence, uint32_t ackNum, + bool URG, bool ACK, bool PSH, bool RST, bool SYN, bool FIN, + bool ECE, bool CWR, uint8_t *data, uint32_t size) { + uint32_t s = + SYN ? (sizeof(struct TCPPesudoHeader) + sizeof(struct TCPMessage) + size + + 4) + : (sizeof(struct TCPPesudoHeader) + sizeof(struct TCPMessage) + size); + uint8_t *dat = (uint8_t *)kmalloc(s); + struct TCPPesudoHeader *phdr = (struct TCPPesudoHeader *)dat; + struct TCPMessage *tcp = + (struct TCPMessage *)(dat + sizeof(struct TCPPesudoHeader)); + memcpy((void *)(tcp) + (SYN ? (sizeof(struct TCPMessage) + 4) + : sizeof(struct TCPMessage)), + (void *)data, size); + phdr->dstIP = swap32(dstIP); + phdr->srcIP = swap32(srcIP); + phdr->protocol = 0x0600; + phdr->totalLength = swap16(sizeof(struct TCPMessage) + size); + tcp->dstPort = swap16(dstPort); + tcp->srcPort = swap16(srcPort); + tcp->seqNum = swap32(Sequence); + tcp->ackNum = swap32(ackNum); + tcp->headerLength = sizeof(struct TCPMessage) / 4; + tcp->reserved = 0; + tcp->URG = URG; + tcp->ACK = ACK; + tcp->PSH = PSH; + tcp->RST = RST; + tcp->SYN = SYN; + tcp->FIN = FIN; + tcp->ECE = ECE; + tcp->CWR = CWR; + tcp->window = 0xffff; + tcp->pointer = 0; + if (SYN) { + tcp->options[0] = 0xb4050402; + phdr->totalLength = swap16(swap16(phdr->totalLength) + 4); + tcp->headerLength += 1; + } + tcp->checkSum = 0; + tcp->checkSum = CheckSum((uint16_t *)dat, s); + IPV4ProviderSend(6, IPParseMAC(dstIP), dstIP, srcIP, (uint8_t *)tcp, + s - sizeof(struct TCPPesudoHeader)); + kfree((void *)dat); + return; +} + +void tcp_handler(void *base) { + struct IPV4Message *ipv4 = + (struct IPV4Message *)(base + sizeof(struct EthernetFrame_head)); + struct TCPMessage *tcp = + (struct TCPMessage *)(base + sizeof(struct EthernetFrame_head) + + sizeof(struct IPV4Message)); + struct Socket *socket = + Socket_Find(swap32(ipv4->srcIP), swap16(tcp->srcPort), + swap32(ipv4->dstIP), swap16(tcp->dstPort), TCP_PROTOCOL); + if (socket == -1) { + // printk("Not found %08x %d %08x %d\n",swap32(ipv4->srcIP), + // swap16(tcp->srcPort), swap32(ipv4->dstIP), swap16(tcp->dstPort)); + return; + } + uint8_t flags = (tcp->ACK << 4) | (tcp->PSH << 3) | (tcp->SYN << 1) | + tcp->FIN; // 只看ACK,PSH,SYN,FIN四个flags + if (tcp->RST) { + socket->state = SOCKET_TCP_CLOSED; + } + if (socket->state != SOCKET_TCP_CLOSED) { + switch (flags) { + case 0x12: // 00010010 ACK | SYN + if (socket->state == SOCKET_TCP_SYN_SENT) { + socket->state = SOCKET_TCP_ESTABLISHED; + socket->ackNum = swap32(tcp->seqNum) + 1; + if ((uint16_t)tcp->options == 0x0402) { + uint16_t MSS_ = swap32(tcp->options[0]) & 0xffff; + socket->MSS = (MSS_Default >= MSS_) ? MSS_ : MSS_Default; + } + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0); + } + break; + case 0x02: // 00000010 SYN + if (socket->state == SOCKET_TCP_LISTEN) { + socket->state = SOCKET_TCP_SYN_RECEIVED; + socket->remoteIP = swap32(ipv4->srcIP); + socket->remotePort = swap16(tcp->srcPort); + socket->ackNum = swap32(tcp->seqNum) + 1; + socket->seqNum = 0; + if ((uint16_t)tcp->options == 0x0402) { + uint16_t MSS_ = swap32(tcp->options[0]) & 0xffff; + socket->MSS = (MSS_Default >= MSS_) ? MSS_ : MSS_Default; + } + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 0, 0, 1, 0, 0, 0, 0, 0); + socket->seqNum++; + } + break; + case 0x10: // 00010000 ACK + if (socket->state == SOCKET_TCP_SYN_RECEIVED) { + socket->state = SOCKET_TCP_ESTABLISHED; + } else if (socket->state == SOCKET_TCP_FIN_WAIT1) { + socket->state = SOCKET_TCP_FIN_WAIT2; + } else if (socket->state == SOCKET_TCP_CLOSE_WAIT) { + socket->state = SOCKET_TCP_CLOSED; + } + if (tcp->ACK && !tcp->CWR && !tcp->ECE && !tcp->PSH && + !tcp->URG) { // Only ACK=1 + goto _default; + } + case 0x01: // 00000001 FIN + case 0x11: // 00010001 ACK | FIN + if (socket->state == SOCKET_TCP_ESTABLISHED) { + socket->state = SOCKET_TCP_CLOSE_WAIT; + socket->ackNum++; + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0); + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 0); + } else if (socket->state == SOCKET_TCP_FIN_WAIT1 || + socket->state == SOCKET_TCP_FIN_WAIT2) { + socket->state = SOCKET_TCP_CLOSED; + socket->ackNum++; + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0); + } else if (socket->state == SOCKET_TCP_CLOSE_WAIT) { + socket->state = SOCKET_TCP_CLOSED; + } + break; + default: + _default: + // TCP 传输 + if ((swap16(ipv4->totalLength) - sizeof(struct IPV4Message) - + (tcp->headerLength * 4)) == socket->MSS) { + printf("TCP Segment.\n"); + break; + } + if (socket->ackNum == swap32(tcp->seqNum) && + swap16(ipv4->totalLength) != + (sizeof(struct IPV4Message) + (tcp->headerLength * 4))) { + if (socket->Handler != NULL) { + socket->Handler(socket, base); + } + socket->ackNum += swap16(ipv4->totalLength) - + sizeof(struct IPV4Message) - (tcp->headerLength * 4); + } + tcp_provider_send(socket->remoteIP, socket->localIP, socket->remotePort, + socket->localPort, socket->seqNum, socket->ackNum, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0); + break; + } + } +} \ No newline at end of file diff --git a/network/udp.c b/network/udp.c new file mode 100644 index 0000000..24d3915 --- /dev/null +++ b/network/udp.c @@ -0,0 +1,60 @@ +#include "../include/udp.h" +#include "../include/ipv4.h" +#include "../include/memory.h" +#include "../include/common.h" +#include "../include/dhcp.h" +#include "../include/socket.h" +#include "../include/dns.h" +#include "../include/etherframe.h" + +uint8_t *UDP_Packet(uint16_t dest_port, uint16_t src_port, uint8_t *data, uint32_t size) { + struct UDPMessage *res = + (struct UDPMessage *)kmalloc(size + sizeof(struct UDPMessage)); + uint8_t *dat = (uint8_t *)res; + memcpy(dat + sizeof(struct UDPMessage), data, size); + res->srcPort = ((src_port & 0xff00) >> 8) | ((src_port & 0x00ff) << 8); + res->dstPort = ((dest_port & 0xff00) >> 8) | ((dest_port & 0x00ff) << 8); + res->length = size + sizeof(struct UDPMessage); + res->length = ((res->length & 0xff00) >> 8) | ((res->length & 0x00ff) << 8); + res->checkSum = 0; + return (uint8_t *)res; +} + +void udp_provider_send(uint32_t destip, uint32_t srcip, uint16_t dest_port, + uint16_t src_port, uint8_t *data, uint32_t size) { + if (destip == 0xffffffff) { + IPV4ProviderSend(17, 0xffffffffffff, destip, srcip, + UDP_Packet(dest_port, src_port, data, size), + size + sizeof(struct UDPMessage)); + return; + } + IPV4ProviderSend(17, IPParseMAC(destip), destip, srcip, + UDP_Packet(dest_port, src_port, data, size), + size + sizeof(struct UDPMessage)); +} + +void udp_handler(void *base) { + // printk("UDP Packet:\n"); + struct IPV4Message *ipv4 = + (struct IPV4Message *)(base + sizeof(struct EthernetFrame_head)); + struct UDPMessage *udp = + (struct UDPMessage *)(base + sizeof(struct EthernetFrame_head) + + sizeof(struct IPV4Message)); + if (swap16(udp->srcPort) == DHCP_SERVER_PORT) { // DHCP给我们分配IP + dhcp_handler(base); + } else if (swap32(ipv4->srcIP) == DNS_SERVER_IP && + swap16(udp->srcPort) == DNS_PORT) { + dns_handler(base); + } else { + // Socket + struct Socket *socket = + Socket_Find(swap32(ipv4->srcIP), swap16(udp->srcPort), + swap32(ipv4->dstIP), swap16(udp->dstPort), UDP_PROTOCOL); + if (socket == -1) { + return; + } + if (socket->Handler != NULL) { + socket->Handler(socket, base); + } + } +}