User | Revision | Line number | New contents of line |
etherealflaim |
0:7e2eb93442e7
|
1
|
#ifndef IP_H
|
etherealflaim |
0:7e2eb93442e7
|
2
|
#define IP_H
|
etherealflaim |
0:7e2eb93442e7
|
3
|
|
etherealflaim |
0:7e2eb93442e7
|
4
|
#include "net.h"
|
etherealflaim |
0:7e2eb93442e7
|
5
|
|
etherealflaim |
0:7e2eb93442e7
|
6
|
/**
|
etherealflaim |
0:7e2eb93442e7
|
7
|
\file ip.h
|
etherealflaim |
0:7e2eb93442e7
|
8
|
\brief IP Packet header
|
etherealflaim |
0:7e2eb93442e7
|
9
|
|
etherealflaim |
0:7e2eb93442e7
|
10
|
This file contains the memory map and associated functions for IP packet header
|
etherealflaim |
0:7e2eb93442e7
|
11
|
creation and deconstruction.
|
etherealflaim |
0:7e2eb93442e7
|
12
|
*/
|
etherealflaim |
0:7e2eb93442e7
|
13
|
|
etherealflaim |
0:7e2eb93442e7
|
14
|
#define ETHERTYPE_IPV4 0x0800
|
etherealflaim |
0:7e2eb93442e7
|
15
|
#define ETHERTYPE_IPV6 0x86DD
|
etherealflaim |
0:7e2eb93442e7
|
16
|
|
etherealflaim |
0:7e2eb93442e7
|
17
|
/// IP Address memory map
|
etherealflaim |
0:7e2eb93442e7
|
18
|
typedef struct {
|
etherealflaim |
0:7e2eb93442e7
|
19
|
unsigned char octet[4]; ///< Individual address octets
|
etherealflaim |
0:7e2eb93442e7
|
20
|
} IP_Address;
|
etherealflaim |
0:7e2eb93442e7
|
21
|
|
etherealflaim |
0:7e2eb93442e7
|
22
|
/// IP Packet memory map
|
etherealflaim |
0:7e2eb93442e7
|
23
|
typedef struct {
|
etherealflaim |
0:7e2eb93442e7
|
24
|
/// 4 bits that contain the version, that specifies if it's an IPv4 or IPv6 packet,
|
etherealflaim |
0:7e2eb93442e7
|
25
|
unsigned version:4; // Only 0x4 supported
|
etherealflaim |
0:7e2eb93442e7
|
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:7e2eb93442e7
|
27
|
unsigned header_bytes_div4:4;
|
etherealflaim |
0:7e2eb93442e7
|
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:7e2eb93442e7
|
29
|
unsigned tos:8;
|
etherealflaim |
0:7e2eb93442e7
|
30
|
/// 16 bits that contain the total length of the IP packet (datagram) in bytes,
|
etherealflaim |
0:7e2eb93442e7
|
31
|
u16 packet_bytes;
|
etherealflaim |
0:7e2eb93442e7
|
32
|
/// 16 bits that contain an identification tag to help reconstruct the packet from several fragments,
|
etherealflaim |
0:7e2eb93442e7
|
33
|
u16 fragment_id;
|
etherealflaim |
0:7e2eb93442e7
|
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:7e2eb93442e7
|
35
|
unsigned unused_0:1;
|
etherealflaim |
0:7e2eb93442e7
|
36
|
unsigned dont_fragment:1;
|
etherealflaim |
0:7e2eb93442e7
|
37
|
unsigned more_follow:1;
|
etherealflaim |
0:7e2eb93442e7
|
38
|
/// 13 bits that contain the fragment offset, a field to identify position of fragment within original packet
|
etherealflaim |
0:7e2eb93442e7
|
39
|
unsigned fragment_offset:13; ///< This and the ones above may not work properly due to endianness
|
etherealflaim |
0:7e2eb93442e7
|
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:7e2eb93442e7
|
41
|
unsigned ttl:8;
|
etherealflaim |
0:7e2eb93442e7
|
42
|
/// 8 bits that contain the protocol (TCP, UDP, ICMP, etc...)
|
etherealflaim |
0:7e2eb93442e7
|
43
|
/// 0x01 ICMP
|
etherealflaim |
0:7e2eb93442e7
|
44
|
/// 0x06 TCP
|
etherealflaim |
0:7e2eb93442e7
|
45
|
/// 0x11 UDP
|
etherealflaim |
0:7e2eb93442e7
|
46
|
unsigned protocol:8;
|
etherealflaim |
0:7e2eb93442e7
|
47
|
/// 16 bits that contain the Header Checksum, a number used in error detection,
|
etherealflaim |
0:7e2eb93442e7
|
48
|
u16 header_checksum;
|
etherealflaim |
0:7e2eb93442e7
|
49
|
/// 32 bits that contain the source IP address,
|
etherealflaim |
0:7e2eb93442e7
|
50
|
IP_Address source;
|
etherealflaim |
0:7e2eb93442e7
|
51
|
/// 32 bits that contain the destination address.
|
etherealflaim |
0:7e2eb93442e7
|
52
|
IP_Address destination;
|
etherealflaim |
0:7e2eb93442e7
|
53
|
/// Zero-length field for memory mapping the packet data
|
etherealflaim |
0:7e2eb93442e7
|
54
|
unsigned char data[];
|
etherealflaim |
0:7e2eb93442e7
|
55
|
} IP_PacketHeader;
|
etherealflaim |
0:7e2eb93442e7
|
56
|
|
etherealflaim |
0:7e2eb93442e7
|
57
|
/// Convert from wire to host or host to wire endianness
|
etherealflaim |
0:7e2eb93442e7
|
58
|
inline void fix_endian_ip(IP_PacketHeader *packet)
|
etherealflaim |
0:7e2eb93442e7
|
59
|
{
|
etherealflaim |
0:7e2eb93442e7
|
60
|
packet->version ^= packet->header_bytes_div4;
|
etherealflaim |
0:7e2eb93442e7
|
61
|
packet->header_bytes_div4 ^= packet->version;
|
etherealflaim |
0:7e2eb93442e7
|
62
|
packet->version ^= packet->header_bytes_div4;
|
etherealflaim |
0:7e2eb93442e7
|
63
|
fix_endian_u16(&packet->packet_bytes);
|
etherealflaim |
0:7e2eb93442e7
|
64
|
fix_endian_u16(&packet->fragment_id);
|
etherealflaim |
0:7e2eb93442e7
|
65
|
// Don't fix checksums; they are done bitwise
|
etherealflaim |
0:7e2eb93442e7
|
66
|
}
|
etherealflaim |
0:7e2eb93442e7
|
67
|
|
etherealflaim |
0:7e2eb93442e7
|
68
|
/// Get a constant string of the given IP protocol (e.g. "ICMP", "TCP", "UDP") if known
|
etherealflaim |
0:7e2eb93442e7
|
69
|
inline const char *ipproto2name(u8 proto)
|
etherealflaim |
0:7e2eb93442e7
|
70
|
{
|
etherealflaim |
0:7e2eb93442e7
|
71
|
switch (proto)
|
etherealflaim |
0:7e2eb93442e7
|
72
|
{
|
etherealflaim |
0:7e2eb93442e7
|
73
|
case 0x01: return "ICMP";
|
etherealflaim |
0:7e2eb93442e7
|
74
|
case 0x02: return "IGMP";
|
etherealflaim |
0:7e2eb93442e7
|
75
|
case 0x06: return "TCP";
|
etherealflaim |
0:7e2eb93442e7
|
76
|
case 0x11: return "UDP";
|
etherealflaim |
0:7e2eb93442e7
|
77
|
}
|
etherealflaim |
0:7e2eb93442e7
|
78
|
return "<UNKNOWN>";
|
etherealflaim |
0:7e2eb93442e7
|
79
|
}
|
etherealflaim |
0:7e2eb93442e7
|
80
|
|
etherealflaim |
0:7e2eb93442e7
|
81
|
/// Parse the string (in decimal triple-dot notation) into the IP address structure
|
etherealflaim |
0:7e2eb93442e7
|
82
|
inline void str2ipaddr(const char *ip, IP_Address *addr)
|
etherealflaim |
0:7e2eb93442e7
|
83
|
{
|
etherealflaim |
0:7e2eb93442e7
|
84
|
static short a,b,c,d;
|
etherealflaim |
0:7e2eb93442e7
|
85
|
sscanf(ip, "%3hd.%3hd.%3hd.%3hd", &a, &b, &c, &d);
|
etherealflaim |
0:7e2eb93442e7
|
86
|
addr->octet[0] = a;
|
etherealflaim |
0:7e2eb93442e7
|
87
|
addr->octet[1] = b;
|
etherealflaim |
0:7e2eb93442e7
|
88
|
addr->octet[2] = c;
|
etherealflaim |
0:7e2eb93442e7
|
89
|
addr->octet[3] = d;
|
etherealflaim |
0:7e2eb93442e7
|
90
|
}
|
etherealflaim |
0:7e2eb93442e7
|
91
|
|
etherealflaim |
0:7e2eb93442e7
|
92
|
#endif |