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