summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/eth.c24
-rw-r--r--net/eth.h4
-rw-r--r--net/icmp.c33
-rw-r--r--net/icmp.h1
-rw-r--r--net/inet.c22
-rw-r--r--net/inet.h5
-rw-r--r--net/ipv4.c29
-rw-r--r--net/ipv4.h12
-rw-r--r--net/netdev.c4
-rw-r--r--net/netdev.h2
-rw-r--r--net/ntp.c36
-rw-r--r--net/ntp.h34
-rw-r--r--net/udp.c16
-rw-r--r--net/udp.h11
14 files changed, 225 insertions, 8 deletions
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 <stdint.h>
+#include <stdbool.h>
+#include <netdev.h>
#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 <stdint.h>
-#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 <stdint.h>
+
+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);