diff options
Diffstat (limited to 'net')
| -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 |
7 files changed, 222 insertions, 0 deletions
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 |
