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