summaryrefslogtreecommitdiff
path: root/libdde_linux26/examples/ne2k/arping.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdde_linux26/examples/ne2k/arping.c')
-rw-r--r--libdde_linux26/examples/ne2k/arping.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/libdde_linux26/examples/ne2k/arping.c b/libdde_linux26/examples/ne2k/arping.c
new file mode 100644
index 00000000..18876806
--- /dev/null
+++ b/libdde_linux26/examples/ne2k/arping.c
@@ -0,0 +1,185 @@
+/****************************************************************
+ * (c) 2007 Technische Universitaet Dresden *
+ * This file is part of DROPS, which is distributed under the *
+ * terms of the GNU General Public License 2. Please see the *
+ * COPYING file for details. *
+ ****************************************************************/
+
+#include <l4/log/l4log.h>
+#include <l4/util/util.h>
+#include <l4/util/l4_macros.h>
+#include <l4/sys/ipc.h>
+
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+
+#include "arping.h"
+
+#define PROT_ICMP 1
+#define ICMP_REPLY 0
+#define ICMP_REQ 8
+#define ETH_ALEN 6
+
+/* configuration */
+int arping_verbose = 0; // verbose
+
+#define VERBOSE_LOG(fmt, ...) \
+ do { \
+ if (arping_verbose) printk(fmt, ##__VA_ARGS__); \
+ } while (0);
+
+char LOG_tag[9] = "arping";
+l4_ssize_t l4libc_heapsize = 32 * 1024;
+
+static unsigned char broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static int exit_somewhen = 0;
+
+
+struct ethernet_hdr
+{
+ unsigned char dest[6];
+ unsigned char src[6];
+ unsigned char type[2];
+};
+
+
+struct ip_hdr
+{
+ char version_length;
+ char type;
+ l4_int16_t length;
+ l4_int16_t id;
+ l4_int16_t flags_offset;
+ char ttl;
+ char protocol;
+ l4_int16_t checksum;
+ l4_int32_t src_ip;
+ l4_int32_t dest_ip;
+};
+
+
+struct icmp_hdr
+{
+ char type;
+ char code;
+ l4_uint16_t checksum;
+ l4_uint16_t id;
+ l4_uint16_t seq_num;
+};
+
+
+static int handle_icmp_packet(struct sk_buff *skb);
+static int handle_icmp_packet(struct sk_buff *skb)
+{
+ char *data = skb->data;
+ struct ethernet_hdr *eth = NULL;
+ struct ethernet_hdr *e = NULL;
+ struct ip_hdr *ip = NULL;
+ struct ip_hdr *iphdr = NULL;
+ struct icmp_hdr *icmp = NULL;
+ struct icmp_hdr *icmp2 = NULL;
+ int ver, len;
+ struct sk_buff *snd_skb = NULL;
+
+ eth = (struct ethernet_hdr *)data;
+ VERBOSE_LOG("dest mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth->dest[0], eth->dest[1], eth->dest[2],
+ eth->dest[3], eth->dest[4], eth->dest[5]);
+ VERBOSE_LOG("src mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ eth->src[0], eth->src[1], eth->src[2],
+ eth->src[3], eth->src[4], eth->src[5]);
+ VERBOSE_LOG("type field = %02x%02x\n", eth->type[0], eth->type[1]);
+ if (eth->type[0] != 0x08 || eth->type[1] != 0x00) {
+ printk("unknown ethernet packet type!\n");
+ return -1;
+ }
+
+ ip = (struct ip_hdr *)(data + sizeof(struct ethernet_hdr));
+ VERBOSE_LOG("protocol = %02x (2x?)\n", ip->protocol, PROT_ICMP);
+ if (ip->protocol != PROT_ICMP)
+ {
+ printk("Unknown packet type.\n");
+ return -1;
+ }
+
+ VERBOSE_LOG("ICMP packet!\n");
+ ver = ip->version_length >> 4;
+ len = ip->version_length & 0x0F;
+ VERBOSE_LOG("IP version = %d, length = %d\n", ver, len);
+
+ VERBOSE_LOG("src IP: "NIPQUAD_FMT"\n", NIPQUAD(ip->src_ip));
+ VERBOSE_LOG("dest IP: "NIPQUAD_FMT"\n", NIPQUAD(ip->dest_ip));
+
+ icmp = (struct icmp_hdr *)(data + sizeof(struct ethernet_hdr)
+ + sizeof(struct ip_hdr));
+
+ if (icmp->type != ICMP_REQ)
+ {
+ printk("This is no ICMP request.\n");
+ return -1;
+ }
+ VERBOSE_LOG("Hey this is an ICMP request just for me. :)\n");
+ VERBOSE_LOG("ICMP type : %d\n", icmp->type);
+ VERBOSE_LOG("ICMP code : %d\n", icmp->code);
+ VERBOSE_LOG("ICMP seq : %d\n", ntohs(icmp->seq_num));
+
+ snd_skb = alloc_skb(skb->len + skb->dev->hard_header_len, GFP_KERNEL);
+ memcpy(snd_skb->data, skb->data, skb->len);
+
+ e = (struct ethernet_hdr *)snd_skb->data;
+ memcpy(e->src, eth->dest, ETH_ALEN);
+ memcpy(e->dest, eth->src, ETH_ALEN);
+ VERBOSE_LOG("dest mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ e->dest[0], e->dest[1], e->dest[2],
+ e->dest[3], e->dest[4], e->dest[5]);
+ VERBOSE_LOG("src mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
+ e->src[0], e->src[1], e->src[2],
+ e->src[3], e->src[4], e->src[5]);
+ e->type[0] = 0x08;
+ e->type[1] = 0x00;
+
+ iphdr = (struct ip_hdr *)(snd_skb->data + sizeof(struct ethernet_hdr));
+ *iphdr = *ip;
+ // also switch src and dest
+ iphdr->src_ip = ip->dest_ip;
+ iphdr->dest_ip = ip->src_ip;
+ VERBOSE_LOG("src IP: "NIPQUAD_FMT"\n", NIPQUAD(iphdr->src_ip));
+ VERBOSE_LOG("dest IP: "NIPQUAD_FMT"\n", NIPQUAD(iphdr->dest_ip));
+
+ icmp2 = (struct icmp_hdr *)(snd_skb->data + sizeof(struct ethernet_hdr)
+ + sizeof(struct ip_hdr));
+ *icmp2 = *icmp;
+ icmp2->type = ICMP_REPLY;
+
+ snd_skb->dev = skb->dev;
+ snd_skb->len = skb->len;
+
+ VERBOSE_LOG("sending reply\n");
+ skb->dev->hard_start_xmit(snd_skb, skb->dev);
+ VERBOSE_LOG("done\n");
+
+ return 0;
+}
+
+ddekit_sem_t *arping_semaphore = NULL;
+struct arping_elem *arping_list = NULL;
+
+int arping(void)
+{
+ arping_semaphore = ddekit_sem_init(0);
+
+ while(1)
+ {
+ ddekit_sem_down(arping_semaphore);
+ struct arping_elem *elem = arping_list;
+ arping_list = arping_list->next;
+
+ /* parse packet */
+ int err = handle_icmp_packet(elem->skb);
+ VERBOSE_LOG("handle_icmp_packet: %d\n", err);
+
+ kfree_skb(elem->skb);
+ kfree(elem);
+ }
+}
+