Remove pointless length-checking in get_raw_packet() that can never be triggered

because safe_read() already protects against reads longer than a DHCP
packet in length.

Lots of cosmetic cleanups.  Highlights:
- Remove pointless enums that just define sizeof for various structures.
- Rename struct dhcpMessage to struct dhcpmsg.
This commit is contained in:
Nicholas J. Kain 2011-06-26 17:25:00 -04:00
parent b70070e592
commit 864ad73b20
8 changed files with 74 additions and 87 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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:

View File

@ -30,6 +30,6 @@ enum {
IFCHANGE_NAK = 4
};
void ifchange(struct dhcpMessage *packet, int mode);
void ifchange(struct dhcpmsg *packet, int mode);
#endif

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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);