test icmp

Dependencies:   mbed

Fork of ethspam by Rolf Meyer

Files at this revision

API Documentation at this revision

Comitter:
jamessayer
Date:
Fri Apr 24 03:11:02 2015 +0000
Parent:
0:852db76de235
Commit message:
first version;

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
net/arp.h Show annotated file Show diff for this revision Revisions of this file
net/ethernet.h Show annotated file Show diff for this revision Revisions of this file
net/icmp.h Show annotated file Show diff for this revision Revisions of this file
net/ip.h Show annotated file Show diff for this revision Revisions of this file
net/net.h Show annotated file Show diff for this revision Revisions of this file
net/tcp.h Show annotated file Show diff for this revision Revisions of this file
net/udp.h Show annotated file Show diff for this revision Revisions of this file
sniffer.h Show annotated file Show diff for this revision Revisions of this file
util/types.h Show annotated file Show diff for this revision Revisions of this file
util/util.h Show annotated file Show diff for this revision Revisions of this file
diff -r 852db76de235 -r feaa107f56b3 main.cpp
--- a/main.cpp	Fri Sep 04 12:25:06 2009 +0000
+++ b/main.cpp	Fri Apr 24 03:11:02 2015 +0000
@@ -1,5 +1,9 @@
 #include "mbed.h"                                      // Importing the mbed classes and tools.
 #include "Ethernet.h"
+#include "util/types.h"
+#include "net/net.h"
+#include "sniffer.h"
+
 
 using namespace mbed;
 
@@ -20,54 +24,116 @@
   unsigned char   dhwaddr[6];                          //   Hardware address of the intended receiver. This field is ignored in requests.
   unsigned char   dipaddr[4];                          //   Protocol address of the intended receiver.
 };
-
-Ethernet eth;                                          // The ethernet device
+Sniffer sniffer;
+Ethernet_MAC your_mac;
+//Ethernet eth;                                          // The ethernet device
 DigitalOut led4(LED4);                                 // A LED for showing activity
 
 unsigned short htons(unsigned short n) {               // Host short to network shor
   return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);      // Byte swapping
 }
 
