1/* 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 */ 41#define DHCP6_VCI_STRING "U-Boot" 42 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__ */ 257