summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/arp.c1
-rw-r--r--net/icmp.c21
-rw-r--r--net/icmp.h28
-rw-r--r--net/inet.c37
-rw-r--r--net/inet.h19
-rw-r--r--net/ipv4.c20
-rw-r--r--net/ipv4.h25
-rw-r--r--net/netdev.c8
-rw-r--r--net/netdev.h1
9 files changed, 152 insertions, 8 deletions
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 <stdint.h>
+#include <stdbool.h>
+
+#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 <stdint.h>
+#include <stdbool.h>
+
+#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 <stdint.h>
#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