blob: 65c8e4c71d35e2da4fef9bc79d89b6b418251d53 [file] [log] [blame]
Sean Edmonda0245812023-04-11 10:48:46 -07001/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) Microsoft Corporation
4 * Author: Sean Edmond <seanedmond@microsoft.com>
5 *
6 */
7
8#ifndef __DHCP6_H__
9#define __DHCP6_H__
10
11/* Message types */
12#define DHCP6_MSG_SOLICIT 1
13#define DHCP6_MSG_ADVERTISE 2
14#define DHCP6_MSG_REQUEST 3
15#define DHCP6_MSG_REPLY 7
16
17/* Option Codes */
18#define DHCP6_OPTION_CLIENTID 1
19#define DHCP6_OPTION_SERVERID 2
20#define DHCP6_OPTION_IA_NA 3
21#define DHCP6_OPTION_IA_TA 4
22#define DHCP6_OPTION_IAADDR 5
23#define DHCP6_OPTION_ORO 6
24#define DHCP6_OPTION_PREFERENCE 7
25#define DHCP6_OPTION_ELAPSED_TIME 8
26#define DHCP6_OPTION_STATUS_CODE 13
27#define DHCP6_OPTION_OPT_BOOTFILE_URL 59
28#define DHCP6_OPTION_OPT_BOOTFILE_PARAM 60
29#define DHCP6_OPTION_SOL_MAX_RT 82
30#define DHCP6_OPTION_CLIENT_ARCH_TYPE 61
31#define DHCP6_OPTION_VENDOR_CLASS 16
32#define DHCP6_OPTION_NII 62
33
34/* DUID */
35#define DUID_TYPE_LL 3
36#define DUID_HW_TYPE_ENET 1
37#define DUID_LL_SIZE (sizeof(struct dhcp6_option_duid_ll) + ETH_ALEN)
38#define DUID_MAX_SIZE DUID_LL_SIZE /* only supports DUID-LL currently */
39
40/* vendor-class-data to send in vendor clas option */
Sean Edmond2f7c7152023-05-18 12:35:41 -070041#define DHCP6_VCI_STRING "U-Boot"
Sean Edmonda0245812023-04-11 10:48:46 -070042
43#define DHCP6_MULTICAST_ADDR "ff02::1:2" /* DHCP multicast address */
44
45/* DHCP6 States supported */
46enum dhcp6_state {
47 DHCP6_INIT,
48 DHCP6_SOLICIT,
49 DHCP6_REQUEST,
50 DHCP6_DONE,
51 DHCP6_FAIL,
52};
53
54/* DHCP6 Status codes */
55enum dhcp6_status {
56 DHCP6_SUCCESS = 0,
57 DHCP6_UNSPEC_FAIL = 1,
58 DHCP6_NO_ADDRS_AVAIL = 2,
59 DHCP6_NO_BINDING = 3,
60 DHCP6_NOT_ON_LINK = 4,
61 DHCP6_USE_MULTICAST = 5,
62 DHCP6_NO_PREFIX_AVAIL = 6,
63};
64
65/* DHCP6 message header format */
66struct dhcp6_hdr {
67 unsigned int msg_type : 8; /* message type */
68 unsigned int trans_id : 24; /* transaction ID */
69} __packed;
70
71/* DHCP6 option header format */
72struct dhcp6_option_hdr {
73 __be16 option_id; /* option id */
74 __be16 option_len; /* Option length */
75 u8 option_data[0]; /* Option data */
76} __packed;
77
78/* DHCP6_OPTION_CLIENTID option (DUID-LL) */
79struct dhcp6_option_duid_ll {
80 __be16 duid_type;
81 __be16 hw_type;
82 u8 ll_addr[0];
83} __packed;
84
85/* DHCP6_OPTION_ELAPSED_TIME option */
86struct dhcp6_option_elapsed_time {
87 __be16 elapsed_time;
88} __packed;
89
90/* DHCP6_OPTION_IA_TA option */
91struct dhcp6_option_ia_ta {
92 __be32 iaid;
93 u8 ia_ta_options[0];
94} __packed;
95
96/* DHCP6_OPTION_IA_NA option */
97struct dhcp6_option_ia_na {
98 __be32 iaid;
99 __be32 t1;
100 __be32 t2;
101 u8 ia_na_options[0];
102} __packed;
103
104/* OPTION_ORO option */
105struct dhcp6_option_oro {
106 __be16 req_option_code[0];
107} __packed;
108
109/* DHCP6_OPTION_CLIENT_ARCH_TYPE option */
110struct dhcp6_option_client_arch {
111 __be16 arch_type[0];
112} __packed;
113
114/* vendor-class-data inside OPTION_VENDOR_CLASS option */
115struct vendor_class_data {
116 __be16 vendor_class_len;
117 u8 opaque_data[0];
118} __packed;
119
120/* DHCP6_OPTION_VENDOR_CLASS option */
121struct dhcp6_option_vendor_class {
122 __be32 enterprise_number;
123 struct vendor_class_data vendor_class_data[0];
124} __packed;
125
126/**
127 * struct dhcp6_rx_pkt_status - Structure that holds status
128 * from a received message
129 * @client_id_match: Client ID was found and matches DUID sent
130 * @server_id_found: Server ID was found in the message
131 * @server_uid_ptr: Pointer to received server ID
132 * @server_uid_size: Size of received server ID
133 * @ia_addr_found: IA addr option was found in received message
134 * @ia_addr_ipv6: The IPv6 address received in IA
135 * @ia_status_code: Status code received in the IA
136 * @status_code: Top-level status code received
137 * @preference: Preference code received
138 */
139struct dhcp6_rx_pkt_status {
140 bool client_id_match;
141 bool server_id_found;
142 uchar *server_uid_ptr;
143 u16 server_uid_size;
144 bool ia_addr_found;
145 struct in6_addr ia_addr_ipv6;
146 enum dhcp6_status ia_status_code;
147 enum dhcp6_status status_code;
148 u8 preference;
149};
150
151/**
152 * struct dhcp6_server_uid - Structure that holds the server UID
153 * received from an ADVERTISE and saved
154 * given the server selection criteria.
155 * @uid_ptr: Dynamically allocated and copied server UID
156 * @uid_size: Size of the server UID in uid_ptr (in bytes)
157 * @preference: Preference code associated with this server UID
158 */
159struct dhcp6_server_uid {
160 uchar *uid_ptr;
161 u16 uid_size;
162 u8 preference;
163};
164
165/**
166 * struct dhcp6_sm_params - Structure that holds DHCP6
167 * state machine parameters
168 * @curr_state: current DHCP6 state
169 * @next_state: next DHCP6 state
170 * @dhcp6_start_ms: timestamp DHCP6 start
171 * @dhcp6_retry_start_ms: timestamp of current TX message start
172 * @dhcp6_retry_ms: timestamp of last retransmission
173 * @retry_cnt: retry count
174 * @trans_id: transaction ID
175 * @ia_id: transmitted IA ID
176 * @irt_ms: Initial retransmission time (in ms)
177 * @mrt_ms: Maximum retransmission time (in ms)
178 * @mrc: Maximum retransmission count
179 * @mrd_ms: Maximum retransmission duration (in ms)
180 * @rt_ms: retransmission timeout (is ms)
181 * @rt_prev_ms: previous retransmission timeout
182 * @rx_status: Status from received message
183 * @server_uid: Saved Server UID for selected server
184 * @duid: pointer to transmitted Client DUID
185 */
186struct dhcp6_sm_params {
187 enum dhcp6_state curr_state;
188 enum dhcp6_state next_state;
189 ulong dhcp6_start_ms;
190 ulong dhcp6_retry_start_ms;
191 ulong dhcp6_retry_ms;
192 u32 retry_cnt;
193 u32 trans_id;
194 u32 ia_id;
195 int irt_ms;
196 int mrt_ms;
197 int mrc;
198 int mrd_ms;
199 int rt_ms;
200 int rt_prev_ms;
201 struct dhcp6_rx_pkt_status rx_status;
202 struct dhcp6_server_uid server_uid;
203 char duid[DUID_MAX_SIZE];
204};
205
206/* Starts a DHCPv6 4-message exchange as a DHCPv6 client. On successful exchange,
207 * the DHCPv6 state machine will transition from internal states:
208 * DHCP6_INIT->DHCP6_SOLICIT->DHCP6_REQUEST->DHCP6_DONE
209 *
210 * Transmitted SOLICIT and REQUEST packets will set/request the minimum required
211 * DHCPv6 options to PXE boot.
212 *
213 * After a successful exchange, the DHCPv6 assigned address will be set in net_ip6
214 *
215 * Additionally, the following will be set after receiving these options:
216 * DHCP6_OPTION_OPT_BOOTFILE_URL (option 59) -> net_server_ip6, net_boot_file_name
217 * DHCP6_OPTION_OPT_BOOTFILE_PARAM (option 60) - > pxelinux_configfile
218 *
219 * Illustration of a 4-message exchange with 2 servers (copied from
220 * https://www.rfc-editor.org/rfc/rfc8415):
221 *
222 * Server Server
223 * (not selected) Client (selected)
224 *
225 * v v v
226 * | | |
227 * | Begins initialization |
228 * | | |
229 * start of | _____________/|\_____________ |
230 * 4-message |/ Solicit | Solicit \|
231 * exchange | | |
232 * Determines | Determines
233 * configuration | configuration
234 * | | |
235 * |\ | ____________/|
236 * | \________ | /Advertise |
237 * | Advertise\ |/ |
238 * | \ | |
239 * | Collects Advertises |
240 * | \ | |
241 * | Selects configuration |
242 * | | |
243 * | _____________/|\_____________ |
244 * |/ Request | Request \|
245 * | | |
246 * | | Commits configuration
247 * | | |
248 * end of | | _____________/|
249 * 4-message | |/ Reply |
250 * exchange | | |
251 * | Initialization complete |
252 * | | |
253 */
254void dhcp6_start(void);
255
256#endif /* __DHCP6_H__ */