AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
icmp.c
Go to the documentation of this file.
1
10
11#include <core/system.h>
12#include <core/string.h>
13#include <net/byteorder.h>
14#include <net/inet.h>
15
16#include <aquila/errno.h>
17
20static void icmp_unreachable_input(struct netif *netif, struct icmp_hdr *icmp, size_t len)
21{
22 /* it quotes the datagram's IPv4 header and its first 8 bytes (the UDP
23 * header) */
24 struct ipv4_hdr *ih = (struct ipv4_hdr *) (icmp + 1);
25
26 if (len < sizeof(*icmp) + sizeof(*ih))
27 return;
28
29 size_t hlen = (ih->ver_ihl & 0xf) * 4;
30
31 if (ih->proto != IP_PROTO_UDP || len < sizeof(*icmp) + hlen + sizeof(struct udp_hdr))
32 return;
33
34 struct udp_hdr *uh = (struct udp_hdr *) ((uint8_t *) ih + hlen);
35 struct inet_sock *sock = inet_sock_find(netif, IP_PROTO_UDP, ih->src, uh->src, ih->dst, uh->dst);
36
37 if (sock)
38 inet_sock_error(sock, icmp->code == ICMP_UNREACH_PORT ? ECONNREFUSED : EHOSTUNREACH);
39}
40
50void icmp_input(struct netif *netif, struct netbuf *nb, uint32_t src, uint32_t dst)
51{
52 struct icmp_hdr *icmp = (struct icmp_hdr *) nb->data;
53
54 if (nb->len < sizeof(*icmp) || inet_checksum(nb->data, nb->len)) {
55 netif->stats.rx_errors++;
56 netbuf_free(nb);
57 return;
58 }
59
60 switch (icmp->type) {
62 /* turn the request into the reply, with the same data (only for
63 * a request sent to one of our addresses, not a broadcast) */
64 if (!ipv4_is_local(dst))
65 break;
66
67 icmp->type = ICMP_ECHO_REPLY;
68 icmp->code = 0;
69 icmp->checksum = 0;
70 icmp->checksum = inet_checksum(nb->data, nb->len);
71
72 /* reply from the address it was sent to */
73 ipv4_output(netif, dst, src, IP_PROTO_ICMP, nb);
74 return;
75
76 case ICMP_ECHO_REPLY: {
77 /* deliver it, ICMP header and data, to the ping socket with
78 * that identifier */
79 struct inet_sock *sock = inet_sock_find(netif, IP_PROTO_ICMP, dst, icmp->id, src, 0);
80
81 if (!sock)
82 break;
83
84 nb->src_ip = src;
85 nb->src_port = 0;
86 inet_sock_deliver(sock, nb);
87 return;
88 }
89
90 case ICMP_UNREACH:
92 break;
93 }
94
95 netbuf_free(nb);
96}
97
105void icmp_unreachable(struct netif *netif, const struct ipv4_hdr *ih, int code)
106{
107 struct netbuf *nb = netbuf_alloc();
108
109 if (!nb)
110 return;
111
112 /* quote the header, and the first 8 bytes after it */
113 size_t quote = (ih->ver_ihl & 0xf) * 4 + 8;
114
115 if (quote > ntohs(ih->len))
116 quote = ntohs(ih->len);
117
118 struct icmp_hdr *icmp = netbuf_put(nb, sizeof(*icmp) + quote);
119
120 icmp->type = ICMP_UNREACH;
121 icmp->code = code;
122 icmp->checksum = 0;
123 icmp->id = 0;
124 icmp->seq = 0;
125 memcpy(icmp + 1, ih, quote);
126 icmp->checksum = inet_checksum(icmp, sizeof(*icmp) + quote);
127
128 ipv4_output(netif, 0, ih->src, IP_PROTO_ICMP, nb);
129}
#define ntohs(x)
Definition byteorder.h:17
static void icmp_unreachable_input(struct netif *netif, struct icmp_hdr *icmp, size_t len)
Handles a "destination unreachable" about a datagram we sent: the UDP socket that sent it gets the er...
Definition icmp.c:20
uint16_t inet_checksum(const void *data, size_t len)
Computes the Internet checksum (RFC 1071): the ones' complement of the ones' complement sum of the da...
Definition ether.c:76
struct inet_sock * inet_sock_find(struct netif *netif, uint8_t proto, uint32_t local, uint16_t port, uint32_t remote, uint16_t remote_port)
Finds the socket that a received datagram is for: a socket connected to its sender first,...
Definition socket.c:154
void icmp_input(struct netif *netif, struct netbuf *nb, uint32_t src, uint32_t dst)
Takes in an ICMP message that IPv4 received.
Definition icmp.c:50
#define ICMP_ECHO_REPLY
Definition inet.h:60
#define ICMP_ECHO_REQUEST
Definition inet.h:62
#define IP_PROTO_UDP
Definition inet.h:43
int ipv4_is_local(uint32_t ip)
Says whether an address is one of ours: a loopback address, or an interface's.
Definition ipv4.c:48
void icmp_unreachable(struct netif *netif, const struct ipv4_hdr *ih, int code)
Tells the sender of a datagram that it couldn't get where it was sent.
Definition icmp.c:105
void inet_sock_error(struct inet_sock *sock, int err)
Gives a socket an error (from ICMP), which its next call reports.
Definition socket.c:211
#define IP_PROTO_ICMP
Definition inet.h:41
int ipv4_output(struct netif *netif, uint32_t src, uint32_t dst, uint8_t proto, struct netbuf *nb)
Sends a packet through an interface: adds its IPv4 header and sends it to dst, or to the gateway if d...
Definition ipv4.c:190
void inet_sock_deliver(struct inet_sock *sock, struct netbuf *nb)
Queues a received datagram on its socket, and wakes up its readers.
Definition socket.c:185
#define ICMP_UNREACH
Definition inet.h:61
#define ICMP_UNREACH_PORT
Definition inet.h:65
void * memcpy(void *dst, const void *src, size_t n)
Copies n bytes; dst and src must not overlap.
Definition libc.c:11
void netbuf_free(struct netbuf *nb)
Frees a netbuf.
Definition netbuf.c:99
struct netbuf * netbuf_alloc(void)
Allocates a netbuf, empty, with room for the headers that will be put in front of its data.
Definition netbuf.c:58
unsigned int uint32_t
Definition stddef.h:22
unsigned char uint8_t
Definition stddef.h:20
An ICMP message's header.
Definition inet.h:68
uint16_t seq
Definition inet.h:73
uint8_t type
Definition inet.h:69
uint16_t id
Definition inet.h:72
uint8_t code
Definition inet.h:70
uint16_t checksum
Definition inet.h:71
A UDP or ping socket.
Definition socket.c:45
An IPv4 packet's header.
Definition inet.h:46
uint16_t len
Definition inet.h:49
uint32_t dst
Definition inet.h:56
uint8_t ver_ihl
Definition inet.h:47
uint8_t proto
Definition inet.h:53
uint32_t src
Definition inet.h:55
A packet (net/netbuf.c).
Definition netbuf.h:16
uint32_t src_ip
Definition netbuf.h:25
uint8_t * data
Definition netbuf.h:19
uint16_t src_port
Definition netbuf.h:26
size_t len
Definition netbuf.h:20
A network interface (net/netif.c): a device that sends and receives Ethernet frames,...
Definition netif.h:16
struct netif::@020302303320120142126121344055047003105154122231 stats
A UDP datagram's header.
Definition inet.h:77
uint16_t src
Definition inet.h:78
uint16_t dst
Definition inet.h:79