diff --git a/ndhc/arp.c b/ndhc/arp.c index 2cfb3f9..6523681 100644 --- a/ndhc/arp.c +++ b/ndhc/arp.c @@ -42,7 +42,7 @@ static struct arpMsg arpreply; static int arpreply_offset; -static struct dhcpMessage arp_dhcp_packet; +static struct dhcpmsg arp_dhcp_packet; static int arp_packet_num; static int arp_open_fd(struct client_state_t *cs) @@ -135,14 +135,14 @@ static void arpreply_clear() arpreply_offset = 0; } -int arp_check(struct client_state_t *cs, struct dhcpMessage *packet) +int arp_check(struct client_state_t *cs, struct dhcpmsg *packet) { if (arpping(cs, arp_dhcp_packet.yiaddr) == -1) return -1; cs->arpPrevState = cs->dhcpState; cs->dhcpState = DS_ARP_CHECK; cs->timeout = 2000; - memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpMessage)); + memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpmsg)); arpreply_clear(); return 0; } @@ -155,7 +155,7 @@ int arp_gw_check(struct client_state_t *cs) cs->dhcpState = DS_ARP_GW_CHECK; cs->oldTimeout = cs->timeout; cs->timeout = 2000; - memset(&arp_dhcp_packet, 0, sizeof (struct dhcpMessage)); + memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg)); arpreply_clear(); return 0; } @@ -167,7 +167,7 @@ int arp_get_gw_hwaddr(struct client_state_t *cs) if (arpping(cs, cs->routerAddr) == -1) return -1; log_line("arp: Searching for gw address"); - memset(&arp_dhcp_packet, 0, sizeof (struct dhcpMessage)); + memset(&arp_dhcp_packet, 0, sizeof (struct dhcpmsg)); arpreply_clear(); return 0; } diff --git a/ndhc/arp.h b/ndhc/arp.h index addf6c9..bdcb2df 100644 --- a/ndhc/arp.h +++ b/ndhc/arp.h @@ -49,7 +49,7 @@ struct arpMsg { uint8_t pad[18]; /* 2a pad for min. ethernet payload (60 bytes) */ }; -int arp_check(struct client_state_t *cs, struct dhcpMessage *packet); +int arp_check(struct client_state_t *cs, struct dhcpmsg *packet); int arp_gw_check(struct client_state_t *cs); int arp_get_gw_hwaddr(struct client_state_t *cs); void arp_success(struct client_state_t *cs); diff --git a/ndhc/ifchange.c b/ndhc/ifchange.c index 123d7da..a2d9603 100644 --- a/ndhc/ifchange.c +++ b/ndhc/ifchange.c @@ -181,7 +181,7 @@ static void deconfig_if(void) close(sockfd); } -static void send_cmd(int sockfd, struct dhcpMessage *packet, uint8_t code) +static void send_cmd(int sockfd, struct dhcpmsg *packet, uint8_t code) { char buf[256]; uint8_t *optdata; @@ -197,7 +197,7 @@ static void send_cmd(int sockfd, struct dhcpMessage *packet, uint8_t code) sockwrite(sockfd, buf, strlen(buf)); } -static void bound_if(struct dhcpMessage *packet, int mode) +static void bound_if(struct dhcpmsg *packet, int mode) { int sockfd; char buf[256]; @@ -234,7 +234,7 @@ static void bound_if(struct dhcpMessage *packet, int mode) } } -void ifchange(struct dhcpMessage *packet, int mode) +void ifchange(struct dhcpmsg *packet, int mode) { switch (mode) { case IFCHANGE_DECONFIG: diff --git a/ndhc/ifchange.h b/ndhc/ifchange.h index 0faaec5..795a9d7 100644 --- a/ndhc/ifchange.h +++ b/ndhc/ifchange.h @@ -30,6 +30,6 @@ enum { IFCHANGE_NAK = 4 }; -void ifchange(struct dhcpMessage *packet, int mode); +void ifchange(struct dhcpmsg *packet, int mode); #endif diff --git a/ndhc/options.c b/ndhc/options.c index 017635d..17d5ebc 100644 --- a/ndhc/options.c +++ b/ndhc/options.c @@ -216,7 +216,7 @@ static uint8_t *do_get_option_data(uint8_t *buf, ssize_t buflen, int code, // Get an option with bounds checking (warning, result is not aligned) // optlen will be equal to the length of the option data. -uint8_t *get_option_data(struct dhcpMessage *packet, int code, ssize_t *optlen) +uint8_t *get_option_data(struct dhcpmsg *packet, int code, ssize_t *optlen) { uint8_t *option, *buf; ssize_t buflen; @@ -251,7 +251,7 @@ uint8_t *get_option_data(struct dhcpMessage *packet, int code, ssize_t *optlen) /* return the position of the 'end' option */ ssize_t get_end_option_idx(uint8_t *optbuf, size_t bufsize) { - int i; + size_t i; for (i = 0; i < bufsize; ++i) { if (optbuf[i] == DHCP_END) return i; diff --git a/ndhc/options.h b/ndhc/options.h index 8e5c557..afdb98d 100644 --- a/ndhc/options.h +++ b/ndhc/options.h @@ -92,7 +92,7 @@ uint8_t *alloc_option(uint8_t code, uint8_t *optdata, size_t datalen); uint8_t *alloc_dhcp_client_id_option(uint8_t type, uint8_t *idstr, size_t idstrlen); -uint8_t *get_option_data(struct dhcpMessage *packet, int code, ssize_t *optlen); +uint8_t *get_option_data(struct dhcpmsg *packet, int code, ssize_t *optlen); ssize_t get_end_option_idx(uint8_t *optbuf, size_t bufsize); size_t add_option_string(uint8_t *optbuf, size_t buflen, uint8_t *optstr); size_t add_u32_option(uint8_t *optbuf, size_t buflen, uint8_t code, diff --git a/ndhc/packet.c b/ndhc/packet.c index fc87acd..47abe50 100644 --- a/ndhc/packet.c +++ b/ndhc/packet.c @@ -184,12 +184,12 @@ out: } // Read a packet from a cooked socket. Returns -1 on fatal error, -2 on // transient error. -static int get_packet(struct dhcpMessage *packet, int fd) +static int get_packet(struct dhcpmsg *packet, int fd) { int bytes; - memset(packet, 0, DHCP_SIZE); - bytes = safe_read(fd, (char *)packet, DHCP_SIZE); + memset(packet, 0, sizeof *packet); + bytes = safe_read(fd, (char *)packet, sizeof *packet); if (bytes == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) return -2; @@ -270,27 +270,22 @@ static int udp_checksum(struct ip_udp_dhcp_packet *packet) // Read a packet from a raw socket. Returns -1 on fatal error, -2 on // transient error. -static int get_raw_packet(struct dhcpMessage *payload, int fd) +static int get_raw_packet(struct dhcpmsg *payload, int fd) { struct ip_udp_dhcp_packet packet; - memset(&packet, 0, IP_UPD_DHCP_SIZE); + memset(&packet, 0, sizeof packet); - int len = safe_read(fd, (char *)&packet, IP_UPD_DHCP_SIZE); - if (len == -1) { + ssize_t inc = safe_read(fd, (char *)&packet, sizeof packet); + if (inc == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) return -2; log_line("get_raw_packet: read error %s", strerror(errno)); return -1; } - /* ignore any extra garbage bytes */ - if (ntohs(packet.ip.tot_len) != len) { - log_line("Received %u bytes for a %u byte UDP packet. Discarding extra.", - len, packet.ip.tot_len); - len = ntohs(packet.ip.tot_len); - } + if (inc > ntohs(packet.ip.tot_len)) + log_line("Discarded extra bytes after reading a single UDP datagram."); - // Validate the IP and UDP headers. if (packet.ip.protocol != IPPROTO_UDP) { log_line("IP header is not UDP: %d", packet.ip.protocol); return -2; @@ -307,15 +302,11 @@ static int get_raw_packet(struct dhcpMessage *payload, int fd) log_line("IP header checksum incorrect"); return -2; } - if (packet.udp.dest != htons(DHCP_CLIENT_PORT)) { + if (ntohs(packet.udp.dest) != DHCP_CLIENT_PORT) { log_line("UDP destination port incorrect: %d", ntohs(packet.udp.dest)); return -2; } - if (len > IP_UPD_DHCP_SIZE) { - log_line("Data longer than that of a IP+UDP+DHCP message: %d", len); - return -2; - } - if (ntohs(packet.udp.len) != (short)(len - sizeof packet.ip)) { + if (ntohs(packet.udp.len) != ntohs(packet.ip.tot_len) - sizeof packet.ip) { log_line("UDP header length incorrect"); return -2; } @@ -325,15 +316,15 @@ static int get_raw_packet(struct dhcpMessage *payload, int fd) return -2; } - memcpy(payload, &packet.data, - len - sizeof packet.ip - sizeof packet.udp); + size_t l = ntohs(packet.ip.tot_len) - sizeof packet.ip - sizeof packet.udp; + memcpy(payload, &packet.data, l); log_line("Received a packet via raw socket."); - return len - sizeof packet.ip - sizeof packet.udp; + return l; } // Broadcast a DHCP message using a raw socket. -static int send_dhcp_raw(struct dhcpMessage *payload) +static int send_dhcp_raw(struct dhcpmsg *payload) { int fd, r = -1; @@ -367,36 +358,38 @@ static int send_dhcp_raw(struct dhcpMessage *payload) // Send packets that are as short as possible, since some servers are buggy // and drop packets that are longer than 562 bytes. ssize_t endloc = get_end_option_idx(payload->options, DHCP_OPTIONS_BUFSIZE); - if (endloc == -1) { + if (endloc < 0) { log_error("send_dhcp_raw: attempt to send packet with no DHCP_END"); goto out_fd; } - unsigned int padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc; - struct ip_udp_dhcp_packet packet = { + size_t padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc; + size_t iud_len = sizeof(struct ip_udp_dhcp_packet) - padding; + size_t ud_len = sizeof(struct udp_dhcp_packet) - padding; + // UDP checksumming needs a temporary pseudoheader with a fake length. + struct ip_udp_dhcp_packet iudmsg = { .ip = { .protocol = IPPROTO_UDP, .saddr = INADDR_ANY, .daddr = INADDR_BROADCAST, - .tot_len = htons(UPD_DHCP_SIZE - padding), + .tot_len = htons(ud_len), }, .udp = { .source = htons(DHCP_CLIENT_PORT), .dest = htons(DHCP_SERVER_PORT), - .len = htons(UPD_DHCP_SIZE - padding), + .len = htons(ud_len), }, .data = *payload, }; - // UDP checksumming needs a temporary pseudoheader with a fake length. - packet.udp.check = net_checksum(&packet, IP_UPD_DHCP_SIZE - padding); + iudmsg.udp.check = net_checksum(&iudmsg, iud_len); // Set the true IP packet length for the final packet. - packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE - padding); - packet.ip.ihl = sizeof packet.ip >> 2; - packet.ip.version = IPVERSION; - packet.ip.ttl = IPDEFTTL; - packet.ip.check = net_checksum(&packet.ip, sizeof packet.ip); + iudmsg.ip.tot_len = htons(iud_len); + iudmsg.ip.ihl = sizeof iudmsg.ip >> 2; + iudmsg.ip.version = IPVERSION; + iudmsg.ip.ttl = IPDEFTTL; + iudmsg.ip.check = net_checksum(&iudmsg.ip, sizeof iudmsg.ip); - r = safe_sendto(fd, (const char *)&packet, IP_UPD_DHCP_SIZE - padding, - 0, (struct sockaddr *)&dest, sizeof dest); + r = safe_sendto(fd, (const char *)&iudmsg, iud_len, 0, + (struct sockaddr *)&dest, sizeof dest); if (r == -1) log_error("send_dhcp_raw: sendto failed: %s", strerror(errno)); out_fd: @@ -406,7 +399,7 @@ static int send_dhcp_raw(struct dhcpMessage *payload) } // Broadcast a DHCP message using a UDP socket. -static int send_dhcp_cooked(struct dhcpMessage *payload, uint32_t source_ip, +static int send_dhcp_cooked(struct dhcpmsg *payload, uint32_t source_ip, uint32_t dest_ip) { int fd, result = -1; @@ -463,12 +456,12 @@ static int send_dhcp_cooked(struct dhcpMessage *payload, uint32_t source_ip, ssize_t endloc = get_end_option_idx(payload->options, DHCP_OPTIONS_BUFSIZE); - if (endloc == -1) { + if (endloc < 0) { log_error("send_dhcp_cooked: attempt to send packet with no DHCP_END"); goto out_fd; } - unsigned int padding = DHCP_OPTIONS_BUFSIZE - 1 - endloc; - result = safe_write(fd, (const char *)payload, DHCP_SIZE - padding); + size_t payload_len = sizeof *payload - DHCP_OPTIONS_BUFSIZE - 1 - endloc; + result = safe_write(fd, (const char *)payload, payload_len); if (result == -1) log_error("send_dhcp_cooked: write failed: %s", strerror(errno)); out_fd: @@ -509,7 +502,7 @@ void change_listen_mode(struct client_state_t *cs, int new_mode) } static void init_selecting_packet(struct client_state_t *cs, - struct dhcpMessage *packet, + struct dhcpmsg *packet, uint8_t *message) { uint8_t *temp = NULL; @@ -529,7 +522,7 @@ static void init_selecting_packet(struct client_state_t *cs, } static void dhcp_ack_or_nak_packet(struct client_state_t *cs, - struct dhcpMessage *packet, + struct dhcpmsg *packet, uint8_t *message) { uint8_t *temp = NULL; @@ -575,7 +568,7 @@ void handle_packet(struct client_state_t *cs) { uint8_t *message = NULL; int len; - struct dhcpMessage packet; + struct dhcpmsg packet; ssize_t optlen; if (cs->listenMode == LM_KERNEL) @@ -595,7 +588,7 @@ void handle_packet(struct client_state_t *cs) change_listen_mode(cs, cs->listenMode); } - if (len < DHCP_SIZE - 308) { + if (len < sizeof packet - sizeof packet.options) { log_line("Packet is too short to contain magic cookie. Ignoring."); return; } @@ -664,9 +657,9 @@ uint32_t random_xid(void) } /* Initializes dhcp packet header for a -client- packet. */ -static void init_header(struct dhcpMessage *packet, char type) +static void init_header(struct dhcpmsg *packet, char type) { - memset(packet, 0, DHCP_SIZE); + memset(packet, 0, sizeof *packet); packet->op = 1; // BOOTREQUEST (client) packet->htype = 1; // ETH_10MB packet->hlen = 6; // ETH_10MB_LEN @@ -677,7 +670,7 @@ static void init_header(struct dhcpMessage *packet, char type) } /* initialize a packet with the proper defaults */ -static void init_packet(struct dhcpMessage *packet, char type) +static void init_packet(struct dhcpmsg *packet, char type) { struct vendor { char vendor; @@ -700,7 +693,7 @@ static void init_packet(struct dhcpMessage *packet, char type) * requested IP */ int send_discover(uint32_t xid, uint32_t requested) { - struct dhcpMessage packet; + struct dhcpmsg packet; init_packet(&packet, DHCPDISCOVER); packet.xid = xid; @@ -719,7 +712,7 @@ int send_discover(uint32_t xid, uint32_t requested) /* Broadcasts a DHCP request message */ int send_selecting(uint32_t xid, uint32_t server, uint32_t requested) { - struct dhcpMessage packet; + struct dhcpmsg packet; struct in_addr addr; init_packet(&packet, DHCPREQUEST); @@ -738,7 +731,7 @@ int send_selecting(uint32_t xid, uint32_t server, uint32_t requested) /* Unicasts or broadcasts a DHCP renew message */ int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) { - struct dhcpMessage packet; + struct dhcpmsg packet; init_packet(&packet, DHCPREQUEST); packet.xid = xid; @@ -755,7 +748,7 @@ int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) /* Broadcast a DHCP decline message */ int send_decline(uint32_t xid, uint32_t server, uint32_t requested) { - struct dhcpMessage packet; + struct dhcpmsg packet; /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields, * client-id option (unless -C), message type option: @@ -780,7 +773,7 @@ int send_decline(uint32_t xid, uint32_t server, uint32_t requested) /* Unicasts a DHCP release message */ int send_release(uint32_t server, uint32_t ciaddr) { - struct dhcpMessage packet; + struct dhcpmsg packet; init_packet(&packet, DHCPRELEASE); packet.xid = random_xid(); diff --git a/ndhc/packet.h b/ndhc/packet.h index 45f43fb..fecf17b 100644 --- a/ndhc/packet.h +++ b/ndhc/packet.h @@ -42,24 +42,24 @@ enum { DHCPINFORM = 8 }; -struct dhcpMessage { - uint8_t op; // Message type: 1 = BOOTREQUEST for clients. - uint8_t htype; // ARP HW address type: always '1' for 10MB ethernet. - uint8_t hlen; // Hardware address length: always '6' for 10MB ethernet. - uint8_t hops; // Client sets to zero. - uint32_t xid; // Transaction ID: random number identifying session - uint16_t secs; // Filled by client: seconds since client began address - // aquisition or renewal process. - uint16_t flags; // DHCP flags +struct dhcpmsg { + uint8_t op; // Message type: 1 = BOOTREQUEST for clients. + uint8_t htype; // ARP HW address type: always '1' for 10MB ethernet. + uint8_t hlen; // Hardware address length: always '6' for 10MB ethernet. + uint8_t hops; // Client sets to zero. + uint32_t xid; // Transaction ID: random number identifying session + uint16_t secs; // Filled by client: seconds since client began address + // aquisition or renewal process. + uint16_t flags; // DHCP flags uint32_t ciaddr; // Client IP: only filled in if client is inBOUND, RENEW, // or REBINDING and can reply to ARP requests uint32_t yiaddr; // 'your' (client) IP address uint32_t siaddr; // IP address of next server to use in bootstrap; returned // in DHCPOFFER or DHCPACK by server uint32_t giaddr; // relay agent IP: used when booting via relay agent - uint8_t chaddr[16]; // Client MAC address - uint8_t sname[64]; // Server host name (optional); null-terminated string - uint8_t file[128]; // boot file name, null-terminated string + uint8_t chaddr[16]; // Client MAC address + uint8_t sname[64]; // Server host name (optional); null-terminated string + uint8_t file[128]; // boot file name, null-terminated string uint32_t cookie; uint8_t options[308]; /* 312 - cookie */ }; @@ -67,18 +67,12 @@ struct dhcpMessage { struct ip_udp_dhcp_packet { struct iphdr ip; struct udphdr udp; - struct dhcpMessage data; + struct dhcpmsg data; }; struct udp_dhcp_packet { struct udphdr udp; - struct dhcpMessage data; -}; - -enum { - IP_UPD_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet), - UPD_DHCP_SIZE = sizeof(struct udp_dhcp_packet), - DHCP_SIZE = sizeof(struct dhcpMessage), + struct dhcpmsg data; }; void change_listen_mode(struct client_state_t *cs, int new_mode);