Skip to content

Commit bf51704

Browse files
Many networking tweaks
- Simple path MTU - ICMP error handling - DNS cname chasing - DNS buffer strengthening - IP protocol registration system - ICMP port unreachable replies - ICMP rate limiting for unreachables
1 parent c1d849b commit bf51704

14 files changed

Lines changed: 588 additions & 129 deletions

File tree

include/dns.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ enum query_type_t {
4646
DNS_QUERY_PTR6 = 0xFFFE
4747
};
4848

49+
#define DNS_HEADER_SIZE 12
50+
51+
#define DNS_RR_FIXED_SIZE 10
52+
53+
#define DNS_RESULT_MAX 1023
54+
4955
/** Represents a dns request/reply header, and its payload as opaque data.
5056
*/
5157
typedef struct dns_header {

include/ethernet.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,25 @@ typedef void (*ethernet_protocol_t)(void*, int);
1616
#define HARDWARE_TYPE_ETHERNET 0x01
1717

1818
/**
19-
* @brief There is actually more to an ethernet frame than this
20-
* (see the STD documents!) but we don't have access to it from the
21-
* software.
19+
* @brief Ethernet II frame header visible to the network stack
20+
*
21+
* Real Ethernet frames also contain a preamble, start frame delimiter,
22+
* frame check sequence and inter-frame gap. Those fields are handled by
23+
* the NIC/MAC layer and are not normally present in the packet buffer
24+
* delivered to software.
2225
*/
2326
typedef struct ethernet_frame {
24-
uint8_t dst_mac_addr[6]; // Destination MAC address
25-
uint8_t src_mac_addr[6]; // Source MAC address
26-
uint16_t type; // Packet type
27-
uint8_t data[]; // Raw data
27+
/** Destination MAC address */
28+
uint8_t dst_mac_addr[6];
29+
30+
/** Source MAC address */
31+
uint8_t src_mac_addr[6];
32+
33+
/** EtherType field */
34+
uint16_t type;
35+
36+
/** Ethernet payload */
37+
uint8_t data[];
2838
} __attribute__((packed)) ethernet_frame_t;
2939

3040
/**
@@ -36,15 +46,15 @@ typedef struct ethernet_frame {
3646
* @param protocol protocol type
3747
* @return int nonzero on successful queue of packet
3848
*/
39-
int ethernet_send_packet(uint8_t* dst_mac_addr, uint8_t* data, uint32_t len, uint16_t protocol);
49+
int ethernet_send_packet(const uint8_t* dst_mac_addr, const uint8_t* data, size_t len, uint16_t protocol);
4050

4151
/**
4252
* @brief Handle inbound packet via interrupt from network card driver
4353
*
4454
* @param packet raw packet data
4555
* @param len packet data length
4656
*/
47-
void ethernet_handle_packet(ethernet_frame_t * packet, int len);
57+
void ethernet_handle_packet(ethernet_frame_t * packet, size_t len);
4858

4959
/**
5060
* @brief Register a protocol with the ethernet layer

include/icmp.h

Lines changed: 200 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,111 +7,305 @@
77

88
#include "kernel.h"
99

10+
/**
11+
* @brief ICMP packet types
12+
*/
1013
enum icmp_type_t {
14+
/** Echo reply */
1115
ICMP_ECHO_REPLY = 0,
16+
17+
/** Destination unreachable */
1218
ICMP_DESTINATION_UNREACHABLE = 3,
19+
20+
/** Source quench, deprecated */
1321
ICMP_SOURCE_QUENCH = 4,
22+
23+
/** Redirect */
1424
ICMP_REDIRECT = 5,
25+
26+
/** Echo request */
1527
ICMP_ECHO = 8,
28+
29+
/** Time exceeded */
1630
ICMP_TIME_EXCEEDED = 11,
31+
32+
/** Parameter problem */
1733
ICMP_PARAMETER_PROBLEM = 12,
34+
35+
/** Timestamp request */
1836
ICMP_TIMESTAMP = 13,
37+
38+
/** Timestamp reply */
1939
ICMP_TIMESTAMP_REPLY = 14,
40+
41+
/** Information request */
2042
ICMP_INFORMATION_REQUEST = 15,
43+
44+
/** Information reply */
2145
ICMP_INFORMATION_REPLY = 16,
2246
};
2347

48+
/**
49+
* @brief ICMP destination unreachable reason codes
50+
*/
2451
enum icmp_unreachable_code_t {
52+
/** Destination network is unreachable */
2553
ICMP_NET_UNREACHABLE = 0,
54+
55+
/** Destination host is unreachable */
2656
ICMP_HOST_UNREACHABLE = 1,
57+
58+
/** Destination protocol is unreachable */
2759
ICMP_PROTOCOL_UNREACHABLE = 2,
60+
61+
/** Destination port is unreachable */
2862
ICMP_PORT_UNREACHABLE = 3,
63+
64+
/** Fragmentation is required but the IPv4 DF bit was set */
2965
ICMP_FRAGMENTATION_NEEDED = 4,
66+
67+
/** Source route failed */
3068
ICMP_SOURCE_ROUTE_FAILED = 5,
3169
};
3270

71+
/**
72+
* @brief ICMP time exceeded reason codes
73+
*/
3374
enum icmp_time_exceeded_code_t {
75+
/** Packet TTL expired in transit */
3476
ICMP_TTL_EXCEEDED = 0,
77+
78+
/** Fragment reassembly timeout expired */
3579
ICMP_FRAGMENT_REASSEMBLY_TIME_EXCEEDED = 1,
3680
};
3781

82+
/**
83+
* @brief ICMP redirect reason codes
84+
*/
3885
enum icmp_redirect_code_t {
86+
/** Redirect traffic for a network */
3987
ICMP_REDIRECT_NETWORK = 0,
88+
89+
/** Redirect traffic for a host */
4090
ICMP_REDIRECT_HOST = 1,
91+
92+
/** Redirect traffic for a TOS/network combination */
4193
ICMP_REDIRECT_TOS_NETWORK = 2,
94+
95+
/** Redirect traffic for a TOS/host combination */
4296
ICMP_REDIRECT_TOS_HOST = 3,
4397
};
4498

99+
/**
100+
* @brief Generic ICMP packet carrying a quoted IPv4 datagram
101+
*
102+
* Used for destination unreachable and time exceeded messages. For
103+
* fragmentation-needed messages, unused carries the next-hop MTU in network
104+
* byte order.
105+
*/
45106
typedef struct icmp_packet {
107+
/** ICMP packet type */
46108
uint8_t type;
109+
110+
/** ICMP type-specific code */
47111
uint8_t code;
112+
113+
/** Internet checksum of the ICMP packet */
48114
uint16_t checksum;
115+
116+
/** Type-specific auxiliary field */
49117
uint32_t unused;
118+
119+
/** Quoted IPv4 datagram that triggered the ICMP message */
50120
ip_packet_t original_datagram;
51121
} __attribute__((packed)) icmp_packet_t;
52122

123+
/**
124+
* @brief ICMP redirect packet
125+
*/
53126
typedef struct icmp_redirect_packet {
127+
/** ICMP packet type */
54128
uint8_t type;
129+
130+
/** ICMP redirect reason code */
55131
uint8_t code;
132+
133+
/** Internet checksum of the ICMP packet */
56134
uint16_t checksum;
135+
136+
/** Replacement gateway IPv4 address */
57137
uint32_t gateway;
138+
139+
/** Quoted IPv4 datagram that triggered the redirect */
58140
ip_packet_t original_datagram;
59141
} __attribute__((packed)) icmp_redirect_packet_t;
60142

143+
/**
144+
* @brief ICMP information request/reply packet
145+
*/
61146
typedef struct icmp_information {
147+
/** ICMP packet type */
62148
uint8_t type;
149+
150+
/** ICMP type-specific code */
63151
uint8_t code;
152+
153+
/** Internet checksum of the ICMP packet */
64154
uint16_t checksum;
155+
156+
/** Request identifier */
65157
uint16_t id;
158+
159+
/** Request sequence number */
66160
uint16_t seq;
67161
} __attribute__((packed)) icmp_information_t;
68162

163+
/**
164+
* @brief ICMP parameter problem packet
165+
*/
69166
typedef struct icmp_parameter_problem_packet {
167+
/** ICMP packet type */
70168
uint8_t type;
169+
170+
/** ICMP parameter problem code */
71171
uint8_t code;
172+
173+
/** Internet checksum of the ICMP packet */
72174
uint16_t checksum;
175+
176+
/** Offset of invalid byte within the IPv4 header */
73177
uint8_t problem_ptr;
178+
179+
/** Reserved field */
74180
uint16_t unused1;
181+
182+
/** Reserved field */
75183
uint16_t unused2;
184+
185+
/** Quoted IPv4 datagram containing the invalid header */
76186
ip_packet_t original_datagram;
77187
} __attribute__((packed)) icmp_parameter_problem_packet_t;
78188

189+
/**
190+
* @brief ICMP echo request/reply packet
191+
*/
79192
typedef struct icmp_echo_packet {
193+
/** ICMP packet type */
80194
uint8_t type;
195+
196+
/** ICMP type-specific code */
81197
uint8_t code;
198+
199+
/** Internet checksum of the ICMP packet */
82200
uint16_t checksum;
201+
202+
/** Echo identifier */
83203
uint16_t id;
204+
205+
/** Echo sequence number */
84206
uint16_t seq;
85207
} __attribute__((packed)) icmp_echo_packet_t;
86208

209+
/**
210+
* @brief ICMP timestamp request/reply packet
211+
*/
87212
typedef struct icmp_timestamp_packet {
213+
/** ICMP packet type */
88214
uint8_t type;
215+
216+
/** ICMP type-specific code */
89217
uint8_t code;
218+
219+
/** Internet checksum of the ICMP packet */
90220
uint16_t checksum;
221+
222+
/** Request identifier */
91223
uint16_t id;
224+
225+
/** Request sequence number */
92226
uint16_t seq;
227+
228+
/** Sender originate timestamp */
93229
uint32_t originate_timestamp;
230+
231+
/** Receiver receive timestamp */
94232
uint32_t receive_timestamp;
233+
234+
/** Sender transmit timestamp */
95235
uint32_t transmit_timestamp;
96236
} __attribute__((packed)) icmp_timestamp_packet_t;
97237

98238
/**
99-
* @brief Handle ICMP packet from the IP driver
100-
*
101-
* @param ip Encapsulating IP packet
102-
* @param packet raw ICMP packet
103-
* @param length ICMP packet length
239+
* @brief Callback for protocol handlers interested in ICMP unreachable messages
240+
*
241+
* The quoted IPv4 datagram identifies the protocol endpoint that triggered the
242+
* ICMP error. The MTU value is only meaningful for ICMP_FRAGMENTATION_NEEDED.
243+
*
244+
* @param quoted_ip Quoted IPv4 datagram from the ICMP payload
245+
* @param code ICMP unreachable reason code
246+
* @param mtu Path MTU for ICMP_FRAGMENTATION_NEEDED, otherwise zero
247+
*/
248+
typedef void (*icmp_unreachable_handler_t)(ip_packet_t*, uint8_t, uint16_t);
249+
250+
/**
251+
* @brief Register a handler for ICMP unreachable notifications
252+
*
253+
* @param protocol IP protocol number to register for
254+
* @param handler Callback function
104255
*/
105-
void icmp_handle_packet([[maybe_unused]] ip_packet_t* encap_packet, icmp_packet_t* packet, size_t len);
256+
void icmp_register_unreachable_handler(uint8_t protocol, icmp_unreachable_handler_t handler);
106257

258+
/**
259+
* @brief Send an ICMP echo request
260+
*
261+
* @param destination Destination IPv4 address
262+
* @param id Echo identifier
263+
* @param seq Echo sequence number
264+
*/
107265
void icmp_send_echo(uint8_t* destination, uint16_t id, uint16_t seq);
108266

267+
/**
268+
* @brief Send an ICMP time exceeded packet
269+
*
270+
* @param original_ip Original IPv4 packet that triggered the error
271+
* @param code ICMP time exceeded reason code
272+
*/
109273
void icmp_send_time_exceeded(ip_packet_t* original_ip, uint8_t code);
110274

275+
/**
276+
* @brief Send an ICMP destination unreachable packet
277+
*
278+
* @param original_ip Original IPv4 packet that triggered the error
279+
* @param code ICMP unreachable reason code
280+
*/
111281
void icmp_send_destination_unreachable(ip_packet_t* original_ip, uint8_t code);
112282

283+
/**
284+
* @brief Send an ICMP parameter problem packet
285+
*
286+
* @param original_ip Original IPv4 packet that triggered the error
287+
* @param pointer_offset Offset of invalid byte within the IPv4 header
288+
*/
113289
void icmp_send_parameter_problem(ip_packet_t* original_ip, uint8_t pointer_offset);
114290

291+
/**
292+
* @brief Send an ICMP redirect packet
293+
*
294+
* @param original_ip Original IPv4 packet that triggered the redirect
295+
* @param code ICMP redirect reason code
296+
* @param new_gateway_ip Replacement gateway IPv4 address
297+
*/
115298
void icmp_send_redirect(ip_packet_t* original_ip, uint8_t code, uint32_t new_gateway_ip);
116299

300+
/**
301+
* @brief Send an ICMP fragmentation needed packet
302+
*
303+
* @param original_ip Original IPv4 packet that could not be forwarded
304+
* @param mtu Path MTU required for successful forwarding
305+
*/
117306
void icmp_send_fragmentation_needed(ip_packet_t* original_ip, uint16_t mtu);
307+
308+
/**
309+
* @brief Initialise the ICMP subsystem
310+
*/
311+
void icmp_init();

include/ip.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@ typedef struct packet_queue_item {
102102
struct packet_queue_item* next;
103103
} packet_queue_item_t;
104104

105+
typedef void (*ip_protocol_handler_t)(ip_packet_t*, void*, size_t);
106+
107+
typedef enum {
108+
IP_ERROR_PROTOCOL_UNREACHABLE,
109+
} ip_error_t;
110+
111+
typedef void (*ip_error_handler_t)(ip_packet_t *packet, ip_error_t error);
112+
113+
bool ip_register_protocol(uint8_t protocol_number, ip_protocol_handler_t handler);
114+
115+
bool ip_unregister_protocol(uint8_t protocol_number);
116+
117+
void ip_register_error_handler(ip_error_handler_t handler);
118+
105119
/**
106120
* @brief Convert network byte order IP to a string form for display
107121
*

0 commit comments

Comments
 (0)