test icmp
Fork of ethspam by
Revision 1:feaa107f56b3, committed 2015-04-24
- Comitter:
- jamessayer
- Date:
- Fri Apr 24 03:11:02 2015 +0000
- Parent:
- 0:852db76de235
- Commit message:
- first version;
Changed in this revision
--- 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:
--- 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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
