diff --git a/dhcpctl/dhcpctl.c b/dhcpctl/dhcpctl.c
index 8f2b1ff..3d0f099 100644
--- a/dhcpctl/dhcpctl.c
+++ b/dhcpctl/dhcpctl.c
@@ -849,6 +849,7 @@ do_extra_stats(u_int64_t *s)
 
 	printf("packets.badlength.ip=%llu\n",	s[STATS_IP_BAD_LEN]);
 	printf("packets.badlength.udp=%llu\n",	s[STATS_UDP_BAD_LEN]);
+	printf("packets.badlength.bootp=%llu\n",s[STATS_BOOTP_BAD_LEN]);
 	printf("packets.badlength.dhcp=%llu\n",	s[STATS_DHCP_BAD_LEN]);
 
 	printf("packets.bootp.only=%llu\n",	s[STATS_BOOTP_ONLY]);
diff --git a/dhcpd/dhcpd.h b/dhcpd/dhcpd.h
index 8a0c2a4..5662b0a 100644
--- a/dhcpd/dhcpd.h
+++ b/dhcpd/dhcpd.h
@@ -339,6 +339,7 @@ enum {
 	STATS_IP_NO_ADDRESS,
 	STATS_IP_BAD_LEN,
 	STATS_UDP_BAD_LEN,
+	STATS_BOOTP_BAD_LEN,
 	STATS_DHCP_BAD_LEN,
 	STATS_DHCP_NOT_FOR_US,
 	STATS_BOOTP_ONLY,
@@ -481,6 +482,7 @@ int	dhcp_options_parse(u_int8_t *, size_t, u_int8_t **);
 int	bootp_input(u_int8_t *, size_t, struct request *);
 
 /* protocol_logic.c */
+int	bootrequest(struct request *, void *, ssize_t);
 int	dhcpdecline(struct request *);
 int	dhcpdiscover(struct request *);
 int	dhcpinform(struct request *);
diff --git a/dhcpd/protocol_input.c b/dhcpd/protocol_input.c
index 96028c8..3b0f090 100644
--- a/dhcpd/protocol_input.c
+++ b/dhcpd/protocol_input.c
@@ -199,7 +199,7 @@ bootp_input(u_int8_t *data, size_t len, struct request *req)
 		}		tail;
 	} *packet = (void *) data;
 
-	if (len > MTU || len <= sizeof packet->bootp) {
+	if (len > MTU || len <= sizeof packet->bootp + 4) {
 		log_warnx("%s: rcvd packet of length %zu", __func__, len);
 		return (-1);
 	}
@@ -208,17 +208,17 @@ bootp_input(u_int8_t *data, size_t len, struct request *req)
 
 	if (packet->bootp.op != BOOTREQUEST) {
 		++stats[STATS_BOOTP_NOT_BOOTREQUEST];
-		log_info("it is NOT a BOOTREQUEST, but %u", packet->bootp.op);
+		log_info("NOT a BOOTREQUEST, but %u", packet->bootp.op);
 		return (-1);
 	}
 	if (packet->bootp.htype != HTYPE_ETHERNET) {
 		++stats[STATS_BOOTP_BAD_HTYPE];
-		log_info("it is NOT a HTYPE_ETHERNET, but %u", packet->bootp.htype);
+		log_info("NOT a HTYPE_ETHERNET, but %u", packet->bootp.htype);
 		return (-1);
 	}
 	if (packet->bootp.hlen != ETHER_ADDR_LEN) {
 		++stats[STATS_BOOTP_BAD_HLEN];
-		log_info("it is NOT a ETHER_ADDR_LEN, but %u", packet->bootp.hlen);
+		log_info("NOT a ETHER_ADDR_LEN, but %u", packet->bootp.hlen);
 		return (-1);
 	}
 
@@ -232,11 +232,18 @@ bootp_input(u_int8_t *data, size_t len, struct request *req)
 		return (-1);
 	}
 
-	/* No space for DHCP magic, or no magic at all?  It's a BOOTP packet. */
-	if (len <= sizeof packet->bootp + 4 ||
-	    packet->tail.dhcp.magic != ntohl(DHCP_OPTION_START_MAGIC)) {
-		log_info("it is NOT a DHCP packet");
+	/* No DHCP magic?  It's a BOOTP packet. */
+	if (packet->tail.dhcp.magic != ntohl(DHCP_OPTION_START_MAGIC)) {
 		++stats[STATS_BOOTP_ONLY];
+
+		/* Strip away what the BOOTP header we parsed. */
+		if ((len -= sizeof(struct bootp)) < 64) {
+			++stats[STATS_BOOTP_BAD_LEN];
+			log_info("%s: vendor options only %zu", __func__, len);
+			return (-1);
+		}
+
+		return bootrequest(req, &packet->tail.bootp_vend, len);
 	}
 	else {
 		/*
@@ -245,9 +252,6 @@ bootp_input(u_int8_t *data, size_t len, struct request *req)
 		 */
 		len -= (char *) &packet->tail.dhcp.options - (char *) packet;
 
-		if (dhcp_input(packet->tail.dhcp.options, len, req) < 0)
-			return (-1);
+		return dhcp_input(packet->tail.dhcp.options, len, req);
 	}
-
-	return ((int) len);
 }
diff --git a/dhcpd/protocol_logic.c b/dhcpd/protocol_logic.c
index fc01c85..7cf85fc 100644
--- a/dhcpd/protocol_logic.c
+++ b/dhcpd/protocol_logic.c
@@ -407,3 +407,32 @@ dhcpinform(struct request *req)
 
 	return dhcpack(req, &fake_lease, REPLY_TO_DHCPINFORM);
 }
+
+int
+bootrequest(struct request *req, void *vendor, ssize_t len)
+{
+	struct reply	 reply;
+	struct lease	 fake;
+	struct host	*h;
+	u_int32_t	*magic = vendor;
+
+	if ((h = shared_network_find_mac(req)) == NULL) {
+		log_info("%s: BOOTREQUEST: unsatisfied %s, magic %#x, len %zd",
+		    req->shared->name, ether_ntoa(&req->bootp->chaddr.ether),
+		    ntohl(magic[0]), len);
+		return (0);
+	}
+
+	log_info("%s: BOOTREQUEST->BOOTREPLY: %s -> %s, magic %#x, len %zd",
+	    req->shared->name, ether_ntoa(&req->bootp->chaddr.ether),
+	    inet_ntoa(h->address), ntohl(magic[0]), len);
+
+	memset(&fake, 0, sizeof fake);
+	fake.host = h;
+	fake.address = h->address;
+	fake.group = h->group;
+
+	memset(&reply, 0, sizeof reply);
+	reply.lease = &fake;
+	return bootp_output(req, &reply);
+}
