1 /* vi: set sw=4 ts=4: */ 2 /* 3 * Russ Dill <Russ.Dill@asu.edu> September 2001 4 * Rewritten by Vladimir Oleynik <dzo@simtreas.ru> (C) 2003 5 * 6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 */ 8 #ifndef UDHCP_COMMON_H 9 #define UDHCP_COMMON_H 1 10 11 #include "libbb.h" 12 #include "common_bufsiz.h" 13 #include <netinet/udp.h> 14 #include <netinet/ip.h> 15 16 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 17 18 extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */ 19 20 21 /*** DHCP packet ***/ 22 23 /* DHCP protocol. See RFC 2131 */ 24 #define DHCP_MAGIC 0x63825363 25 #define DHCP_OPTIONS_BUFSIZE 308 26 #define BOOTREQUEST 1 27 #define BOOTREPLY 2 28 29 //TODO: rename ciaddr/yiaddr/chaddr 30 struct dhcp_packet { 31 uint8_t op; /* BOOTREQUEST or BOOTREPLY */ 32 uint8_t htype; /* hardware address type. 1 = 10mb ethernet */ 33 uint8_t hlen; /* hardware address length */ 34 uint8_t hops; /* used by relay agents only */ 35 uint32_t xid; /* unique id */ 36 uint16_t secs; /* elapsed since client began acquisition/renewal */ 37 uint16_t flags; /* only one flag so far: */ 38 #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ 39 uint32_t ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ 40 uint32_t yiaddr; /* 'your' (client) IP address */ 41 /* IP address of "next server" (usually meant to be an TFTP server) 42 * to use in bootstrap, returned in DHCPOFFER, DHCPACK by server: */ 43 uint32_t siaddr_nip; 44 /* RFC 951 (BOOTP): "place my (server) IP address in the 'siaddr' field" 45 * (IOW: unconditionally, not just if we are also a TFTP server). 46 * DHCP servers don't have to do this, they add SERVER_ID option 47 * to their reply packets to let client identify lease-giving server. 48 */ 49 uint32_t gateway_nip; /* aka 'giaddr': relay agent IP address, else 0 */ 50 uint8_t chaddr[16]; /* link-layer client hardware address (MAC) */ 51 uint8_t sname[64]; /* server host name (ASCIZ) */ 52 /* RFC 951 (BOOTP): "If the client wishes to restrict booting 53 * to a particular server name, it may place [it] in 'sname'" 54 */ 55 uint8_t file[128]; /* boot file name (ASCIZ) */ 56 /* RFC 951 (BOOTP): in client requests, "...can be a 'generic' name 57 * such as 'unix' or 'gateway'; this means 'boot the named program 58 * configured for my machine'" 59 */ 60 /* BOOTP fields end here, BOOTP says optional uint8_t vend[64] follows */ 61 uint32_t cookie; /* DHCP magic bytes: 99,130,83,99 decimal */ 62 uint8_t options[DHCP_OPTIONS_BUFSIZE + CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS]; 63 }; 64 #define DHCP_PKT_SNAME_LEN 64 65 #define DHCP_PKT_FILE_LEN 128 66 #define DHCP_PKT_SNAME_LEN_STR "64" 67 #define DHCP_PKT_FILE_LEN_STR "128" 68 69 struct ip_udp_dhcp_packet { 70 struct iphdr ip; 71 struct udphdr udp; 72 struct dhcp_packet data; 73 }; 74 75 struct udp_dhcp_packet { 76 struct udphdr udp; 77 struct dhcp_packet data; 78 }; 79 80 enum { 81 IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 82 UDP_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 83 DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 84 }; 85 86 /* Let's see whether compiler understood us right */ 87 struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { 88 char c[IP_UDP_DHCP_SIZE == 576 ? 1 : -1]; 89 }; 90 91 92 /*** Options ***/ 93 94 enum { 95 OPTION_IP = 0, 96 OPTION_IP_PAIR, 97 OPTION_STRING, 98 /* Opts of STRING_HOST type will be sanitized before they are passed 99 * to udhcpc script's environment: */ 100 OPTION_STRING_HOST, 101 // OPTION_BOOLEAN, 102 OPTION_U8, 103 OPTION_U16, 104 // OPTION_S16, 105 OPTION_U32, 106 OPTION_S32, 107 OPTION_BIN, 108 OPTION_STATIC_ROUTES, 109 OPTION_6RD, 110 #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 111 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ 112 #endif 113 #if ENABLE_FEATURE_UDHCP_RFC3397 114 OPTION_SIP_SERVERS, 115 #endif 116 117 OPTION_TYPE_MASK = 0x0f, 118 /* Client requests this option by default */ 119 OPTION_REQ = 0x10, 120 /* There can be a list of 1 or more of these */ 121 OPTION_LIST = 0x20, 122 }; 123 124 struct dhcp_scan_state { 125 int overload; 126 int rem; 127 uint8_t *optionptr; 128 }; 129 130 /* DHCP option codes (partial list). See RFC 2132 and 131 * http://www.iana.org/assignments/bootp-dhcp-parameters/ 132 * Commented out options are handled by common option machinery, 133 * uncommented ones have special cases (grep for them to see). 134 */ 135 #define DHCP_PADDING 0x00 136 #define DHCP_SUBNET 0x01 137 //#define DHCP_TIME_OFFSET 0x02 /* (localtime - UTC_time) in seconds. signed */ 138 //#define DHCP_ROUTER 0x03 139 //#define DHCP_TIME_SERVER 0x04 /* RFC 868 time server (32-bit, 0 = 1.1.1900) */ 140 //#define DHCP_NAME_SERVER 0x05 /* IEN 116 _really_ ancient kind of NS */ 141 //#define DHCP_DNS_SERVER 0x06 142 //#define DHCP_LOG_SERVER 0x07 /* port 704 UDP log (not syslog) */ 143 //#define DHCP_COOKIE_SERVER 0x08 /* "quote of the day" server */ 144 //#define DHCP_LPR_SERVER 0x09 145 #define DHCP_HOST_NAME 0x0c /* 12: either client informs server or server gives name to client */ 146 //#define DHCP_BOOT_SIZE 0x0d 147 //#define DHCP_DOMAIN_NAME 0x0f /* 15: server gives domain suffix */ 148 //#define DHCP_SWAP_SERVER 0x10 149 //#define DHCP_ROOT_PATH 0x11 150 //#define DHCP_IP_TTL 0x17 151 //#define DHCP_MTU 0x1a 152 //#define DHCP_BROADCAST 0x1c 153 //#define DHCP_ROUTES 0x21 154 //#define DHCP_NIS_DOMAIN 0x28 155 //#define DHCP_NIS_SERVER 0x29 156 //#define DHCP_NTP_SERVER 0x2a 157 //#define DHCP_WINS_SERVER 0x2c 158 #define DHCP_REQUESTED_IP 0x32 /* 50: sent by client if specific IP is wanted */ 159 #define DHCP_LEASE_TIME 0x33 /* 51: 32bit big-endian */ 160 #define DHCP_OPTION_OVERLOAD 0x34 /* 52: 1 byte */ 161 #define DHCP_MESSAGE_TYPE 0x35 /* 53: 1 byte */ 162 #define DHCP_SERVER_ID 0x36 /* 54: server's IP */ 163 #define DHCP_PARAM_REQ 0x37 /* 55: list of options client wants */ 164 //#define DHCP_ERR_MESSAGE 0x38 /* 56: error message when sending NAK etc */ 165 #define DHCP_MAX_SIZE 0x39 /* 57: 16bit big-endian */ 166 // 0x3a /* 58: from server: renew time, 32bit big-endian */ 167 // 0x3b /* 59: from server: rebind time, 32bit big-endian */ 168 #define DHCP_VENDOR 0x3c /* 60: client's vendor (a string) */ 169 #define DHCP_CLIENT_ID 0x3d /* 61: by default client's MAC addr, but may be arbitrarily long */ 170 //#define DHCP_TFTP_SERVER_NAME 0x42 /* 66: same as 'sname' field */ 171 //#define DHCP_BOOT_FILE 0x43 /* 67: same as 'file' field */ 172 //#define DHCP_USER_CLASS 0x4d /* 77: RFC 3004. set of LASCII strings. "I am a printer" etc */ 173 // 0x50 /* 80: rapid commit ("I'm ok with getting immediate ACK, not just OFFER"), 0 bytes */ 174 #define DHCP_FQDN 0x51 /* 81: client asks to update DNS to map its FQDN to its new IP */ 175 //#define DHCP_PCODE 0x64 /* 100: RFC 4833. IEEE 1003.1 TZ string */ 176 //#define DHCP_TCODE 0x65 /* 101: RFC 4833. Reference to the TZ database string */ 177 //#define DHCP_DOMAIN_SEARCH 0x77 /* 119: RFC 3397. set of ASCIZ string, DNS-style compressed */ 178 //#define DHCP_SIP_SERVERS 0x78 /* 120: RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ 179 //#define DHCP_STATIC_ROUTES 0x79 /* 121: RFC 3442. (mask,ip,router) tuples */ 180 //#define DHCP_VLAN_ID 0x84 /* 132: 802.1P VLAN ID */ 181 //#define DHCP_VLAN_PRIORITY 0x85 /* 133: 802.1Q VLAN priority */ 182 //#define DHCP_PXE_CONF_FILE 0xd1 /* 209: RFC 5071 Configuration file */ 183 //#define DHCP_PXE_PATH_PREFIX 0xd2 /* 210: RFC 5071 Path prefix */ 184 //#define DHCP_REBOOT_TIME 0xd3 /* 211: RFC 5071 Reboot time */ 185 //#define DHCP_MS_STATIC_ROUTES 0xf9 /* 249: Microsoft's pre-RFC 3442 code for 0x79? */ 186 //#define DHCP_WPAD 0xfc /* 252: MSIE's Web Proxy Autodiscovery Protocol */ 187 #define DHCP_END 0xff /* 255: */ 188 189 /* Offsets in option byte sequence */ 190 #define OPT_CODE 0 191 #define OPT_LEN 1 192 #define OPT_DATA 2 193 /* Offsets in option byte sequence for DHCPv6 */ 194 #define D6_OPT_CODE 0 195 #define D6_OPT_LEN 2 196 #define D6_OPT_DATA 4 197 /* Bits in "overload" option */ 198 #define OPTION_FIELD 0 199 #define FILE_FIELD 1 200 #define SNAME_FIELD 2 201 202 /* DHCP_MESSAGE_TYPE values */ 203 #define DHCPDISCOVER 1 /* client -> server */ 204 #define DHCPOFFER 2 /* client <- server */ 205 #define DHCPREQUEST 3 /* client -> server */ 206 #define DHCPDECLINE 4 /* client -> server */ 207 #define DHCPACK 5 /* client <- server */ 208 #define DHCPNAK 6 /* client <- server */ 209 #define DHCPRELEASE 7 /* client -> server */ 210 #define DHCPINFORM 8 /* client -> server */ 211 #define DHCP_MINTYPE DHCPDISCOVER 212 #define DHCP_MAXTYPE DHCPINFORM 213 214 struct dhcp_optflag { 215 uint8_t flags; 216 uint8_t code; 217 }; 218 219 struct option_set { 220 uint8_t *data; 221 struct option_set *next; 222 }; 223 224 #if ENABLE_UDHCPC || ENABLE_UDHCPD 225 extern const struct dhcp_optflag dhcp_optflags[]; 226 extern const char dhcp_option_strings[] ALIGN1; 227 #endif 228 extern const uint8_t dhcp_option_lengths[] ALIGN1; 229 230 unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings); 231 232 void init_scan_state(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; 233 uint8_t *udhcp_scan_options(struct dhcp_packet *packet, struct dhcp_scan_state *scan_state) FAST_FUNC; 234 uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC; 235 /* Same as above + ensures that option length is 4 bytes 236 * (returns NULL if size is different) 237 */ 238 uint8_t *udhcp_get_option32(struct dhcp_packet *packet, int code) FAST_FUNC; 239 int udhcp_end_option(uint8_t *optionptr) FAST_FUNC; 240 void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC; 241 #if ENABLE_UDHCPC || ENABLE_UDHCPD 242 void udhcp_add_simple_option(struct dhcp_packet *packet, uint8_t code, uint32_t data) FAST_FUNC; 243 #endif 244 #if ENABLE_FEATURE_UDHCP_RFC3397 || ENABLE_FEATURE_UDHCPC6_RFC3646 || ENABLE_FEATURE_UDHCPC6_RFC4704 245 char *dname_dec(const uint8_t *cstr, int clen, const char *pre) FAST_FUNC; 246 uint8_t *dname_enc(/*const uint8_t *cstr, int clen,*/ const char *src, int *retlen) FAST_FUNC; 247 #endif 248 #if !ENABLE_UDHCPC6 249 #define udhcp_find_option(opt_list, code, dhcpv6) \ 250 udhcp_find_option(opt_list, code) 251 #endif 252 struct option_set *udhcp_find_option(struct option_set *opt_list, uint8_t code, bool dhcpv6) FAST_FUNC; 253 254 // RFC 2131 Table 5: Fields and options used by DHCP clients 255 // 256 // Fields 'hops', 'yiaddr', 'siaddr', 'giaddr' are always zero, 'chaddr' is always client's MAC 257 // 258 // Field DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE 259 // ----- ------------ ------------ ----------- ----------- ----------- 260 // 'xid' selected by client selected by client 'xid' from server selected by client selected by client 261 // DHCPOFFER message 262 // 'secs' 0 or seconds since 0 or seconds since 0 or seconds since 0 0 263 // DHCP process started DHCP process started DHCP process started 264 // 'flags' Set 'BROADCAST' Set 'BROADCAST' Set 'BROADCAST' 0 0 265 // flag if client needs flag if client needs flag if client needs 266 // broadcast reply broadcast reply broadcast reply 267 // 'ciaddr' 0 client's IP 0 or client's IP 0 client's IP 268 // (BOUND/RENEW/REBIND) 269 // 'sname' options or sname options or sname options or sname (unused) (unused) 270 // 'file' options or file options or file options or file (unused) (unused) 271 // 'options' options options options message type opt message type opt 272 // 273 // Option DHCPDISCOVER DHCPINFORM DHCPREQUEST DHCPDECLINE DHCPRELEASE 274 // ------ ------------ ---------- ----------- ----------- ----------- 275 // Requested IP address MAY MUST NOT MUST (in SELECTING MUST MUST NOT 276 // or INIT-REBOOT) 277 // MUST NOT (in BOUND 278 // or RENEWING) 279 // IP address lease time MAY MUST NOT MAY MUST NOT MUST NOT 280 // Use 'file'/'sname' fields MAY MAY MAY MAY MAY 281 // Client identifier MAY MAY MAY MAY MAY 282 // Vendor class identifier MAY MAY MAY MUST NOT MUST NOT 283 // Server identifier MUST NOT MUST NOT MUST (after SELECTING) MUST MUST 284 // MUST NOT (after 285 // INIT-REBOOT, BOUND, 286 // RENEWING or REBINDING) 287 // Parameter request list MAY MAY MAY MUST NOT MUST NOT 288 // Maximum message size MAY MAY MAY MUST NOT MUST NOT 289 // Message SHOULD NOT SHOULD NOT SHOULD NOT SHOULD SHOULD 290 // Site-specific MAY MAY MAY MUST NOT MUST NOT 291 // All others MAY MAY MAY MUST NOT MUST NOT 292 293 /*** Logging ***/ 294 295 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 296 # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ 297 extern unsigned dhcp_verbose; 298 # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) 299 //# define log1s(msg) do { if (dhcp_verbose >= 1) bb_simple_info_msg(msg); } while (0) 300 void log1s(const char *msg) FAST_FUNC; 301 # if CONFIG_UDHCP_DEBUG >= 2 302 void udhcp_dump_packet(struct dhcp_packet *packet) FAST_FUNC; 303 # define log2(...) do { if (dhcp_verbose >= 2) bb_info_msg(__VA_ARGS__); } while (0) 304 # define log2s(msg) do { if (dhcp_verbose >= 2) bb_simple_info_msg(msg); } while (0) 305 # else 306 # define udhcp_dump_packet(...) ((void)0) 307 # define log2(...) ((void)0) 308 # define log2s(msg) ((void)0) 309 # endif 310 # if CONFIG_UDHCP_DEBUG >= 3 311 # define log3(...) do { if (dhcp_verbose >= 3) bb_info_msg(__VA_ARGS__); } while (0) 312 # define log3s(msg) do { if (dhcp_verbose >= 3) bb_simple_info_msg(msg); } while (0) 313 # else 314 # define log3(...) ((void)0) 315 # define log3s(msg) ((void)0) 316 # endif 317 #else 318 # define IF_UDHCP_VERBOSE(...) 319 # define udhcp_dump_packet(...) ((void)0) 320 # define log1(...) ((void)0) 321 # define log1s(msg) ((void)0) 322 # define log2(...) ((void)0) 323 # define log2s(msg) ((void)0) 324 # define log3(...) ((void)0) 325 # define log3s(msg) ((void)0) 326 #endif 327 328 /*** Other shared functions ***/ 329 330 /* 2nd param is "uint32_t*" */ 331 int FAST_FUNC udhcp_str2nip(const char *str, void *arg); 332 333 #if !ENABLE_UDHCPC6 334 #define udhcp_insert_new_option(opt_list, code, length, dhcpv6) \ 335 udhcp_insert_new_option(opt_list, code, length) 336 #endif 337 void* FAST_FUNC udhcp_insert_new_option(struct option_set **opt_list, 338 unsigned code, 339 unsigned length, 340 bool dhcpv6); 341 342 /* 2nd param is "struct option_set**" */ 343 #if !ENABLE_UDHCPC6 344 #define udhcp_str2optset(str, arg, optflags, option_strings, dhcpv6) \ 345 udhcp_str2optset(str, arg, optflags, option_strings) 346 #endif 347 int FAST_FUNC udhcp_str2optset(const char *str, 348 void *arg, 349 const struct dhcp_optflag *optflags, 350 const char *option_strings, 351 bool dhcpv6); 352 353 #if ENABLE_UDHCPC || ENABLE_UDHCPD 354 void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; 355 #endif 356 357 int udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) FAST_FUNC; 358 359 int udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, 360 uint32_t source_nip, int source_port, 361 uint32_t dest_nip, int dest_port, const uint8_t *dest_arp, 362 int ifindex) FAST_FUNC; 363 364 int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, 365 uint32_t source_nip, int source_port, 366 uint32_t dest_nip, int dest_port, 367 const char *ifname) FAST_FUNC; 368 369 void udhcp_sp_setup(void) FAST_FUNC; 370 void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; 371 int udhcp_sp_read(void) FAST_FUNC; 372 373 int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; 374 375 int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC; 376 377 /* Returns 1 if no reply received */ 378 int arpping(uint32_t test_nip, 379 const uint8_t *safe_mac, 380 uint32_t from_ip, 381 uint8_t *from_mac, 382 const char *interface, 383 unsigned timeo) FAST_FUNC; 384 385 /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ 386 int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC; 387 388 POP_SAVED_FUNCTION_VISIBILITY 389 390 #endif 391