- * Copyright (c) 2008, 2009, 2010 Nicira Networks.
+ * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#define DHCLIENT_STATES \
DHCLIENT_STATE(INIT, 1 << 0) \
DHCLIENT_STATE(INIT_REBOOT, 1 << 1) \
#define DHCLIENT_STATES \
DHCLIENT_STATE(INIT, 1 << 0) \
DHCLIENT_STATE(INIT_REBOOT, 1 << 1) \
memset(&netdev_options, 0, sizeof netdev_options);
netdev_options.name = netdev_name;
netdev_options.ethertype = ETH_TYPE_IP;
memset(&netdev_options, 0, sizeof netdev_options);
netdev_options.name = netdev_name;
netdev_options.ethertype = ETH_TYPE_IP;
error = netdev_open(&netdev_options, &netdev);
/* XXX install socket filter to catch only DHCP packets. */
if (error) {
error = netdev_open(&netdev_options, &netdev);
/* XXX install socket filter to catch only DHCP packets. */
if (error) {
netdev_name, strerror(error));
return error;
}
error = netdev_turn_flags_on(netdev, NETDEV_UP, false);
if (error) {
netdev_name, strerror(error));
return error;
}
error = netdev_turn_flags_on(netdev, NETDEV_UP, false);
if (error) {
+/* Returns the name of the network device in use by 'cli'. The caller must
+ * not modify or destroy the returned string. */
+const char *
+dhclient_get_name(const struct dhclient *cli)
+{
+ return netdev_get_name(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
/* 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
struct in_addr addr = { dhclient_get_ip(cli) };
struct in_addr mask = { dhclient_get_netmask(cli) };
struct in_addr router = { dhclient_get_router(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) };
- 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),
+ VLOG_ERR("%s: could not set address "IP_FMT"/"IP_FMT" (%s)",
+ cli_name, 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) {
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));
+ VLOG_ERR("%s: failed to add default route to "IP_FMT" (%s)",
+ cli_name, IP_ARGS(&router), strerror(error));
return 0;
}
if (!dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, 0, &dns_server)) {
return 0;
}
if (!dhcp_msg_get_ip(cli->binding, DHCP_CODE_DNS_SERVER, 0, &dns_server)) {
return 0;
}
sprintf(new_name, "/etc/resolv.conf.tmp%ld", (long int) getpid());
new = fopen(new_name, "w");
if (!new) {
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));
+ VLOG_WARN("%s: could not create %s (%s)",
+ cli_name, new_name, strerror(errno));
"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(domain_name)) {
fprintf(new, "domain %s\n", domain_name);
} else {
"ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(domain_name)) {
fprintf(new, "domain %s\n", domain_name);
} else {
- VLOG_WARN("ignoring invalid domain name %s", domain_name);
+ VLOG_WARN("%s: ignoring invalid domain name %s",
+ cli_name, domain_name);
- VLOG_DBG("/etc/resolv.conf: open: %s", strerror(errno));
+ VLOG_DBG("%s: failed to open /etc/resolv.conf (%s)",
+ cli_name, strerror(errno));
- VLOG_WARN("%s: close: %s", new_name, strerror(errno));
+ VLOG_WARN("%s: closing %s failed (%s)",
+ cli_name, new_name, strerror(errno));
- VLOG_WARN("failed to rename %s to /etc/resolv.conf: %s",
- new_name, strerror(errno));
+ VLOG_WARN("%s: failed to rename %s to /etc/resolv.conf (%s)",
+ cli_name, new_name, strerror(errno));
dhcp_receive(struct dhclient *cli, unsigned int msgs, struct dhcp_msg *msg)
{
while (do_receive_msg(cli, msg)) {
dhcp_receive(struct dhclient *cli, unsigned int msgs, struct dhcp_msg *msg)
{
while (do_receive_msg(cli, msg)) {
dhcp_type_name(msg->type), state_name(cli->state),
dhcp_msg_to_string(msg, false, &cli->s));
} else if (msg->xid != cli->xid) {
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_RL(&rl,
- "ignoring %s with xid != %08"PRIx32" in %s state: %s",
+ VLOG_DBG_RL(&rl, "%s: ignoring %s with xid != %08"PRIx32" "
+ "in %s state: %s", cli_name,
dhcp_type_name(msg->type), msg->xid,
state_name(cli->state),
dhcp_msg_to_string(msg, false, &cli->s));
dhcp_type_name(msg->type), msg->xid,
state_name(cli->state),
dhcp_msg_to_string(msg, false, &cli->s));
if (!dhcp_msg_get_secs(msg, DHCP_CODE_LEASE_TIME, 0, &lease)) {
if (!dhcp_msg_get_secs(msg, DHCP_CODE_LEASE_TIME, 0, &lease)) {
- VLOG_WARN_RL(&rl, "%s lacks lease time: %s", dhcp_type_name(msg->type),
+ VLOG_WARN_RL(&rl, "%s: %s lacks lease time (%s)",
+ cli_name, 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)) {
dhcp_msg_to_string(msg, false, &cli->s));
} else if (!dhcp_msg_get_ip(msg, DHCP_CODE_SUBNET_MASK, 0, &netmask)) {
- VLOG_WARN_RL(&rl, "%s lacks netmask: %s", dhcp_type_name(msg->type),
+ VLOG_WARN_RL(&rl, "%s: %s lacks netmask (%s)",
+ cli_name, dhcp_type_name(msg->type),
dhcp_msg_to_string(msg, false, &cli->s));
} else if (lease < MIN_ACCEPTABLE_LEASE) {
dhcp_msg_to_string(msg, false, &cli->s));
} else if (lease < MIN_ACCEPTABLE_LEASE) {
- VLOG_WARN_RL(&rl, "Ignoring %s with %"PRIu32"-second lease time: %s",
+ VLOG_WARN_RL(&rl, "%s: ignoring %s with %"PRIu32"-second "
+ "lease time (%s)", cli_name,
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)) {
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_RL(&rl, "client validation hook refused offer: %s",
- dhcp_msg_to_string(msg, false, &cli->s));
+ VLOG_DBG_RL(&rl, "%s: client validation hook refused offer (%s)",
+ cli_name, dhcp_msg_to_string(msg, false, &cli->s));
- VLOG_WARN_RL(&rl, "DHCPOFFER lacks server identifier: %s",
- dhcp_msg_to_string(&msg, false, &cli->s));
+ VLOG_WARN_RL(&rl, "%s: DHCPOFFER lacks server identifier (%s)",
+ cli_name, dhcp_msg_to_string(&msg, false, &cli->s));
- VLOG_DBG_RL(&rl, "accepting DHCPOFFER: %s",
- dhcp_msg_to_string(&msg, false, &cli->s));
+ VLOG_DBG_RL(&rl, "%s: accepting DHCPOFFER (%s)",
+ cli_name, dhcp_msg_to_string(&msg, false, &cli->s));
cli->ipaddr = msg.yiaddr;
state_transition(cli, S_REQUESTING);
break;
cli->ipaddr = msg.yiaddr;
state_transition(cli, S_REQUESTING);
break;
-same_binding(const struct dhcp_msg *old, const struct dhcp_msg *new)
+same_binding(const char *cli_name,
+ const struct dhcp_msg *old, const struct dhcp_msg *new)
- VLOG_WARN("DHCP binding changed IP address from "IP_FMT" to "IP_FMT,
- IP_ARGS(&old->yiaddr), IP_ARGS(&new->yiaddr));
+ VLOG_WARN("%s: DHCP binding changed IP address "
+ "from "IP_FMT" to "IP_FMT,
+ cli_name, IP_ARGS(&old->yiaddr), IP_ARGS(&new->yiaddr));
if (!dhcp_option_equals(old_opt, new_opt)) {
struct ds old_string = DS_EMPTY_INITIALIZER;
struct ds new_string = DS_EMPTY_INITIALIZER;
if (!dhcp_option_equals(old_opt, new_opt)) {
struct ds old_string = DS_EMPTY_INITIALIZER;
struct ds new_string = DS_EMPTY_INITIALIZER;
dhcp_option_to_string(old_opt, code, &old_string),
dhcp_option_to_string(new_opt, code, &new_string));
ds_destroy(&old_string);
dhcp_option_to_string(old_opt, code, &old_string),
dhcp_option_to_string(new_opt, code, &new_string));
ds_destroy(&old_string);
cli->router = INADDR_ANY;
}
state_transition(cli, S_BOUND);
cli->router = INADDR_ANY;
}
state_transition(cli, S_BOUND);
- VLOG_DBG("Bound: %s", dhcp_msg_to_string(&msg, false, &cli->s));
+ VLOG_DBG("%s: bound (%s)", dhclient_get_name(cli),
+ dhcp_msg_to_string(&msg, false, &cli->s));
- 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));
- }
+ long long int wake = sat_add(cli->state_entered, cli->min_timeout);
+ poll_timer_wait_until(wake * 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,
}
/* Reset timeout to 1 second. This will have no effect ordinarily, because
* dhclient_run() will typically set it back to a higher value. If,
if (am_bound) {
assert(cli->binding != NULL);
VLOG_INFO("%s: obtained address "IP_FMT", netmask "IP_FMT,
if (am_bound) {
assert(cli->binding != NULL);
VLOG_INFO("%s: obtained address "IP_FMT", netmask "IP_FMT,
IP_ARGS(&cli->ipaddr), IP_ARGS(&cli->netmask));
if (cli->router) {
VLOG_INFO("%s: obtained default gateway "IP_FMT,
IP_ARGS(&cli->ipaddr), IP_ARGS(&cli->netmask));
if (cli->router) {
VLOG_INFO("%s: obtained default gateway "IP_FMT,
do_send_msg(cli, &msg);
cli->delay = MIN(cli->max_timeout, MAX(4, cli->delay * 2));
cli->retransmit += fuzz(cli->delay, 1);
do_send_msg(cli, &msg);
cli->delay = MIN(cli->max_timeout, MAX(4, cli->delay * 2));
cli->retransmit += fuzz(cli->delay, 1);
- netdev_get_mtu(cli->netdev, &mtu);
- ofpbuf_init(&b, mtu + VLAN_ETH_HEADER_LEN);
+ ofpbuf_init(&b, ETH_TOTAL_MAX + VLAN_ETH_HEADER_LEN);
netdev_get_etheraddr(cli->netdev, cli_mac);
for (; cli->received < 50; cli->received++) {
const struct ip_header *ip;
const struct dhcp_header *dhcp;
netdev_get_etheraddr(cli->netdev, cli_mac);
for (; cli->received < 50; cli->received++) {
const struct ip_header *ip;
const struct dhcp_header *dhcp;
flow_extract(&b, 0, 0, &flow);
if (flow.dl_type != htons(ETH_TYPE_IP)
flow_extract(&b, 0, 0, &flow);
if (flow.dl_type != htons(ETH_TYPE_IP)
|| flow.tp_dst != htons(DHCP_CLIENT_PORT)
|| !(eth_addr_is_broadcast(flow.dl_dst)
|| eth_addr_equals(flow.dl_dst, cli_mac))) {
|| flow.tp_dst != htons(DHCP_CLIENT_PORT)
|| !(eth_addr_is_broadcast(flow.dl_dst)
|| eth_addr_equals(flow.dl_dst, cli_mac))) {
error = dhcp_parse(msg, &b);
if (!error) {
if (VLOG_IS_DBG_ENABLED()) {
error = dhcp_parse(msg, &b);
if (!error) {
if (VLOG_IS_DBG_ENABLED()) {
- VLOG_DBG_RL(&rl, "received %s",
- dhcp_msg_to_string(msg, false, &cli->s));
+ VLOG_DBG_RL(&rl, "%s: received %s", cli_name,
+ dhcp_msg_to_string(msg, false, &cli->s));
- VLOG_INFO_RL(&rl, "received %s", dhcp_type_name(msg->type));
+ VLOG_INFO_RL(&rl, "%s: received %s",
+ cli_name, dhcp_type_name(msg->type));
nh.ip_csum = 0;
nh.ip_src = dhclient_get_ip(cli);
/* XXX need to use UDP socket for nonzero server IPs so that we can get
nh.ip_csum = 0;
nh.ip_src = dhclient_get_ip(cli);
/* XXX need to use UDP socket for nonzero server IPs so that we can get
th.udp_csum = 0;
udp_csum = csum_add32(0, nh.ip_src);
udp_csum = csum_add32(udp_csum, nh.ip_dst);
th.udp_csum = 0;
udp_csum = csum_add32(0, nh.ip_src);
udp_csum = csum_add32(udp_csum, nh.ip_dst);
udp_csum = csum_add16(udp_csum, th.udp_len);
udp_csum = csum_continue(udp_csum, &th, sizeof th);
th.udp_csum = csum_finish(csum_continue(udp_csum, b.data, b.size));
udp_csum = csum_add16(udp_csum, th.udp_len);
udp_csum = csum_continue(udp_csum, &th, sizeof th);
th.udp_csum = csum_finish(csum_continue(udp_csum, b.data, b.size));
* Ethernet at some point. 1500 bytes should be enough for anyone. */
if (b.size <= ETH_TOTAL_MAX) {
if (VLOG_IS_DBG_ENABLED()) {
* Ethernet at some point. 1500 bytes should be enough for anyone. */
if (b.size <= ETH_TOTAL_MAX) {
if (VLOG_IS_DBG_ENABLED()) {
- VLOG_DBG("sending %s", dhcp_msg_to_string(msg, false, &cli->s));
+ VLOG_DBG("%s: sending %s",
+ cli_name, dhcp_msg_to_string(msg, false, &cli->s));