-void send(const char *ipaddr) {
-  static char data[0x600];                             // Packet buffer
-  const unsigned char arplen = 6;                      // Hardware address length
-  const unsigned char ethlen = 4;                      // IP address length
-  char hwaddr[arplen];                                 // Hardware address buffer
-  struct ethpkt *pkg   = (struct ethpkt *) &data[0];   // Force the buffer to an ethpkg
-  unsigned char pos    = arplen;                       // Hardware/IP address position
-
-  eth.address(hwaddr);                                 // Get own hardware address
+#define PING_BUFEFERSIZE (sizeof(IP_PacketHeader) + sizeof(ICMP_Packet))
 
-  pkg->type            = htons(0x0806);                // Set type to ARP (0x0806)
-  pkg->hwtype          = htons(0x0001);                // Hardware type is Ethernet (0x0001)
-  pkg->proto           = htons(0x0800);                // Protocol is ARP Request (0x0800)
-  pkg->hwlen           = arplen;                       // Hardware addresses are 6 Bytes long
-  pkg->protolen        = ethlen;                       // And protocol addresses 4 Bytes
-  pkg->opcode          = htons(0x0001);                // Send: whois XX:XX:XX:XX:XX:XX?
+void send(const char *ipaddr) {
+    IP_Address dest_ip;
+    IP_Address my_ip;
+    str2ipaddr(ipaddr,&dest_ip);
+    str2ipaddr("192.168.0.16",&my_ip);
+    
+    u8 buffer[PING_BUFEFERSIZE];
+    IP_PacketHeader *ip_packet = (IP_PacketHeader*)buffer;
+    ICMP_Packet *ping_packet = (ICMP_Packet*)ip_packet->data;
+    
+    memset(buffer, '\0', PING_BUFEFERSIZE);
+    
+    *ip_packet = (IP_PacketHeader){0x04, 5, 0, sizeof(IP_PacketHeader)+sizeof(ICMP_Packet), 0, 0, 0, 0, 0, 32, IPPROTO_ICMP, 0x00, my_ip, dest_ip};
+    *ping_packet = (ICMP_Packet){ICMP_ECHO_REQUEST, 0x00, 0x00, 0x00, 0x00};
+    
+    fix_endian_icmp(ping_packet);
+    fix_endian_ip(ip_packet);
+    ip_packet->header_checksum = checksum(ip_packet, sizeof(IP_PacketHeader), &ip_packet->header_checksum, 2);
+    ping_packet->checksum = checksum(ping_packet, sizeof(ICMP_Packet), &ping_packet->checksum, 2);
+    
+    
+    printf("PING sent...\n");
+    
+    sniffer.inject(your_mac, ETHERTYPE_IPV4, buffer, PING_BUFEFERSIZE);
+    
+    
+    
+//    printf("a\n");
+//    IP_Address dest_ip;
+//    IP_Address my_ip;
+//    str2ipaddr(ipaddr,&dest_ip);
+//    str2ipaddr("192.168.0.5",&my_ip);
+//    printf("b\n");
+//    u8 buffer[PING_BUFEFERSIZE];
+//    IP_PacketHeader *ip_packet = (IP_PacketHeader*)buffer;
+//    ICMP_Packet *ping_packet = (ICMP_Packet*)ip_packet->data;
+//    printf("c\n");
+//    memset(buffer, '\0', PING_BUFEFERSIZE);
+//    printf("d\n");
+//    *ip_packet = (IP_PacketHeader){0x4, 5, 0, sizeof(IP_PacketHeader)+sizeof(ICMP_Packet), 0, 0, 0, 0, 0, 32, IPPROTO_ICMP, 0x00, my_ip, dest_ip};
+//    *ping_packet = (ICMP_Packet){ICMP_ECHO_REQUEST, 0x00, 0x00, 0x00, 0x00};
+//    printf("e\n");
+    
+    
+///    fix_endian_icmp(ping_packet);
+//    fix_endian_ip(ip_packet);
+//    printf("f\n");
+//    ip_packet->header_checksum = checksum(ip_packet, sizeof(IP_PacketHeader), &ip_packet->header_checksum, 2);
+//    ping_packet->checksum = checksum(ping_packet, sizeof(ICMP_Packet), &ping_packet->checksum, 2);
+//    printf("h\n");
+//    
+//    print_icmp(ping_packet);
+//    print_ip(ip_packet);
+//    
+//    printf("i\n");
+//    eth.write((char*)buffer, PING_BUFEFERSIZE);                                 // Write the package
+//    eth.send();                                          // Send the package
+//    printf("j\n");
   
-  while(pos-- > 0) {                                   // Write IP/MAC-Addresses (combined loop for all addresses)
-    pkg->src[pos]        = hwaddr[pos];                // Set source MAC address to hwaddr on ethernet layer
-    pkg->dest[pos]       = 0xFF;                       // Set destination MAC address to everybody (FF:FF:FF:FF:FF:FF) on ethernet layer
-    pkg->shwaddr[pos]    = hwaddr[pos];                // Set source MAC address on ARP layer
-    pkg->dhwaddr[pos]    = 0xFF;                       // Set destination MAC address on ARP layer
-    if(pos < ethlen) {                                 // Check if we can copy IP addresses too.
-      pkg->sipaddr[pos]  = 0xFF;                       // Set source ip address to 255.255.255.255
-      pkg->dipaddr[pos]  = ipaddr[pos];                // Set destination ip address to ipaddr
-    }
-  }
-
-  eth.write(data, 60);                                 // Write the package
-  eth.send();                                          // Send the package
+//  static char data[0x600];                             // Packet buffer
+//  const unsigned char arplen = 6;                      // Hardware address length
+//  const unsigned char ethlen = 4;                      // IP address length
+//  char hwaddr[arplen];                                 // Hardware address buffer
+//  struct ethpkt *pkg   = (struct ethpkt *) &data[0];   // Force the buffer to an ethpkg
+//  unsigned char pos    = arplen;                       // Hardware/IP address position
+//
+//  eth.address(hwaddr);                                 // Get own hardware address
+//
+//  pkg->type            = htons(0x0806);                // Set type to ARP (0x0806)
+//  pkg->hwtype          = htons(0x0001);                // Hardware type is Ethernet (0x0001)
+//  pkg->proto           = htons(0x0800);                // Protocol is ARP Request (0x0800)
+//  pkg->hwlen           = arplen;                       // Hardware addresses are 6 Bytes long
+//  pkg->protolen        = ethlen;                       // And protocol addresses 4 Bytes
+//  pkg->opcode          = htons(0x0001);                // Send: whois XX:XX:XX:XX:XX:XX?
+//  
+//  while(pos-- > 0) {                                   // Write IP/MAC-Addresses (combined loop for all addresses)
+//    pkg->src[pos]        = hwaddr[pos];                // Set source MAC address to hwaddr on ethernet layer
+//    pkg->dest[pos]       = 0xFF;                       // Set destination MAC address to everybody (FF:FF:FF:FF:FF:FF) on ethernet layer
+//    pkg->shwaddr[pos]    = hwaddr[pos];                // Set source MAC address on ARP layer
+//    pkg->dhwaddr[pos]    = 0xFF;                       // Set destination MAC address on ARP layer
+//    if(pos < ethlen) {                                 // Check if we can copy IP addresses too.
+//      pkg->sipaddr[pos]  = 0xFF;                       // Set source ip address to 255.255.255.255
+//      pkg->dipaddr[pos]  = ipaddr[pos];                // Set destination ip address to ipaddr
+//    }
+//  }
+//
+//  eth.write(data, 60);                                 // Write the package
+//  eth.send();                                          // Send the package
 }
                                                        // In this example we would like to make ARP requests to ask for every ip address.
 int main() {                                           // The programm starts here!
   unsigned int i = 1;                                  // The integer we use as counter and target IP address.
-  char *c        = (char *)&i;                         // We cast the integer to an array of char c[4] to handle it as IP address.
+  //char *c        = (char *)&i;                         // We cast the integer to an array of char c[4] to handle it as IP address.
   
   printf("Lowlevel Ethernet Spammer\n\n");             // Print out that the programm has been started.
 
-  while(1) {                                           // Do forever:
-    send(c);                                           //   Assamble and send our request. See eth_send function!
+  while(1) {
+    char* ip = "192.168.10.10";                                           // Do forever:
+    send(ip);                                           //   Assamble and send our request. See eth_send function!
     i++;                                               //   Increment counter. What will increment the IP (c[4]) address as well.
     
     led4 = 1;                                          //   Show activity, by blinking with led 4:
diff -r 852db76de235 -r feaa107f56b3 mbed.bld
--- a/mbed.bld	Fri Sep 04 12:25:06 2009 +0000
+++ b/mbed.bld	Fri Apr 24 03:11:02 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/f63353af7be8
+http://mbed.org/users/mbed_official/code/mbed/builds/433970e64889
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/arp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/arp.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,58 @@
+#ifndef ARP_H
+#define ARP_H
+
+#include "net.h"
+
+/**
+  \file
+  \brief ARP packet
+  
+  This file contains the memory map and associated functions for ARP packet
+  creation and deconstruction. 
+*/
+
+#define ETHERTYPE_ARP 0x0806
+
+/// ARP Packet memory map
+typedef struct {
+  u16 hardware_type; ///< 0x0001 for ethernet
+  u16 protocol_type; ///< 0x0800 for IPv4
+  u8  hardware_length; ///< Bytes.  Ethernet is 6
+  u8  protocol_length; ///< Bytes.  IPv4 is 4
+  u16 operation; ///< Operation.  1 for request, 2 for reply or announce
+  // The following are only valid for IPv4 over Ethernet
+  u8  sender_hardware_address[6]; ///< Generator of the request or reply
+  u8  sender_protocol_address[4]; ///< All zeroes for an ARP probe
+  u8  target_hardware_address[6]; ///< Announce - same as SHA
+  u8  target_protocol_address[4]; ///< Announce - Same as TPA
+} ARP_Packet;
+
+/// Convert from wire to host or host to wire endianness
+inline void fix_endian_arp(ARP_Packet *packet)
+{
+  fix_endian_u16(&packet->hardware_type);
+  fix_endian_u16(&packet->protocol_type);
+  fix_endian_u16(&packet->operation);
+}
+
+/// Print the ARP packet
+inline void print_arp(ARP_Packet *packet)
+{
+    printf("ARP Packet: \n");
+    printf("  Hardware:  0x%04X \n", packet->hardware_type);
+    printf("  Protocol:  0x%04X \n", packet->protocol_type);
+    printf("  Type:      %d \n", packet->operation);
+    if (packet->hardware_type != 0x0001 || packet->protocol_type != 0x0800) return;
+    
+    u8 *bytes;
+    bytes = packet->sender_hardware_address;
+    printf("  Source:    MAC - %02X:%02X:%02X:%02X:%02X:%02X \n", bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5]);
+    bytes = packet->target_hardware_address;
+    printf("  Target:    MAC - %02X:%02X:%02X:%02X:%02X:%02X \n", bytes[0],bytes[1],bytes[2],bytes[3],bytes[4],bytes[5]);
+    bytes = packet->sender_protocol_address;
+    printf("  Source:    IP  - %03d.%03d.%03d.%03d \n", bytes[0], bytes[1], bytes[2], bytes[3]);
+    bytes = packet->target_protocol_address;
+    printf("  Target:    IP  - %03d.%03d.%03d.%03d \n", bytes[0], bytes[1], bytes[2], bytes[3]);
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/ethernet.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/ethernet.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,49 @@
+#ifndef ETHERNET_H
+#define ETHERNET_H
+
+#include "net.h"
+
+/**
+  \file ethernet.h
+  \brief Ethernet frame header
+  
+  This file contains the memory map and associated functions for Ethernet frame header
+  creation and deconstruction. 
+*/
+
+/// Ethernet MAC address memory map
+typedef struct {
+  unsigned char octet[6]; ///< Individual octsts of the MAC address
+} Ethernet_MAC;
+
+/// Ethernet II Frame Header Memory map
+typedef struct {
+  /// Destination MAC address (6 octets)
+  Ethernet_MAC destination;
+  /// Source MAC address (6 octets)
+  Ethernet_MAC source;
+  // (optional) VLAN Tag (unsupported)
+  /// Ethernet type or length (only <0x600 or 0x0800 IPv4 supported)
+  u16 ethertype;
+  /// Payload (used for memory mapping; has zero size)
+  unsigned char payload[];
+} Ethernet_FrameHeader;
+
+/// Convert from wire to host or host to wire endian-ness
+inline void fix_endian_ethernet(Ethernet_FrameHeader *header)
+{
+  fix_endian_u16(&header->ethertype);
+}
+
+/// Print out an ethernet packet
+inline void print_ethernet(Ethernet_FrameHeader *frame)
+{
+  printf("Ethernet frame: \n");
+  u8 *src = frame->source.octet;
+  u8 *dst = frame->destination.octet;
+  printf("  Source:    MAC - %02X:%02X:%02X:%02X:%02X:%02X \n", src[6], src[7], src[8], src[9], src[10], src[11]);
+  printf("  Dest:      MAC - %02X:%02X:%02X:%02X:%02X:%02X \n", dst[0], dst[1], dst[2], dst[3], dst[4], dst[5]);
+  printf("  Ethertype: 0x%04X \n", frame->ethertype);
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/icmp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/icmp.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,47 @@
+#ifndef ICMP_H
+#define ICMP_H
+
+#include "net.h"
+
+/**
+  \file icmp.h
+  \brief ICMP frame header
+  
+  This file contains the memory map and associated functions for ICMP packet
+  creation and deconstruction. 
+*/
+
+#define ICMP_ECHO_REPLY   0x00
+#define ICMP_ECHO_REQUEST 0x08
+#define IPPROTO_ICMP      0x01
+
+/// ICMP packet memory map
+typedef struct {
+    u8 type;        ///< type of ICMP message
+    u8 code;        ///< code number associated with certain message types
+    u16 checksum; 
+    u16 id;         ///< ID value, returned in ECHO REPLY
+    u16 sequence;   ///< Sequence value to be returned with ECHO REPLY
+    u8 data[];      ///< Data memory map
+} ICMP_Packet;
+
+/// Convert from wire to host or host to wire endianness
+inline void fix_endian_icmp(ICMP_Packet *segment)
+{
+  fix_endian_u16(&segment->checksum);
+  fix_endian_u16(&segment->id);
+  fix_endian_u16(&segment->sequence);
+}
+
+/// Print the ICMP packet
+inline void print_icmp(ICMP_Packet *segment)
+{
+  printf("ICMP Packet:");
+  printf("  Type:      0x%02X \n", segment->type);
+  printf("  Code:      0x%02X \n", segment->code);
+  printf("  Checksum:  0x%04X \n", segment->checksum);
+  printf("  ID:        0x%04X \n", segment->id);
+  printf("  Sequence:  0x%04X \n", segment->sequence);
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/ip.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/ip.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,115 @@
+#ifndef IP_H
+#define IP_H
+
+#include "net.h"
+
+/**
+  \file ip.h
+  \brief IP Packet header
+  
+  This file contains the memory map and associated functions for IP packet header
+  creation and deconstruction. 
+*/
+
+#define ETHERTYPE_IPV4 0x0800
+#define ETHERTYPE_IPV6 0x86DD
+
+/// IP Address memory map
+typedef struct {
+  unsigned char octet[4]; ///< Individual address octets
+} IP_Address;
+
+/// IP Packet memory map
+typedef struct {
+  /// 4 bits that contain the version, that specifies if it's an IPv4 or IPv6 packet,
+  unsigned version:4; // Only 0x4 supported
+  /// 4 bits that contain the Internet Header Length which is the length of the header in multiples of 4 bytes (eg. 5 means 20 bytes).
+  unsigned header_bytes_div4:4;
+  /// 8 bits that contain the Type of Service, also referred to as Quality of Service (QoS), which describes what priority the packet should have,
+  unsigned tos:8;
+  /// 16 bits that contain the total length of the IP packet (datagram) in bytes,
+  u16 packet_bytes;
+  /// 16 bits that contain an identification tag to help reconstruct the packet from several fragments,
+  u16 fragment_id;
+  /// 3 bits that contain a zero, a flag that says whether the packet is allowed to be fragmented or not (DF: Don't fragment), and a flag to state whether more fragments of a packet follow (MF: More Fragments)
+  unsigned unused_0:1;
+  unsigned dont_fragment:1;
+  unsigned more_follow:1;
+  /// 13 bits that contain the fragment offset, a field to identify position of fragment within original packet
+  unsigned fragment_offset:13; ///< This and the ones above may not work properly due to endianness
+  /// 8 bits that contain the Time to live (TTL) which is the number of hops (router, computer or device along a network) the packet is allowed to pass before it dies (for example, a packet with a TTL of 16 will be allowed to go across 16 routers to get to its destination before it is discarded),
+  unsigned ttl:8;
+  /// 8 bits that contain the protocol (TCP, UDP, ICMP, etc...)
+  ///   0x01 ICMP
+  ///   0x06 TCP
+  ///   0x11 UDP
+  unsigned protocol:8;
+  /// 16 bits that contain the Header Checksum, a number used in error detection,
+  u16 header_checksum;
+  /// 32 bits that contain the source IP address,
+  IP_Address source;
+  /// 32 bits that contain the destination address.
+  IP_Address destination;
+  /// Zero-length field for memory mapping the packet data
+  unsigned char data[];
+} IP_PacketHeader;
+
+/// Convert from wire to host or host to wire endianness
+inline void fix_endian_ip(IP_PacketHeader *packet)
+{
+  packet->version ^= packet->header_bytes_div4;
+  packet->header_bytes_div4 ^= packet->version;
+  packet->version ^= packet->header_bytes_div4;
+  fix_endian_u16(&packet->packet_bytes);
+  fix_endian_u16(&packet->fragment_id);
+  // Don't fix checksums; they are done bitwise
+}
+
+/// Get a constant string of the given IP protocol (e.g. "ICMP", "TCP", "UDP") if known
+inline const char *ipproto2name(u8 proto)
+{
+  switch (proto)
+  {
+    case 0x01: return "ICMP";
+    case 0x02: return "IGMP";
+    case 0x06: return "TCP";
+    case 0x11: return "UDP";
+  }
+  return "<UNKNOWN>";
+}
+
+/// Print the IP packet
+inline void print_ip(IP_PacketHeader *packet)
+{
+  printf("IPv%d Packet: \n", packet->version);
+  if (packet->version != 4)
+  {
+    printf("Not an IPv4 packet (skipping)");
+    return;
+  }
+    
+  u8 *dst = packet->destination.octet;
+  u8 *src = packet->source.octet;
+  printf("  Source:    IP - %03d.%03d.%03d.%03d \n", src[0], src[1], src[2], src[3]);
+  printf("  Dest:      IP - %03d.%03d.%03d.%03d \n", dst[0], dst[1], dst[2], dst[3]);
+  printf("  TTL:       %d \n", packet->ttl);
+  printf("  Protocol:  0x%02X (%s) \n", packet->protocol, ipproto2name(packet->protocol));
+  printf("  ToS:       0x%02X \n", packet->tos);
+  printf("  Header:    %d bytes \n", packet->header_bytes_div4*4);
+  printf("  Packet:    %d bytes \n", packet->packet_bytes);
+  printf("  Fragment:  0x%04X DF=%d MF=%d OFFSET=0x04X", packet->fragment_id, packet->dont_fragment, packet->more_follow, packet->fragment_offset);
+  printf("  Checksum:  0x%04X \n", packet->header_checksum);
+}
+
+/// Parse the string (in decimal triple-dot notation) into the IP address structure
+inline void str2ipaddr(const char *ip, IP_Address *addr)
+{
+  static short a,b,c,d;
+  sscanf(ip, "%3hd.%3hd.%3hd.%3hd", &a, &b, &c, &d);
+  addr->octet[0] = a;
+  addr->octet[1] = b;
+  addr->octet[2] = c;
+  addr->octet[3] = d;
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/net.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/net.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,103 @@
+/**
+ @file net.h
+ @brief This file encompasses all of the networking headers and includes them automatically
+ 
+ This file has some utility functions and definitions used by all of the networking headers,
+ and includes them all.  This is the only file necessary to include to use all of the networking
+ facilities in nettool
+*/
+
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#include "mbed.h"
+
+#include "ctype.h"
+
+/// General networking checksum - Used for IP, TCP, UDP, ICMP, etc.
+/// Computes the one's complement of the one's complement sum of all of the given bytes except for the memory
+/// at skip_byte for skip_count bytes (e.g. the checksum).  Optionally resumes computation from the (given) last checksum.
+inline u16 checksum(void *_mem, unsigned int bytes, void *skip_byte = NULL, unsigned int skip_count = 0, u16 last = 0)
+{
+  u32 sum = 0;
+  u16 *mem = (u16*)_mem;
+  unsigned int skip_start = (u16*)skip_byte - mem;
+  
+  if (last)
+    sum = last ^ 0xFFFF;
+  
+  //main_log.printf("CK:            0x%8X", sum);
+  for (register unsigned int i = 0; i < bytes/sizeof(u16); ++i)
+  {
+    // Skip bytes we don't use (e.g. the checksum itself)
+    if (i == skip_start)
+      i += skip_count/sizeof(u16);
+    
+    // Sum them up
+    sum += mem[i];
+    
+    //main_log.printf("CK: + 0x%04X = 0x%8X", mem[i], sum);
+  }
+    
+  // One's complement of the one's complement sum
+  sum += sum >> 16;
+  sum &= 0xFFFF;
+  sum ^= 0xFFFF;
+  
+  //main_log.printf("CK:          ~ 0x%8X", sum);
+  
+  return (u16)(sum);
+}
+
+/// Generic u16 endian swapping
+inline void fix_endian_u16(u16 *p)
+{
+  char *bytes = (char*)p;
+  bytes[0] ^= bytes[1];
+  bytes[1] ^= bytes[0];
+  bytes[0] ^= bytes[1];
+}
+
+/// Generic u32 endian swapping
+inline void fix_endian_u32(u32 *p)
+{
+  char *bytes = (char*)p;
+  // Swap outer bytes
+  bytes[0] ^= bytes[3];
+  bytes[3] ^= bytes[0];
+  bytes[0] ^= bytes[3];
+  // Swap inner bytes
+  bytes[1] ^= bytes[2];
+  bytes[2] ^= bytes[1];
+  bytes[1] ^= bytes[2];
+}
+
+/* Printing character */
+#define PCHAR(x) (isprint(x)?(x):'.')
+
+/// Hex dump a word-aligned number of bytes (will print extra bytes if length is not a multiple of 32 bits)
+inline void hex_dump(void *base, unsigned int length)
+{
+  char line[/*indent*/ 2 + /*0x*/ 2 + /*addr*/ 8 + /* : */ 3 + /*4xXXXX */ 4*5 + /*: */ 2 + /*8x.*/ 8 + /*\0*/ 1];
+  for (char *p = (char*)base; p - (char*)base < length; p += 8)
+  {
+    sprintf(line, "  0x%08X : %02X%02X %02X%02X %02X%02X %02X%02X : %c%c%c%c%c%c%c%c \n", p,
+                  p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
+                  PCHAR(p[0]), PCHAR(p[1]), PCHAR(p[2]), PCHAR(p[3]), PCHAR(p[4]), PCHAR(p[5]), PCHAR(p[6]), PCHAR(p[7]));
+    printf(line);
+  }
+}
+
+// Ethernet
+#include "ethernet.h"
+
+// ARP and IP
+#include "arp.h"
+#include "ip.h"
+
+// TCP, UDP, and ICMP
+#include "tcp.h"
+#include "udp.h"
+#include "icmp.h"
+
+#endif // NETWORK_H
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/tcp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/tcp.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,90 @@
+#ifndef TCP_H
+#define TCP_H
+
+#include "net.h"
+
+/**
+  \file tcp.h
+  \brief TCP segment header
+  
+  This file contains the memory map and associated functions for TCP segment header
+  creation and deconstruction. 
+*/
+
+#define IPPROTO_TCP 0x06
+
+/// TCP Segment memory map
+typedef struct {
+  u16 source_port;         ///< Source port (1-65535)
+  u16 destination_port;    ///< Destination port (1-65535)
+  u32 sequence_number;     ///< TCP Sequence number (initial one if SYN set)
+  u32 acknowledge_number;  ///< TCP Acknowledge number (valid if ACK set)
+  
+  unsigned data_offset_bytes_div4:4; ///< Length of this header (20) divided by 4 (should be 5)
+  unsigned unused_0:4;               ///< Unused, should be zero
+  
+  unsigned fin:1; ///< connection FINished (no more data from sender)
+  unsigned syn:1; ///< SYNchronize sequence numbers
+  unsigned rst:1; ///< ReSeT the connection
+  unsigned psh:1; ///< PuSH to receiving application
+  unsigned ack:1; ///< ACKnowledge fiend is significant
+  unsigned urg:1; ///< URGent field is significant
+  unsigned ece:1; ///< ECn Echo
+  unsigned cwr:1; ///< Congestion Window Reduced
+  
+  u16 window_size;    ///< TCP Maxumum window size (8192 is good)
+  u16 checksum;       ///< TCP checksum (computed with pseudo header)
+  u16 urgent_pointer; ///< Urgent pointer (valid if URG set)
+  
+  /// Memory map for data if no options are set
+  unsigned char data[];
+} TCP_SegmentHeader;
+
+/// Convert from wire to host or host to wire endianness
+inline void fix_endian_tcp(TCP_SegmentHeader *segment)
+{
+  segment->unused_0 ^= segment->data_offset_bytes_div4;
+  segment->data_offset_bytes_div4 ^= segment->unused_0;
+  segment->unused_0 ^= segment->data_offset_bytes_div4;
+  fix_endian_u16(&segment->source_port);
+  fix_endian_u16(&segment->destination_port);
+  fix_endian_u16(&segment->window_size);
+  // No fixing checksums
+  fix_endian_u16(&segment->urgent_pointer);
+  fix_endian_u32(&segment->sequence_number);
+  fix_endian_u32(&segment->acknowledge_number);
+}
+
+/// Print the TCP segment header
+inline void print_tcp(TCP_SegmentHeader *segment)
+{
+  printf("TCP Segment: \n");
+  printf("  Source:    PORT %d \n", segment->source_port);
+  printf("  Dest:      PORT %d \n", segment->destination_port);
+  printf("  TCP Seqno: 0x%08X \n", segment->sequence_number);
+  printf("  TCP Ackno: 0x%08X \n", segment->acknowledge_number);
+  printf("  Header:    %d bytes \n", segment->data_offset_bytes_div4*4);
+  if (segment->cwr) printf("  Flag:      CWR \n");
+  if (segment->ece) printf("  Flag:      ECE \n");
+  if (segment->urg) printf("  Flag:      URG \n");
+  if (segment->ack) printf("  Flag:      ACK \n");
+  if (segment->psh) printf("  Flag:      PSH \n");
+  if (segment->rst) printf("  Flag:      RST \n");
+  if (segment->syn) printf("  Flag:      SYN \n");
+  if (segment->fin) printf("  Flag:      FIN \n");
+}
+
+/// Compute the pseudo header checksum with the given source, destination, and length
+inline u16 pseudo_header_checksum(IP_Address source, IP_Address destination, u16 length)
+{
+  struct {
+    IP_Address src, dst;
+    u8 zeros;
+    u8 proto;
+    u16 length;
+  } pseudoheader = {source, destination, 0, IPPROTO_TCP, length};
+  fix_endian_u16(&pseudoheader.length);
+  return checksum(&pseudoheader, sizeof(pseudoheader));
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 net/udp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/net/udp.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,42 @@
+#ifndef UDP_H
+#define UDP_H
+
+#include "net.h"
+
+/**
+  \file udp.h
+  \brief UDP packet
+  
+  This file contains the memory map and associated functions for UDP packet
+  creation and deconstruction. 
+*/
+
+#define IPPROTO_UDP 0x11
+
+/// UDP Packet memory map
+typedef struct {
+  u16 source_port;       ///< Source port (1-65535)
+  u16 destination_port;  ///< Destination port (1-65535) 
+  u16 length;            ///< Entire datagram size in bytes
+  u16 checksum;          ///< Checksum
+  u8 data[];             ///< Data memory map
+} UDP_Packet;
+
+/// Convert from wire to host or host to wire endianness
+inline void fix_endian_udp(UDP_Packet *segment)
+{
+  fix_endian_u16(&segment->source_port);
+  fix_endian_u16(&segment->destination_port);
+  fix_endian_u16(&segment->length);
+}
+
+/// Print the UDP packet
+inline void print_udp(UDP_Packet *segment)
+{
+  printf("UDP Packet: \n");
+  printf("  Source:    PORT %d \n", segment->source_port);
+  printf("  Dest:      PORT %d \n", segment->destination_port);
+  printf("  Length:    %d \n", segment->length);
+}
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 sniffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sniffer.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,268 @@
+#ifndef SNIFFER_H
+#define SNIFFER_H
+
+#include "mbed.h"
+
+#include "util/types.h"
+#include "net/net.h"
+
+#include <cstdio>
+#include <cstring>
+#include <functional>
+
+/**
+  \file sniffer.h
+  \brief Ethernet packet Sniffer
+  
+  This file is the bread and butter of the NetTool; it processes and constructs ethernet frames
+  on a bitwise level.
+*/
+
+template <class Arg1, class Arg2, class Result>
+class handler
+{
+public:
+  virtual inline Result operator() (Arg1 x, Arg2 y) const {};
+};
+
+template <class Arg1, class Arg2, class Result>
+class function_handler
+: public handler <Arg1,Arg2,Result>
+{
+protected:
+  Result (*pfunc)(Arg1,Arg2);
+public:
+  explicit inline function_handler ( Result (*f)(Arg1,Arg2) ) : pfunc (f) {}
+  virtual inline Result operator() (Arg1 x, Arg2 y) const { return pfunc(x,y); }
+};
+
+template <class Type, class Arg1, class Arg2, class Result>
+class member_handler
+: public handler <Arg1,Arg2,Result>
+{
+protected:
+  Type *inst;
+  Result (Type::*pfunc)(Arg1,Arg2);
+public:
+  explicit inline member_handler ( Type *i, Result (Type::*f)(Arg1,Arg2) ) : inst(i), pfunc (f) {}
+  virtual inline Result operator() (Arg1 x, Arg2 y) const { return (inst->*pfunc)(x,y); }
+};
+
+/// Demo - Ethernet Packet Sniffer
+class Sniffer {
+public:
+  Ethernet_MAC mac;
+  
+private:
+  // Ethernet interface
+  Ethernet     eth;
+  IP_Address   addr;
+  
+  // Status LEDs
+  DigitalOut linked;
+  DigitalOut received;
+
+  // Frame data (big enough for largest ethernet frame)
+  int  frame_size;
+  char frame[0x600];
+  
+  // Outgoing frames
+  char outframe[0x600];
+  Ethernet_FrameHeader *outframe_header;
+
+public:  
+  /// Ethernet Frame Header (incoming)
+  Ethernet_FrameHeader *frame_header;
+  
+  /// IP Packet Header (incoming)
+  IP_PacketHeader *ip_packet;
+  
+  /// ARP Packet (incoming)
+  ARP_Packet *arp_packet;
+  
+  /// TCP Packet (incoming)
+  TCP_SegmentHeader *tcp_packet;
+  
+  /// UDP Packet (incoming)
+  UDP_Packet *udp_packet;
+  
+  /// ICMP Packet (incoming)
+  ICMP_Packet *icmp_packet;
+  
+  /// Generic - total data bytes
+  unsigned int data_bytes;
+
+public:
+  /// Constructor
+  inline Sniffer()
+  : linked(LED1), received(LED2)
+  {
+    eth.set_link(Ethernet::AutoNegotiate);
+    eth.address((char *)mac.octet);
+  }
+  
+  /// Inject the raw ethernet frame
+  inline bool inject(void *data, unsigned int bytes)
+  {
+    // Send the packet
+    eth.write((char*)data, bytes);
+    int send_status = eth.send();
+
+    //decode_ethernet(data);
+    
+    return send_status;
+  }
+  
+  /// Inject the raw payload into an ethernet frame with the given destination and ethertype
+  inline bool inject(Ethernet_MAC dest, u16 ethertype, void *packet, unsigned int bytes)
+  {
+    memset(outframe, 0x00, bytes);
+    
+    outframe_header = (Ethernet_FrameHeader*)outframe;
+    
+    // Set the ethernet frame source
+    memcpy(&outframe_header->source, mac.octet, 6);
+    
+    // Set the ethernet frame destination
+    outframe_header->destination = dest;
+    
+    // Set the ethernet ethertype
+    outframe_header->ethertype = ethertype;
+    
+    // Make sure the payload won't be too large
+    if (sizeof(Ethernet_FrameHeader) + bytes > sizeof(outframe))
+    {
+      printf("ERROR: Attempt to inject packet failed; Payload size of %d is too large /n", bytes);
+      return false;
+    }
+    
+    // Set the payload
+    memcpy(outframe_header->payload, packet, bytes);
+    fix_endian_ethernet(outframe_header);
+    
+    // Send the packet
+    eth.write(outframe, sizeof(Ethernet_FrameHeader) + bytes);
+    int send_status = eth.send();
+
+    //decode_ethernet(outframe);
+
+    return send_status;
+  }
+  
+  /// Wait until there is more data to receive
+  inline void wait_for_data()
+  { 
+    while (true)
+    {
+      wait(0.0001);
+      
+      if (!(linked = eth.link()))
+        continue;
+      
+      received = (frame_size = eth.receive());
+      if (!frame_size)
+        continue;
+      
+      eth.read(frame, frame_size);
+      break;
+    }
+  }
+
+  /// Wait for an ethernet frame (will be stored in appropriate class member pointers)
+  inline void next()
+  {
+    wait_for_data();
+    
+    // Zero out all of the packet pointers
+    frame_header = NULL;
+    arp_packet = NULL;
+    icmp_packet = NULL;
+    tcp_packet = NULL;
+    udp_packet = NULL;
+    data_bytes = 0;
+    
+    decode_ethernet(frame);
+  }
+  
+  /// Decode the given ethernet frame
+  inline void decode_ethernet(void *frame)
+  {
+    Ethernet_FrameHeader *header = frame_header = (Ethernet_FrameHeader*)frame;
+    fix_endian_ethernet(header);
+    
+    switch (header->ethertype)
+    {
+      case ETHERTYPE_IPV4:
+      case ETHERTYPE_IPV6:
+        decode_ip((IP_PacketHeader*)header->payload);
+        break;
+      case ETHERTYPE_ARP:
+        decode_arp((ARP_Packet*)header->payload);
+        break;
+      default:
+        break; // Unknown ethertype
+    }
+  }
+  
+  /// Decode the given ARP packet
+  inline void decode_arp(ARP_Packet *packet)
+  {
+    fix_endian_arp(packet);
+    if (packet->hardware_type != 0x0001 || packet->protocol_type != 0x0800) return;
+    arp_packet = packet;
+  }
+  
+  /// Decode the given IPv4 packet
+  inline void decode_ip(IP_PacketHeader *packet)
+  {
+    u16 chk = checksum(packet, sizeof(IP_PacketHeader), &packet->header_checksum, 2);
+    fix_endian_ip(packet);
+    ip_packet = packet;
+  
+    if (packet->version != 4) return;
+    
+    data_bytes = packet->packet_bytes;
+    data_bytes -= sizeof(IP_PacketHeader);
+    
+    if (packet->protocol == IPPROTO_UDP)
+    {
+      UDP_Packet *segment = udp_packet = (UDP_Packet*)packet->data;
+      fix_endian_udp(segment);
+      data_bytes -= sizeof(UDP_Packet);
+    }
+    else if (packet->protocol == IPPROTO_ICMP)
+    {
+      ICMP_Packet *segment = icmp_packet = (ICMP_Packet *)packet->data;
+      fix_endian_icmp(segment);
+      data_bytes -= sizeof(ICMP_Packet);
+    }
+    else if (packet->protocol == IPPROTO_TCP)
+    {
+      TCP_SegmentHeader *segment = tcp_packet = (TCP_SegmentHeader*)packet->data;
+      fix_endian_tcp(segment);
+      data_bytes -= sizeof(TCP_SegmentHeader);
+      dispatch_tcp(segment,data_bytes);
+    }
+  }
+  
+  handler<TCP_SegmentHeader*,u32,void> *tcp_handler;
+  inline void dispatch_tcp(TCP_SegmentHeader *tcp_packet, u32 data_bytes)
+  {
+    if (tcp_handler) (*tcp_handler)(tcp_packet,data_bytes);
+  }
+  
+  /// Attach a member function to be called on all TCP packets
+  template <class T>
+  inline void attach_tcp(T *inst, void (T::*func)(TCP_SegmentHeader *tcp_packet, u32 data_bytes))
+  {
+    tcp_handler = new member_handler<T,TCP_SegmentHeader*,u32,void>(inst, func);
+  }
+  
+  /// Attach a non-member function to be called on all TCP packets
+  inline void attach_tcp(void (*func)(TCP_SegmentHeader *tcp_packet, u32 data_bytes))
+  {
+    tcp_handler = new function_handler<TCP_SegmentHeader*,u32,void>(func);
+  }
+};
+
+#endif // SNIFFER_H
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 util/types.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/types.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,20 @@
+#ifndef TYPES_H
+#define TYPES_H
+
+/**
+  \file types.h
+  \brief Type definitions
+  
+  This file contains some utility type definitions
+*/
+
+/// Unsigned 8 bit value
+typedef unsigned char u8;
+
+/// Unsigned 16 bit value
+typedef unsigned short u16;
+
+/// Unsigned 32 bit value
+typedef unsigned int u32;
+
+#endif
\ No newline at end of file
diff -r 852db76de235 -r feaa107f56b3 util/util.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/util.h	Fri Apr 24 03:11:02 2015 +0000
@@ -0,0 +1,35 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "types.h"
+
+/**
+  \file util.h
+  \brief Primary utility header
+  
+  In addition to providing some utility functions, this file also includes
+  the other utility headers automatically.
+*/
+
+/// Is any byte memory at start for bytes nonzero?
+inline bool is_nonzero_mem(u8 *start, unsigned int bytes)
+{
+  for (; bytes--; ++start) if (*start) return true;
+  return false;
+}
+
+/// Are all bytes at start for bytes zero?
+inline bool is_zero_mem(u8 *start, unsigned int bytes)
+{
+  for (; bytes--; ++start) if (*start) return false;
+  return true;
+}
+
+/// Are the memory locations at and and b equal for bytes?
+inline bool is_equal_mem(u8 *a, u8 *b, unsigned int bytes)
+{
+  for (; bytes--; ++a, ++b) if (*a != *b) return false;
+  return true;
+}
+
+#endif
\ No newline at end of file