1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #pragma once
6
7 #include <endian.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11
12 #include <zircon/types.h>
13
14 typedef struct mac_addr mac_addr_t;
15 typedef union ip6_addr ip6_addr_t;
16 typedef struct ip6_hdr ip6_hdr_t;
17 typedef struct udp_hdr udp_hdr_t;
18 typedef struct icmp6_hdr icmp6_hdr_t;
19 typedef struct ndp_n_hdr ndp_n_hdr_t;
20
21 #define ETH_ADDR_LEN 6
22 #define ETH_HDR_LEN 14
23 #define ETH_MTU 1514
24
25 #define IP6_ADDR_LEN 16
26 #define IP6_U32_LEN 4
27 #define IP6_U64_LEN 2
28
29 #define IP6_HDR_LEN 40
30
31 #define IP6_MIN_MTU 1280
32
33 #define UDP_HDR_LEN 8
34
35 struct mac_addr {
36 uint8_t x[ETH_ADDR_LEN];
37 } __attribute__((packed));
38
39 union ip6_addr {
40 uint8_t u8[IP6_ADDR_LEN];
41 uint32_t u32[IP6_U32_LEN];
42 uint64_t u64[IP6_U64_LEN];
43 } __attribute__((packed));
44
45 extern const ip6_addr_t ip6_ll_all_nodes;
46 extern const ip6_addr_t ip6_ll_all_routers;
47
ip6_addr_eq(const ip6_addr_t * a,const ip6_addr_t * b)48 static inline bool ip6_addr_eq(const ip6_addr_t* a, const ip6_addr_t* b) {
49 return ((a->u64[0] == b->u64[0]) && (a->u64[1] == b->u64[1]));
50 }
51
52 #define ETH_IP4 0x0800
53 #define ETH_ARP 0x0806
54 #define ETH_IP6 0x86DD
55
56 #define HDR_HNH_OPT 0
57 #define HDR_TCP 6
58 #define HDR_UDP 17
59 #define HDR_ROUTING 43
60 #define HDR_FRAGMENT 44
61 #define HDR_ICMP6 58
62 #define HDR_NONE 59
63 #define HDR_DST_OPT 60
64
65 struct ip6_hdr {
66 uint32_t ver_tc_flow;
67 uint16_t length;
68 uint8_t next_header;
69 uint8_t hop_limit;
70 ip6_addr_t src;
71 ip6_addr_t dst;
72 } __attribute__((packed));
73
74 struct udp_hdr {
75 uint16_t src_port;
76 uint16_t dst_port;
77 uint16_t length;
78 uint16_t checksum;
79 } __attribute__((packed));
80
81 #define ICMP6_DEST_UNREACHABLE 1
82 #define ICMP6_PACKET_TOO_BIG 2
83 #define ICMP6_TIME_EXCEEDED 3
84 #define ICMP6_PARAMETER_PROBLEM 4
85
86 #define ICMP6_ECHO_REQUEST 128
87 #define ICMP6_ECHO_REPLY 129
88
89 #define ICMP6_NDP_N_SOLICIT 135
90 #define ICMP6_NDP_N_ADVERTISE 136
91
92 struct icmp6_hdr {
93 uint8_t type;
94 uint8_t code;
95 uint16_t checksum;
96 } __attribute__((packed));
97
98 struct ndp_n_hdr {
99 uint8_t type;
100 uint8_t code;
101 uint16_t checksum;
102 uint32_t flags;
103 uint8_t target[IP6_ADDR_LEN];
104 uint8_t options[0];
105 } __attribute__((packed));
106
107 #define NDP_N_SRC_LL_ADDR 1
108 #define NDP_N_TGT_LL_ADDR 2
109 #define NDP_N_PREFIX_INFO 3
110 #define NDP_N_REDIRECTED_HDR 4
111 #define NDP_N_MTU 5
112
113 #ifndef ntohs
114 #define ntohs(n) be16toh(n)
115 #define htons(n) htobe16(n)
116 #endif
117
118 #ifndef ntohl
119 #define ntohl(n) be32toh(n)
120 #define htonl(n) htobe32(n)
121 #endif
122
123 // Formats an IP6 address into the provided buffer (which must be
124 // at least IP6TOAMAX bytes in size), and returns the buffer address.
125 char* ip6toa(char* _out, void* ip6addr);
126 #define IP6TOAMAX 40
127
128 // provided by inet6.c
129 void ip6_init(void* macaddr);
130 void eth_recv(void* data, size_t len);
131
132 typedef struct eth_buffer eth_buffer_t;
133
134 // provided by interface driver
135 zx_status_t eth_get_buffer(size_t len, void** data, eth_buffer_t** out,
136 bool block);
137 void eth_put_buffer(eth_buffer_t* ethbuf);
138
139 zx_status_t eth_send(eth_buffer_t* ethbuf, size_t skip, size_t len);
140
141 int eth_add_mcast_filter(const mac_addr_t* addr);
142
143 // call to transmit a UDP packet
144 zx_status_t udp6_send(const void* data, size_t len,
145 const ip6_addr_t* daddr, uint16_t dport,
146 uint16_t sport, bool block);
147
148 // implement to recive UDP packets
149 void udp6_recv(void* data, size_t len,
150 const ip6_addr_t* daddr, uint16_t dport,
151 const ip6_addr_t* saddr, uint16_t sport);
152
153 unsigned ip6_checksum(ip6_hdr_t* ip, unsigned type, size_t length);
154
155 // NOTES
156 //
157 // This is an extremely minimal IPv6 stack, supporting just enough
158 // functionality to talk to link local hosts over UDP.
159 //
160 // It responds to ICMPv6 Neighbor Solicitations for its link local
161 // address, which is computed from the mac address provided by the
162 // ethernet interface driver.
163 //
164 // It responds to PINGs.
165 //
166 // It can only transmit to multicast addresses or to the address it
167 // last received a packet from (general usecase is to reply to a UDP
168 // packet from the UDP callback, which this supports)
169 //
170 // It does not currently do duplicate address detection, which is
171 // probably the most severe bug.
172 //
173 // It does not support any IPv6 options and will drop packets with
174 // options.
175 //
176 // It expects the network stack to provide transmit buffer allocation
177 // and free functionality. It will allocate a single transmit buffer
178 // from udp6_send() or icmp6_send() to fill out and either pass to the
179 // network stack via eth_send() or, in the event of an error, release
180 // via eth_put_buffer().
181 //
182