From b58e7bc7cb8ce4fc6f824761ac8ef3920e7dfcc1 Mon Sep 17 00:00:00 2001 From: Miguel Date: Tue, 25 Sep 2018 20:46:52 +0200 Subject: working on icmp ping reply --- net/arp.c | 1 + net/icmp.c | 21 +++++++++++++++++++++ net/icmp.h | 28 ++++++++++++++++++++++++++++ net/inet.c | 37 +++++++++++++++++++++++++++++++++++++ net/inet.h | 19 +++++++++++-------- net/ipv4.c | 20 ++++++++++++++++++++ net/ipv4.h | 25 +++++++++++++++++++++++++ net/netdev.c | 8 ++++++++ net/netdev.h | 1 + 9 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 net/icmp.c create mode 100644 net/icmp.h create mode 100644 net/inet.c create mode 100644 net/ipv4.c create mode 100644 net/ipv4.h (limited to 'net') diff --git a/net/arp.c b/net/arp.c index 501186f..0a3b75c 100644 --- a/net/arp.c +++ b/net/arp.c @@ -117,6 +117,7 @@ void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr) switch (arphdr->opcode) { case ARP_REQUEST: + klog("Arp Reply"); arp_reply(netdev, hdr, arphdr); break; default: diff --git a/net/icmp.c b/net/icmp.c new file mode 100644 index 0000000..038e32a --- /dev/null +++ b/net/icmp.c @@ -0,0 +1,21 @@ +#include "inet.h" +#include "icmp.h" +#include "log.h" + +bool icmp_incoming(struct netdev *dev,struct icmp_v4 *data, uint32_t count_bytes) +{ + klog ("icmp type=%d",data->type); + klog ("icmp code=%d",data->code); + klog ("icmp csum=0x%04x",ntohs(data->csum)); + data->csum=0; + klog("expected checksum = 0x%04X",checksum(data,count_bytes)); + + if(data->type==ICMP_ECHO_REQUEST) // echo request + { + struct icmp_v4_echo *echo=data->data; + klog ("received echo request id=%d, seq=%d, data=%d ",ntohs(echo->id),ntohs(echo->seq),echo->data); +// icmp_reply(); /// TODO watchout that this is the memory managed by the network card we are dealing with!!. fix this later. + } + + return true; +} diff --git a/net/icmp.h b/net/icmp.h new file mode 100644 index 0000000..c2c5e8f --- /dev/null +++ b/net/icmp.h @@ -0,0 +1,28 @@ +//http://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/ +#include +#include + +#include "netdev.h" + +struct icmp_v4 { + uint8_t type; // purpose 0-echo reply, 3- unreachable, 8- echo request, etc... + uint8_t code; // reason (type=3,code=0 net unreachable, etc..) + uint16_t csum; // checksum (Same as in ipv4 header) + uint8_t data[]; // payload (example icmp_v4_echo) +} __attribute__((packed)); + +// payload +struct icmp_v4_echo { + uint16_t id; // set by sender + uint16_t seq; // starting at 0 + uint8_t data[]; // optinal (example timestamp) +} __attribute__((packed)); + +struct icmp_v4_dst_unreachable { + uint8_t unused; + uint8_t len; // lenght of original datagramm + uint16_t var; // depends on icmp code + uint8_t data[]; +} __attribute__((packed)); + +bool icmp_incoming(struct netdev *dev,struct icmp_v4 *data, uint32_t count_bytes); diff --git a/net/inet.c b/net/inet.c new file mode 100644 index 0000000..f7cc2a6 --- /dev/null +++ b/net/inet.c @@ -0,0 +1,37 @@ +#include "inet.h" + +uint16_t ntohs(uint16_t val) +{ + return val<<8|val>>8; +} +uint16_t htons(uint16_t val) +{ + return val<<8|val>>8; +} + +uint16_t checksum(void *addr, int count) +{ + /* Compute Internet Checksum for "count" bytes + * beginning at location "addr". + * Taken from https://tools.ietf.org/html/rfc1071 + */ + + register uint32_t sum = 0; + uint16_t * ptr = addr; + + while( count > 1 ) { + /* This is the inner loop */ + sum += ntohs(* ptr++); + count -= 2; + } + + /* Add left-over byte, if any */ + if( count > 0 ) + sum += * (uint8_t *) ptr; + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} diff --git a/net/inet.h b/net/inet.h index a2e8dd8..75ab6db 100644 --- a/net/inet.h +++ b/net/inet.h @@ -8,13 +8,16 @@ #define ARP_IPV4 0x800 #define ARP_REPLY 2 #define ARP_REQUEST 1 + #define ETH_P_ARP 0x0806 +#define ETH_P_IPV4 0x0800 + +#define IPV4_P_ICMP 0x1 + +#define ICMP_ECHO_REPLY 0 +#define ICMP_UNREACHABLE 3 +#define ICMP_ECHO_REQUEST 8 -static uint16_t ntohs(uint16_t val) -{ - return val<<8|val>>8; -} -static uint16_t htons(uint16_t val) -{ - return val<<8|val>>8; -} +uint16_t checksum(void *addr, int count); +uint16_t ntohs(uint16_t val); +uint16_t htons(uint16_t val); diff --git a/net/ipv4.c b/net/ipv4.c new file mode 100644 index 0000000..aa8502e --- /dev/null +++ b/net/ipv4.c @@ -0,0 +1,20 @@ +#include "inet.h" +#include "ipv4.h" +#include "eth.h" +#include "log.h" +#include "icmp.h" + +bool ipv4_incoming(struct netdev *dev,struct eth_hdr *hdr) +{ + struct ipv4_hdr *ipv4=hdr->payload; + klog("ipv4 incoming with checksum: 0x%04X",ntohs(ipv4->csum)); + 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,((uint32_t *)ipv4)+ipv4->ihl,ntohs(ipv4->len)-ipv4->ihl*4); + } + + return true; +} diff --git a/net/ipv4.h b/net/ipv4.h new file mode 100644 index 0000000..e3cbc36 --- /dev/null +++ b/net/ipv4.h @@ -0,0 +1,25 @@ +// http://www.saminiir.com/lets-code-tcp-ip-stack-2-ipv4-icmpv4/ +#include +#include + +#include "eth.h" +#include "netdev.h" + +struct ipv4_hdr { + uint8_t ihl : 4; // 4bit / number of 32 bit words in header + uint8_t version : 4; // 4bit / 4 - ipv4 + 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 + 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 + uint32_t saddr; // source ip address + 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); diff --git a/net/netdev.c b/net/netdev.c index 3acd7a4..1539bd6 100644 --- a/net/netdev.c +++ b/net/netdev.c @@ -1,9 +1,17 @@ #include #include "inet.h" #include "eth.h" +#include "arp.h" +#include "ipv4.h" #include "netdev.h" #include "lib/string/string.h" +void net_incoming(struct netdev *netdev, struct eth_hdr *hdr) +{ + if(hdr->ethertype==htons(ETH_P_ARP))arp_incoming(netdev,hdr); + if(hdr->ethertype==htons(ETH_P_IPV4))ipv4_incoming(netdev,hdr); +} + void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst) { hdr->ethertype = htons(ethertype); diff --git a/net/netdev.h b/net/netdev.h index c6c02dd..73f9783 100644 --- a/net/netdev.h +++ b/net/netdev.h @@ -11,5 +11,6 @@ struct netdev }; 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); #endif -- cgit v1.2.3