diff options
| author | Miguel <m.i@gmx.at> | 2018-09-25 12:43:03 +0200 |
|---|---|---|
| committer | Miguel <m.i@gmx.at> | 2018-09-25 12:43:03 +0200 |
| commit | 112ca29a3bb2ab38693943ed33ee51f4fd7d2d81 (patch) | |
| tree | c843051f9291ebe2de6e603c45d924d843d35ea4 | |
| parent | 2ba77c01a33c3454aeed42d5394dd5ccede10851 (diff) | |
arp replies working!
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.md | 3 | ||||
| -rw-r--r-- | driver/e1000.c | 25 | ||||
| -rw-r--r-- | driver/e1000.h | 3 | ||||
| -rw-r--r-- | driver/keyboard.c | 28 | ||||
| -rw-r--r-- | net/arp.c | 126 | ||||
| -rw-r--r-- | net/arp.h | 28 | ||||
| -rw-r--r-- | net/eth.c | 1 | ||||
| -rw-r--r-- | net/eth.h | 16 | ||||
| -rw-r--r-- | net/inet.h | 20 | ||||
| -rw-r--r-- | net/netdev.c | 16 | ||||
| -rw-r--r-- | net/netdev.h | 15 |
12 files changed, 249 insertions, 34 deletions
@@ -32,6 +32,7 @@ CFLAGS+=-I./asm CFLAGS+=-I./kernel CFLAGS+=-I./driver CFLAGS+=-I./fs +CFLAGS+=-I./net CFLAGS+=-gstabs #CFLAGS+=-fstack-protector-all @@ -81,6 +82,7 @@ SOURCES+=$(wildcard ./driver/*.c) SOURCES+=$(wildcard ./terminal/*.c) SOURCES+=$(wildcard ./lib/*/*.c) SOURCES+=$(wildcard ./testing/*.c) +SOURCES+=$(wildcard ./net/*.c) #derive kernel object files OBJECTS=$(patsubst %.c, %.o, $(SOURCES)) @@ -86,6 +86,8 @@ FoolOS is tested/developed on the following emulators/machines Todos ----- +* ethernet drivers: vbox E1000 /virtio / NS2000 / ipxe network drivers? +* tcp/ip stack * threads! semaphores * return value / argv / env @@ -100,7 +102,6 @@ Todos * GCC optimizations (break kernel?) / volatile?? -* Ethernet driver E1000 / NS2000 & Networking stack (ipxe network drivers?) * Unit Testing diff --git a/driver/e1000.c b/driver/e1000.c index 35e106e..4c6b8de 100644 --- a/driver/e1000.c +++ b/driver/e1000.c @@ -5,9 +5,14 @@ //registers etc. verified from pdf at https://pdos.csail.mit.edu/6.828/2006/readings/hardware/8254x_GBe_SDM.pdf #include <stdint.h> + #include "log.h" #include "e1000.h" #include "kmalloc.h" +#include "netdev.h" +#include "arp.h" + +#include "lib/string/string.h" #define REG_CTRL 0x0000 // device control R/W #define REG_CTRL_LRST 1<<3 // Link Reset / transition to 0 to initiates auto-negotiation @@ -130,6 +135,10 @@ #define E1000_NUM_RX_DESC 32 #define E1000_NUM_TX_DESC 8 +// TODO: move all global stuff to some struct so we can run multiple e1000 cards! +// +struct netdev dev; ///TODO not global! + struct e1000_rx_desc { volatile uint32_t addr_lo; // 4 volatile uint32_t addr_hi; // 4 @@ -413,6 +422,7 @@ void e1000_handleReceive() uint16_t len = rx_descs[rx_cur]->length; // Here you should inject the received packet into your network stack + arp_incoming(&dev,buf); rx_descs[rx_cur]->status = 0; old_cur = rx_cur; @@ -472,8 +482,11 @@ void e1000_linkdown() } -bool e1000_init(uint32_t base) +struct netdev e1000_init(uint32_t base) { + dev.ip=0; + dev.hwaddr[0]=dev.hwaddr[1]=dev.hwaddr[2]=dev.hwaddr[3]=dev.hwaddr[4]=dev.hwaddr[5]=0; + klog("init E1000"); klog("interrupt mask: 0x%08X",readCommand(REG_IMS)); klog("device status: 0x%08X",readCommand(REG_STATUS)); @@ -485,10 +498,14 @@ bool e1000_init(uint32_t base) if(base!=0){ mem_base=base;} detectEEProm(); - if (! readMACAddress()) return false; + if (! readMACAddress()) return dev; klog("mac : %02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],mac[6]); + memcpy(dev.hwaddr,mac,6); // use mac obtained from device + dev.ip=(192<<0)+(168<<8)+(0<<16)+(20<<24); // 192.168.0.20 // TODO: not hardcode! + dev.transmit=e1000_sendPacket; + // clear multicast table for(int i = 0; i < 0x80; i++)writeCommand(REG_MTA + i*4, 0); @@ -498,10 +515,10 @@ bool e1000_init(uint32_t base) txinit(); rxinit(); - + klog("E1000 initialized"); - return true; + return dev; } void e1000_irq (int irq) { diff --git a/driver/e1000.h b/driver/e1000.h index ba7db7d..27a052e 100644 --- a/driver/e1000.h +++ b/driver/e1000.h @@ -1,5 +1,6 @@ #include <stdint.h> -bool e1000_init(uint32_t base); +#include "netdev.h" +struct netdev e1000_init(uint32_t base); int e1000_sendPacket(const void * p_data, uint16_t p_len); void e1000_irq (int irq); void e1000_linkup(); diff --git a/driver/keyboard.c b/driver/keyboard.c index d6ce465..d201882 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -23,34 +23,6 @@ int hex_to_dec(char c) } static void put(uint8_t c) { - /* -0000 8a b1 aa 7e 4d 00 52 54 00 12 34 56 08 00 45 00 -0010 00 54 1e c0 00 00 40 01 da 1f c0 a8 00 14 c0 a8 -0020 00 65 00 00 ce 07 1f 02 03 b0 bf 79 a9 5b 00 00 -0030 00 00 df 9d 08 00 00 00 00 00 10 11 12 13 14 15 -0040 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 -0050 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 -0060 36 37 -*/ - - static char data_raw[]="8ab1aa7e4d005254001234560800450000541ec000004001da1fc0a80014c0a800650000ce071f0203b0bf79a95b00000000df9d080000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"; - static uint8_t data[256];//=kballoc(1); - int i=0; - - while(data_raw[i]!=0) - { - uint8_t val=hex_to_dec(data_raw[i])*16+hex_to_dec(data_raw[i+1]); - data[i/2]=val; - i+=2; - } - - - if(c=='p')e1000_sendPacket(data,i/2); // packet -// if(c=='s')e1000_init(0); // start - // if(c=='i')e1000_irq(11); // interrupt - // if(c=='u')e1000_linkup(); // up - //if(c=='d')e1000_linkdown(); // down - syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0); } diff --git a/net/arp.c b/net/arp.c new file mode 100644 index 0000000..501186f --- /dev/null +++ b/net/arp.c @@ -0,0 +1,126 @@ +// https://github.com/saminiir/level-ip/blob/e9ceb08f01a5499b85f03e2d615309c655b97e8f/src/arp.c#L53 +// https://github.com/chobits/tapip +// https://tools.ietf.org/html/rfc826 + +#include "inet.h" +#include "eth.h" +#include "arp.h" +#include "netdev.h" +#include "log.h" + +#include "lib/string/string.h" + +/* + */ +/* +static struct arp_cache_entry arp_cache[ARP_CACHE_LEN]; + +static int insert_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data) +{ + struct arp_cache_entry *entry; + for (int i = 0; i<ARP_CACHE_LEN; i++) { + entry = &arp_cache[i]; + + if (entry->state == ARP_FREE) { + entry->state = ARP_RESOLVED; + + entry->hwtype = hdr->hwtype; + entry->sip = data->sip; + memcpy(entry->smac, data->smac, sizeof(entry->smac)); + + return 0; + } + } + + return -1; +} + +static int update_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data) +{ + struct arp_cache_entry *entry; + + for (int i = 0; i<ARP_CACHE_LEN; i++) { + entry = &arp_cache[i]; + + if (entry->state == ARP_FREE) continue; + + if (entry->hwtype == hdr->hwtype && entry->sip == data->sip) { + memcpy(entry->smac, data->smac, 6); + return 1; + } + } + + return 0; +} + +void arp_init() +{ + memset(arp_cache, 0, ARP_CACHE_LEN * sizeof(struct arp_cache_entry)); +} +*/ + +void arp_reply(struct netdev *netdev, struct eth_hdr *hdr, struct arp_hdr *arphdr) +{ + struct arp_ipv4 *arpdata; + int len; + + arpdata = (struct arp_ipv4 *) arphdr->data; + + memcpy(arpdata->dmac, arpdata->smac, 6); + arpdata->dip = arpdata->sip; + memcpy(arpdata->smac, netdev->hwaddr, 6); + arpdata->sip = netdev->ip; + + arphdr->opcode = ARP_REPLY; + + arphdr->opcode = htons(arphdr->opcode); + arphdr->hwtype = htons(arphdr->hwtype); + arphdr->protype = htons(arphdr->protype); + + len = sizeof(struct arp_hdr) + sizeof(struct arp_ipv4); + netdev_transmit(netdev, hdr, ETH_P_ARP, len, arpdata->dmac); +} + +void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr) +{ + struct arp_hdr *arphdr; + struct arp_ipv4 *arpdata; + int merge = 0; + + arphdr = (struct arp_hdr *) hdr->payload; + + arphdr->hwtype = ntohs(arphdr->hwtype); + arphdr->protype = ntohs(arphdr->protype); + arphdr->opcode = ntohs(arphdr->opcode); + + if (arphdr->hwtype != ARP_ETHERNET) { + klog("Unsupported HW type\n"); + return; + } + + if (arphdr->protype != ARP_IPV4) { + klog("Unsupported protocol\n"); + return; + } + + arpdata = (struct arp_ipv4 *) arphdr->data; + +// merge = update_arp_translation_table(arphdr, arpdata); + + if (netdev->ip != arpdata->dip) { + klog("ARP was not for us\n"); + } + +// if (!merge && insert_arp_translation_table(arphdr, arpdata) != 0) { + // klog("ERR: No free space in ARP translation table\n"); + // } + + switch (arphdr->opcode) { + case ARP_REQUEST: + arp_reply(netdev, hdr, arphdr); + break; + default: + klog("Opcode not supported\n"); + break; + } +} diff --git a/net/arp.h b/net/arp.h new file mode 100644 index 0000000..a690ac0 --- /dev/null +++ b/net/arp.h @@ -0,0 +1,28 @@ +// http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/ +// + +#include <stdint.h> + +#include "netdev.h" + +struct arp_hdr +{ + uint16_t hwtype; // link layer type (1 - ethernet) + uint16_t protype; // protocol (0x800 - ipv4) + unsigned char hwsize; // hardware field size (6 bytes mac) + unsigned char prosize; // protocol field size (4 byte ip) + uint16_t opcode; // arp message type (1- arp request, 2- arp reply, 3- rarp request, 4- rarp reply) + unsigned char data[]; // payload +} __attribute__((packed)); + +// arp ipv4 payload +struct arp_ipv4 +{ + unsigned char smac[6]; // sender mac + uint32_t sip; // sender ip + unsigned char dmac[6]; // receiver mac + uint32_t dip; // receiver ip +} __attribute__((packed)); + +void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr); +void arp_reply(struct netdev *netdev, struct eth_hdr *hdr, struct arp_hdr *arphdr); diff --git a/net/eth.c b/net/eth.c new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/net/eth.c @@ -0,0 +1 @@ + diff --git a/net/eth.h b/net/eth.h new file mode 100644 index 0000000..f90e615 --- /dev/null +++ b/net/eth.h @@ -0,0 +1,16 @@ +//http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/ +//https://tools.ietf.org/html/rfc7414 +#ifndef FOOLOS_ETH_H +#define FOOLOS_ETH_H + +#include <stdint.h> + +struct eth_hdr +{ + unsigned char dmac[6]; // destination mac + unsigned char smac[6]; // source mac + uint16_t ethertype; // length or type + unsigned char payload[]; // payload +} __attribute__((packed)); + +#endif diff --git a/net/inet.h b/net/inet.h new file mode 100644 index 0000000..a2e8dd8 --- /dev/null +++ b/net/inet.h @@ -0,0 +1,20 @@ +/* + * @file + * https://en.wikipedia.org/wiki/OSI_model + */ +#include <stdint.h> + +#define ARP_ETHERNET 1 +#define ARP_IPV4 0x800 +#define ARP_REPLY 2 +#define ARP_REQUEST 1 +#define ETH_P_ARP 0x0806 + +static uint16_t ntohs(uint16_t val) +{ + return val<<8|val>>8; +} +static uint16_t htons(uint16_t val) +{ + return val<<8|val>>8; +} diff --git a/net/netdev.c b/net/netdev.c new file mode 100644 index 0000000..3acd7a4 --- /dev/null +++ b/net/netdev.c @@ -0,0 +1,16 @@ +#include <stdint.h> +#include "inet.h" +#include "eth.h" +#include "netdev.h" +#include "lib/string/string.h" + +void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst) +{ + hdr->ethertype = htons(ethertype); + memcpy(hdr->smac, dev->hwaddr, 6); + memcpy(hdr->dmac, dst, 6); + + len += sizeof(struct eth_hdr); + + dev->transmit(hdr,len); +} diff --git a/net/netdev.h b/net/netdev.h new file mode 100644 index 0000000..c6c02dd --- /dev/null +++ b/net/netdev.h @@ -0,0 +1,15 @@ +#ifndef FOOLOS_NETDEV_H +#define FOOLOS_NETDEV_H + +#include "eth.h" + +struct netdev +{ + unsigned char hwaddr[6]; // device hardware address + uint32_t ip; // device ip + int (*transmit)(const void *data, uint16_t p_len); +}; + +void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst); + +#endif |
