This is a low-level network debugging utility that utilizes raw packet i/o to construct and deconstruct tcp, udp, ipv4, arp, and icmp packets over ethernet.

Dependencies:   mbed

Committer:
etherealflaim
Date:
Tue Oct 12 06:14:19 2010 +0000
Revision:
3:c32d9660b888
Parent:
2:e8e09adc41fc
Child:
6:66c4cd9073aa
Documentation updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
etherealflaim 0:d494b853ce97 1 #ifndef IP_H
etherealflaim 0:d494b853ce97 2 #define IP_H
etherealflaim 0:d494b853ce97 3
etherealflaim 0:d494b853ce97 4 #include "net.h"
etherealflaim 0:d494b853ce97 5
etherealflaim 2:e8e09adc41fc 6 /// \file IP Packet
etherealflaim 2:e8e09adc41fc 7
etherealflaim 0:d494b853ce97 8 #define ETHERTYPE_IPV4 0x0800
etherealflaim 0:d494b853ce97 9 #define ETHERTYPE_IPV6 0x86DD
etherealflaim 0:d494b853ce97 10
etherealflaim 2:e8e09adc41fc 11 /// IP Address memory map
etherealflaim 0:d494b853ce97 12 typedef struct {
etherealflaim 2:e8e09adc41fc 13 unsigned char octet[4]; ///< Individual address octets
etherealflaim 0:d494b853ce97 14 } IP_Address;
etherealflaim 0:d494b853ce97 15
etherealflaim 3:c32d9660b888 16 /// IP Packet memory map
etherealflaim 0:d494b853ce97 17 typedef struct {
etherealflaim 2:e8e09adc41fc 18 /// 4 bits that contain the version, that specifies if it's an IPv4 or IPv6 packet,
etherealflaim 0:d494b853ce97 19 unsigned version:4; // Only 0x4 supported
etherealflaim 2:e8e09adc41fc 20 /// 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).
etherealflaim 0:d494b853ce97 21 unsigned header_bytes_div4:4;
etherealflaim 2:e8e09adc41fc 22 /// 8 bits that contain the Type of Service, also referred to as Quality of Service (QoS), which describes what priority the packet should have,
etherealflaim 0:d494b853ce97 23 unsigned tos:8;
etherealflaim 2:e8e09adc41fc 24 /// 16 bits that contain the total length of the IP packet (datagram) in bytes,
etherealflaim 0:d494b853ce97 25 u16 packet_bytes;
etherealflaim 2:e8e09adc41fc 26 /// 16 bits that contain an identification tag to help reconstruct the packet from several fragments,
etherealflaim 0:d494b853ce97 27 u16 fragment_id;
etherealflaim 2:e8e09adc41fc 28 /// 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)
etherealflaim 0:d494b853ce97 29 unsigned unused_0:1;
etherealflaim 0:d494b853ce97 30 unsigned dont_fragment:1;
etherealflaim 0:d494b853ce97 31 unsigned more_follow:1;
etherealflaim 2:e8e09adc41fc 32 /// 13 bits that contain the fragment offset, a field to identify position of fragment within original packet
etherealflaim 3:c32d9660b888 33 unsigned fragment_offset:13; ///< This and the ones above may not work properly due to endianness
etherealflaim 2:e8e09adc41fc 34 /// 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),
etherealflaim 0:d494b853ce97 35 unsigned ttl:8;
etherealflaim 2:e8e09adc41fc 36 /// 8 bits that contain the protocol (TCP, UDP, ICMP, etc...)
etherealflaim 2:e8e09adc41fc 37 /// 0x01 ICMP
etherealflaim 2:e8e09adc41fc 38 /// 0x06 TCP
etherealflaim 2:e8e09adc41fc 39 /// 0x11 UDP
etherealflaim 0:d494b853ce97 40 unsigned protocol:8;
etherealflaim 2:e8e09adc41fc 41 /// 16 bits that contain the Header Checksum, a number used in error detection,
etherealflaim 0:d494b853ce97 42 u16 header_checksum;
etherealflaim 2:e8e09adc41fc 43 /// 32 bits that contain the source IP address,
etherealflaim 0:d494b853ce97 44 IP_Address source;
etherealflaim 2:e8e09adc41fc 45 /// 32 bits that contain the destination address.
etherealflaim 0:d494b853ce97 46 IP_Address destination;
etherealflaim 2:e8e09adc41fc 47 /// Zero-length field for memory mapping the packet data
etherealflaim 0:d494b853ce97 48 unsigned char data[];
etherealflaim 0:d494b853ce97 49 } IP_PacketHeader;
etherealflaim 0:d494b853ce97 50
etherealflaim 2:e8e09adc41fc 51 /// Convert from wire to host or host to wire endianness
etherealflaim 0:d494b853ce97 52 inline void fix_endian_ip(IP_PacketHeader *packet)
etherealflaim 0:d494b853ce97 53 {
etherealflaim 0:d494b853ce97 54 packet->version ^= packet->header_bytes_div4;
etherealflaim 0:d494b853ce97 55 packet->header_bytes_div4 ^= packet->version;
etherealflaim 0:d494b853ce97 56 packet->version ^= packet->header_bytes_div4;
etherealflaim 0:d494b853ce97 57 fix_endian_u16(&packet->packet_bytes);
etherealflaim 0:d494b853ce97 58 fix_endian_u16(&packet->fragment_id);
etherealflaim 0:d494b853ce97 59 // Don't fix checksums; they are done bitwise
etherealflaim 0:d494b853ce97 60 }
etherealflaim 0:d494b853ce97 61
etherealflaim 2:e8e09adc41fc 62 /// Get a constant string of the given IP protocol (e.g. "ICMP", "TCP", "UDP") if known
etherealflaim 0:d494b853ce97 63 inline const char *ipproto2name(u8 proto)
etherealflaim 0:d494b853ce97 64 {
etherealflaim 0:d494b853ce97 65 switch (proto)
etherealflaim 0:d494b853ce97 66 {
etherealflaim 0:d494b853ce97 67 case 0x01: return "ICMP";
etherealflaim 0:d494b853ce97 68 case 0x02: return "IGMP";
etherealflaim 0:d494b853ce97 69 case 0x06: return "TCP";
etherealflaim 0:d494b853ce97 70 case 0x11: return "UDP";
etherealflaim 0:d494b853ce97 71 }
etherealflaim 0:d494b853ce97 72 return "<UNKNOWN>";
etherealflaim 0:d494b853ce97 73 }
etherealflaim 0:d494b853ce97 74
etherealflaim 2:e8e09adc41fc 75 /// Print the IP packet
etherealflaim 0:d494b853ce97 76 inline void print_ip(IP_PacketHeader *packet)
etherealflaim 0:d494b853ce97 77 {
etherealflaim 0:d494b853ce97 78 main_log.printf("IPv%d Packet:", packet->version);
etherealflaim 0:d494b853ce97 79 if (packet->version != 4)
etherealflaim 0:d494b853ce97 80 {
etherealflaim 0:d494b853ce97 81 main_log.printf("Not an IPv4 packet (skipping)");
etherealflaim 0:d494b853ce97 82 return;
etherealflaim 0:d494b853ce97 83 }
etherealflaim 0:d494b853ce97 84
etherealflaim 0:d494b853ce97 85 u8 *dst = packet->destination.octet;
etherealflaim 0:d494b853ce97 86 u8 *src = packet->source.octet;
etherealflaim 0:d494b853ce97 87 main_log.printf(" Source: IP - %03d.%03d.%03d.%03d", src[0], src[1], src[2], src[3]);
etherealflaim 0:d494b853ce97 88 main_log.printf(" Dest: IP - %03d.%03d.%03d.%03d", dst[0], dst[1], dst[2], dst[3]);
etherealflaim 0:d494b853ce97 89 main_log.printf(" TTL: %d", packet->ttl);
etherealflaim 0:d494b853ce97 90 main_log.printf(" Protocol: 0x%02X (%s)", packet->protocol, ipproto2name(packet->protocol));
etherealflaim 0:d494b853ce97 91 main_log.printf(" ToS: 0x%02X", packet->tos);
etherealflaim 0:d494b853ce97 92 main_log.printf(" Header: %d bytes", packet->header_bytes_div4*4);
etherealflaim 0:d494b853ce97 93 main_log.printf(" Packet: %d bytes", packet->packet_bytes);
etherealflaim 0:d494b853ce97 94 main_log.printf(" Fragment: 0x%04X DF=%d MF=%d OFFSET=0x04X", packet->fragment_id, packet->dont_fragment, packet->more_follow, packet->fragment_offset);
etherealflaim 0:d494b853ce97 95 main_log.printf(" Checksum: 0x%04X", packet->header_checksum);
etherealflaim 0:d494b853ce97 96 }
etherealflaim 0:d494b853ce97 97
etherealflaim 2:e8e09adc41fc 98 /// Parse the string (in decimal triple-dot notation) into the IP address structure
etherealflaim 0:d494b853ce97 99 inline void str2ipaddr(const char *ip, IP_Address *addr)
etherealflaim 0:d494b853ce97 100 {
etherealflaim 0:d494b853ce97 101 static short a,b,c,d;
etherealflaim 0:d494b853ce97 102 sscanf(ip, "%3hd.%3hd.%3hd.%3hd", &a, &b, &c, &d);
etherealflaim 0:d494b853ce97 103 addr->octet[0] = a;
etherealflaim 0:d494b853ce97 104 addr->octet[1] = b;
etherealflaim 0:d494b853ce97 105 addr->octet[2] = c;
etherealflaim 0:d494b853ce97 106 addr->octet[3] = d;
etherealflaim 0:d494b853ce97 107 }
etherealflaim 0:d494b853ce97 108
etherealflaim 0:d494b853ce97 109 #endif