Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/networking/udhcp
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- Location:
- branches/3.2/mindi-busybox/networking/udhcp
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/networking/udhcp/Config.src
r2725 r3232 9 9 bool "udhcp server (udhcpd)" 10 10 default y 11 depends onPLATFORM_LINUX11 select PLATFORM_LINUX 12 12 help 13 13 udhcpd is a DHCP server geared primarily toward embedded systems, … … 40 40 time a new lease has been accepted, thus eliminating the need 41 41 to send SIGUSR1 for the initial writing or updating. Any timed 42 rewriting remains undisturbed 42 rewriting remains undisturbed. 43 44 config FEATURE_UDHCPD_BASE_IP_ON_MAC 45 bool "Select IP address based on client MAC" 46 default n 47 depends on UDHCPD 48 help 49 If selected, udhcpd will base its selection of IP address to offer 50 on the client's hardware address. Otherwise udhcpd uses the next 51 consecutive free address. 52 53 This reduces the frequency of IP address changes for clients 54 which let their lease expire, and makes consecutive DHCPOFFERS 55 for the same client to (almost always) contain the same 56 IP address. 43 57 44 58 config DHCPD_LEASES_FILE … … 53 67 bool "udhcp client (udhcpc)" 54 68 default y 55 depends onPLATFORM_LINUX69 select PLATFORM_LINUX 56 70 help 57 71 udhcpc is a DHCP client geared primarily toward embedded systems, … … 73 87 config FEATURE_UDHCP_PORT 74 88 bool "Enable '-P port' option for udhcpd and udhcpc" 75 default y89 default n 76 90 depends on UDHCPD || UDHCPC 77 91 help … … 99 113 search lists via option 119, specified in RFC 3397, 100 114 and SIP servers option 120, specified in RFC 3361. 115 116 config FEATURE_UDHCP_8021Q 117 bool "Support for 802.1Q VLAN parameters" 118 default y 119 depends on UDHCPD || UDHCPC 120 help 121 If selected, both client and server will support passing of VLAN 122 ID and priority via options 132 and 133 as per 802.1Q. 101 123 102 124 config UDHCPC_DEFAULT_SCRIPT -
branches/3.2/mindi-busybox/networking/udhcp/arpping.c
r2725 r3232 119 119 } 120 120 } 121 timeout_ms -= (unsigned)monotonic_ms() - prevTime; 122 } while (timeout_ms > 0); 121 timeout_ms -= (unsigned)monotonic_ms() - prevTime + 1; 122 123 /* We used to check "timeout_ms > 0", but 124 * this is more under/overflow-resistant 125 * (people did see overflows here when system time jumps): 126 */ 127 } while ((unsigned)timeout_ms <= 2000); 123 128 124 129 ret: -
branches/3.2/mindi-busybox/networking/udhcp/common.c
r2725 r3232 30 30 // { OPTION_IP | OPTION_LIST , 0x08 }, /* DHCP_COOKIE_SERVER */ 31 31 { OPTION_IP | OPTION_LIST , 0x09 }, /* DHCP_LPR_SERVER */ 32 { OPTION_STRING 32 { OPTION_STRING_HOST | OPTION_REQ, 0x0c }, /* DHCP_HOST_NAME */ 33 33 { OPTION_U16 , 0x0d }, /* DHCP_BOOT_SIZE */ 34 { OPTION_STRING 34 { OPTION_STRING_HOST | OPTION_REQ, 0x0f }, /* DHCP_DOMAIN_NAME */ 35 35 { OPTION_IP , 0x10 }, /* DHCP_SWAP_SERVER */ 36 36 { OPTION_STRING , 0x11 }, /* DHCP_ROOT_PATH */ 37 37 { OPTION_U8 , 0x17 }, /* DHCP_IP_TTL */ 38 38 { OPTION_U16 , 0x1a }, /* DHCP_MTU */ 39 //TODO: why do we request DHCP_BROADCAST? Can't we assume that 40 //in the unlikely case it is different from typical N.N.255.255, 41 //server would let us know anyway? 39 42 { OPTION_IP | OPTION_REQ, 0x1c }, /* DHCP_BROADCAST */ 40 43 { OPTION_IP_PAIR | OPTION_LIST , 0x21 }, /* DHCP_ROUTES */ 41 { OPTION_STRING 44 { OPTION_STRING_HOST , 0x28 }, /* DHCP_NIS_DOMAIN */ 42 45 { OPTION_IP | OPTION_LIST , 0x29 }, /* DHCP_NIS_SERVER */ 43 46 { OPTION_IP | OPTION_LIST | OPTION_REQ, 0x2a }, /* DHCP_NTP_SERVER */ … … 47 50 { OPTION_STRING , 0x38 }, /* DHCP_ERR_MESSAGE */ 48 51 //TODO: must be combined with 'sname' and 'file' handling: 49 { OPTION_STRING 52 { OPTION_STRING_HOST , 0x42 }, /* DHCP_TFTP_SERVER_NAME */ 50 53 { OPTION_STRING , 0x43 }, /* DHCP_BOOT_FILE */ 51 54 //TODO: not a string, but a set of LASCII strings: … … 55 58 { OPTION_SIP_SERVERS , 0x78 }, /* DHCP_SIP_SERVERS */ 56 59 #endif 57 { OPTION_STATIC_ROUTES , 0x79 }, /* DHCP_STATIC_ROUTES */ 58 { OPTION_STATIC_ROUTES , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ 60 { OPTION_STATIC_ROUTES | OPTION_LIST , 0x79 }, /* DHCP_STATIC_ROUTES */ 61 #if ENABLE_FEATURE_UDHCP_8021Q 62 { OPTION_U16 , 0x84 }, /* DHCP_VLAN_ID */ 63 { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ 64 #endif 65 { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ 66 { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ 59 67 { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ 60 68 … … 116 124 "sipsrv" "\0" /* DHCP_SIP_SERVERS */ 117 125 #endif 118 // doesn't work in udhcpd.conf since OPTION_STATIC_ROUTES119 // is not handled yet by "string->option" conversion code:120 126 "staticroutes" "\0"/* DHCP_STATIC_ROUTES */ 127 #if ENABLE_FEATURE_UDHCP_8021Q 128 "vlanid" "\0" /* DHCP_VLAN_ID */ 129 "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ 130 #endif 131 "ip6rd" "\0" /* DHCP_6RD */ 121 132 "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ 122 133 "wpad" "\0" /* DHCP_WPAD */ … … 136 147 // [OPTION_BOOLEAN] = 1, 137 148 [OPTION_STRING] = 1, /* ignored by udhcp_str2optset */ 149 [OPTION_STRING_HOST] = 1, /* ignored by udhcp_str2optset */ 138 150 #if ENABLE_FEATURE_UDHCP_RFC3397 139 151 [OPTION_DNS_STRING] = 1, /* ignored by both udhcp_str2optset and xmalloc_optname_optval */ … … 147 159 /* Just like OPTION_STRING, we use minimum length here */ 148 160 [OPTION_STATIC_ROUTES] = 5, 161 [OPTION_6RD] = 22, /* ignored by udhcp_str2optset */ 149 162 }; 150 163 … … 324 337 if (!lsa) 325 338 return 0; 326 *(uint32_t*)arg = lsa->u.sin.sin_addr.s_addr; 339 /* arg maybe unaligned */ 340 move_to_unaligned32((uint32_t*)arg, lsa->u.sin.sin_addr.s_addr); 327 341 free(lsa); 328 342 return 1; … … 404 418 405 419 existing->data = xrealloc(existing->data, OPT_DATA + 1 + old_len + length); 406 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING) { 420 if ((optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING 421 || (optflag->flags & OPTION_TYPE_MASK) == OPTION_STRING_HOST 422 ) { 407 423 /* add space separator between STRING options in a list */ 408 424 existing->data[OPT_DATA + old_len] = ' '; … … 421 437 { 422 438 struct option_set **opt_list = arg; 423 char *opt, *val , *endptr;439 char *opt, *val; 424 440 char *str; 425 441 const struct dhcp_optflag *optflag; … … 427 443 unsigned optcode; 428 444 int retval, length; 429 char buffer[8] ALIGNED(4); 445 /* IP_PAIR needs 8 bytes, STATIC_ROUTES needs 9 max */ 446 char buffer[9] ALIGNED(4); 430 447 uint16_t *result_u16 = (uint16_t *) buffer; 431 448 uint32_t *result_u32 = (uint32_t *) buffer; … … 468 485 break; 469 486 case OPTION_STRING: 487 case OPTION_STRING_HOST: 470 488 #if ENABLE_FEATURE_UDHCP_RFC3397 471 489 case OPTION_DNS_STRING: … … 484 502 // } 485 503 case OPTION_U8: 486 buffer[0] = strtoul(val, &endptr, 0);487 retval = (e ndptr[0] == '\0');504 buffer[0] = bb_strtou32(val, NULL, 0); 505 retval = (errno == 0); 488 506 break; 489 507 /* htonX are macros in older libc's, using temp var … … 491 509 /* TODO: use bb_strtoX? */ 492 510 case OPTION_U16: { 493 u nsigned long tmp = strtoul(val, &endptr, 0);511 uint32_t tmp = bb_strtou32(val, NULL, 0); 494 512 *result_u16 = htons(tmp); 495 retval = (e ndptr[0] == '\0'/*&& tmp < 0x10000*/);513 retval = (errno == 0 /*&& tmp < 0x10000*/); 496 514 break; 497 515 } 498 516 // case OPTION_S16: { 499 // long tmp = strtol(val, &endptr, 0);517 // long tmp = bb_strtoi32(val, NULL, 0); 500 518 // *result_u16 = htons(tmp); 501 // retval = (e ndptr[0] == '\0');519 // retval = (errno == 0); 502 520 // break; 503 521 // } 504 522 case OPTION_U32: { 505 u nsigned long tmp = strtoul(val, &endptr, 0);523 uint32_t tmp = bb_strtou32(val, NULL, 0); 506 524 *result_u32 = htonl(tmp); 507 retval = (e ndptr[0] == '\0');525 retval = (errno == 0); 508 526 break; 509 527 } 510 528 case OPTION_S32: { 511 long tmp = strtol(val, &endptr, 0);529 int32_t tmp = bb_strtoi32(val, NULL, 0); 512 530 *result_u32 = htonl(tmp); 513 retval = (endptr[0] == '\0'); 531 retval = (errno == 0); 532 break; 533 } 534 case OPTION_STATIC_ROUTES: { 535 /* Input: "a.b.c.d/m" */ 536 /* Output: mask(1 byte),pfx(0-4 bytes),gw(4 bytes) */ 537 unsigned mask; 538 char *slash = strchr(val, '/'); 539 if (slash) { 540 *slash = '\0'; 541 retval = udhcp_str2nip(val, buffer + 1); 542 buffer[0] = mask = bb_strtou(slash + 1, NULL, 10); 543 val = strtok(NULL, ", \t/-"); 544 if (!val || mask > 32 || errno) 545 retval = 0; 546 if (retval) { 547 length = ((mask + 7) >> 3) + 5; 548 retval = udhcp_str2nip(val, buffer + (length - 4)); 549 } 550 } 514 551 break; 515 552 } … … 522 559 if (retval) 523 560 attach_option(opt_list, optflag, opt, length); 524 } while (retval && optflag->flags & OPTION_LIST);561 } while (retval && (optflag->flags & OPTION_LIST)); 525 562 526 563 return retval; 527 564 } 565 566 /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ 567 int FAST_FUNC sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) 568 { 569 char hexstrbuf[16 * 2]; 570 bin2hex(hexstrbuf, (void*)ip, 16); 571 return sprintf(dest, /* "%s" */ 572 "%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s:%.4s", 573 /* pre, */ 574 hexstrbuf + 0 * 4, 575 hexstrbuf + 1 * 4, 576 hexstrbuf + 2 * 4, 577 hexstrbuf + 3 * 4, 578 hexstrbuf + 4 * 4, 579 hexstrbuf + 5 * 4, 580 hexstrbuf + 6 * 4, 581 hexstrbuf + 7 * 4 582 ); 583 } -
branches/3.2/mindi-busybox/networking/udhcp/common.h
r2725 r3232 15 15 PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 16 16 17 extern const uint8_t MAC_BCAST_ADDR[6] ; /* six all-ones */17 extern const uint8_t MAC_BCAST_ADDR[6] ALIGN2; /* six all-ones */ 18 18 19 19 … … 81 81 OPTION_IP_PAIR, 82 82 OPTION_STRING, 83 /* Opts of STRING_HOST type will be sanitized before they are passed 84 * to udhcpc script's environment: */ 85 OPTION_STRING_HOST, 83 86 // OPTION_BOOLEAN, 84 87 OPTION_U8, … … 89 92 OPTION_BIN, 90 93 OPTION_STATIC_ROUTES, 94 OPTION_6RD, 91 95 #if ENABLE_FEATURE_UDHCP_RFC3397 92 96 OPTION_DNS_STRING, /* RFC1035 compressed domain name list */ … … 104 108 * http://www.iana.org/assignments/bootp-dhcp-parameters/ 105 109 * Commented out options are handled by common option machinery, 106 * uncommented ones have sp acial cases (grep for them to see).110 * uncommented ones have special cases (grep for them to see). 107 111 */ 108 112 #define DHCP_PADDING 0x00 … … 146 150 //#define DHCP_SIP_SERVERS 0x78 /* RFC 3361. flag byte, then: 0: domain names, 1: IP addrs */ 147 151 //#define DHCP_STATIC_ROUTES 0x79 /* RFC 3442. (mask,ip,router) tuples */ 152 #define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ 153 #define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ 148 154 //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ 149 155 //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ … … 182 188 183 189 extern const struct dhcp_optflag dhcp_optflags[]; 184 extern const char dhcp_option_strings[] ;185 extern const uint8_t dhcp_option_lengths[] ;190 extern const char dhcp_option_strings[] ALIGN1; 191 extern const uint8_t dhcp_option_lengths[] ALIGN1; 186 192 187 193 unsigned FAST_FUNC udhcp_option_idx(const char *name); … … 247 253 248 254 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 255 # define IF_UDHCP_VERBOSE(...) __VA_ARGS__ 249 256 extern unsigned dhcp_verbose; 250 257 # define log1(...) do { if (dhcp_verbose >= 1) bb_info_msg(__VA_ARGS__); } while (0) … … 262 269 # endif 263 270 #else 271 # define IF_UDHCP_VERBOSE(...) 264 272 # define udhcp_dump_packet(...) ((void)0) 265 273 # define log1(...) ((void)0) … … 275 283 /* 2nd param is "struct option_set**" */ 276 284 int FAST_FUNC udhcp_str2optset(const char *str, void *arg); 277 278 uint16_t udhcp_checksum(void *addr, int count) FAST_FUNC;279 285 280 286 void udhcp_init_header(struct dhcp_packet *packet, char type) FAST_FUNC; … … 306 312 const char *interface) FAST_FUNC; 307 313 314 /* note: ip is a pointer to an IPv6 in network order, possibly misaliged */ 315 int sprint_nip6(char *dest, /*const char *pre,*/ const uint8_t *ip) FAST_FUNC; 316 308 317 POP_SAVED_FUNCTION_VISIBILITY 309 318 -
branches/3.2/mindi-busybox/networking/udhcp/dhcpc.c
r2725 r3232 26 26 #include "dhcpc.h" 27 27 28 #include <asm/types.h> 29 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined(_NEWLIB_VERSION) 30 # include <netpacket/packet.h> 31 # include <net/ethernet.h> 32 #else 33 # include <linux/if_packet.h> 34 # include <linux/if_ether.h> 28 #include <netinet/if_ether.h> 29 #include <linux/filter.h> 30 #include <linux/if_packet.h> 31 32 /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ 33 34 35 #if ENABLE_LONG_OPTS 36 static const char udhcpc_longopts[] ALIGN1 = 37 "clientid-none\0" No_argument "C" 38 "vendorclass\0" Required_argument "V" 39 "hostname\0" Required_argument "H" 40 "fqdn\0" Required_argument "F" 41 "interface\0" Required_argument "i" 42 "now\0" No_argument "n" 43 "pidfile\0" Required_argument "p" 44 "quit\0" No_argument "q" 45 "release\0" No_argument "R" 46 "request\0" Required_argument "r" 47 "script\0" Required_argument "s" 48 "timeout\0" Required_argument "T" 49 "retries\0" Required_argument "t" 50 "tryagain\0" Required_argument "A" 51 "syslog\0" No_argument "S" 52 "request-option\0" Required_argument "O" 53 "no-default-options\0" No_argument "o" 54 "foreground\0" No_argument "f" 55 "background\0" No_argument "b" 56 "broadcast\0" No_argument "B" 57 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a") 58 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P") 59 ; 35 60 #endif 36 #include <linux/filter.h> 37 38 /* struct client_config_t client_config is in bb_common_bufsiz1 */ 61 /* Must match getopt32 option string order */ 62 enum { 63 OPT_C = 1 << 0, 64 OPT_V = 1 << 1, 65 OPT_H = 1 << 2, 66 OPT_h = 1 << 3, 67 OPT_F = 1 << 4, 68 OPT_i = 1 << 5, 69 OPT_n = 1 << 6, 70 OPT_p = 1 << 7, 71 OPT_q = 1 << 8, 72 OPT_R = 1 << 9, 73 OPT_r = 1 << 10, 74 OPT_s = 1 << 11, 75 OPT_T = 1 << 12, 76 OPT_t = 1 << 13, 77 OPT_S = 1 << 14, 78 OPT_A = 1 << 15, 79 OPT_O = 1 << 16, 80 OPT_o = 1 << 17, 81 OPT_x = 1 << 18, 82 OPT_f = 1 << 19, 83 OPT_B = 1 << 20, 84 /* The rest has variable bit positions, need to be clever */ 85 OPTBIT_B = 20, 86 USE_FOR_MMU( OPTBIT_b,) 87 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 88 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 89 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,) 90 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,) 91 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 92 }; 39 93 40 94 … … 46 100 [OPTION_IP_PAIR ] = sizeof("255.255.255.255 ") * 2, 47 101 [OPTION_STATIC_ROUTES ] = sizeof("255.255.255.255/32 255.255.255.255 "), 102 [OPTION_6RD ] = sizeof("32 128 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 255.255.255.255 "), 48 103 [OPTION_STRING ] = 1, 104 [OPTION_STRING_HOST ] = 1, 49 105 #if ENABLE_FEATURE_UDHCP_RFC3397 50 106 [OPTION_DNS_STRING ] = 1, /* unused */ … … 81 137 } 82 138 139 /* Check if a given label represents a valid DNS label 140 * Return pointer to the first character after the label upon success, 141 * NULL otherwise. 142 * See RFC1035, 2.3.1 143 */ 144 /* We don't need to be particularly anal. For example, allowing _, hyphen 145 * at the end, or leading and trailing dots would be ok, since it 146 * can't be used for attacks. (Leading hyphen can be, if someone uses 147 * cmd "$hostname" 148 * in the script: then hostname may be treated as an option) 149 */ 150 static const char *valid_domain_label(const char *label) 151 { 152 unsigned char ch; 153 unsigned pos = 0; 154 155 for (;;) { 156 ch = *label; 157 if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { 158 if (pos == 0) { 159 /* label must begin with letter */ 160 return NULL; 161 } 162 if (ch < '0' || ch > '9') { 163 if (ch == '\0' || ch == '.') 164 return label; 165 /* DNS allows only '-', but we are more permissive */ 166 if (ch != '-' && ch != '_') 167 return NULL; 168 } 169 } 170 label++; 171 pos++; 172 //Do we want this? 173 //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ 174 // return NULL; 175 } 176 } 177 178 /* Check if a given name represents a valid DNS name */ 179 /* See RFC1035, 2.3.1 */ 180 static int good_hostname(const char *name) 181 { 182 //const char *start = name; 183 184 for (;;) { 185 name = valid_domain_label(name); 186 if (!name) 187 return 0; 188 if (!name[0]) 189 return 1; 190 //Do we want this? 191 //return ((name - start) < 1025); /* NS_MAXDNAME */ 192 name++; 193 } 194 } 195 83 196 /* Create "opt_name=opt_value" string */ 84 197 static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_optflag *optflag, const char *opt_name) … … 88 201 char *dest, *ret; 89 202 90 /* option points to OPT_DATA, need to go back andget OPT_LEN */91 len = option[ OPT_LEN - OPT_DATA];203 /* option points to OPT_DATA, need to go back to get OPT_LEN */ 204 len = option[-OPT_DATA + OPT_LEN]; 92 205 93 206 type = optflag->flags & OPTION_TYPE_MASK; 94 207 optlen = dhcp_option_lengths[type]; 95 upper_length = len_of_option_as_string[type] * ((unsigned)len / (unsigned)optlen); 208 upper_length = len_of_option_as_string[type] 209 * ((unsigned)(len + optlen - 1) / (unsigned)optlen); 96 210 97 211 dest = ret = xmalloc(upper_length + strlen(opt_name) + 2); … … 99 213 100 214 while (len >= optlen) { 101 unsigned ip_ofs = 0;102 103 215 switch (type) { 216 case OPTION_IP: 104 217 case OPTION_IP_PAIR: 105 218 dest += sprint_nip(dest, "", option); 106 *dest++ = '/'; 107 ip_ofs = 4; 108 /* fall through */ 109 case OPTION_IP: 110 dest += sprint_nip(dest, "", option + ip_ofs); 219 if (type == OPTION_IP) 220 break; 221 dest += sprint_nip(dest, "/", option + 4); 111 222 break; 112 223 // case OPTION_BOOLEAN: … … 130 241 break; 131 242 } 243 /* Note: options which use 'return' instead of 'break' 244 * (for example, OPTION_STRING) skip the code which handles 245 * the case of list of options. 246 */ 132 247 case OPTION_STRING: 248 case OPTION_STRING_HOST: 133 249 memcpy(dest, option, len); 134 250 dest[len] = '\0'; 135 return ret; /* Short circuit this case */ 251 if (type == OPTION_STRING_HOST && !good_hostname(dest)) 252 safe_strncpy(dest, "bad", len); 253 return ret; 136 254 case OPTION_STATIC_ROUTES: { 137 255 /* Option binary format: … … 178 296 return ret; 179 297 } 298 case OPTION_6RD: 299 /* Option binary format (see RFC 5969): 300 * 0 1 2 3 301 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 302 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 303 * | OPTION_6RD | option-length | IPv4MaskLen | 6rdPrefixLen | 304 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 305 * | 6rdPrefix | 306 * ... (16 octets) ... 307 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 308 * ... 6rdBRIPv4Address(es) ... 309 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 310 * We convert it to a string 311 * "IPv4MaskLen 6rdPrefixLen 6rdPrefix 6rdBRIPv4Address..." 312 * 313 * Sanity check: ensure that our length is at least 22 bytes, that 314 * IPv4MaskLen <= 32, 315 * 6rdPrefixLen <= 128, 316 * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 317 * (2nd condition need no check - it follows from 1st and 3rd). 318 * Else, return envvar with empty value ("optname=") 319 */ 320 if (len >= (1 + 1 + 16 + 4) 321 && option[0] <= 32 322 && (option[1] + 32 - option[0]) <= 128 323 ) { 324 /* IPv4MaskLen */ 325 dest += sprintf(dest, "%u ", *option++); 326 /* 6rdPrefixLen */ 327 dest += sprintf(dest, "%u ", *option++); 328 /* 6rdPrefix */ 329 dest += sprint_nip6(dest, /* "", */ option); 330 option += 16; 331 len -= 1 + 1 + 16 + 4; 332 /* "+ 4" above corresponds to the length of IPv4 addr 333 * we consume in the loop below */ 334 while (1) { 335 /* 6rdBRIPv4Address(es) */ 336 dest += sprint_nip(dest, " ", option); 337 option += 4; 338 len -= 4; /* do we have yet another 4+ bytes? */ 339 if (len < 0) 340 break; /* no */ 341 } 342 } 343 344 return ret; 180 345 #if ENABLE_FEATURE_UDHCP_RFC3397 181 346 case OPTION_DNS_STRING: … … 217 382 #endif 218 383 } /* switch */ 384 385 /* If we are here, try to format any remaining data 386 * in the option as another, similarly-formatted option 387 */ 219 388 option += optlen; 220 389 len -= optlen; … … 222 391 // Should we bail out/warn if we see multi-ip option which is 223 392 // not allowed to be such (for example, DHCP_BROADCAST)? - 224 if (len < = 0/* || !(optflag->flags & OPTION_LIST) */)393 if (len < optlen /* || !(optflag->flags & OPTION_LIST) */) 225 394 break; 226 395 *dest++ = ' '; 227 396 *dest = '\0'; 228 } 397 } /* while */ 398 229 399 return ret; 230 400 } … … 239 409 uint8_t *temp; 240 410 uint8_t overload = 0; 411 412 #define BITMAP unsigned 413 #define BBITS (sizeof(BITMAP) * 8) 414 #define BMASK(i) (1 << (i & (sizeof(BITMAP) * 8 - 1))) 415 #define FOUND_OPTS(i) (found_opts[(unsigned)i / BBITS]) 416 BITMAP found_opts[256 / BBITS]; 417 418 memset(found_opts, 0, sizeof(found_opts)); 241 419 242 420 /* We need 6 elements for: … … 251 429 /* +1 element for each option, +2 for subnet option: */ 252 430 if (packet) { 253 for (i = 0; dhcp_optflags[i].code; i++) { 254 if (udhcp_get_option(packet, dhcp_optflags[i].code)) { 255 if (dhcp_optflags[i].code == DHCP_SUBNET) 256 envc++; /* for mton */ 431 /* note: do not search for "pad" (0) and "end" (255) options */ 432 //TODO: change logic to scan packet _once_ 433 for (i = 1; i < 255; i++) { 434 temp = udhcp_get_option(packet, i); 435 if (temp) { 436 if (i == DHCP_OPTION_OVERLOAD) 437 overload = *temp; 438 else if (i == DHCP_SUBNET) 439 envc++; /* for $mask */ 257 440 envc++; 441 /*if (i != DHCP_MESSAGE_TYPE)*/ 442 FOUND_OPTS(i) |= BMASK(i); 258 443 } 259 444 } 260 temp = udhcp_get_option(packet, DHCP_OPTION_OVERLOAD); 261 if (temp) 262 overload = *temp; 263 } 264 curr = envp = xzalloc(sizeof(char *) * envc); 445 } 446 curr = envp = xzalloc(sizeof(envp[0]) * envc); 265 447 266 448 *curr = xasprintf("interface=%s", client_config.interface); … … 270 452 return envp; 271 453 454 /* Export BOOTP fields. Fields we don't (yet?) export: 455 * uint8_t op; // always BOOTREPLY 456 * uint8_t htype; // hardware address type. 1 = 10mb ethernet 457 * uint8_t hlen; // hardware address length 458 * uint8_t hops; // used by relay agents only 459 * uint32_t xid; 460 * uint16_t secs; // elapsed since client began acquisition/renewal 461 * uint16_t flags; // only one flag so far: bcast. Never set by server 462 * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different 463 * // if during renew server wants to give us differn IP?) 464 * uint32_t gateway_nip; // relay agent IP address 465 * uint8_t chaddr[16]; // link-layer client hardware address (MAC) 466 * TODO: export gateway_nip as $giaddr? 467 */ 468 /* Most important one: yiaddr as $ip */ 272 469 *curr = xmalloc(sizeof("ip=255.255.255.255")); 273 470 sprint_nip(*curr, "ip=", (uint8_t *) &packet->yiaddr); 274 471 putenv(*curr++); 275 276 opt_name = dhcp_option_strings;277 i = 0;278 while (*opt_name) {279 temp = udhcp_get_option(packet, dhcp_optflags[i].code);280 if (!temp)281 goto next;282 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name);283 putenv(*curr++);284 if (dhcp_optflags[i].code == DHCP_SUBNET) {285 /* Subnet option: make things like "$ip/$mask" possible */286 uint32_t subnet;287 move_from_unaligned32(subnet, temp);288 *curr = xasprintf("mask=%d", mton(subnet));289 putenv(*curr++);290 }291 next:292 opt_name += strlen(opt_name) + 1;293 i++;294 }295 472 if (packet->siaddr_nip) { 473 /* IP address of next server to use in bootstrap */ 296 474 *curr = xmalloc(sizeof("siaddr=255.255.255.255")); 297 475 sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); … … 308 486 putenv(*curr++); 309 487 } 488 489 /* Export known DHCP options */ 490 opt_name = dhcp_option_strings; 491 i = 0; 492 while (*opt_name) { 493 uint8_t code = dhcp_optflags[i].code; 494 BITMAP *found_ptr = &FOUND_OPTS(code); 495 BITMAP found_mask = BMASK(code); 496 if (!(*found_ptr & found_mask)) 497 goto next; 498 *found_ptr &= ~found_mask; /* leave only unknown options */ 499 temp = udhcp_get_option(packet, code); 500 *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); 501 putenv(*curr++); 502 if (code == DHCP_SUBNET) { 503 /* Subnet option: make things like "$ip/$mask" possible */ 504 uint32_t subnet; 505 move_from_unaligned32(subnet, temp); 506 *curr = xasprintf("mask=%u", mton(subnet)); 507 putenv(*curr++); 508 } 509 next: 510 opt_name += strlen(opt_name) + 1; 511 i++; 512 } 513 /* Export unknown options */ 514 for (i = 0; i < 256;) { 515 BITMAP bitmap = FOUND_OPTS(i); 516 if (!bitmap) { 517 i += BBITS; 518 continue; 519 } 520 if (bitmap & BMASK(i)) { 521 unsigned len, ofs; 522 523 temp = udhcp_get_option(packet, i); 524 /* udhcp_get_option returns ptr to data portion, 525 * need to go back to get len 526 */ 527 len = temp[-OPT_DATA + OPT_LEN]; 528 *curr = xmalloc(sizeof("optNNN=") + 1 + len*2); 529 ofs = sprintf(*curr, "opt%u=", i); 530 *bin2hex(*curr + ofs, (void*) temp, len) = '\0'; 531 putenv(*curr++); 532 } 533 i++; 534 } 535 310 536 return envp; 311 537 } … … 316 542 char **envp, **curr; 317 543 char *argv[3]; 318 319 if (client_config.script == NULL)320 return;321 544 322 545 envp = fill_envp(packet); … … 347 570 static void init_packet(struct dhcp_packet *packet, char type) 348 571 { 572 uint16_t secs; 573 349 574 /* Fill in: op, htype, hlen, cookie fields; message type option: */ 350 575 udhcp_init_header(packet, type); 351 576 352 577 packet->xid = random_xid(); 578 579 client_config.last_secs = monotonic_sec(); 580 if (client_config.first_secs == 0) 581 client_config.first_secs = client_config.last_secs; 582 secs = client_config.last_secs - client_config.first_secs; 583 packet->secs = htons(secs); 353 584 354 585 memcpy(packet->chaddr, client_config.client_mac, 6); … … 359 590 static void add_client_options(struct dhcp_packet *packet) 360 591 { 361 uint8_t c;362 592 int i, end, len; 363 593 … … 369 599 end = udhcp_end_option(packet->options); 370 600 len = 0; 371 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { 372 if (( (dhcp_optflags[i].flags & OPTION_REQ) 373 && !client_config.no_default_options 374 ) 375 || (client_config.opt_mask[c >> 3] & (1 << (c & 7))) 376 ) { 377 packet->options[end + OPT_DATA + len] = c; 601 for (i = 1; i < DHCP_END; i++) { 602 if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) { 603 packet->options[end + OPT_DATA + len] = i; 378 604 len++; 379 605 } … … 392 618 udhcp_add_binary_option(packet, client_config.fqdn); 393 619 620 /* Request broadcast replies if we have no IP addr */ 621 if ((option_mask32 & OPT_B) && packet->ciaddr == 0) 622 packet->flags |= htons(BROADCAST_FLAG); 623 394 624 /* Add -x options if any */ 395 625 { … … 404 634 // strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); 405 635 } 636 637 // This will be needed if we remove -V VENDOR_STR in favor of 638 // -x vendor:VENDOR_STR 639 //if (!udhcp_find_option(packet.options, DHCP_VENDOR)) 640 // /* not set, set the default vendor ID */ 641 // ...add (DHCP_VENDOR, "udhcp "BB_VER) opt... 406 642 } 407 643 … … 548 784 /* Broadcast a DHCP decline message */ 549 785 /* NOINLINE: limit stack usage in caller */ 550 static NOINLINE int send_decline( uint32_t xid,uint32_t server, uint32_t requested)786 static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t requested) 551 787 { 552 788 struct dhcp_packet packet; … … 557 793 init_packet(&packet, DHCPDECLINE); 558 794 795 #if 0 559 796 /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client, 560 797 * but in case the server is buggy and wants DHCPDECLINE's xid … … 563 800 */ 564 801 packet.xid = xid; 802 #endif 565 803 /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */ 566 804 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); … … 599 837 struct ip_udp_dhcp_packet packet; 600 838 uint16_t check; 601 602 memset(&packet, 0, sizeof(packet)); 603 bytes = safe_read(fd, &packet, sizeof(packet)); 604 if (bytes < 0) { 605 log1("Packet read error, ignoring"); 606 /* NB: possible down interface, etc. Caller should pause. */ 607 return bytes; /* returns -1 */ 839 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; 840 struct iovec iov; 841 struct msghdr msg; 842 struct cmsghdr *cmsg; 843 844 /* used to use just safe_read(fd, &packet, sizeof(packet)) 845 * but we need to check for TP_STATUS_CSUMNOTREADY :( 846 */ 847 iov.iov_base = &packet; 848 iov.iov_len = sizeof(packet); 849 memset(&msg, 0, sizeof(msg)); 850 msg.msg_iov = &iov; 851 msg.msg_iovlen = 1; 852 msg.msg_control = cmsgbuf; 853 msg.msg_controllen = sizeof(cmsgbuf); 854 for (;;) { 855 bytes = recvmsg(fd, &msg, 0); 856 if (bytes < 0) { 857 if (errno == EINTR) 858 continue; 859 log1("Packet read error, ignoring"); 860 /* NB: possible down interface, etc. Caller should pause. */ 861 return bytes; /* returns -1 */ 862 } 863 break; 608 864 } 609 865 … … 623 879 624 880 /* make sure its the right packet for us, and that it passes sanity checks */ 625 if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION 881 if (packet.ip.protocol != IPPROTO_UDP 882 || packet.ip.version != IPVERSION 626 883 || packet.ip.ihl != (sizeof(packet.ip) >> 2) 627 884 || packet.udp.dest != htons(CLIENT_PORT) … … 636 893 check = packet.ip.check; 637 894 packet.ip.check = 0; 638 if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) {895 if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { 639 896 log1("Bad IP header checksum, ignoring"); 640 897 return -2; 898 } 899 900 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 901 if (cmsg->cmsg_level == SOL_PACKET 902 && cmsg->cmsg_type == PACKET_AUXDATA 903 ) { 904 /* some VMs don't checksum UDP and TCP data 905 * they send to the same physical machine, 906 * here we detect this case: 907 */ 908 struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); 909 if (aux->tp_status & TP_STATUS_CSUMNOTREADY) 910 goto skip_udp_sum_check; 911 } 641 912 } 642 913 … … 647 918 check = packet.udp.check; 648 919 packet.udp.check = 0; 649 if (check && check != udhcp_checksum(&packet, bytes)) {920 if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { 650 921 log1("Packet with bad UDP checksum received, ignoring"); 651 922 return -2; 652 923 } 653 654 memcpy(dhcp_pkt, &packet.data, bytes - (sizeof(packet.ip) + sizeof(packet.udp))); 655 656 if (dhcp_pkt->cookie != htonl(DHCP_MAGIC)) { 924 skip_udp_sum_check: 925 926 if (packet.data.cookie != htonl(DHCP_MAGIC)) { 657 927 bb_info_msg("Packet with bad magic, ignoring"); 658 928 return -2; 659 929 } 660 log1("Got valid DHCP packet"); 661 udhcp_dump_packet(dhcp_pkt); 662 return bytes - (sizeof(packet.ip) + sizeof(packet.udp)); 930 931 log1("Received a packet"); 932 udhcp_dump_packet(&packet.data); 933 934 bytes -= sizeof(packet.ip) + sizeof(packet.udp); 935 memcpy(dhcp_pkt, &packet.data, bytes); 936 return bytes; 663 937 } 664 938 … … 715 989 * TODO: make conditional? 716 990 */ 717 #define SERVER_AND_CLIENT_PORTS ((67 << 16) + 68)718 991 static const struct sock_filter filter_instr[] = { 719 /* check for udp*/992 /* load 9th byte (protocol) */ 720 993 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 9), 721 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 2, 0), /* L5, L1, is UDP? */ 722 /* ugly check for arp on ethernet-like and IPv4 */ 723 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), /* L1: */ 724 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x08000604, 3, 4), /* L3, L4 */ 725 /* skip IP header */ 726 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), /* L5: */ 727 /* check udp source and destination ports */ 728 BPF_STMT(BPF_LD|BPF_W|BPF_IND, 0), 729 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SERVER_AND_CLIENT_PORTS, 0, 1), /* L3, L4 */ 730 /* returns */ 731 BPF_STMT(BPF_RET|BPF_K, 0x0fffffff ), /* L3: pass */ 732 BPF_STMT(BPF_RET|BPF_K, 0), /* L4: reject */ 994 /* jump to L1 if it is IPPROTO_UDP, else to L4 */ 995 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_UDP, 0, 6), 996 /* L1: load halfword from offset 6 (flags and frag offset) */ 997 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 6), 998 /* jump to L4 if any bits in frag offset field are set, else to L2 */ 999 BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x1fff, 4, 0), 1000 /* L2: skip IP header (load index reg with header len) */ 1001 BPF_STMT(BPF_LDX|BPF_B|BPF_MSH, 0), 1002 /* load udp destination port from halfword[header_len + 2] */ 1003 BPF_STMT(BPF_LD|BPF_H|BPF_IND, 2), 1004 /* jump to L3 if udp dport is CLIENT_PORT, else to L4 */ 1005 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 68, 0, 1), 1006 /* L3: accept packet */ 1007 BPF_STMT(BPF_RET|BPF_K, 0xffffffff), 1008 /* L4: discard packet */ 1009 BPF_STMT(BPF_RET|BPF_K, 0), 733 1010 }; 734 1011 static const struct sock_fprog filter_prog = { … … 741 1018 742 1019 fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 743 log1("Got raw socket fd %d", fd); //log2? 744 745 if (SERVER_PORT == 67 && CLIENT_PORT == 68) { 746 /* Use only if standard ports are in use */ 747 /* Ignoring error (kernel may lack support for this) */ 748 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 749 sizeof(filter_prog)) >= 0) 750 log1("Attached filter to raw socket fd %d", fd); // log? 751 } 1020 log1("Got raw socket fd"); //log2? 752 1021 753 1022 sock.sll_family = AF_PACKET; … … 755 1024 sock.sll_ifindex = ifindex; 756 1025 xbind(fd, (struct sockaddr *) &sock, sizeof(sock)); 1026 1027 if (CLIENT_PORT == 68) { 1028 /* Use only if standard port is in use */ 1029 /* Ignoring error (kernel may lack support for this) */ 1030 if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, 1031 sizeof(filter_prog)) >= 0) 1032 log1("Attached filter to raw socket fd"); // log? 1033 } 1034 1035 if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, 1036 &const_int_1, sizeof(int)) < 0 1037 ) { 1038 if (errno != ENOPROTOOPT) 1039 log1("Can't set PACKET_AUXDATA on raw socket"); 1040 } 1041 757 1042 log1("Created raw socket"); 758 1043 … … 780 1065 } 781 1066 1067 /* Called only on SIGUSR1 */ 782 1068 static void perform_renew(void) 783 1069 { … … 802 1088 } 803 1089 804 static void perform_release(uint32_t requested_ip, uint32_t server_addr)1090 static void perform_release(uint32_t server_addr, uint32_t requested_ip) 805 1091 { 806 1092 char buffer[sizeof("255.255.255.255")]; … … 850 1136 //usage:#endif 851 1137 //usage:#define udhcpc_trivial_usage 852 //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR ] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"853 //usage: " [- H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")1138 //usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" 1139 //usage: " [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") 854 1140 //usage:#define udhcpc_full_usage "\n" 855 1141 //usage: IF_LONG_OPTS( … … 857 1143 //usage: "\n -p,--pidfile FILE Create pidfile" 858 1144 //usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 1145 //usage: "\n -B,--broadcast Request broadcast replies" 859 1146 //usage: "\n -t,--retries N Send up to N discover packets" 860 1147 //usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" … … 883 1170 //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" 884 1171 //usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME" 885 //usage: "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)"886 1172 //usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" 887 1173 //usage: "\n -C,--clientid-none Don't send MAC as client identifier" … … 894 1180 //usage: "\n -p FILE Create pidfile" 895 1181 //usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 1182 //usage: "\n -B Request broadcast replies" 896 1183 //usage: "\n -t N Send up to N discover packets" 897 1184 //usage: "\n -T N Pause between packets (default 3 seconds)" … … 920 1207 //usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)" 921 1208 //usage: "\n -F NAME Ask server to update DNS mapping for NAME" 922 //usage: "\n -H,-h NAME Send NAME as client hostname (default none)"923 1209 //usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" 924 1210 //usage: "\n -C Don't send MAC as client identifier" … … 927 1213 //usage: ) 928 1214 //usage: ) 1215 //usage: "\nSignals:" 1216 //usage: "\n USR1 Renew lease" 1217 //usage: "\n USR2 Release lease" 1218 929 1219 930 1220 int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; … … 942 1232 uint32_t server_addr = server_addr; /* for compiler */ 943 1233 uint32_t requested_ip = 0; 944 uint32_t xid = 0; 945 uint32_t lease_seconds = 0; /* can be given as 32-bit quantity */ 1234 uint32_t xid = xid; /* for compiler */ 946 1235 int packet_num; 947 1236 int timeout; /* must be signed */ … … 950 1239 int max_fd; 951 1240 int retval; 952 struct timeval tv;953 struct dhcp_packet packet;954 1241 fd_set rfds; 955 956 #if ENABLE_LONG_OPTS957 static const char udhcpc_longopts[] ALIGN1 =958 "clientid-none\0" No_argument "C"959 "vendorclass\0" Required_argument "V"960 "hostname\0" Required_argument "H"961 "fqdn\0" Required_argument "F"962 "interface\0" Required_argument "i"963 "now\0" No_argument "n"964 "pidfile\0" Required_argument "p"965 "quit\0" No_argument "q"966 "release\0" No_argument "R"967 "request\0" Required_argument "r"968 "script\0" Required_argument "s"969 "timeout\0" Required_argument "T"970 "version\0" No_argument "v"971 "retries\0" Required_argument "t"972 "tryagain\0" Required_argument "A"973 "syslog\0" No_argument "S"974 "request-option\0" Required_argument "O"975 "no-default-options\0" No_argument "o"976 "foreground\0" No_argument "f"977 "background\0" No_argument "b"978 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")979 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")980 ;981 #endif982 enum {983 OPT_C = 1 << 0,984 OPT_V = 1 << 1,985 OPT_H = 1 << 2,986 OPT_h = 1 << 3,987 OPT_F = 1 << 4,988 OPT_i = 1 << 5,989 OPT_n = 1 << 6,990 OPT_p = 1 << 7,991 OPT_q = 1 << 8,992 OPT_R = 1 << 9,993 OPT_r = 1 << 10,994 OPT_s = 1 << 11,995 OPT_T = 1 << 12,996 OPT_t = 1 << 13,997 OPT_S = 1 << 14,998 OPT_A = 1 << 15,999 OPT_O = 1 << 16,1000 OPT_o = 1 << 17,1001 OPT_x = 1 << 18,1002 OPT_f = 1 << 19,1003 /* The rest has variable bit positions, need to be clever */1004 OPTBIT_f = 19,1005 USE_FOR_MMU( OPTBIT_b,)1006 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)1007 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)1008 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)1009 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)1010 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)1011 };1012 1242 1013 1243 /* Default options */ … … 1020 1250 /* Parse command line */ 1021 1251 /* O,x: list; -T,-t,-A take numeric param */ 1022 opt_complementary = "O::x::T+:t+:A+" 1023 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1024 ":vv" 1025 #endif 1026 ; 1252 opt_complementary = "O::x::T+:t+:A+" IF_UDHCP_VERBOSE(":vv") ; 1027 1253 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1028 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f "1254 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB" 1029 1255 USE_FOR_MMU("b") 1030 1256 IF_FEATURE_UDHCPC_ARPING("a") … … 1038 1264 , &list_x 1039 1265 IF_FEATURE_UDHCP_PORT(, &str_P) 1040 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1041 , &dhcp_verbose1042 #endif 1043 );1044 if (opt & (OPT_h|OPT_H))1266 IF_UDHCP_VERBOSE(, &dhcp_verbose) 1267 ); 1268 if (opt & (OPT_h|OPT_H)) { 1269 //msg added 2011-11 1270 bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); 1045 1271 client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); 1272 } 1046 1273 if (opt & OPT_F) { 1047 1274 /* FQDN option format: [0x51][len][flags][0][0]<fqdn> */ … … 1067 1294 } 1068 1295 #endif 1069 if (opt & OPT_o)1070 client_config.no_default_options = 1;1071 1296 while (list_O) { 1072 1297 char *optstr = llist_pop(&list_O); 1073 unsigned n = udhcp_option_idx(optstr); 1074 n = dhcp_optflags[n].code; 1298 unsigned n = bb_strtou(optstr, NULL, 0); 1299 if (errno || n > 254) { 1300 n = udhcp_option_idx(optstr); 1301 n = dhcp_optflags[n].code; 1302 } 1075 1303 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1304 } 1305 if (!(opt & OPT_o)) { 1306 unsigned i, n; 1307 for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { 1308 if (dhcp_optflags[i].flags & OPTION_REQ) { 1309 client_config.opt_mask[n >> 3] |= 1 << (n & 7); 1310 } 1311 } 1076 1312 } 1077 1313 while (list_x) { … … 1101 1337 memcpy(clientid_mac_ptr, client_config.client_mac, 6); 1102 1338 } 1103 if (str_V[0] != '\0') 1339 if (str_V[0] != '\0') { 1340 // can drop -V, str_V, client_config.vendorclass, 1341 // but need to add "vendor" to the list of recognized 1342 // string opts for this to work; 1343 // and need to tweak add_client_options() too... 1344 // ...so the question is, should we? 1345 //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); 1104 1346 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 1347 } 1348 1105 1349 #if !BB_MMU 1106 1350 /* on NOMMU reexec (i.e., background) early */ … … 1140 1384 */ 1141 1385 for (;;) { 1386 struct timeval tv; 1387 struct dhcp_packet packet; 1142 1388 /* silence "uninitialized!" warning */ 1143 1389 unsigned timestamp_before_wait = timestamp_before_wait; … … 1159 1405 /* If we already timed out, fall through with retval = 0, else... */ 1160 1406 if ((int)tv.tv_sec > 0) { 1407 log1("Waiting on select %u seconds", (int)tv.tv_sec); 1161 1408 timestamp_before_wait = (unsigned)monotonic_sec(); 1162 log1("Waiting on select...");1163 1409 retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); 1164 1410 if (retval < 0) { … … 1187 1433 client_config.client_mac) 1188 1434 ) { 1189 return 1; /* iface is gone? */1435 goto ret0; /* iface is gone? */ 1190 1436 } 1191 1437 if (clientid_mac_ptr) … … 1197 1443 switch (state) { 1198 1444 case INIT_SELECTING: 1199 if ( packet_num < discover_retries) {1445 if (!discover_retries || packet_num < discover_retries) { 1200 1446 if (packet_num == 0) 1201 1447 xid = random_xid(); … … 1226 1472 continue; 1227 1473 case REQUESTING: 1228 if ( packet_num < discover_retries) {1474 if (!discover_retries || packet_num < discover_retries) { 1229 1475 /* send broadcast select packet */ 1230 1476 send_select(xid, server_addr, requested_ip); … … 1243 1489 /* 1/2 lease passed, enter renewing state */ 1244 1490 state = RENEWING; 1491 client_config.first_secs = 0; /* make secs field count from 0 */ 1245 1492 change_listen_mode(LISTEN_KERNEL); 1246 1493 log1("Entering renew state"); … … 1282 1529 udhcp_run_script(NULL, "deconfig"); 1283 1530 state = INIT_SELECTING; 1531 client_config.first_secs = 0; /* make secs field count from 0 */ 1284 1532 /*timeout = 0; - already is */ 1285 1533 packet_num = 0; … … 1298 1546 switch (udhcp_sp_read(&rfds)) { 1299 1547 case SIGUSR1: 1548 client_config.first_secs = 0; /* make secs field count from 0 */ 1549 already_waited_sec = 0; 1300 1550 perform_renew(); 1301 if (state == RENEW_REQUESTED) 1551 if (state == RENEW_REQUESTED) { 1552 /* We might be either on the same network 1553 * (in which case renew might work), 1554 * or we might be on a completely different one 1555 * (in which case renew won't ever succeed). 1556 * For the second case, must make sure timeout 1557 * is not too big, or else we can send 1558 * futile renew requests for hours. 1559 * (Ab)use -A TIMEOUT value (usually 20 sec) 1560 * as a cap on the timeout. 1561 */ 1562 if (timeout > tryagain_timeout) 1563 timeout = tryagain_timeout; 1302 1564 goto case_RENEW_REQUESTED; 1565 } 1303 1566 /* Start things over */ 1304 1567 packet_num = 0; … … 1307 1570 continue; 1308 1571 case SIGUSR2: 1309 perform_release( requested_ip, server_addr);1572 perform_release(server_addr, requested_ip); 1310 1573 timeout = INT_MAX; 1311 1574 continue; 1312 1575 case SIGTERM: 1313 1576 bb_info_msg("Received SIGTERM"); 1314 if (opt & OPT_R) /* release on quit */1315 perform_release(requested_ip, server_addr);1316 1577 goto ret0; 1317 1578 } … … 1366 1627 switch (state) { 1367 1628 case INIT_SELECTING: 1368 /* Must be a DHCPOFFER to one of our xid's*/1629 /* Must be a DHCPOFFER */ 1369 1630 if (*message == DHCPOFFER) { 1370 /* TODO: why we don't just fetch server's IP from IP header? */ 1631 /* What exactly is server's IP? There are several values. 1632 * Example DHCP offer captured with tchdump: 1633 * 1634 * 10.34.25.254:67 > 10.34.25.202:68 // IP header's src 1635 * BOOTP fields: 1636 * Your-IP 10.34.25.202 1637 * Server-IP 10.34.32.125 // "next server" IP 1638 * Gateway-IP 10.34.25.254 // relay's address (if DHCP relays are in use) 1639 * DHCP options: 1640 * DHCP-Message Option 53, length 1: Offer 1641 * Server-ID Option 54, length 4: 10.34.255.7 // "server ID" 1642 * Default-Gateway Option 3, length 4: 10.34.25.254 // router 1643 * 1644 * We think that real server IP (one to use in renew/release) 1645 * is one in Server-ID option. But I am not 100% sure. 1646 * IP header's src and Gateway-IP (same in this example) 1647 * might work too. 1648 * "Next server" and router are definitely wrong ones to use, though... 1649 */ 1371 1650 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1372 1651 if (!temp) { … … 1392 1671 case REBINDING: 1393 1672 if (*message == DHCPACK) { 1673 uint32_t lease_seconds; 1674 struct in_addr temp_addr; 1675 1394 1676 temp = udhcp_get_option(&packet, DHCP_LEASE_TIME); 1395 1677 if (!temp) { … … 1400 1682 move_from_unaligned32(lease_seconds, temp); 1401 1683 lease_seconds = ntohl(lease_seconds); 1402 lease_seconds &= 0x0fffffff; /* paranoia: must not be prone to overflows */ 1403 if (lease_seconds < 10) /* and not too small */ 1404 lease_seconds = 10; 1684 /* paranoia: must not be too small and not prone to overflows */ 1685 if (lease_seconds < 0x10) 1686 lease_seconds = 0x10; 1687 if (lease_seconds >= 0x10000000) 1688 lease_seconds = 0x0fffffff; 1405 1689 } 1406 1690 #if ENABLE_FEATURE_UDHCPC_ARPING … … 1423 1707 bb_info_msg("Offered address is in use " 1424 1708 "(got ARP reply), declining"); 1425 send_decline( xid,server_addr, packet.yiaddr);1709 send_decline(/*xid,*/ server_addr, packet.yiaddr); 1426 1710 1427 1711 if (state != REQUESTING) … … 1429 1713 change_listen_mode(LISTEN_RAW); 1430 1714 state = INIT_SELECTING; 1715 client_config.first_secs = 0; /* make secs field count from 0 */ 1431 1716 requested_ip = 0; 1432 1717 timeout = tryagain_timeout; … … 1439 1724 /* enter bound state */ 1440 1725 timeout = lease_seconds / 2; 1441 { 1442 struct in_addr temp_addr; 1443 temp_addr.s_addr = packet.yiaddr; 1444 bb_info_msg("Lease of %s obtained, lease time %u", 1445 inet_ntoa(temp_addr), (unsigned)lease_seconds); 1446 } 1726 temp_addr.s_addr = packet.yiaddr; 1727 bb_info_msg("Lease of %s obtained, lease time %u", 1728 inet_ntoa(temp_addr), (unsigned)lease_seconds); 1447 1729 requested_ip = packet.yiaddr; 1448 1730 udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); … … 1451 1733 change_listen_mode(LISTEN_NONE); 1452 1734 if (opt & OPT_q) { /* quit after lease */ 1453 if (opt & OPT_R) /* release on quit */1454 perform_release(requested_ip, server_addr);1455 1735 goto ret0; 1456 1736 } … … 1464 1744 } 1465 1745 #endif 1746 /* make future renew packets use different xid */ 1747 /* xid = random_xid(); ...but why bother? */ 1466 1748 already_waited_sec = 0; 1467 1749 continue; /* back to main loop */ … … 1476 1758 sleep(3); /* avoid excessive network traffic */ 1477 1759 state = INIT_SELECTING; 1760 client_config.first_secs = 0; /* make secs field count from 0 */ 1478 1761 requested_ip = 0; 1479 1762 timeout = 0; … … 1489 1772 1490 1773 ret0: 1774 if (opt & OPT_R) /* release on quit */ 1775 perform_release(server_addr, requested_ip); 1491 1776 retval = 0; 1492 1777 ret: -
branches/3.2/mindi-busybox/networking/udhcp/dhcpc.h
r2725 r3232 10 10 struct client_config_t { 11 11 uint8_t client_mac[6]; /* Our mac address */ 12 char no_default_options; /* Do not include default options in request */13 12 IF_FEATURE_UDHCP_PORT(uint16_t port;) 14 13 int ifindex; /* Index number of the interface to use */ … … 22 21 uint8_t *hostname; /* Optional hostname to use */ 23 22 uint8_t *fqdn; /* Optional fully qualified domain name to use */ 23 24 uint16_t first_secs; 25 uint16_t last_secs; 24 26 } FIX_ALIASING; 25 27 -
branches/3.2/mindi-busybox/networking/udhcp/dhcpd.c
r2725 r3232 21 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 22 */ 23 24 //usage:#define udhcpd_trivial_usage 25 //usage: "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]" 26 //usage:#define udhcpd_full_usage "\n\n" 27 //usage: "DHCP server\n" 28 //usage: "\n -f Run in foreground" 29 //usage: "\n -S Log to syslog too" 30 //usage: IF_FEATURE_UDHCP_PORT( 31 //usage: "\n -P N Use port N (default 67)" 32 //usage: ) 33 23 34 #include <syslog.h> 24 35 #include "common.h" … … 134 145 /* We got a DHCP DISCOVER. Send an OFFER. */ 135 146 /* NOINLINE: limit stack usage in caller */ 136 static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) 147 static NOINLINE void send_offer(struct dhcp_packet *oldpacket, 148 uint32_t static_lease_nip, 149 struct dyn_lease *lease, 150 uint8_t *requested_ip_opt) 137 151 { 138 152 struct dhcp_packet packet; … … 148 162 /* We have no static lease for client's chaddr */ 149 163 uint32_t req_nip; 150 uint8_t *req_ip_opt;151 164 const char *p_host_name; 152 165 … … 159 172 } 160 173 /* Or: if client has requested an IP */ 161 else if ( (req_ip_opt = udhcp_get_option(oldpacket, DHCP_REQUESTED_IP))!= NULL174 else if (requested_ip_opt != NULL 162 175 /* (read IP) */ 163 && (move_from_unaligned32(req_nip, req _ip_opt), 1)176 && (move_from_unaligned32(req_nip, requested_ip_opt), 1) 164 177 /* and the IP is in the lease range */ 165 178 && ntohl(req_nip) >= server_config.start_ip … … 284 297 int udhcpd_main(int argc UNUSED_PARAM, char **argv) 285 298 { 286 fd_set rfds;287 299 int server_socket = -1, retval, max_sock; 288 struct dhcp_packet packet;289 300 uint8_t *state; 290 uint32_t static_lease_nip;291 301 unsigned timeout_end; 292 302 unsigned num_ips; 293 303 unsigned opt; 294 304 struct option_set *option; 295 struct dyn_lease *lease, fake_lease;296 305 IF_FEATURE_UDHCP_PORT(char *str_P;) 297 306 … … 306 315 opt = getopt32(argv, "fSv" 307 316 IF_FEATURE_UDHCP_PORT("P:", &str_P) 308 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 309 , &dhcp_verbose 310 #endif 317 IF_UDHCP_VERBOSE(, &dhcp_verbose) 311 318 ); 312 319 if (!(opt & 1)) { /* no -f */ … … 371 378 udhcp_sp_setup(); 372 379 380 continue_with_autotime: 373 381 timeout_end = monotonic_sec() + server_config.auto_time; 374 382 while (1) { /* loop until universe collapses */ 383 fd_set rfds; 384 struct dhcp_packet packet; 375 385 int bytes; 376 386 struct timeval tv; 377 387 uint8_t *server_id_opt; 378 uint8_t *requested_ opt;388 uint8_t *requested_ip_opt; 379 389 uint32_t requested_nip = requested_nip; /* for compiler */ 390 uint32_t static_lease_nip; 391 struct dyn_lease *lease, fake_lease; 380 392 381 393 if (server_socket < 0) { … … 396 408 if (retval == 0) { 397 409 write_leases(); 398 timeout_end = monotonic_sec() + server_config.auto_time; 399 continue; 410 goto continue_with_autotime; 400 411 } 401 412 if (retval < 0 && errno != EINTR) { … … 409 420 write_leases(); 410 421 /* why not just reset the timeout, eh */ 411 timeout_end = monotonic_sec() + server_config.auto_time; 412 continue; 422 goto continue_with_autotime; 413 423 case SIGTERM: 414 424 bb_info_msg("Received SIGTERM"); 425 write_leases(); 415 426 goto ret0; 416 427 case 0: /* no signal: read a packet */ … … 442 453 bb_error_msg("no or bad message type option, ignoring packet"); 443 454 continue; 455 } 456 457 /* Get SERVER_ID if present */ 458 server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); 459 if (server_id_opt) { 460 uint32_t server_id_network_order; 461 move_from_unaligned32(server_id_network_order, server_id_opt); 462 if (server_id_network_order != server_config.server_nip) { 463 /* client talks to somebody else */ 464 log1("server ID doesn't match, ignoring"); 465 continue; 466 } 444 467 } 445 468 … … 456 479 } 457 480 458 /* Get REQUESTED_IP and SERVER_ID if present */ 459 server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID); 460 if (server_id_opt) { 461 uint32_t server_id_net; 462 move_from_unaligned32(server_id_net, server_id_opt); 463 if (server_id_net != server_config.server_nip) { 464 /* client talks to somebody else */ 465 log1("server ID doesn't match, ignoring"); 466 continue; 467 } 468 } 469 requested_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); 470 if (requested_opt) { 471 move_from_unaligned32(requested_nip, requested_opt); 481 /* Get REQUESTED_IP if present */ 482 requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP); 483 if (requested_ip_opt) { 484 move_from_unaligned32(requested_nip, requested_ip_opt); 472 485 } 473 486 … … 477 490 log1("Received DISCOVER"); 478 491 479 send_offer(&packet, static_lease_nip, lease );492 send_offer(&packet, static_lease_nip, lease, requested_ip_opt); 480 493 break; 481 494 … … 568 581 administrative authority to do so. 569 582 */ 570 if (!requested_ opt) {583 if (!requested_ip_opt) { 571 584 requested_nip = packet.ciaddr; 572 585 if (requested_nip == 0) { … … 581 594 break; 582 595 } 583 if (server_id_opt) { 584 /* client was talking specifically to us. 585 * "No, we don't have this IP for you". */ 596 /* No lease for this MAC, or lease IP != requested IP */ 597 598 if (server_id_opt /* client is in SELECTING state */ 599 || requested_ip_opt /* client is in INIT-REBOOT state */ 600 ) { 601 /* "No, we don't have this IP for you" */ 586 602 send_NAK(&packet); 587 } 603 } /* else: client is in RENEWING or REBINDING, do not answer */ 604 588 605 break; 589 606 … … 604 621 log1("Received DECLINE"); 605 622 if (server_id_opt 606 && requested_ opt623 && requested_ip_opt 607 624 && lease /* chaddr matches this lease */ 608 625 && requested_nip == lease->lease_nip -
branches/3.2/mindi-busybox/networking/udhcp/dhcprelay.c
r2725 r3232 10 10 * Upstream has GPL v2 or later 11 11 */ 12 13 //usage:#define dhcprelay_trivial_usage 14 //usage: "CLIENT_IFACE[,CLIENT_IFACE2]... SERVER_IFACE [SERVER_IP]" 15 //usage:#define dhcprelay_full_usage "\n\n" 16 //usage: "Relay DHCP requests between clients and server" 17 12 18 #include "common.h" 13 19 … … 26 32 struct sockaddr_in ip; 27 33 struct xid_item *next; 28 } ;34 } FIX_ALIASING; 29 35 30 36 #define dhcprelay_xid_list (*(struct xid_item*)&bb_common_bufsiz1) -
branches/3.2/mindi-busybox/networking/udhcp/dumpleases.c
r2725 r3232 3 3 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 4 4 */ 5 6 //usage:#define dumpleases_trivial_usage 7 //usage: "[-r|-a] [-f LEASEFILE]" 8 //usage:#define dumpleases_full_usage "\n\n" 9 //usage: "Display DHCP leases granted by udhcpd\n" 10 //usage: IF_LONG_OPTS( 11 //usage: "\n -f,--file=FILE Lease file" 12 //usage: "\n -r,--remaining Show remaining time" 13 //usage: "\n -a,--absolute Show expiration time" 14 //usage: ) 15 //usage: IF_NOT_LONG_OPTS( 16 //usage: "\n -f FILE Lease file" 17 //usage: "\n -r Show remaining time" 18 //usage: "\n -a Show expiration time" 19 //usage: ) 20 5 21 #include "common.h" 6 22 #include "dhcpd.h" … … 58 74 #if ENABLE_UNICODE_SUPPORT 59 75 { 60 char *uni_name = unicode_conv_to_printable_fixedwidth( NULL,lease.hostname, 19);76 char *uni_name = unicode_conv_to_printable_fixedwidth(/*NULL,*/ lease.hostname, 19); 61 77 printf(" %-16s%s ", inet_ntoa(addr), uni_name); 62 78 free(uni_name); -
branches/3.2/mindi-busybox/networking/udhcp/files.c
r2725 r3232 81 81 {"option" , udhcp_str2optset, &server_config.options , ""}, 82 82 {"opt" , udhcp_str2optset, &server_config.options , ""}, 83 {"notify_file" , read_str , &server_config.notify_file , ""},84 {"sname" , read_str , &server_config.sname , ""},85 {"boot_file" , read_str , &server_config.boot_file , ""},83 {"notify_file" , read_str , &server_config.notify_file , NULL}, 84 {"sname" , read_str , &server_config.sname , NULL}, 85 {"boot_file" , read_str , &server_config.boot_file , NULL}, 86 86 {"static_lease" , read_staticlease, &server_config.static_leases, ""}, 87 87 }; -
branches/3.2/mindi-busybox/networking/udhcp/leases.c
r2725 r3232 138 138 struct dyn_lease *oldest_lease = NULL; 139 139 140 addr = server_config.start_ip; /* addr is in host order here */ 141 for (; addr <= server_config.end_ip; addr++) { 140 #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC 141 uint32_t stop; 142 unsigned i, hash; 143 144 /* hash hwaddr: use the SDBM hashing algorithm. Seems to give good 145 * dispersal even with similarly-valued "strings". 146 */ 147 hash = 0; 148 for (i = 0; i < 6; i++) 149 hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash; 150 151 /* pick a seed based on hwaddr then iterate until we find a free address. */ 152 addr = server_config.start_ip 153 + (hash % (1 + server_config.end_ip - server_config.start_ip)); 154 stop = addr; 155 #else 156 addr = server_config.start_ip; 157 #define stop (server_config.end_ip + 1) 158 #endif 159 do { 142 160 uint32_t nip; 143 161 struct dyn_lease *lease; … … 145 163 /* ie, 192.168.55.0 */ 146 164 if ((addr & 0xff) == 0) 147 continue;165 goto next_addr; 148 166 /* ie, 192.168.55.255 */ 149 167 if ((addr & 0xff) == 0xff) 150 continue;168 goto next_addr; 151 169 nip = htonl(addr); 170 /* skip our own address */ 171 if (nip == server_config.server_nip) 172 goto next_addr; 152 173 /* is this a static lease addr? */ 153 174 if (is_nip_reserved(server_config.static_leases, nip)) 154 continue;175 goto next_addr; 155 176 156 177 lease = find_lease_by_nip(nip); … … 163 184 oldest_lease = lease; 164 185 } 165 } 186 187 next_addr: 188 addr++; 189 #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC 190 if (addr > server_config.end_ip) 191 addr = server_config.start_ip; 192 #endif 193 } while (addr != stop); 166 194 167 195 if (oldest_lease -
branches/3.2/mindi-busybox/networking/udhcp/packet.c
r2725 r3232 7 7 * Licensed under GPLv2, see file LICENSE in this source tree. 8 8 */ 9 #include <netinet/in.h>10 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION11 # include <netpacket/packet.h>12 # include <net/ethernet.h>13 #else14 # include <asm/types.h>15 # include <linux/if_packet.h>16 # include <linux/if_ether.h>17 #endif18 19 9 #include "common.h" 20 10 #include "dhcpd.h" 11 #include <netinet/in.h> 12 #include <netinet/if_ether.h> 13 #include <netpacket/packet.h> 21 14 22 15 void FAST_FUNC udhcp_init_header(struct dhcp_packet *packet, char type) … … 89 82 { 90 83 int bytes; 91 unsigned char *vendor;92 84 93 85 memset(packet, 0, sizeof(*packet)); … … 98 90 } 99 91 100 if (packet->cookie != htonl(DHCP_MAGIC)) { 92 if (bytes < offsetof(struct dhcp_packet, options) 93 || packet->cookie != htonl(DHCP_MAGIC) 94 ) { 101 95 bb_info_msg("Packet with bad magic, ignoring"); 102 96 return -2; … … 105 99 udhcp_dump_packet(packet); 106 100 107 if (packet->op == BOOTREQUEST) {108 vendor = udhcp_get_option(packet, DHCP_VENDOR);109 if (vendor) {110 #if 0111 static const char broken_vendors[][8] = {112 "MSFT 98",113 ""114 };115 int i;116 for (i = 0; broken_vendors[i][0]; i++) {117 if (vendor[OPT_LEN - OPT_DATA] == (uint8_t)strlen(broken_vendors[i])118 && strncmp((char*)vendor, broken_vendors[i], vendor[OPT_LEN - OPT_DATA]) == 0119 ) {120 log1("Broken client (%s), forcing broadcast replies",121 broken_vendors[i]);122 packet->flags |= htons(BROADCAST_FLAG);123 }124 }125 #else126 if (vendor[OPT_LEN - OPT_DATA] == (uint8_t)(sizeof("MSFT 98")-1)127 && memcmp(vendor, "MSFT 98", sizeof("MSFT 98")-1) == 0128 ) {129 log1("Broken client (%s), forcing broadcast replies", "MSFT 98");130 packet->flags |= htons(BROADCAST_FLAG);131 }132 #endif133 }134 }135 136 101 return bytes; 137 }138 139 uint16_t FAST_FUNC udhcp_checksum(void *addr, int count)140 {141 /* Compute Internet Checksum for "count" bytes142 * beginning at location "addr".143 */144 int32_t sum = 0;145 uint16_t *source = (uint16_t *) addr;146 147 while (count > 1) {148 /* This is the inner loop */149 sum += *source++;150 count -= 2;151 }152 153 /* Add left-over byte, if any */154 if (count > 0) {155 /* Make sure that the left-over byte is added correctly both156 * with little and big endian hosts */157 uint16_t tmp = 0;158 *(uint8_t*)&tmp = *(uint8_t*)source;159 sum += tmp;160 }161 /* Fold 32-bit sum to 16 bits */162 while (sum >> 16)163 sum = (sum & 0xffff) + (sum >> 16);164 165 return ~sum;166 102 } 167 103 … … 220 156 /* for UDP checksumming, ip.len is set to UDP packet len */ 221 157 packet.ip.tot_len = packet.udp.len; 222 packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding); 158 packet.udp.check = inet_cksum((uint16_t *)&packet, 159 IP_UDP_DHCP_SIZE - padding); 223 160 /* but for sending, it is set to IP packet len */ 224 161 packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); … … 226 163 packet.ip.version = IPVERSION; 227 164 packet.ip.ttl = IPDEFTTL; 228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));165 packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip)); 229 166 230 167 udhcp_dump_packet(dhcp_pkt); … … 246 183 uint32_t dest_nip, int dest_port) 247 184 { 248 struct sockaddr_in client;185 struct sockaddr_in sa; 249 186 unsigned padding; 250 187 int fd; … … 259 196 setsockopt_reuseaddr(fd); 260 197 261 memset(& client, 0, sizeof(client));262 client.sin_family = AF_INET;263 client.sin_port = htons(source_port);264 client.sin_addr.s_addr = source_nip;265 if (bind(fd, (struct sockaddr *)& client, sizeof(client)) == -1) {198 memset(&sa, 0, sizeof(sa)); 199 sa.sin_family = AF_INET; 200 sa.sin_port = htons(source_port); 201 sa.sin_addr.s_addr = source_nip; 202 if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 266 203 msg = "bind(%s)"; 267 204 goto ret_close; 268 205 } 269 206 270 memset(& client, 0, sizeof(client));271 client.sin_family = AF_INET;272 client.sin_port = htons(dest_port);273 client.sin_addr.s_addr = dest_nip;274 if (connect(fd, (struct sockaddr *)& client, sizeof(client)) == -1) {207 memset(&sa, 0, sizeof(sa)); 208 sa.sin_family = AF_INET; 209 sa.sin_port = htons(dest_port); 210 sa.sin_addr.s_addr = dest_nip; 211 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 275 212 msg = "connect"; 276 213 goto ret_close; … … 278 215 279 216 udhcp_dump_packet(dhcp_pkt); 280 281 217 padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options); 282 218 result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding); -
branches/3.2/mindi-busybox/networking/udhcp/socket.c
r2725 r3232 23 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 24 */ 25 #include "common.h" 25 26 #include <net/if.h> 26 #if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) || defined _NEWLIB_VERSION27 # include <netpacket/packet.h>28 # include <net/ethernet.h>29 #else30 # include <asm/types.h>31 # include <linux/if_packet.h>32 # include <linux/if_ether.h>33 #endif34 35 #include "common.h"36 27 37 28 int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) 38 29 { 30 /* char buffer instead of bona-fide struct avoids aliasing warning */ 31 char ifr_buf[sizeof(struct ifreq)]; 32 struct ifreq *const ifr = (void *)ifr_buf; 33 39 34 int fd; 40 struct ifreq ifr;41 35 struct sockaddr_in *our_ip; 42 36 43 memset( &ifr, 0, sizeof(ifr));37 memset(ifr, 0, sizeof(*ifr)); 44 38 fd = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 45 39 46 ifr .ifr_addr.sa_family = AF_INET;47 strncpy_IFNAMSIZ(ifr .ifr_name, interface);40 ifr->ifr_addr.sa_family = AF_INET; 41 strncpy_IFNAMSIZ(ifr->ifr_name, interface); 48 42 if (nip) { 49 if (ioctl_or_perror(fd, SIOCGIFADDR, &ifr,43 if (ioctl_or_perror(fd, SIOCGIFADDR, ifr, 50 44 "is interface %s up and configured?", interface) 51 45 ) { … … 53 47 return -1; 54 48 } 55 our_ip = (struct sockaddr_in *) &ifr .ifr_addr;49 our_ip = (struct sockaddr_in *) &ifr->ifr_addr; 56 50 *nip = our_ip->sin_addr.s_addr; 57 51 log1("IP %s", inet_ntoa(our_ip->sin_addr)); … … 59 53 60 54 if (ifindex) { 61 if (ioctl_or_warn(fd, SIOCGIFINDEX, &ifr) != 0) {55 if (ioctl_or_warn(fd, SIOCGIFINDEX, ifr) != 0) { 62 56 close(fd); 63 57 return -1; 64 58 } 65 log1("Adapter index %d", ifr .ifr_ifindex);66 *ifindex = ifr .ifr_ifindex;59 log1("Adapter index %d", ifr->ifr_ifindex); 60 *ifindex = ifr->ifr_ifindex; 67 61 } 68 62 69 63 if (mac) { 70 if (ioctl_or_warn(fd, SIOCGIFHWADDR, &ifr) != 0) {64 if (ioctl_or_warn(fd, SIOCGIFHWADDR, ifr) != 0) { 71 65 close(fd); 72 66 return -1; 73 67 } 74 memcpy(mac, ifr .ifr_hwaddr.sa_data, 6);68 memcpy(mac, ifr->ifr_hwaddr.sa_data, 6); 75 69 log1("MAC %02x:%02x:%02x:%02x:%02x:%02x", 76 70 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); … … 87 81 int fd; 88 82 struct sockaddr_in addr; 83 char *colon; 89 84 90 85 log1("Opening listen socket on *:%d %s", port, inf); … … 95 90 bb_perror_msg_and_die("SO_BROADCAST"); 96 91 97 /* NB: bug 1032 says this doesn't work on ethernet aliases (ethN:M) */ 92 /* SO_BINDTODEVICE doesn't work on ethernet aliases (ethN:M) */ 93 colon = strrchr(inf, ':'); 94 if (colon) 95 *colon = '\0'; 96 98 97 if (setsockopt_bindtodevice(fd, inf)) 99 98 xfunc_die(); /* warning is already printed */ 99 100 if (colon) 101 *colon = ':'; 100 102 101 103 memset(&addr, 0, sizeof(addr));
Note:
See TracChangeset
for help on using the changeset viewer.