Robustify get_raw_packet(). Error messages are now more specific, and
read() properly handles short reads and EINTR/EAGAIN/EWOULDBLOCK. Update documentation.
This commit is contained in:
parent
81398c79fb
commit
2262845be6
2
README
2
README
@ -92,9 +92,11 @@ USAGE
|
|||||||
# cd /var/lib/ndhc
|
# cd /var/lib/ndhc
|
||||||
# mkdir dev
|
# mkdir dev
|
||||||
# mknod dev/urandom c 1 9
|
# mknod dev/urandom c 1 9
|
||||||
|
# mknod dev/null c 1 3
|
||||||
# chown -R root.root dev
|
# chown -R root.root dev
|
||||||
# chmod a+rx dev
|
# chmod a+rx dev
|
||||||
# chmod a+r dev/urandom
|
# chmod a+r dev/urandom
|
||||||
|
# chmod a+rw dev/null
|
||||||
|
|
||||||
d) (optional) If you wish for logging to properly work, you
|
d) (optional) If you wish for logging to properly work, you
|
||||||
will need to properly configure your logging daemon so that it
|
will need to properly configure your logging daemon so that it
|
||||||
|
@ -180,41 +180,83 @@ int send_release(unsigned long server, unsigned long ciaddr)
|
|||||||
* -2 for those that aren't */
|
* -2 for those that aren't */
|
||||||
int get_raw_packet(struct dhcpMessage *payload, int fd)
|
int get_raw_packet(struct dhcpMessage *payload, int fd)
|
||||||
{
|
{
|
||||||
int bytes;
|
|
||||||
struct udp_dhcp_packet packet;
|
struct udp_dhcp_packet packet;
|
||||||
uint32_t source, dest;
|
uint32_t source, dest;
|
||||||
uint16_t check;
|
uint16_t check;
|
||||||
|
|
||||||
|
ssize_t len = 0;
|
||||||
|
const ssize_t wanted = sizeof(struct iphdr) + sizeof(struct udphdr);
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(struct udp_dhcp_packet));
|
memset(&packet, 0, sizeof(struct udp_dhcp_packet));
|
||||||
bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet));
|
while (len < wanted) {
|
||||||
if (bytes < 0) {
|
ssize_t r = read(fd, &packet + len,
|
||||||
log_line("couldn't read on raw listening socket -- ignoring");
|
sizeof(struct udp_dhcp_packet) - len);
|
||||||
usleep(500000); /* possible down interface, looping condition */
|
if (r == 0)
|
||||||
return -1;
|
break;
|
||||||
|
if (r == -1) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
log_line("EAGAIN or EWOULDBLOCK hit");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log_line("couldn't read on raw listening socket -- ignoring");
|
||||||
|
usleep(500000); /* possible down interface, looping condition */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
len += r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes < (int) (sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
if (len == 0) {
|
||||||
log_line("message too short, ignoring");
|
usleep(50000);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes < ntohs(packet.ip.tot_len)) {
|
log_line("len: %d wanted: %d", len, wanted);
|
||||||
|
if (len < wanted) {
|
||||||
|
log_line("Message too short to contain IP + UDP headers, ignoring");
|
||||||
|
sleep(1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < ntohs(packet.ip.tot_len)) {
|
||||||
log_line("Truncated packet");
|
log_line("Truncated packet");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore any extra garbage bytes */
|
/* ignore any extra garbage bytes */
|
||||||
bytes = ntohs(packet.ip.tot_len);
|
len = ntohs(packet.ip.tot_len);
|
||||||
|
|
||||||
/* Make sure its the right packet for us, and that it passes
|
/* Make sure its the right packet for us, and that it passes
|
||||||
* sanity checks */
|
* sanity checks */
|
||||||
if (packet.ip.protocol != IPPROTO_UDP
|
if (packet.ip.protocol != IPPROTO_UDP) {
|
||||||
|| packet.ip.version != IPVERSION
|
log_line("IP header is not UDP");
|
||||||
|| packet.ip.ihl != sizeof(packet.ip) >> 2
|
sleep(1);
|
||||||
|| packet.udp.dest != htons(CLIENT_PORT)
|
return -2;
|
||||||
|| bytes > (int)sizeof(struct udp_dhcp_packet)
|
}
|
||||||
|| ntohs(packet.udp.len) != (short)(bytes - sizeof(packet.ip))) {
|
if (packet.ip.version != IPVERSION) {
|
||||||
log_line("unrelated/bogus packet");
|
log_line("IP version is not IPv4");
|
||||||
|
sleep(1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (packet.ip.ihl != sizeof(packet.ip) >> 2) {
|
||||||
|
log_line("IP header length incorrect");
|
||||||
|
sleep(1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (packet.udp.dest != htons(CLIENT_PORT)) {
|
||||||
|
log_line("UDP destination port incorrect");
|
||||||
|
sleep(1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (len > (int)sizeof(struct udp_dhcp_packet)) {
|
||||||
|
log_line("Data longer than that of a IP+UDP+DHCP message");
|
||||||
|
sleep(1);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (ntohs(packet.udp.len) != (short)(len - sizeof(packet.ip))) {
|
||||||
|
log_line("UDP header length incorrect");
|
||||||
|
sleep(1);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,20 +279,20 @@ int get_raw_packet(struct dhcpMessage *payload, int fd)
|
|||||||
packet.ip.saddr = source;
|
packet.ip.saddr = source;
|
||||||
packet.ip.daddr = dest;
|
packet.ip.daddr = dest;
|
||||||
packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */
|
packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */
|
||||||
if (check && check != checksum(&packet, bytes)) {
|
if (check && check != checksum(&packet, len)) {
|
||||||
log_error("packet with bad UDP checksum received, ignoring");
|
log_error("packet with bad UDP checksum received, ignoring");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(payload, &(packet.data),
|
memcpy(payload, &(packet.data),
|
||||||
bytes - (sizeof(packet.ip) + sizeof(packet.udp)));
|
len - (sizeof(packet.ip) + sizeof(packet.udp)));
|
||||||
|
|
||||||
if (ntohl(payload->cookie) != DHCP_MAGIC) {
|
if (ntohl(payload->cookie) != DHCP_MAGIC) {
|
||||||
log_error("received bogus message (bad magic) -- ignoring");
|
log_error("received bogus message (bad magic) -- ignoring");
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
log_line("oooooh!!! got some!");
|
log_line("oooooh!!! got some!");
|
||||||
return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
|
return len - (sizeof(packet.ip) + sizeof(packet.udp));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user