X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=networking%2Fudhcp%2Fdhcpc.c;h=102178a4f94e18be637a06c193337a28e44960ce;hb=d30d1ebc117db182a6156df182057291d6fbaae1;hp=5b3fd531caeb3f31a21682b2c31a6b1155b8fd77;hpb=6d3b4bb24da9a07c263f3c1acf8df85382ff562c;p=oweals%2Fbusybox.git diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 5b3fd531c..102178a4f 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -49,7 +49,7 @@ struct tpacket_auxdata { #endif -/* "struct client_config_t client_config" is in bb_common_bufsiz1 */ +/* "struct client_data_t client_data" is in bb_common_bufsiz1 */ #if ENABLE_LONG_OPTS @@ -159,61 +159,27 @@ static int mton(uint32_t mask) } #if ENABLE_FEATURE_UDHCPC_SANITIZEOPT -/* Check if a given label represents a valid DNS label - * Return pointer to the first character after the label - * (NUL or dot) upon success, NULL otherwise. - * See RFC1035, 2.3.1 - */ +/* Check if a given name represents a valid DNS name */ +/* See RFC1035, 2.3.1 */ /* We don't need to be particularly anal. For example, allowing _, hyphen * at the end, or leading and trailing dots would be ok, since it - * can't be used for attacks. (Leading hyphen can be, if someone uses - * cmd "$hostname" + * can't be used for attacks. (Leading hyphen can be, if someone uses cmd "$hostname" * in the script: then hostname may be treated as an option) */ -static const char *valid_domain_label(const char *label) -{ - unsigned char ch; - //unsigned pos = 0; - - if (label[0] == '-') - return NULL; - for (;;) { - ch = *label; - if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { - if (ch < '0' || ch > '9') { - if (ch == '\0' || ch == '.') - return label; - /* DNS allows only '-', but we are more permissive */ - if (ch != '-' && ch != '_') - return NULL; - } - } - label++; - //pos++; - //Do we want this? - //if (pos > 63) /* NS_MAXLABEL; labels must be 63 chars or less */ - // return NULL; - } -} - -/* Check if a given name represents a valid DNS name */ -/* See RFC1035, 2.3.1 */ static int good_hostname(const char *name) { - //const char *start = name; - - for (;;) { - name = valid_domain_label(name); - if (!name) - return 0; - if (!name[0]) - return 1; - //Do we want this? - //return ((name - start) < 1025); /* NS_MAXDNAME */ - name++; - if (*name == '\0') - return 1; // We allow trailing dot too + if (*name == '-') /* Can't start with '-' */ + return 0; + + while (*name) { + unsigned char ch = *name++; + if (!isalnum(ch)) + /* DNS allows only '-', but we are more permissive */ + if (ch != '-' && ch != '_' && ch != '.') + return 0; + // TODO: do we want to validate lengths against NS_MAXLABEL and NS_MAXDNAME? } + return 1; } #else # define good_hostname(name) 1 @@ -242,9 +208,8 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ case OPTION_IP: case OPTION_IP_PAIR: dest += sprint_nip(dest, "", option); - if (type == OPTION_IP) - break; - dest += sprint_nip(dest, "/", option + 4); + if (type == OPTION_IP_PAIR) + dest += sprint_nip(dest, "/", option + 4); break; // case OPTION_BOOLEAN: // dest += sprintf(dest, *option ? "yes" : "no"); @@ -346,7 +311,7 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ * IPv4MaskLen <= 32, * 6rdPrefixLen <= 128, * 6rdPrefixLen + (32 - IPv4MaskLen) <= 128 - * (2nd condition need no check - it follows from 1st and 3rd). + * (2nd condition needs no check - it follows from 1st and 3rd). * Else, return envvar with empty value ("optname=") */ if (len >= (1 + 1 + 16 + 4) @@ -360,17 +325,12 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ /* 6rdPrefix */ dest += sprint_nip6(dest, /* "", */ option); option += 16; - len -= 1 + 1 + 16 + 4; - /* "+ 4" above corresponds to the length of IPv4 addr - * we consume in the loop below */ - while (1) { - /* 6rdBRIPv4Address(es) */ - dest += sprint_nip(dest, " ", option); - option += 4; - len -= 4; /* do we have yet another 4+ bytes? */ - if (len < 0) - break; /* no */ - } + len -= 1 + 1 + 16; + *dest++ = ' '; + /* 6rdBRIPv4Address(es), use common IPv4 logic to process them */ + type = OPTION_IP; + optlen = 4; + continue; } return ret; @@ -392,23 +352,18 @@ static NOINLINE char *xmalloc_optname_optval(uint8_t *option, const struct dhcp_ */ option++; len--; + if (option[-1] == 1) { + /* use common IPv4 logic to process IP addrs */ + type = OPTION_IP; + optlen = 4; + continue; + } if (option[-1] == 0) { dest = dname_dec(option, len, ret); if (dest) { free(ret); return dest; } - } else - if (option[-1] == 1) { - const char *pfx = ""; - while (1) { - len -= 4; - if (len < 0) - break; - dest += sprint_nip(dest, pfx, option); - pfx = " "; - option += 4; - } } return ret; #endif @@ -449,15 +404,16 @@ static char **fill_envp(struct dhcp_packet *packet) memset(found_opts, 0, sizeof(found_opts)); - /* We need 6 elements for: + /* We need 7 elements for: * "interface=IFACE" * "ip=N.N.N.N" from packet->yiaddr + * "giaddr=IP" from packet->gateway_nip (unless 0) * "siaddr=IP" from packet->siaddr_nip (unless 0) * "boot_file=FILE" from packet->file (unless overloaded) * "sname=SERVER_HOSTNAME" from packet->sname (unless overloaded) * terminating NULL */ - envc = 6; + envc = 7; /* +1 element for each option, +2 for subnet option: */ if (packet) { /* note: do not search for "pad" (0) and "end" (255) options */ @@ -477,7 +433,7 @@ static char **fill_envp(struct dhcp_packet *packet) } curr = envp = xzalloc(sizeof(envp[0]) * envc); - *curr = xasprintf("interface=%s", client_config.interface); + *curr = xasprintf("interface=%s", client_data.interface); putenv(*curr++); if (!packet) @@ -493,9 +449,7 @@ static char **fill_envp(struct dhcp_packet *packet) * uint16_t flags; // only one flag so far: bcast. Never set by server * uint32_t ciaddr; // client IP (usually == yiaddr. can it be different * // if during renew server wants to give us different IP?) - * uint32_t gateway_nip; // relay agent IP address * uint8_t chaddr[16]; // link-layer client hardware address (MAC) - * TODO: export gateway_nip as $giaddr? */ /* Most important one: yiaddr as $ip */ *curr = xmalloc(sizeof("ip=255.255.255.255")); @@ -507,6 +461,12 @@ static char **fill_envp(struct dhcp_packet *packet) sprint_nip(*curr, "siaddr=", (uint8_t *) &packet->siaddr_nip); putenv(*curr++); } + if (packet->gateway_nip) { + /* IP address of DHCP relay agent */ + *curr = xmalloc(sizeof("giaddr=255.255.255.255")); + sprint_nip(*curr, "giaddr=", (uint8_t *) &packet->gateway_nip); + putenv(*curr++); + } if (!(overload & FILE_FIELD) && packet->file[0]) { /* watch out for invalid packets */ *curr = xasprintf("boot_file=%."DHCP_PKT_FILE_LEN_STR"s", packet->file); @@ -531,7 +491,7 @@ static char **fill_envp(struct dhcp_packet *packet) temp = udhcp_get_option(packet, code); *curr = xmalloc_optname_optval(temp, &dhcp_optflags[i], opt_name); putenv(*curr++); - if (code == DHCP_SUBNET) { + if (code == DHCP_SUBNET && temp[-OPT_DATA + OPT_LEN] == 4) { /* Subnet option: make things like "$ip/$mask" possible */ uint32_t subnet; move_from_unaligned32(subnet, temp); @@ -577,8 +537,8 @@ static void udhcp_run_script(struct dhcp_packet *packet, const char *name) envp = fill_envp(packet); /* call script */ - log1("executing %s %s", client_config.script, name); - argv[0] = (char*) client_config.script; + log1("executing %s %s", client_data.script, name); + argv[0] = (char*) client_data.script; argv[1] = (char*) name; argv[2] = NULL; spawn_and_wait(argv); @@ -601,22 +561,22 @@ static ALWAYS_INLINE uint32_t random_xid(void) /* Initialize the packet with the proper defaults */ static void init_packet(struct dhcp_packet *packet, char type) { - uint16_t secs; + unsigned secs; /* Fill in: op, htype, hlen, cookie fields; message type option: */ udhcp_init_header(packet, type); packet->xid = random_xid(); - client_config.last_secs = monotonic_sec(); - if (client_config.first_secs == 0) - client_config.first_secs = client_config.last_secs; - secs = client_config.last_secs - client_config.first_secs; - packet->secs = htons(secs); + client_data.last_secs = monotonic_sec(); + if (client_data.first_secs == 0) + client_data.first_secs = client_data.last_secs; + secs = client_data.last_secs - client_data.first_secs; + packet->secs = (secs < 0xffff) ? htons(secs) : 0xffff; - memcpy(packet->chaddr, client_config.client_mac, 6); - if (client_config.clientid) - udhcp_add_binary_option(packet, client_config.clientid); + memcpy(packet->chaddr, client_data.client_mac, 6); + if (client_data.clientid) + udhcp_add_binary_option(packet, client_data.clientid); } static void add_client_options(struct dhcp_packet *packet) @@ -631,7 +591,7 @@ static void add_client_options(struct dhcp_packet *packet) end = udhcp_end_option(packet->options); len = 0; for (i = 1; i < DHCP_END; i++) { - if (client_config.opt_mask[i >> 3] & (1 << (i & 7))) { + if (client_data.opt_mask[i >> 3] & (1 << (i & 7))) { packet->options[end + OPT_DATA + len] = i; len++; } @@ -642,12 +602,12 @@ static void add_client_options(struct dhcp_packet *packet) packet->options[end + OPT_DATA + len] = DHCP_END; } - if (client_config.vendorclass) - udhcp_add_binary_option(packet, client_config.vendorclass); - if (client_config.hostname) - udhcp_add_binary_option(packet, client_config.hostname); - if (client_config.fqdn) - udhcp_add_binary_option(packet, client_config.fqdn); + if (client_data.vendorclass) + udhcp_add_binary_option(packet, client_data.vendorclass); + if (client_data.hostname) + udhcp_add_binary_option(packet, client_data.hostname); + if (client_data.fqdn) + udhcp_add_binary_option(packet, client_data.fqdn); /* Request broadcast replies if we have no IP addr */ if ((option_mask32 & OPT_B) && packet->ciaddr == 0) @@ -655,15 +615,15 @@ static void add_client_options(struct dhcp_packet *packet) /* Add -x options if any */ { - struct option_set *curr = client_config.options; + struct option_set *curr = client_data.options; while (curr) { udhcp_add_binary_option(packet, curr->data); curr = curr->next; } -// if (client_config.sname) -// strncpy((char*)packet->sname, client_config.sname, sizeof(packet->sname) - 1); -// if (client_config.boot_file) -// strncpy((char*)packet->file, client_config.boot_file, sizeof(packet->file) - 1); +// if (client_data.sname) +// strncpy((char*)packet->sname, client_data.sname, sizeof(packet->sname) - 1); +// if (client_data.boot_file) +// strncpy((char*)packet->file, client_data.boot_file, sizeof(packet->file) - 1); } // This will be needed if we remove -V VENDOR_STR in favor of @@ -691,12 +651,12 @@ static void add_client_options(struct dhcp_packet *packet) * client reverts to using the IP broadcast address. */ -static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet, uint32_t src_nip) +static int raw_bcast_from_client_data_ifindex(struct dhcp_packet *packet, uint32_t src_nip) { return udhcp_send_raw_packet(packet, /*src*/ src_nip, CLIENT_PORT, /*dst*/ INADDR_BROADCAST, SERVER_PORT, MAC_BCAST_ADDR, - client_config.ifindex); + client_data.ifindex); } static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t server) @@ -705,7 +665,7 @@ static int bcast_or_ucast(struct dhcp_packet *packet, uint32_t ciaddr, uint32_t return udhcp_send_kernel_packet(packet, ciaddr, CLIENT_PORT, server, SERVER_PORT); - return raw_bcast_from_client_config_ifindex(packet, ciaddr); + return raw_bcast_from_client_data_ifindex(packet, ciaddr); } /* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ @@ -730,8 +690,8 @@ static NOINLINE int send_discover(uint32_t xid, uint32_t requested) */ add_client_options(&packet); - bb_error_msg("sending %s", "discover"); - return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + bb_info_msg("sending %s", "discover"); + return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); } /* Broadcast a DHCP request message */ @@ -774,8 +734,8 @@ static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requeste add_client_options(&packet); temp_addr.s_addr = requested; - bb_error_msg("sending select for %s", inet_ntoa(temp_addr)); - return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + bb_info_msg("sending select for %s", inet_ntoa(temp_addr)); + return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); } /* Unicast or broadcast a DHCP renew message */ @@ -815,7 +775,7 @@ static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) add_client_options(&packet); temp_addr.s_addr = server; - bb_error_msg("sending renew to %s", inet_ntoa(temp_addr)); + bb_info_msg("sending renew to %s", inet_ntoa(temp_addr)); return bcast_or_ucast(&packet, ciaddr, server); } @@ -844,8 +804,8 @@ static NOINLINE int send_decline(/*uint32_t xid,*/ uint32_t server, uint32_t req udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); - bb_error_msg("sending %s", "decline"); - return raw_bcast_from_client_config_ifindex(&packet, INADDR_ANY); + bb_info_msg("sending %s", "decline"); + return raw_bcast_from_client_data_ifindex(&packet, INADDR_ANY); } #endif @@ -866,7 +826,7 @@ int send_release(uint32_t server, uint32_t ciaddr) udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); - bb_error_msg("sending %s", "release"); + bb_info_msg("sending %s", "release"); /* Note: normally we unicast here since "server" is not zero. * However, there _are_ people who run "address-less" DHCP servers, * and reportedly ISC dhcp client and Windows allow that. @@ -901,7 +861,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) if (bytes < 0) { if (errno == EINTR) continue; - log1("packet read error, ignoring"); + log1s("packet read error, ignoring"); /* NB: possible down interface, etc. Caller should pause. */ return bytes; /* returns -1 */ } @@ -909,13 +869,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) } if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { - log1("packet is too short, ignoring"); + log1s("packet is too short, ignoring"); return -2; } if (bytes < ntohs(packet.ip.tot_len)) { /* packet is bigger than sizeof(packet), we did partial read */ - log1("oversized packet, ignoring"); + log1s("oversized packet, ignoring"); return -2; } @@ -930,7 +890,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) /* || bytes > (int) sizeof(packet) - can't happen */ || ntohs(packet.udp.len) != (uint16_t)(bytes - sizeof(packet.ip)) ) { - log1("unrelated/bogus packet, ignoring"); + log1s("unrelated/bogus packet, ignoring"); return -2; } @@ -938,7 +898,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) check = packet.ip.check; packet.ip.check = 0; if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { - log1("bad IP header checksum, ignoring"); + log1s("bad IP header checksum, ignoring"); return -2; } @@ -963,13 +923,13 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) check = packet.udp.check; packet.udp.check = 0; if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { - log1("packet with bad UDP checksum received, ignoring"); + log1s("packet with bad UDP checksum received, ignoring"); return -2; } skip_udp_sum_check: if (packet.data.cookie != htonl(DHCP_MAGIC)) { - bb_error_msg("packet with bad magic, ignoring"); + bb_simple_info_msg("packet with bad magic, ignoring"); return -2; } @@ -984,13 +944,12 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) /*** Main ***/ -static int sockfd = -1; - +/* Values for client_data.listen_mode */ #define LISTEN_NONE 0 #define LISTEN_KERNEL 1 #define LISTEN_RAW 2 -static smallint listen_mode; +/* Values for client_data.state */ /* initial state: (re)start DHCP negotiation */ #define INIT_SELECTING 0 /* discover was sent, DHCPOFFER reply received */ @@ -1005,7 +964,6 @@ static smallint listen_mode; #define RENEW_REQUESTED 5 /* release, possibly manually requested (SIGUSR2) */ #define RELEASED 6 -static smallint state; static int udhcp_raw_socket(int ifindex) { @@ -1019,7 +977,7 @@ static int udhcp_raw_socket(int ifindex) * SOCK_DGRAM: remove link-layer headers on input (SOCK_RAW keeps them) * ETH_P_IP: want to receive only packets with IPv4 eth type */ - log2("got raw socket fd"); + log3("got raw socket fd %d", fd); memset(&sock, 0, sizeof(sock)); /* let's be deterministic */ sock.sll_family = AF_PACKET; @@ -1086,10 +1044,10 @@ static int udhcp_raw_socket(int ifindex) if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { if (errno != ENOPROTOOPT) - log1("can't set PACKET_AUXDATA on raw socket"); + log1s("can't set PACKET_AUXDATA on raw socket"); } - log1("created raw socket"); + log1s("created raw socket"); return fd; } @@ -1102,35 +1060,35 @@ static void change_listen_mode(int new_mode) : "none" ); - listen_mode = new_mode; - if (sockfd >= 0) { - close(sockfd); - sockfd = -1; + client_data.listen_mode = new_mode; + if (client_data.sockfd >= 0) { + close(client_data.sockfd); + client_data.sockfd = -1; } if (new_mode == LISTEN_KERNEL) - sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_config.interface); + client_data.sockfd = udhcp_listen_socket(/*INADDR_ANY,*/ CLIENT_PORT, client_data.interface); else if (new_mode != LISTEN_NONE) - sockfd = udhcp_raw_socket(client_config.ifindex); - /* else LISTEN_NONE: sockfd stays closed */ + client_data.sockfd = udhcp_raw_socket(client_data.ifindex); + /* else LISTEN_NONE: client_data.sockfd stays closed */ } /* Called only on SIGUSR1 */ static void perform_renew(void) { - bb_error_msg("performing DHCP renew"); - switch (state) { + bb_simple_info_msg("performing DHCP renew"); + switch (client_data.state) { case BOUND: change_listen_mode(LISTEN_KERNEL); case RENEWING: case REBINDING: - state = RENEW_REQUESTED; + client_data.state = RENEW_REQUESTED; break; case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ udhcp_run_script(NULL, "deconfig"); case REQUESTING: case RELEASED: change_listen_mode(LISTEN_RAW); - state = INIT_SELECTING; + client_data.state = INIT_SELECTING; break; case INIT_SELECTING: break; @@ -1143,19 +1101,19 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) struct in_addr temp_addr; /* send release packet */ - if (state == BOUND - || state == RENEWING - || state == REBINDING - || state == RENEW_REQUESTED + if (client_data.state == BOUND + || client_data.state == RENEWING + || client_data.state == REBINDING + || client_data.state == RENEW_REQUESTED ) { temp_addr.s_addr = server_addr; strcpy(buffer, inet_ntoa(temp_addr)); temp_addr.s_addr = requested_ip; - bb_error_msg("unicasting a release of %s to %s", + bb_info_msg("unicasting a release of %s to %s", inet_ntoa(temp_addr), buffer); send_release(server_addr, requested_ip); /* unicast */ } - bb_error_msg("entering released state"); + bb_simple_info_msg("entering released state"); /* * We can be here on: SIGUSR2, * or on exit (SIGTERM) and -R "release on quit" is specified. @@ -1165,7 +1123,7 @@ static void perform_release(uint32_t server_addr, uint32_t requested_ip) udhcp_run_script(NULL, "deconfig"); change_listen_mode(LISTEN_NONE); - state = RELEASED; + client_data.state = RELEASED; } static uint8_t* alloc_dhcp_option(int code, const char *str, int extra) @@ -1185,7 +1143,7 @@ static void client_background(void) bb_daemonize(0); logmode &= ~LOGMODE_STDIO; /* rewrite pidfile, as our pid is different now */ - write_pidfile(client_config.pidfile); + write_pidfile(client_data.pidfile); } #endif @@ -1209,13 +1167,13 @@ static void client_background(void) //usage: "\n -t N Send up to N discover packets (default 3)" //usage: "\n -T SEC Pause between packets (default 3)" //usage: "\n -A SEC Wait if lease is not obtained (default 20)" +//usage: USE_FOR_MMU( +//usage: "\n -b Background if lease is not obtained" +//usage: ) //usage: "\n -n Exit if lease is not obtained" //usage: "\n -q Exit after obtaining lease" //usage: "\n -R Release IP on exit" //usage: "\n -f Run in foreground" -//usage: USE_FOR_MMU( -//usage: "\n -b Background if lease is not obtained" -//usage: ) //usage: "\n -S Log to syslog too" //usage: IF_FEATURE_UDHCPC_ARPING( //usage: "\n -a[MSEC] Validate offered address with ARP ping" @@ -1268,10 +1226,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Default options */ IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) - client_config.interface = "eth0"; - client_config.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; + client_data.interface = "eth0"; + client_data.script = CONFIG_UDHCPC_DEFAULT_SCRIPT; + client_data.sockfd = -1; str_V = "udhcp "BB_VER; + /* Make sure fd 0,1,2 are open */ + /* Set up the signal pipe on fds 3,4 - must be before openlog() */ + udhcp_sp_setup(); + /* Parse command line */ opt = getopt32long(argv, "^" /* O,x: list; -T,-t,-A take numeric param */ @@ -1283,9 +1246,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) "\0" IF_UDHCP_VERBOSE("vv") /* -v is a counter */ , udhcpc_longopts , &str_V, &str_h, &str_h, &str_F - , &client_config.interface, &client_config.pidfile /* i,p */ + , &client_data.interface, &client_data.pidfile /* i,p */ , &str_r /* r */ - , &client_config.script /* s */ + , &client_data.script /* s */ , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ , &list_O , &list_x @@ -1295,12 +1258,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) ); if (opt & (OPT_h|OPT_H)) { //msg added 2011-11 - bb_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); - client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); + bb_simple_error_msg("option -h NAME is deprecated, use -x hostname:NAME"); + client_data.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0); } if (opt & OPT_F) { /* FQDN option format: [0x51][len][flags][0][0] */ - client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); + client_data.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3); /* Flag bits: 0000NEOS * S: 1 = Client requests server to update A RR in DNS as well as PTR * O: 1 = Server indicates to client that DNS has been updated regardless @@ -1309,9 +1272,9 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * N: 1 = Client requests server to not update DNS (S must be 0 then) * Two [0] bytes which follow are deprecated and must be 0. */ - client_config.fqdn[OPT_DATA + 0] = 0x1; - /*client_config.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ - /*client_config.fqdn[OPT_DATA + 2] = 0; */ + client_data.fqdn[OPT_DATA + 0] = 0x1; + /*client_data.fqdn[OPT_DATA + 1] = 0; - xzalloc did it */ + /*client_data.fqdn[OPT_DATA + 2] = 0; */ } if (opt & OPT_r) requested_ip = inet_addr(str_r); @@ -1329,49 +1292,49 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) n = udhcp_option_idx(optstr, dhcp_option_strings); n = dhcp_optflags[n].code; } - client_config.opt_mask[n >> 3] |= 1 << (n & 7); + client_data.opt_mask[n >> 3] |= 1 << (n & 7); } if (!(opt & OPT_o)) { unsigned i, n; for (i = 0; (n = dhcp_optflags[i].code) != 0; i++) { if (dhcp_optflags[i].flags & OPTION_REQ) { - client_config.opt_mask[n >> 3] |= 1 << (n & 7); + client_data.opt_mask[n >> 3] |= 1 << (n & 7); } } } while (list_x) { char *optstr = xstrdup(llist_pop(&list_x)); - udhcp_str2optset(optstr, &client_config.options, + udhcp_str2optset(optstr, &client_data.options, dhcp_optflags, dhcp_option_strings, /*dhcpv6:*/ 0 ); free(optstr); } - if (udhcp_read_interface(client_config.interface, - &client_config.ifindex, + if (udhcp_read_interface(client_data.interface, + &client_data.ifindex, NULL, - client_config.client_mac) + client_data.client_mac) ) { return 1; } clientid_mac_ptr = NULL; - if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) { + if (!(opt & OPT_C) && !udhcp_find_option(client_data.options, DHCP_CLIENT_ID)) { /* not suppressed and not set, set the default client ID */ - client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); - client_config.clientid[OPT_DATA] = 1; /* type: ethernet */ - clientid_mac_ptr = client_config.clientid + OPT_DATA+1; - memcpy(clientid_mac_ptr, client_config.client_mac, 6); + client_data.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); + client_data.clientid[OPT_DATA] = 1; /* type: ethernet */ + clientid_mac_ptr = client_data.clientid + OPT_DATA+1; + memcpy(clientid_mac_ptr, client_data.client_mac, 6); } if (str_V[0] != '\0') { - // can drop -V, str_V, client_config.vendorclass, + // can drop -V, str_V, client_data.vendorclass, // but need to add "vendor" to the list of recognized // string opts for this to work; // and need to tweak add_client_options() too... // ...so the question is, should we? //bb_error_msg("option -V VENDOR is deprecated, use -x vendor:VENDOR"); - client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); + client_data.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); } #if !BB_MMU @@ -1386,18 +1349,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) logmode |= LOGMODE_SYSLOG; } - /* Make sure fd 0,1,2 are open */ - bb_sanitize_stdio(); /* Create pidfile */ - write_pidfile(client_config.pidfile); + write_pidfile(client_data.pidfile); /* Goes to stdout (unless NOMMU) and possibly syslog */ - bb_error_msg("started, v"BB_VER); - /* Set up the signal pipe */ - udhcp_sp_setup(); + bb_simple_info_msg("started, v"BB_VER); /* We want random_xid to be random... */ srand(monotonic_us()); - state = INIT_SELECTING; + client_data.state = INIT_SELECTING; udhcp_run_script(NULL, "deconfig"); change_listen_mode(LISTEN_RAW); packet_num = 0; @@ -1415,16 +1374,16 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* silence "uninitialized!" warning */ unsigned timestamp_before_wait = timestamp_before_wait; - //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); + //bb_error_msg("sockfd:%d, listen_mode:%d", client_data.sockfd, client_data.listen_mode); /* Was opening raw or udp socket here - * if (listen_mode != LISTEN_NONE && sockfd < 0), + * if (client_data.listen_mode != LISTEN_NONE && client_data.sockfd < 0), * but on fast network renew responses return faster * than we open sockets. Thus this code is moved * to change_listen_mode(). Thus we open listen socket * BEFORE we send renew request (see "case BOUND:"). */ - udhcp_sp_fd_set(pfds, sockfd); + udhcp_sp_fd_set(pfds, client_data.sockfd); tv = timeout - already_waited_sec; retval = 0; @@ -1440,7 +1399,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) continue; } /* Else: an error occurred, panic! */ - bb_perror_msg_and_die("poll"); + bb_simple_perror_msg_and_die("poll"); } } @@ -1453,20 +1412,20 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * or if the status of the bridge changed). * Refresh ifindex and client_mac: */ - if (udhcp_read_interface(client_config.interface, - &client_config.ifindex, + if (udhcp_read_interface(client_data.interface, + &client_data.ifindex, NULL, - client_config.client_mac) + client_data.client_mac) ) { goto ret0; /* iface is gone? */ } if (clientid_mac_ptr) - memcpy(clientid_mac_ptr, client_config.client_mac, 6); + memcpy(clientid_mac_ptr, client_data.client_mac, 6); /* We will restart the wait in any case */ already_waited_sec = 0; - switch (state) { + switch (client_data.state) { case INIT_SELECTING: if (!discover_retries || packet_num < discover_retries) { if (packet_num == 0) @@ -1481,14 +1440,20 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) udhcp_run_script(NULL, "leasefail"); #if BB_MMU /* -b is not supported on NOMMU */ if (opt & OPT_b) { /* background if no lease */ - bb_error_msg("no lease, forking to background"); + bb_simple_info_msg("no lease, forking to background"); client_background(); /* do not background again! */ - opt = ((opt & ~OPT_b) | OPT_f); + opt = ((opt & ~(OPT_b|OPT_n)) | OPT_f); + /* ^^^ also disables -n (-b takes priority over -n): + * ifup's default udhcpc options are -R -n, + * and users want to be able to add -b + * (in a config file) to make it background + * _and not exit_. + */ } else #endif if (opt & OPT_n) { /* abort if no lease */ - bb_error_msg("no lease, failing"); + bb_simple_info_msg("no lease, failing"); retval = 1; goto ret; } @@ -1509,14 +1474,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * were seen in the wild. Treat them similarly * to "no response to discover" case */ change_listen_mode(LISTEN_RAW); - state = INIT_SELECTING; + client_data.state = INIT_SELECTING; goto leasefail; case BOUND: /* 1/2 lease passed, enter renewing state */ - state = RENEWING; - client_config.first_secs = 0; /* make secs field count from 0 */ + client_data.state = RENEWING; + client_data.first_secs = 0; /* make secs field count from 0 */ change_listen_mode(LISTEN_KERNEL); - log1("entering renew state"); + log1s("entering renew state"); /* fall right through */ case RENEW_REQUESTED: /* manual (SIGUSR1) renew */ case_RENEW_REQUESTED: @@ -1549,8 +1514,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) */ } /* Timed out or error, enter rebinding state */ - log1("entering rebinding state"); - state = REBINDING; + log1s("entering rebinding state"); + client_data.state = REBINDING; /* fall right through */ case REBINDING: /* Switch to bcast receive */ @@ -1564,10 +1529,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) continue; } /* Timed out, enter init state */ - bb_error_msg("lease lost, entering init state"); + bb_simple_info_msg("lease lost, entering init state"); udhcp_run_script(NULL, "deconfig"); - state = INIT_SELECTING; - client_config.first_secs = 0; /* make secs field count from 0 */ + client_data.state = INIT_SELECTING; + client_data.first_secs = 0; /* make secs field count from 0 */ /*timeout = 0; - already is */ packet_num = 0; continue; @@ -1583,10 +1548,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Is it a signal? */ switch (udhcp_sp_read()) { case SIGUSR1: - client_config.first_secs = 0; /* make secs field count from 0 */ + client_data.first_secs = 0; /* make secs field count from 0 */ already_waited_sec = 0; perform_renew(); - if (state == RENEW_REQUESTED) { + if (client_data.state == RENEW_REQUESTED) { /* We might be either on the same network * (in which case renew might work), * or we might be on a completely different one @@ -1609,7 +1574,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) timeout = INT_MAX; continue; case SIGTERM: - bb_error_msg("received %s", "SIGTERM"); + bb_info_msg("received %s", "SIGTERM"); goto ret0; } @@ -1621,15 +1586,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) int len; /* A packet is ready, read it */ - if (listen_mode == LISTEN_KERNEL) - len = udhcp_recv_kernel_packet(&packet, sockfd); + if (client_data.listen_mode == LISTEN_KERNEL) + len = udhcp_recv_kernel_packet(&packet, client_data.sockfd); else - len = udhcp_recv_raw_packet(&packet, sockfd); + len = udhcp_recv_raw_packet(&packet, client_data.sockfd); if (len == -1) { /* Error is severe, reopen socket */ bb_error_msg("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO); sleep(discover_timeout); /* 3 seconds by default */ - change_listen_mode(listen_mode); /* just close and reopen */ + change_listen_mode(client_data.listen_mode); /* just close and reopen */ } /* If this packet will turn out to be unrelated/bogus, * we will go back and wait for next one. @@ -1647,20 +1612,20 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) /* Ignore packets that aren't for us */ if (packet.hlen != 6 - || memcmp(packet.chaddr, client_config.client_mac, 6) != 0 + || memcmp(packet.chaddr, client_data.client_mac, 6) != 0 ) { //FIXME: need to also check that last 10 bytes are zero - log1("chaddr does not match, ignoring packet"); // log2? + log1("chaddr does not match%s", ", ignoring packet"); // log2? continue; } message = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE); if (message == NULL) { - bb_error_msg("no message type option, ignoring packet"); + bb_info_msg("no message type option%s", ", ignoring packet"); continue; } - switch (state) { + switch (client_data.state) { case INIT_SELECTING: /* Must be a DHCPOFFER */ if (*message == DHCPOFFER) { @@ -1685,7 +1650,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) * might work too. * "Next server" and router are definitely wrong ones to use, though... */ -/* We used to ignore pcakets without DHCP_SERVER_ID. +/* We used to ignore packets without DHCP_SERVER_ID. * I've got user reports from people who run "address-less" servers. * They either supply DHCP_SERVER_ID of 0.0.0.0 or don't supply it at all. * They say ISC DHCP client supports this case. @@ -1693,7 +1658,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) server_addr = 0; temp = udhcp_get_option32(&packet, DHCP_SERVER_ID); if (!temp) { - bb_error_msg("no server ID, using 0.0.0.0"); + bb_simple_info_msg("no server ID, using 0.0.0.0"); } else { /* it IS unaligned sometimes, don't "optimize" */ move_from_unaligned32(server_addr, temp); @@ -1702,7 +1667,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) requested_ip = packet.yiaddr; /* enter requesting state */ - state = REQUESTING; + client_data.state = REQUESTING; timeout = 0; packet_num = 0; already_waited_sec = 0; @@ -1720,7 +1685,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME); if (!temp) { - bb_error_msg("no lease time with ACK, using 1 hour lease"); + bb_simple_info_msg("no lease time with ACK, using 1 hour lease"); lease_seconds = 60 * 60; } else { /* it IS unaligned sometimes, don't "optimize" */ @@ -1749,19 +1714,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) if (!arpping(packet.yiaddr, NULL, (uint32_t) 0, - client_config.client_mac, - client_config.interface, + client_data.client_mac, + client_data.interface, arpping_ms) ) { - bb_error_msg("offered address is in use " + bb_simple_info_msg("offered address is in use " "(got ARP reply), declining"); send_decline(/*xid,*/ server_addr, packet.yiaddr); - if (state != REQUESTING) + if (client_data.state != REQUESTING) udhcp_run_script(NULL, "deconfig"); change_listen_mode(LISTEN_RAW); - state = INIT_SELECTING; - client_config.first_secs = 0; /* make secs field count from 0 */ + client_data.state = INIT_SELECTING; + client_data.first_secs = 0; /* make secs field count from 0 */ requested_ip = 0; timeout = tryagain_timeout; packet_num = 0; @@ -1772,12 +1737,12 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) #endif /* enter bound state */ temp_addr.s_addr = packet.yiaddr; - bb_error_msg("lease of %s obtained, lease time %u", + bb_info_msg("lease of %s obtained, lease time %u", inet_ntoa(temp_addr), (unsigned)lease_seconds); requested_ip = packet.yiaddr; start = monotonic_sec(); - udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); + udhcp_run_script(&packet, client_data.state == REQUESTING ? "bound" : "renew"); already_waited_sec = (unsigned)monotonic_sec() - start; timeout = lease_seconds / 2; if ((unsigned)timeout < already_waited_sec) { @@ -1785,7 +1750,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) timeout = already_waited_sec = 0; } - state = BOUND; + client_data.state = BOUND; change_listen_mode(LISTEN_NONE); if (opt & OPT_q) { /* quit after lease */ goto ret0; @@ -1817,7 +1782,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) if (!temp) { non_matching_svid: log1("received DHCP NAK with wrong" - " server ID, ignoring packet"); + " server ID%s", ", ignoring packet"); continue; } move_from_unaligned32(svid, temp); @@ -1825,14 +1790,14 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) goto non_matching_svid; } /* return to init state */ - bb_error_msg("received %s", "DHCP NAK"); + bb_info_msg("received %s", "DHCP NAK"); udhcp_run_script(&packet, "nak"); - if (state != REQUESTING) + if (client_data.state != REQUESTING) udhcp_run_script(NULL, "deconfig"); change_listen_mode(LISTEN_RAW); sleep(3); /* avoid excessive network traffic */ - state = INIT_SELECTING; - client_config.first_secs = 0; /* make secs field count from 0 */ + client_data.state = INIT_SELECTING; + client_data.first_secs = 0; /* make secs field count from 0 */ requested_ip = 0; timeout = 0; packet_num = 0; @@ -1850,7 +1815,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) perform_release(server_addr, requested_ip); retval = 0; ret: - /*if (client_config.pidfile) - remove_pidfile has its own check */ - remove_pidfile(client_config.pidfile); + /*if (client_data.pidfile) - remove_pidfile has its own check */ + remove_pidfile(client_data.pidfile); return retval; }