X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fdhcp-client.c;h=460fedf90f8f12812081efab1b6ae40217e7e9f4;hb=5d69c233557908e25f25acaa8d21da10de1a2868;hp=98f9b445219d400c6be93be8518958d81d58a958;hpb=295b175a8499f2e907dba0b9b1d96d72dd716aea;p=sliver-openvswitch.git diff --git a/lib/dhcp-client.c b/lib/dhcp-client.c index 98f9b4452..460fedf90 100644 --- a/lib/dhcp-client.c +++ b/lib/dhcp-client.c @@ -31,6 +31,7 @@ * derivatives without specific, written prior permission. */ +#include #include "dhcp-client.h" #include #include @@ -39,15 +40,18 @@ #include #include #include +#include #include -#include "buffer.h" +#include #include "csum.h" #include "dhcp.h" #include "dynamic-string.h" #include "flow.h" #include "netdev.h" -#include "ofp-print.h" +#include "ofpbuf.h" #include "poll-loop.h" +#include "sat-math.h" +#include "timeval.h" #define THIS_MODULE VLM_dhcp_client #include "vlog.h" @@ -68,6 +72,8 @@ enum dhclient_state { #undef DHCLIENT_STATE }; +static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(60, 60); + static const char * state_name(enum dhclient_state state) { @@ -97,6 +103,7 @@ struct dhclient { bool changed; unsigned int retransmit, delay; /* Used by send_reliably(). */ + unsigned int max_timeout; unsigned int init_delay; /* Used by S_INIT. */ @@ -136,9 +143,6 @@ static unsigned int calc_t2(unsigned int lease); static unsigned int calc_t1(unsigned int lease, unsigned int t2); static unsigned int clamp(unsigned int x, unsigned int min, unsigned int max); -static unsigned int sat_add(unsigned int x, unsigned int y); -static unsigned int sat_sub(unsigned int x, unsigned int y); -static unsigned int sat_mul(unsigned int x, unsigned int y); /* Creates a new DHCP client to configure the network device 'netdev_name' * (e.g. "eth0"). @@ -163,7 +167,6 @@ dhclient_create(const char *netdev_name, bool (*validate_offer)(const struct dhcp_msg *, void *aux), void *aux, struct dhclient **cli_) { - struct in_addr any = { INADDR_ANY }; struct dhclient *cli; struct netdev *netdev; int error; @@ -178,9 +181,9 @@ dhclient_create(const char *netdev_name, return error; } - error = netdev_set_in4(netdev, any, any); + error = netdev_turn_flags_on(netdev, NETDEV_UP, false); if (error) { - VLOG_ERR("could not remove IPv4 address from %s network device: %s", + VLOG_ERR("could not bring %s device up: %s", netdev_name, strerror(error)); netdev_close(netdev); return error; @@ -192,11 +195,12 @@ dhclient_create(const char *netdev_name, cli->aux = aux; cli->netdev = netdev; cli->state = S_RELEASED; - cli->state_entered = time(0); + cli->state_entered = time_now(); cli->xid = random_uint32(); cli->ipaddr = 0; cli->server_ip = 0; cli->retransmit = cli->delay = 0; + cli->max_timeout = 64; cli->min_timeout = 1; ds_init(&cli->s); cli->changed = true; @@ -204,6 +208,36 @@ dhclient_create(const char *netdev_name, return 0; } +/* Sets the maximum amount of timeout that 'cli' will wait for a reply from + * the DHCP server before retransmitting, in seconds, to 'max_timeout'. The + * default is 64 seconds. */ +void +dhclient_set_max_timeout(struct dhclient *cli, unsigned int max_timeout) +{ + cli->max_timeout = MAX(2, max_timeout); +} + +/* Destroys 'cli' and frees all related resources. */ +void +dhclient_destroy(struct dhclient *cli) +{ + if (cli) { + dhcp_msg_uninit(cli->binding); + free(cli->binding); + netdev_close(cli->netdev); + ds_destroy(&cli->s); + free(cli); + } +} + +/* Returns the network device in use by 'cli'. The caller must not destroy + * the returned device. */ +struct netdev * +dhclient_get_netdev(struct dhclient *cli) +{ + return cli->netdev; +} + /* Forces 'cli' into a (re)initialization state, in which no address is bound * but the client is advertising to obtain one. If 'requested_ip' is nonzero, * then the client will attempt to re-bind to that IP address; otherwise, it @@ -213,7 +247,6 @@ dhclient_init(struct dhclient *cli, uint32_t requested_ip) { state_transition(cli, requested_ip ? S_INIT_REBOOT : S_INIT); cli->ipaddr = requested_ip; - cli->changed = true; cli->min_timeout = 0; cli->init_delay = 0; } @@ -237,7 +270,7 @@ dhclient_release(struct dhclient *cli) static void do_force_renew(struct dhclient *cli, int deadline) { - time_t now = time(0); + time_t now = time_now(); unsigned int lease_left = sat_sub(cli->lease_expiration, now); if (lease_left <= deadline) { if (cli->state & (S_RENEWING | S_REBINDING)) { @@ -303,6 +336,29 @@ dhclient_changed(struct dhclient *cli) return changed; } +/* Returns 'cli''s current state, as a string. The caller must not modify or + * free the string. */ +const char * +dhclient_get_state(const struct dhclient *cli) +{ + return state_name(cli->state); +} + +/* Returns the number of seconds spent so far in 'cli''s current state. */ +unsigned int +dhclient_get_state_elapsed(const struct dhclient *cli) +{ + return elapsed_in_this_state(cli); +} + +/* If 'cli' is bound, returns the number of seconds remaining in its lease; + * otherwise, returns 0. */ +unsigned int +dhclient_get_lease_remaining(const struct dhclient *cli) +{ + return dhclient_is_bound(cli) ? cli->lease_expiration - time_now() : 0; +} + /* If 'cli' is bound to an IP address, returns that IP address; otherwise, * returns 0. */ uint32_t @@ -319,6 +375,14 @@ dhclient_get_netmask(const struct dhclient *cli) return dhclient_is_bound(cli) ? cli->netmask : 0; } +/* If 'cli' is bound to an IP address and 'cli' has a default gateway, returns + * that default gateway; otherwise, returns 0. */ +uint32_t +dhclient_get_router(const struct dhclient *cli) +{ + return dhclient_is_bound(cli) ? cli->router : 0; +} + /* If 'cli' is bound to an IP address, returns the DHCP message that was * received to obtain that IP address (so that the caller can obtain additional * options from it). Otherwise, returns a null pointer. */ @@ -327,6 +391,128 @@ dhclient_get_config(const struct dhclient *cli) { return dhclient_is_bound(cli) ? cli->binding : NULL; } + +/* Configures the network device backing 'cli' to the network address and other + * parameters obtained via DHCP. If no address is bound on 'cli', removes any + * configured address from 'cli'. + * + * To use a dhclient as a regular DHCP client that binds and unbinds from IP + * addresses in the usual fashion, call this function after dhclient_run() if + * anything has changed, like so: + * + * dhclient_run(cli); + * if (dhclient_changed(cli)) { + * dhclient_configure_netdev(cli); + * } + * + */ +int +dhclient_configure_netdev(struct dhclient *cli) +{ + struct in_addr addr = { dhclient_get_ip(cli) }; + struct in_addr mask = { dhclient_get_netmask(cli) }; + struct in_addr router = { dhclient_get_router(cli) }; + int error; + + error = netdev_set_in4(cli->netdev, addr, mask); + if (error) { + VLOG_ERR("could not set %s address "IP_FMT"/"IP_FMT": %s", + netdev_get_name(cli->netdev), + IP_ARGS(&addr.s_addr), IP_ARGS(&mask.s_addr), + strerror(error)); + } + + if (!error && router.s_addr) { + error = netdev_add_router(cli->netdev, router); + if (error) { + VLOG_ERR("failed to add default route to "IP_FMT" on %s: %s", + IP_ARGS(&router), netdev_get_name(cli->netdev), + strerror(error)); + } + } + + return error; +} + +/* If 'cli' is bound and the binding includes DNS domain parameters, updates + * /etc/resolv.conf will be updated to match the received parameters. Returns + * 0 if successful, otherwise a positive errno value. */ +int +dhclient_update_resolv_conf(struct dhclient *cli) +{ + uint32_t dns_server; + char *domain_name; + bool has_domain_name; + char new_name[128]; + FILE *old, *new; + int i; + + if (!dhclient_is_bound(cli)) { + return 0; + } + if (!dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, 0, &dns_server)) { + VLOG_DBG("binding does not include any DNS servers"); + return 0; + } + + sprintf(new_name, "/etc/resolv.conf.tmp%ld", (long int) getpid()); + new = fopen(new_name, "w"); + if (!new) { + VLOG_WARN("%s: create: %s", new_name, strerror(errno)); + return errno; + } + + domain_name = dhcp_msg_get_string(cli->binding, DHCP_CODE_DOMAIN_NAME); + has_domain_name = domain_name != NULL; + if (domain_name) { + if (strspn(domain_name, "-_.0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(domain_name)) { + fprintf(new, "domain %s\n", domain_name); + } else { + VLOG_WARN("ignoring invalid domain name %s", domain_name); + has_domain_name = false; + } + } else { + VLOG_DBG("binding does not include domain name"); + } + free(domain_name); + + for (i = 0; dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, + i, &dns_server); i++) { + fprintf(new, "nameserver "IP_FMT"\n", IP_ARGS(&dns_server)); + } + + old = fopen("/etc/resolv.conf", "r"); + if (old) { + char line[128]; + + while (fgets(line, sizeof line, old)) { + char *kw = xmemdup0(line, strcspn(line, " \t\r\n")); + if (strcmp(kw, "nameserver") + && (!has_domain_name + || (strcmp(kw, "domain") && strcmp(kw, "search")))) { + fputs(line, new); + } + free(kw); + } + fclose(old); + } else { + VLOG_DBG("/etc/resolv.conf: open: %s", strerror(errno)); + } + + if (fclose(new) < 0) { + VLOG_WARN("%s: close: %s", new_name, strerror(errno)); + return errno; + } + + if (rename(new_name, "/etc/resolv.conf") < 0) { + VLOG_WARN("failed to rename %s to /etc/resolv.conf: %s", + new_name, strerror(errno)); + return errno; + } + + return 0; +} /* DHCP protocol. */ @@ -355,7 +541,7 @@ static void do_init(struct dhclient *cli, enum dhclient_state next_state) { if (!cli->init_delay) { - cli->init_delay = clamp(fuzz(2, 8), 1, 10); + cli->init_delay = fuzz(2, 1); } if (timeout(cli, cli->init_delay)) { state_transition(cli, next_state); @@ -388,13 +574,15 @@ dhcp_receive(struct dhclient *cli, unsigned int msgs, struct dhcp_msg *msg) { while (do_receive_msg(cli, msg)) { if (msg->type < 0 || msg->type > 31 || !((1u << msg->type) & msgs)) { - VLOG_DBG("received unexpected %s in %s state: %s", - dhcp_type_name(msg->type), state_name(cli->state), - dhcp_msg_to_string(msg, &cli->s)); + VLOG_DBG_RL(&rl, "received unexpected %s in %s state: %s", + dhcp_type_name(msg->type), state_name(cli->state), + dhcp_msg_to_string(msg, false, &cli->s)); } else if (msg->xid != cli->xid) { - VLOG_DBG("ignoring %s with xid != %08"PRIx32" in %s state: %s", - dhcp_type_name(msg->type), msg->xid, - state_name(cli->state), dhcp_msg_to_string(msg, &cli->s)); + VLOG_DBG_RL(&rl, + "ignoring %s with xid != %08"PRIx32" in %s state: %s", + dhcp_type_name(msg->type), msg->xid, + state_name(cli->state), + dhcp_msg_to_string(msg, false, &cli->s)); } else { return true; } @@ -408,18 +596,18 @@ validate_offered_options(struct dhclient *cli, const struct dhcp_msg *msg) { uint32_t lease, netmask; if (!dhcp_msg_get_secs(msg, DHCP_CODE_LEASE_TIME, 0, &lease)) { - VLOG_WARN("%s lacks lease time: %s", - dhcp_type_name(msg->type), dhcp_msg_to_string(msg, &cli->s)); + VLOG_WARN_RL(&rl, "%s lacks lease time: %s", dhcp_type_name(msg->type), + dhcp_msg_to_string(msg, false, &cli->s)); } else if (!dhcp_msg_get_ip(msg, DHCP_CODE_SUBNET_MASK, 0, &netmask)) { - VLOG_WARN("%s lacks netmask: %s", - dhcp_type_name(msg->type), dhcp_msg_to_string(msg, &cli->s)); + VLOG_WARN_RL(&rl, "%s lacks netmask: %s", dhcp_type_name(msg->type), + dhcp_msg_to_string(msg, false, &cli->s)); } else if (lease < MIN_ACCEPTABLE_LEASE) { - VLOG_WARN("Ignoring %s with %"PRIu32"-second lease time: %s", - dhcp_type_name(msg->type), lease, - dhcp_msg_to_string(msg, &cli->s)); + VLOG_WARN_RL(&rl, "Ignoring %s with %"PRIu32"-second lease time: %s", + dhcp_type_name(msg->type), lease, + dhcp_msg_to_string(msg, false, &cli->s)); } else if (cli->validate_offer && !cli->validate_offer(msg, cli->aux)) { - VLOG_DBG("client validation hook refused offer: %s", - dhcp_msg_to_string(msg, &cli->s)); + VLOG_DBG_RL(&rl, "client validation hook refused offer: %s", + dhcp_msg_to_string(msg, false, &cli->s)); } else { return true; } @@ -442,18 +630,65 @@ dhclient_run_SELECTING(struct dhclient *cli) } if (!dhcp_msg_get_ip(&msg, DHCP_CODE_SERVER_IDENTIFIER, 0, &cli->server_ip)) { - VLOG_WARN("DHCPOFFER lacks server identifier: %s", - dhcp_msg_to_string(&msg, &cli->s)); + VLOG_WARN_RL(&rl, "DHCPOFFER lacks server identifier: %s", + dhcp_msg_to_string(&msg, false, &cli->s)); continue; } - VLOG_DBG("accepting DHCPOFFER: %s", dhcp_msg_to_string(&msg, &cli->s)); + VLOG_DBG_RL(&rl, "accepting DHCPOFFER: %s", + dhcp_msg_to_string(&msg, false, &cli->s)); cli->ipaddr = msg.yiaddr; state_transition(cli, S_REQUESTING); break; } } +static bool +same_binding(const struct dhcp_msg *old, const struct dhcp_msg *new) +{ + static const int codes[] = { + DHCP_CODE_SUBNET_MASK, + DHCP_CODE_ROUTER, + DHCP_CODE_DNS_SERVER, + DHCP_CODE_HOST_NAME, + DHCP_CODE_DOMAIN_NAME, + DHCP_CODE_IP_TTL, + DHCP_CODE_MTU, + DHCP_CODE_BROADCAST_ADDRESS, + DHCP_CODE_STATIC_ROUTE, + DHCP_CODE_ARP_CACHE_TIMEOUT, + DHCP_CODE_ETHERNET_ENCAPSULATION, + DHCP_CODE_TCP_TTL, + DHCP_CODE_SERVER_IDENTIFIER, + DHCP_CODE_OFP_CONTROLLER_VCONN, + DHCP_CODE_OFP_PKI_URI, + }; + int i; + bool same = true; + + if (old->yiaddr != new->yiaddr) { + VLOG_WARN("DHCP binding changed IP address from "IP_FMT" to "IP_FMT, + IP_ARGS(&old->yiaddr), IP_ARGS(&new->yiaddr)); + same = false; + } + for (i = 0; i < ARRAY_SIZE(codes); i++) { + int code = codes[i]; + const struct dhcp_option *old_opt = &old->options[code]; + const struct dhcp_option *new_opt = &new->options[code]; + if (!dhcp_option_equals(old_opt, new_opt)) { + struct ds old_string = DS_EMPTY_INITIALIZER; + struct ds new_string = DS_EMPTY_INITIALIZER; + VLOG_WARN("DHCP binding changed option from %s to %s", + dhcp_option_to_string(old_opt, code, &old_string), + dhcp_option_to_string(new_opt, code, &new_string)); + ds_destroy(&old_string); + ds_destroy(&new_string); + same = false; + } + } + return same; +} + static bool receive_ack(struct dhclient *cli) { @@ -472,6 +707,9 @@ receive_ack(struct dhclient *cli) uint32_t lease = 0, t1 = 0, t2 = 0; if (cli->binding) { + if (!same_binding(cli->binding, &msg)) { + cli->changed = true; + } dhcp_msg_uninit(cli->binding); } else { cli->binding = xmalloc(sizeof *cli->binding); @@ -490,7 +728,7 @@ receive_ack(struct dhclient *cli) t1 = calc_t1(lease, t2); } - cli->lease_expiration = sat_add(time(0), lease); + cli->lease_expiration = sat_add(time_now(), lease); cli->bound_timeout = t1; cli->renewing_timeout = t2 - t1; cli->rebinding_timeout = lease - t2; @@ -501,7 +739,7 @@ receive_ack(struct dhclient *cli) cli->router = INADDR_ANY; } state_transition(cli, S_BOUND); - VLOG_DBG("Bound: %s", dhcp_msg_to_string(&msg, &cli->s)); + VLOG_DBG("Bound: %s", dhcp_msg_to_string(&msg, false, &cli->s)); return true; } } @@ -573,7 +811,13 @@ void dhclient_wait(struct dhclient *cli) { if (cli->min_timeout != UINT_MAX) { - poll_timer_wait(sat_mul(cli->min_timeout, 1000)); + time_t now = time_now(); + unsigned int wake = sat_add(cli->state_entered, cli->min_timeout); + if (wake <= now) { + poll_immediate_wake(); + } else { + poll_timer_wait(sat_mul(sat_sub(wake, now), 1000)); + } } /* Reset timeout to 1 second. This will have no effect ordinarily, because * dhclient_run() will typically set it back to a higher value. If, @@ -591,51 +835,31 @@ state_transition(struct dhclient *cli, enum dhclient_state state) { bool was_bound = dhclient_is_bound(cli); bool am_bound; - VLOG_DBG("entering %s", state_name(state)); - cli->state = state; - cli->state_entered = time(0); + if (cli->state != state) { + VLOG_DBG("entering %s", state_name(state)); + cli->state = state; + } + cli->state_entered = time_now(); cli->retransmit = cli->delay = 0; am_bound = dhclient_is_bound(cli); if (was_bound != am_bound) { - struct in_addr addr, mask; - int error; - cli->changed = true; if (am_bound) { - VLOG_WARN("%s: binding to "IP_FMT"/"IP_FMT, + assert(cli->binding != NULL); + VLOG_WARN("%s: obtained address "IP_FMT", netmask "IP_FMT, netdev_get_name(cli->netdev), IP_ARGS(&cli->ipaddr), IP_ARGS(&cli->netmask)); - addr.s_addr = cli->ipaddr; - mask.s_addr = cli->netmask; - } else { - VLOG_WARN("%s: unbinding IPv4 network address", - netdev_get_name(cli->netdev)); - addr.s_addr = mask.s_addr = INADDR_ANY; - } - error = netdev_set_in4(cli->netdev, addr, mask); - if (error) { - VLOG_ERR("could not set %s address "IP_FMT"/"IP_FMT": %s", - netdev_get_name(cli->netdev), - IP_ARGS(&addr.s_addr), IP_ARGS(&mask.s_addr), - strerror(error)); - } - if (am_bound && !error && cli->router) { - struct in_addr router = { cli->router }; - error = netdev_add_router(cli->netdev, router); - VLOG_WARN("%s: configuring router "IP_FMT, - netdev_get_name(cli->netdev), IP_ARGS(cli->router)); - if (error) { - VLOG_ERR("failed to add default route to "IP_FMT" on %s: %s", - IP_ARGS(&router), netdev_get_name(cli->netdev), - strerror(error)); + if (cli->router) { + VLOG_WARN("%s: obtained default gateway "IP_FMT, + netdev_get_name(cli->netdev), IP_ARGS(&cli->router)); } - } - if (am_bound) { - assert(cli->binding != NULL); } else { dhcp_msg_uninit(cli->binding); free(cli->binding); cli->binding = NULL; + + VLOG_WARN("%s: network address unbound", + netdev_get_name(cli->netdev)); } } if (cli->state & (S_SELECTING | S_REQUESTING | S_REBOOTING)) { @@ -654,7 +878,7 @@ send_reliably(struct dhclient *cli, cli->modify_request(&msg, cli->aux); } do_send_msg(cli, &msg); - cli->delay = MIN(64, MAX(4, cli->delay * 2)); + cli->delay = MIN(cli->max_timeout, MAX(4, cli->delay * 2)); cli->retransmit += fuzz(cli->delay, 1); timeout(cli, cli->retransmit); dhcp_msg_uninit(&msg); @@ -671,38 +895,37 @@ dhclient_msg_init(struct dhclient *cli, enum dhcp_msg_type type, msg->secs = cli->secs; msg->type = type; memcpy(msg->chaddr, netdev_get_etheraddr(cli->netdev), ETH_ADDR_LEN); - } static unsigned int elapsed_in_this_state(const struct dhclient *cli) { - return time(0) - cli->state_entered; + return time_now() - cli->state_entered; } static bool timeout(struct dhclient *cli, unsigned int secs) { cli->min_timeout = MIN(cli->min_timeout, secs); - return time(0) >= sat_add(cli->state_entered, secs); + return time_now() >= sat_add(cli->state_entered, secs); } static bool do_receive_msg(struct dhclient *cli, struct dhcp_msg *msg) { - struct buffer b; + struct ofpbuf b; - buffer_init(&b, netdev_get_mtu(cli->netdev) + VLAN_ETH_HEADER_LEN); + ofpbuf_init(&b, netdev_get_mtu(cli->netdev) + VLAN_ETH_HEADER_LEN); for (; cli->received < 50; cli->received++) { const struct ip_header *ip; const struct dhcp_header *dhcp; struct flow flow; int error; - buffer_clear(&b); + ofpbuf_clear(&b); error = netdev_recv(cli->netdev, &b); if (error) { - break; + goto drained; } flow_extract(&b, 0, &flow); @@ -718,41 +941,47 @@ do_receive_msg(struct dhclient *cli, struct dhcp_msg *msg) ip = b.l3; if (IP_IS_FRAGMENT(ip->ip_frag_off)) { /* We don't do reassembly. */ - VLOG_WARN("ignoring fragmented DHCP datagram"); + VLOG_WARN_RL(&rl, "ignoring fragmented DHCP datagram"); continue; } dhcp = b.l7; if (!dhcp) { - VLOG_WARN("ignoring DHCP datagram with missing payload"); + VLOG_WARN_RL(&rl, "ignoring DHCP datagram with missing payload"); continue; } - buffer_pull(&b, b.l7 - b.data); + ofpbuf_pull(&b, (char *)b.l7 - (char*)b.data); error = dhcp_parse(msg, &b); if (!error) { - VLOG_DBG("received %s", dhcp_msg_to_string(msg, &cli->s)); - buffer_uninit(&b); + if (VLOG_IS_DBG_ENABLED()) { + VLOG_DBG_RL(&rl, "received %s", + dhcp_msg_to_string(msg, false, &cli->s)); + } else { + VLOG_WARN_RL(&rl, "received %s", dhcp_type_name(msg->type)); + } + ofpbuf_uninit(&b); return true; } } netdev_drain(cli->netdev); - buffer_uninit(&b); +drained: + ofpbuf_uninit(&b); return false; } static void do_send_msg(struct dhclient *cli, const struct dhcp_msg *msg) { - struct buffer b; + struct ofpbuf b; struct eth_header eh; struct ip_header nh; struct udp_header th; uint32_t udp_csum; int error; - buffer_init(&b, ETH_TOTAL_MAX); - buffer_reserve(&b, ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN); + ofpbuf_init(&b, ETH_TOTAL_MAX); + ofpbuf_reserve(&b, ETH_HEADER_LEN + IP_HEADER_LEN + UDP_HEADER_LEN); dhcp_assemble(msg, &b); @@ -796,16 +1025,20 @@ do_send_msg(struct dhclient *cli, const struct dhcp_msg *msg) udp_csum = csum_continue(udp_csum, &th, sizeof th); th.udp_csum = csum_finish(csum_continue(udp_csum, b.data, b.size)); - buffer_push(&b, &th, sizeof th); - buffer_push(&b, &nh, sizeof nh); - buffer_push(&b, &eh, sizeof eh); + ofpbuf_push(&b, &th, sizeof th); + ofpbuf_push(&b, &nh, sizeof nh); + ofpbuf_push(&b, &eh, sizeof eh); /* Don't try to send the frame if it's too long for an Ethernet frame. We * disregard the network device's actual MTU because we don't want the * frame to have to be discarded or fragmented if it travels over a regular * Ethernet at some point. 1500 bytes should be enough for anyone. */ if (b.size <= ETH_TOTAL_MAX) { - VLOG_DBG("sending %s", dhcp_msg_to_string(msg, &cli->s)); + if (VLOG_IS_DBG_ENABLED()) { + VLOG_DBG("sending %s", dhcp_msg_to_string(msg, false, &cli->s)); + } else { + VLOG_WARN("sending %s", dhcp_type_name(msg->type)); + } error = netdev_send(cli->netdev, &b); if (error) { VLOG_ERR("send failed on %s: %s", @@ -815,7 +1048,7 @@ do_send_msg(struct dhclient *cli, const struct dhcp_msg *msg) VLOG_ERR("cannot send %zu-byte Ethernet frame", b.size); } - buffer_uninit(&b); + ofpbuf_uninit(&b); } static unsigned int @@ -827,25 +1060,6 @@ fuzz(unsigned int x, int max_fuzz) return fuzz >= 0 ? (y >= x ? y : UINT_MAX) : (y <= x ? y : 0); } -static unsigned int -sat_add(unsigned int x, unsigned int y) -{ - return x + y >= x ? x + y : UINT_MAX; -} - -static unsigned int -sat_sub(unsigned int x, unsigned int y) -{ - return x >= y ? x - y : 0; -} - -static unsigned int -sat_mul(unsigned int x, unsigned int y) -{ - assert(y); - return x <= UINT_MAX / y ? x * y : UINT_MAX; -} - static unsigned int clamp(unsigned int x, unsigned int min, unsigned int max) {