From ae33cc6557790a502a01b380b0926944ca2f3cfa Mon Sep 17 00:00:00 2001 From: Miguel Date: Wed, 26 Sep 2018 10:22:37 +0200 Subject: ntp and udp --- Makefile | 4 ++-- README.md | 3 ++- driver/e1000.c | 4 +++- driver/keyboard.c | 5 +++++ net/eth.c | 24 ++++++++++++++++++++++++ net/eth.h | 4 ++++ net/icmp.c | 33 +++++++++++++++++++++++++++++++++ net/icmp.h | 1 + net/inet.c | 22 ++++++++++++++++++++++ net/inet.h | 5 +++++ net/ipv4.c | 29 +++++++++++++++++++++++++++++ net/ipv4.h | 12 +++++++----- net/netdev.c | 4 ++-- net/netdev.h | 2 +- net/ntp.c | 36 ++++++++++++++++++++++++++++++++++++ net/ntp.h | 34 ++++++++++++++++++++++++++++++++++ net/udp.c | 16 ++++++++++++++++ net/udp.h | 11 +++++++++++ 18 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 net/ntp.c create mode 100644 net/ntp.h create mode 100644 net/udp.c create mode 100644 net/udp.h diff --git a/Makefile b/Makefile index 3760487..e1ffbbe 100644 --- a/Makefile +++ b/Makefile @@ -182,7 +182,7 @@ run-qemu: all echo XDOTOOL HACK...&& sleep 0.2 && xdotool search --name "QEMU" windowsize 100 100 && echo XDOTOOL HACK END. & $(QEMU) -enable-kvm $(FOOLOS_ISO) -smp 4 -serial stdio \ -net nic,model=e1000 \ - -net tap,ifname=tap0 + -net tap,ifname=tap0,script=no,downscript=no #-net dump,file=./netfool run-qemu-16: all @@ -198,7 +198,7 @@ run-qemu-debug: all echo XDOTOOL HACK...&& sleep 0.2 && xdotool search --name "QEMU" windowsize 100 100 && echo XDOTOOL HACK END. & $(QEMU) -s -S -enable-kvm $(FOOLOS_ISO) -smp 4 -serial stdio \ -net nic,model=e1000 \ - -net tap,ifname=tap0 + -net tap,ifname=tap0,script=no,downscript=no #-net dump,file=./netfool \ monitor: echo XDOTOOL HACK...&& sleep 0.2 && xdotool search --name "QEMU" windowsize 100 100 && echo XDOTOOL HACK END. & diff --git a/README.md b/README.md index ad813fd..9fa8d0e 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,9 @@ FoolOS is tested/developed on the following emulators/machines Todos ----- -* ethernet drivers: vbox E1000 /virtio / NS2000 / ipxe network drivers? +* ethernet drivers: vbox E1000 /virtio / NS2000 / ipxe network drivers / laptop acer * tcp/ip stack +* udp traceroute etc * threads! semaphores * return value / argv / env diff --git a/driver/e1000.c b/driver/e1000.c index 31e1b45..2f50df4 100644 --- a/driver/e1000.c +++ b/driver/e1000.c @@ -137,7 +137,8 @@ // TODO: move all global stuff to some struct so we can run multiple e1000 cards! // -struct netdev dev; ///TODO not global! +struct netdev e1000_dev; ///TODO not global! +static struct netdev dev; struct e1000_rx_desc { volatile uint32_t addr_lo; // 4 @@ -518,6 +519,7 @@ struct netdev e1000_init(uint32_t base) rxinit(); klog("E1000 initialized"); + e1000_dev=dev; return dev; } diff --git a/driver/keyboard.c b/driver/keyboard.c index d201882..b9a1dad 100644 --- a/driver/keyboard.c +++ b/driver/keyboard.c @@ -7,6 +7,8 @@ #include +#include "inet.h" + static bool ctrl_l=false; static bool shift_l=false; static bool shift_r=false; @@ -21,8 +23,11 @@ int hex_to_dec(char c) return c+10-'a'; } + +extern struct netdev e1000_dev; static void put(uint8_t c) { + if(c=='p')net_packet(&e1000_dev); syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0); } diff --git a/net/eth.c b/net/eth.c index 8b13789..780a89a 100644 --- a/net/eth.c +++ b/net/eth.c @@ -1 +1,25 @@ +#include "inet.h" +#include "eth.h" +#include "netdev.h" +#include "lib/string/string.h" + +uint32_t eth_generic(struct netdev *dev, uint32_t ip, uint16_t type, uint8_t* pos,uint32_t *end) +{ + pos-=14;// we need 14 bytes for the eth header + struct eth_hdr *eth=pos; + + // TODO: dmac from arp and routing tables. + eth->dmac[0]=0x90; + eth->dmac[1]=0x5c; + eth->dmac[2]=0x44; + eth->dmac[3]=0x2f; + eth->dmac[4]=0x9a; + eth->dmac[5]=0x40; + + memcpy(eth->smac,dev->hwaddr,6); + eth->ethertype=htons(type); + + return pos; +} + diff --git a/net/eth.h b/net/eth.h index f90e615..aa4efeb 100644 --- a/net/eth.h +++ b/net/eth.h @@ -13,4 +13,8 @@ struct eth_hdr unsigned char payload[]; // payload } __attribute__((packed)); +struct netdev; + +uint32_t eth_generic(struct netdev *dev, uint32_t ip, uint16_t type, uint8_t* pos,uint32_t *end); + #endif diff --git a/net/icmp.c b/net/icmp.c index 6f5f14f..20ac203 100644 --- a/net/icmp.c +++ b/net/icmp.c @@ -2,9 +2,42 @@ #include "icmp.h" #include "ipv4.h" #include "log.h" +#include "kmalloc.h" #include "lib/string/string.h" +uint32_t icmp_generic(struct netdev *dev, uint32_t ip, uint8_t type, uint8_t* pos,uint8_t *end) +{ + pos-=4; //we need 32 bytes + struct icmp_v4 *icmp=pos; + + icmp->type=type; + icmp->code=0; + icmp->csum=0; + icmp->csum=checksum(icmp,end-pos); + + return ipv4_generic(dev,ip,IPV4_P_ICMP,pos,end); +} + +uint32_t icmp_ping(struct netdev *dev, uint32_t ip, uint16_t* pos,uint32_t *end) +{ + // payload + for(int i=0;i<64;i++) + { + pos--; + *pos=0xbeef; + } + + // id and sequence number + pos-=2; // we need 32 bytes + struct icmp_v4_echo *ping=pos; + ping->id=htons(0xabcd); // some random number + ping->seq=htons(0); // we just send one single ping with id 1 for now + + return icmp_generic(dev,ip,ICMP_ECHO_REQUEST,pos,end); +} + + bool icmp_reply(struct netdev *dev,struct eth_hdr *hdr) { unsigned char tmp[6]; diff --git a/net/icmp.h b/net/icmp.h index 50613bb..5fbce2e 100644 --- a/net/icmp.h +++ b/net/icmp.h @@ -25,4 +25,5 @@ struct icmp_v4_dst_unreachable { uint8_t data[]; } __attribute__((packed)); +uint32_t icmp_ping(struct netdev *dev, uint32_t ip, uint16_t* pos,uint32_t *end); bool icmp_incoming(struct netdev *dev,struct eth_hdr *hdr); diff --git a/net/inet.c b/net/inet.c index 67895d5..88698c5 100644 --- a/net/inet.c +++ b/net/inet.c @@ -1,4 +1,8 @@ #include "inet.h" +#include "icmp.h" +#include "kmalloc.h" +#include "udp.h" +#include "ntp.h" uint16_t ntohs(uint16_t val) { @@ -36,3 +40,21 @@ uint16_t checksum(void *addr, int count) return ~sum; } + +bool net_packet(struct netdev *dev) +{ + uint32_t packet=kballoc(1)+4096; // we start one byte after the end; + // + uint32_t addr=(144)+(76<<8)+(106<<16)+(46<<24); + uint32_t google_time=216+(239<<8)+(35<<16)+(0<<24); + // this should of course be filled dynamically! + //uint32_t pos=icmp_ping(dev,addr,packet,packet); // create ping packet and get new position; + //uint32_t pos=udp_generic(dev, addr, 666, 123, packet,packet); + uint32_t pos=ntp_generic(dev, google_time, 6666, 123, packet,packet); + + // + dev->transmit(pos,(packet-pos)); + + kbfree(packet-4096); // TODO: take care it is not overwritten before transmitted! + return true; +} diff --git a/net/inet.h b/net/inet.h index 75ab6db..1d75e03 100644 --- a/net/inet.h +++ b/net/inet.h @@ -3,6 +3,8 @@ * https://en.wikipedia.org/wiki/OSI_model */ #include +#include +#include #define ARP_ETHERNET 1 #define ARP_IPV4 0x800 @@ -13,6 +15,8 @@ #define ETH_P_IPV4 0x0800 #define IPV4_P_ICMP 0x1 +#define IPV4_P_TCP 0x6 +#define IPV4_P_UDP 0x11 #define ICMP_ECHO_REPLY 0 #define ICMP_UNREACHABLE 3 @@ -21,3 +25,4 @@ uint16_t checksum(void *addr, int count); uint16_t ntohs(uint16_t val); uint16_t htons(uint16_t val); +bool net_packet(struct netdev *dev); diff --git a/net/ipv4.c b/net/ipv4.c index b7e6a53..b090a7b 100644 --- a/net/ipv4.c +++ b/net/ipv4.c @@ -11,6 +11,7 @@ bool ipv4_incoming(struct netdev *dev,struct eth_hdr *hdr) ipv4->csum=0; klog("expected checksum: 0x%04X",checksum(ipv4,ntohs(ipv4->len))); klog("ipv4 header len=%d",ipv4->ihl); + if(ipv4->proto==IPV4_P_ICMP) { icmp_incoming(dev,hdr); @@ -18,3 +19,31 @@ bool ipv4_incoming(struct netdev *dev,struct eth_hdr *hdr) return true; } + +uint32_t ipv4_generic(struct netdev *dev, uint32_t ip, uint8_t type, uint8_t* pos,uint8_t *end) +{ + + pos-=20; // we need 20 bytes for the ipv4 header. + struct ipv4_hdr *ipv4=pos; + ipv4->ihl=5; // 20 bytes + ipv4->version=4; // ipv 4 + + ipv4->tos=0; // type of service? + ipv4->len=htons(end-pos); // total length of ip datagramm in bytes + ipv4->id=0; // index of datagram for fragmentation + + //ipv4->flags=0x2; // various control flags 0x20 do not fragment + //ipv4->frag_offset=0; // fragment offset 0 - first + ipv4->flags_and_offset=0; // TODO! 0x2? + + ipv4->ttl=64; // time to live - countdown decreased by each receiver + ipv4->proto=type; // payload protocol / 1-icmp, 16 - udp , 6 -tcp + ipv4->csum=0; // header checksum + ipv4->saddr=dev->ip; // source ip address + ipv4->daddr=ip; // destination ip address + + //ipv4->csum=checksum(ipv4,ntohs(ipv4->len)); + ipv4->csum=checksum(ipv4,20); + + return eth_generic(dev,ip,ETH_P_IPV4,pos,end); +} diff --git a/net/ipv4.h b/net/ipv4.h index e3cbc36..7357aac 100644 --- a/net/ipv4.h +++ b/net/ipv4.h @@ -11,8 +11,11 @@ struct ipv4_hdr { uint8_t tos; // type of service uint16_t len; // total length of ip datagramm uint16_t id; // index of datagram for fragmentation - uint16_t flags : 3; // various control flags - uint16_t frag_offset : 13; // fragment offset 0 - first + + //uint16_t flags : 3; // various control flags + //uint16_t frag_offset : 13; // fragment offset 0 - first + uint16_t flags_and_offset; + uint8_t ttl; // time to live - countdown decreased by each receiver uint8_t proto; // payload protocol / 1-icmp, 16 - udp , 6 -tcp uint16_t csum; // header checksum @@ -20,6 +23,5 @@ struct ipv4_hdr { uint32_t daddr; // destination ip address } __attribute__((packed)); -uint16_t ipv4_checksum(void *addr, int count); -bool ipv4_incoming(struct netdev *,struct eth_hdr *); -uint16_t ipv4_checksum(void *addr, int count); +bool ipv4_incoming(struct netdev *,struct eth_hdr *); +uint32_t ipv4_generic(struct netdev *dev, uint32_t ip, uint8_t type, uint8_t* pos,uint8_t *end); diff --git a/net/netdev.c b/net/netdev.c index 1539bd6..69fd45f 100644 --- a/net/netdev.c +++ b/net/netdev.c @@ -1,10 +1,10 @@ #include -#include "inet.h" #include "eth.h" +#include "inet.h" #include "arp.h" #include "ipv4.h" -#include "netdev.h" #include "lib/string/string.h" +#include "netdev.h" void net_incoming(struct netdev *netdev, struct eth_hdr *hdr) { diff --git a/net/netdev.h b/net/netdev.h index 73f9783..92ff9f2 100644 --- a/net/netdev.h +++ b/net/netdev.h @@ -10,7 +10,7 @@ struct netdev 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); void net_incoming(struct netdev *netdev, struct eth_hdr *hdr); +void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst); #endif diff --git a/net/ntp.c b/net/ntp.c new file mode 100644 index 0000000..137d677 --- /dev/null +++ b/net/ntp.c @@ -0,0 +1,36 @@ +#include "udp.h" +#include "ntp.h" + +uint32_t ntp_generic(struct netdev *dev, uint32_t ip, uint16_t src, uint16_t dst, uint8_t* pos,uint8_t *end) +{ + pos-=48; // we need 48 bytes + struct udp_v4_ntp *ntp=pos; + + ntp->li_vn_mode=0x1b; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + ntp->stratum=0; // Eight bits. Stratum level of the local clock. + ntp->poll=0; // Eight bits. Maximum interval between successive messages. + ntp->precision=0; // Eight bits. Precision of the local clock. + + ntp->rootDelay=0; // 32 bits. Total round trip delay time. + ntp->rootDispersion=0; // 32 bits. Max error aloud from primary clock source. + ntp->refId=0; // 32 bits. Reference clock identifier. + + ntp->refTm_s=0; // 32 bits. Reference time-stamp seconds. + ntp->refTm_f=0; // 32 bits. Reference time-stamp fraction of a second. + + ntp->origTm_s=0; // 32 bits. Originate time-stamp seconds. + ntp->origTm_f=0; // 32 bits. Originate time-stamp fraction of a second. + + ntp->rxTm_s=0; // 32 bits. Received time-stamp seconds. + ntp->rxTm_f=0; // 32 bits. Received time-stamp fraction of a second. + + ntp->txTm_s=0; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + ntp->txTm_f=0; // 32 bits. Transmit time-stamp fraction of a second. + + return udp_generic(dev, ip, src, dst, pos,end); +} + diff --git a/net/ntp.h b/net/ntp.h new file mode 100644 index 0000000..0b7fa00 --- /dev/null +++ b/net/ntp.h @@ -0,0 +1,34 @@ +//https://lettier.github.io/posts/2016-04-26-lets-make-a-ntp-client-in-c.html + +struct udp_v4_ntp +{ + + uint8_t li_vn_mode; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + uint8_t stratum; // Eight bits. Stratum level of the local clock. + uint8_t poll; // Eight bits. Maximum interval between successive messages. + uint8_t precision; // Eight bits. Precision of the local clock. + + uint32_t rootDelay; // 32 bits. Total round trip delay time. + uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. + uint32_t refId; // 32 bits. Reference clock identifier. + + uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. + uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. + + uint32_t origTm_s; // 32 bits. Originate time-stamp seconds. + uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second. + + uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. + uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. + + uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. + + // Total: 384 bits or 48 bytes. +} __attribute__((packed)); + +uint32_t ntp_generic(struct netdev *dev, uint32_t ip, uint16_t src, uint16_t dst, uint8_t* pos,uint8_t *end); diff --git a/net/udp.c b/net/udp.c new file mode 100644 index 0000000..6913256 --- /dev/null +++ b/net/udp.c @@ -0,0 +1,16 @@ +#include "udp.h" +#include "inet.h" +#include "ipv4.h" + +uint32_t udp_generic(struct netdev *dev, uint32_t ip, uint16_t src, uint16_t dst, uint8_t* pos,uint8_t *end) +{ + pos-=8; //we need 64 bytes + struct udp_v4 *udp=pos; + + udp->src_port=htons(src); + udp->dst_port=htons(dst); + udp->len=htons(end-pos); + udp->csum=0; // TODO: optional + + return ipv4_generic(dev,ip,IPV4_P_UDP,pos,end); +} diff --git a/net/udp.h b/net/udp.h new file mode 100644 index 0000000..2c30804 --- /dev/null +++ b/net/udp.h @@ -0,0 +1,11 @@ +#include "netdev.h" +#include + +struct udp_v4{ + uint16_t src_port; + uint16_t dst_port; + uint16_t len; + uint16_t csum; +} __attribute__((packed)); + +uint32_t udp_generic(struct netdev *dev, uint32_t ip, uint16_t src, uint16_t dst, uint8_t* pos,uint8_t *end); -- cgit v1.2.3