diff --git a/ndhc/arp.c b/ndhc/arp.c index 10af334..090b6df 100644 --- a/ndhc/arp.c +++ b/ndhc/arp.c @@ -201,17 +201,17 @@ static int arp_open_fd(struct client_state_t *cs) int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (fd == -1) { - log_error("arp: failed to create socket: %s", strerror(errno)); + log_error("arp: Failed to create socket: %s", strerror(errno)); goto out; } int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof opt) == -1) { - log_error("arp: failed to set broadcast: %s", strerror(errno)); + log_error("arp: Failed to set broadcast: %s", strerror(errno)); goto out_fd; } if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { - log_error("arp: failed to set non-blocking: %s", strerror(errno)); + log_error("arp: Failed to set non-blocking: %s", strerror(errno)); goto out_fd; } struct sockaddr_ll saddr = { @@ -246,7 +246,7 @@ static void arp_switch_state(struct client_state_t *cs, arp_state_t state) } if (cs->arpFd == -1) { if (arp_open_fd(cs) == -1) - suicide("arp: failed to open arpFd when changing state to %u", + suicide("arp: Failed to open arpFd when changing state to %u", arpState); if (arpState != AS_DEFENSE) arp_set_bpf_basic(cs->arpFd); @@ -285,8 +285,8 @@ static int arp_reopen_fd(struct client_state_t *cs) arp_state_t prev_state = arpState; arp_min_close_fd(cs); if (arp_open_fd(cs) == -1) { - log_warning("arp_reopen_fd: Failed to open. Something is very wrong."); - log_warning("arp_reopen_fd: Client will still run, but functionality will be degraded."); + log_warning("arp: Failed to re-open fd. Something is very wrong."); + log_warning("arp: Client will still run, but functionality will be degraded."); return -1; } arp_switch_state(cs, prev_state); @@ -303,7 +303,7 @@ static int arp_send(struct client_state_t *cs, struct arpMsg *arp) memcpy(addr.sll_addr, client_config.arp, 6); if (cs->arpFd == -1) { - log_warning("arp_send: Send attempted when no ARP fd is open."); + log_warning("arp: Send attempted when no ARP fd is open."); return -1; } @@ -403,6 +403,7 @@ int arp_gw_check(struct client_state_t *cs) return 0; } +// Should only be called from DS_BOUND state. static int arp_get_gw_hwaddr(struct client_state_t *cs) { if (cs->dhcpState != DS_BOUND) @@ -428,7 +429,7 @@ static int arp_get_gw_hwaddr(struct client_state_t *cs) static void arp_failed(struct client_state_t *cs) { - log_line("arp: Offered address is in use -- declining"); + log_line("arp: Offered address is in use. Declining."); send_decline(cs, arp_dhcp_packet.yiaddr); arp_wake_ts[AS_COLLISION_CHECK] = -1; reinit_selecting(cs, total_conflicts < MAX_CONFLICTS ? @@ -464,7 +465,7 @@ void arp_set_defense_mode(struct client_state_t *cs) void arp_success(struct client_state_t *cs) { struct in_addr temp_addr = {.s_addr = arp_dhcp_packet.yiaddr}; - log_line("arp: Lease of %s obtained, lease time %ld", + log_line("Lease of %s obtained. Lease time is %ld seconds.", inet_ntoa(temp_addr), cs->lease); cs->clientAddr = arp_dhcp_packet.yiaddr; cs->dhcpState = DS_BOUND; @@ -494,7 +495,7 @@ void arp_success(struct client_state_t *cs) static void arp_gw_success(struct client_state_t *cs) { - log_line("arp: Network seems unchanged"); + log_line("arp: Network seems unchanged. Resuming normal operation."); arp_switch_state(cs, AS_DEFENSE); arp_announcement(cs); @@ -645,7 +646,7 @@ static void arp_do_defense(struct client_state_t *cs) if (!arp_validate_bpf_defense(cs, &arpreply)) return; - log_line("arp: detected a peer attempting to use our IP!"); + log_line("arp: Detected a peer attempting to use our IP!"); long long nowts = curms(); arp_wake_ts[AS_DEFENSE] = -1; if (!last_conflict_ts || diff --git a/ndhc/dhcp.c b/ndhc/dhcp.c index e6c0f12..aea262a 100644 --- a/ndhc/dhcp.c +++ b/ndhc/dhcp.c @@ -62,12 +62,12 @@ static int create_udp_socket(uint32_t ip, uint16_t port, char *iface) } int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof opt) == -1) { - log_error("create_udp_socket: set reuse addr failed: %s", + log_error("create_udp_socket: Set reuse addr failed: %s", strerror(errno)); goto out_fd; } if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof opt) == -1) { - log_error("create_udp_socket: set don't route failed: %s", + log_error("create_udp_socket: Set don't route failed: %s", strerror(errno)); goto out_fd; } @@ -75,12 +75,12 @@ static int create_udp_socket(uint32_t ip, uint16_t port, char *iface) memset(&ifr, 0, sizeof (struct ifreq)); strlcpy(ifr.ifr_name, iface, IFNAMSIZ); if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof ifr) < 0) { - log_error("create_udp_socket: set bind to device failed: %s", + log_error("create_udp_socket: Set bind to device failed: %s", strerror(errno)); goto out_fd; } if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { - log_error("create_udp_socket: set non-blocking failed: %s", + log_error("create_udp_socket: Set non-blocking failed: %s", strerror(errno)); goto out_fd; } @@ -109,7 +109,7 @@ static int create_udp_listen_socket(struct client_state_t *cs, char *inf) return -1; int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof opt) == -1) { - log_error("create_udp_listen_socket: set broadcast failed: %s", + log_error("create_udp_listen_socket: Set broadcast failed: %s", strerror(errno)); close(fd); return -1; @@ -138,7 +138,7 @@ static int send_dhcp_cooked(struct client_state_t *cs, struct dhcpmsg *payload) ssize_t endloc = get_end_option_idx(payload); if (endloc < 0) { - log_error("send_dhcp_cooked: attempt to send packet with no DHCP_END"); + log_error("send_dhcp_cooked: Attempt to send packet with no DHCP_END."); goto out_fd; } size_t payload_len = @@ -236,11 +236,11 @@ static int udp_checksum(struct ip_udp_dhcp_packet *packet) static int get_raw_packet_validate_bpf(struct ip_udp_dhcp_packet *packet) { if (packet->ip.version != IPVERSION) { - log_line("IP version is not IPv4"); + log_line("IP version is not IPv4."); return 0; } if (packet->ip.ihl != sizeof packet->ip >> 2) { - log_line("IP header length incorrect"); + log_line("IP header length incorrect."); return 0; } if (packet->ip.protocol != IPPROTO_UDP) { @@ -253,7 +253,7 @@ static int get_raw_packet_validate_bpf(struct ip_udp_dhcp_packet *packet) } if (ntohs(packet->udp.len) != ntohs(packet->ip.tot_len) - sizeof packet->ip) { - log_line("UDP header length incorrect"); + log_line("UDP header length incorrect."); return 0; } return 1; @@ -281,11 +281,11 @@ static int get_raw_packet(struct client_state_t *cs, struct dhcpmsg *payload) return -2; if (!ip_checksum(&packet)) { - log_line("IP header checksum incorrect"); + log_line("IP header checksum incorrect."); return -2; } if (packet.udp.check && !udp_checksum(&packet)) { - log_error("Packet with bad UDP checksum received, ignoring"); + log_error("Packet with bad UDP checksum received. Ignoring."); return -2; } @@ -313,12 +313,12 @@ static int create_raw_socket(struct client_state_t *cs, struct sockaddr_ll *sa, int opt = 1; if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof opt) == -1) { - log_error("create_raw_socket: failed to set don't route: %s", + log_error("create_raw_socket: Failed to set don't route: %s", strerror(errno)); goto out_fd; } if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { - log_error("create_raw_socket: set non-blocking failed: %s", + log_error("create_raw_socket: Set non-blocking failed: %s", strerror(errno)); goto out_fd; } @@ -399,7 +399,7 @@ static int send_dhcp_raw(struct dhcpmsg *payload) // and drop packets that are longer than 562 bytes. ssize_t endloc = get_end_option_idx(payload); if (endloc < 0) { - log_error("send_dhcp_raw: attempt to send packet with no DHCP_END"); + log_error("send_dhcp_raw: Attempt to send packet with no DHCP_END."); close(fd); return ret; } @@ -452,20 +452,16 @@ static void change_listen_mode(struct client_state_t *cs, int new_mode) close(cs->listenFd); cs->listenFd = -1; } - if (new_mode == LM_NONE) { - log_line("Stopped listening for DHCP packets."); + if (new_mode == LM_NONE) return; - } cs->listenFd = new_mode == LM_RAW ? create_raw_listen_socket(cs, client_config.ifindex) : create_udp_listen_socket(cs, client_config.interface); if (cs->listenFd < 0) { - log_error("FATAL: couldn't listen on socket: %s.", strerror(errno)); + log_error("FATAL: Couldn't listen on socket: %s.", strerror(errno)); exit(EXIT_FAILURE); } epoll_add(cs, cs->listenFd); - log_line("Listening for DHCP packets using a %s socket.", - new_mode == LM_RAW ? "raw" : "cooked"); } void set_listen_raw(struct client_state_t *cs) @@ -529,7 +525,6 @@ void handle_packet(struct client_state_t *cs) if (!validate_dhcp_packet(cs, len, &packet, &message)) return; - log_line("Received a reply."); packet_action(cs, &packet, message); } diff --git a/ndhc/netlink.c b/ndhc/netlink.c index 438c52e..8709534 100644 --- a/ndhc/netlink.c +++ b/ndhc/netlink.c @@ -55,10 +55,10 @@ static void get_if_index_and_mac(const struct nlmsghdr *nlh, if (!strcmp(client_config.interface, nlattr_get_data(tb[IFLA_IFNAME]))) { client_config.ifindex = ifm->ifi_index; if (!tb[IFLA_ADDRESS]) - suicide("FATAL: adapter %s lacks a hardware address"); + suicide("FATAL: Adapter %s lacks a hardware address."); int maclen = nlattr_get_len(tb[IFLA_ADDRESS]) - 4; if (maclen != 6) - suicide("FATAL: adapter hardware address length should be 6, but is %u", + suicide("FATAL: Adapter hardware address length should be 6, but is %u.", maclen); const unsigned char *mac = @@ -105,7 +105,7 @@ static int nl_process_msgs(const struct nlmsghdr *nlh, void *data) break; if (cs->ifsPrevState != IFS_REMOVED) { cs->ifsPrevState = IFS_REMOVED; - log_line("Interface removed; exiting."); + log_line("Interface removed. Exiting."); exit(EXIT_SUCCESS); } break; diff --git a/ndhc/nl.c b/ndhc/nl.c index 69b889b..962b14f 100644 --- a/ndhc/nl.c +++ b/ndhc/nl.c @@ -45,11 +45,11 @@ ssize_t nl_recv_buf(int fd, char *buf, size_t blen) return -1; } if (msg.msg_flags & MSG_TRUNC) { - log_error("nl_fill_buf: buffer not long enough for message"); + log_error("nl_fill_buf: Buffer not long enough for message."); return -1; } if (msg.msg_namelen != sizeof addr) { - log_error("nl_fill_buf: response was not of the same address family"); + log_error("nl_fill_buf: Response was not of the same address family."); return -1; } return ret; @@ -72,13 +72,13 @@ int nl_foreach_nlmsg(char *buf, size_t blen, int portid, } else { switch (nlh->nlmsg_type) { case NLMSG_ERROR: - log_line("nl: received a NLMSG_ERROR: %s", + log_line("nl: Received a NLMSG_ERROR: %s", strerror(nlmsg_get_error(nlh))); return -1; case NLMSG_DONE: return 0; case NLMSG_OVERRUN: - log_line("nl: received a NLMSG_OVERRUN"); + log_line("nl: Received a NLMSG_OVERRUN."); case NLMSG_NOOP: default: break; @@ -98,11 +98,11 @@ int nl_open(int nltype, int nlgroup, int *nlportid) return -1; } if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) { - log_error("nl_open: set non-blocking failed: %s", strerror(errno)); + log_error("nl_open: Set non-blocking failed: %s", strerror(errno)); goto err_close; } if (fcntl(fd, F_SETFD, FD_CLOEXEC)) { - log_error("nl_open: set close-on-exec failed: %s", strerror(errno)); + log_error("nl_open: Set close-on-exec failed: %s", strerror(errno)); goto err_close; } socklen_t al; @@ -120,11 +120,11 @@ int nl_open(int nltype, int nlgroup, int *nlportid) goto err_close; } if (al != sizeof nlsock) { - log_error("nl_open: bound socket doesn't have right family size"); + log_error("nl_open: Bound socket doesn't have right family size."); goto err_close; } if (nlsock.nl_family != AF_NETLINK) { - log_error("nl_open: bound socket isn't AF_NETLINK"); + log_error("nl_open: Bound socket isn't AF_NETLINK."); goto err_close; } if (nlportid) diff --git a/ndhc/state.c b/ndhc/state.c index da43012..ab05a69 100644 --- a/ndhc/state.c +++ b/ndhc/state.c @@ -116,12 +116,6 @@ static void bound_timeout(struct client_state_t *cs, long long nowts) renewing_timeout(cs, nowts); } -static void lease_timedout(struct client_state_t *cs) -{ - log_line("Lease lost, entering init state."); - reinit_selecting(cs, 0); -} - // Triggered when a DHCP renew request has been sent and no reply has been // received within the response wait time. This function is also directly // called by bound_timeout() when it is time to renew a lease before it @@ -159,8 +153,10 @@ static void rebinding_timeout(struct client_state_t *cs, long long nowts) } send_rebind(cs); dhcp_wake_ts = nowts + ((elt - nowts) / 2); - } else - lease_timedout(cs); + } else { + log_line("Lease expired. Searching for a new lease..."); + reinit_selecting(cs, 0); + } } static void released_timeout(struct client_state_t *cs, long long nowts) @@ -168,11 +164,32 @@ static void released_timeout(struct client_state_t *cs, long long nowts) dhcp_wake_ts = -1; } +static int validate_serverid(struct client_state_t *cs, struct dhcpmsg *packet, + char *typemsg) +{ + uint8_t *temp = NULL; + ssize_t optlen; + if (!(temp = get_option_data(packet, DHCP_SERVER_ID, &optlen))) { + log_line("Received %s with no server id. Ignoring it."); + return 0; + } + if (memcmp(&cs->serverAddr, temp, 4)) { + uint32_t iptmp; + memcpy(&iptmp, temp, 4); + log_line("Received %s with an unexpected server id: %s. Ignoring it.", + typemsg, inet_ntoa((struct in_addr){.s_addr=iptmp})); + return 0; + } + return 1; +} + // Can transition to DS_BOUND or DS_SELECTING. static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet, uint8_t *message) { if (*message == DHCPACK) { + if (!validate_serverid(cs, packet, "a DHCP ACK")) + return; ssize_t optlen; uint8_t *temp = get_option_data(packet, DHCP_LEASE_TIME, &optlen); cs->leaseStartTime = curms(); @@ -197,18 +214,23 @@ static void an_packet(struct client_state_t *cs, struct dhcpmsg *packet, // have received a lease with a different IP than what we had before. if (cs->dhcpState == DS_REQUESTING || memcmp(&packet->yiaddr, &cs->clientAddr, 4)) { + log_line("Accepted a firm offer for %s. Validating...", + inet_ntoa((struct in_addr){.s_addr=cs->clientAddr})); if (arp_check(cs, packet) == -1) { - log_warning("arp_check failed to make arp socket, retrying lease"); + log_warning("Failed to make arp socket. Searching for new lease..."); reinit_selecting(cs, 3000); } } else { + log_line("Lease refreshed to %u seconds.", cs->lease); cs->dhcpState = DS_BOUND; arp_set_defense_mode(cs); set_listen_none(cs); } } else if (*message == DHCPNAK) { - log_line("Received DHCP NAK."); + if (!validate_serverid(cs, packet, "a DHCP NAK")) + return; + log_line("Our request was rejected. Searching for a new lease..."); reinit_selecting(cs, 3000); } } @@ -226,8 +248,11 @@ static void selecting_packet(struct client_state_t *cs, struct dhcpmsg *packet, cs->dhcpState = DS_REQUESTING; dhcp_wake_ts = curms(); num_dhcp_requests = 0; + log_line("Received an offer of %s from server %s.", + inet_ntoa((struct in_addr){.s_addr=cs->clientAddr}), + inet_ntoa((struct in_addr){.s_addr=cs->serverAddr})); } else { - log_line("No server ID in message"); + log_line("Invalid offer received: it didn't have a server id."); } } } @@ -289,14 +314,15 @@ void ifup_action(struct client_state_t *cs) cs->dhcpState == DS_RENEWING || cs->dhcpState == DS_REBINDING)) { if (arp_gw_check(cs) != -1) { - log_line("nl: interface back, revalidating lease"); + log_line("nl: Interface is back. Revalidating lease..."); return; } else - log_warning("nl: arp_gw_check could not make arp socket"); + log_warning("nl: arp_gw_check could not make arp socket."); } if (cs->dhcpState == DS_SELECTING) return; - log_line("nl: %s back, querying for new lease", client_config.interface); + log_line("nl: %s is back. Searching for new lease...", + client_config.interface); reinit_selecting(cs, 0); }