Update libslirp to 4.7.0 with our customizations
This commit is contained in:
@@ -34,6 +34,8 @@
|
||||
|
||||
#define LEASE_TIME (24 * 3600)
|
||||
|
||||
#define UEFI_HTTP_VENDOR_CLASS_ID "HTTPClient"
|
||||
|
||||
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
|
||||
|
||||
#define DPRINTF(fmt, ...) DEBUG_CALL(fmt, ##__VA_ARGS__)
|
||||
@@ -92,21 +94,22 @@ found:
|
||||
return bc;
|
||||
}
|
||||
|
||||
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||
static void dhcp_decode(const struct bootp_t *bp,
|
||||
const uint8_t *bp_end,
|
||||
int *pmsg_type,
|
||||
struct in_addr *preq_addr)
|
||||
{
|
||||
const uint8_t *p, *p_end;
|
||||
const uint8_t *p;
|
||||
int len, tag;
|
||||
|
||||
*pmsg_type = 0;
|
||||
preq_addr->s_addr = htonl(0L);
|
||||
|
||||
p = bp->bp_vend;
|
||||
p_end = p + DHCP_OPT_LEN;
|
||||
if (memcmp(p, rfc1533_cookie, 4) != 0)
|
||||
return;
|
||||
p += 4;
|
||||
while (p < p_end) {
|
||||
while (p < bp_end) {
|
||||
tag = p[0];
|
||||
if (tag == RFC1533_PAD) {
|
||||
p++;
|
||||
@@ -114,10 +117,10 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||
break;
|
||||
} else {
|
||||
p++;
|
||||
if (p >= p_end)
|
||||
if (p >= bp_end)
|
||||
break;
|
||||
len = *p++;
|
||||
if (p + len > p_end) {
|
||||
if (p + len > bp_end) {
|
||||
break;
|
||||
}
|
||||
DPRINTF("dhcp: tag=%d len=%d\n", tag, len);
|
||||
@@ -144,7 +147,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
|
||||
}
|
||||
}
|
||||
|
||||
static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
static void bootp_reply(Slirp *slirp,
|
||||
const struct bootp_t *bp,
|
||||
const uint8_t *bp_end)
|
||||
{
|
||||
BOOTPClient *bc = NULL;
|
||||
struct mbuf *m;
|
||||
@@ -157,7 +162,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
uint8_t client_ethaddr[ETH_ALEN];
|
||||
|
||||
/* extract exact DHCP msg type */
|
||||
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
|
||||
dhcp_decode(bp, bp_end, &dhcp_msg_type, &preq_addr);
|
||||
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
|
||||
if (preq_addr.s_addr != htonl(0L))
|
||||
DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr));
|
||||
@@ -179,9 +184,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
return;
|
||||
}
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN);
|
||||
rbp = (struct bootp_t *)m->m_data;
|
||||
m->m_data += sizeof(struct udpiphdr);
|
||||
memset(rbp, 0, sizeof(struct bootp_t));
|
||||
memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN);
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||
if (preq_addr.s_addr != htonl(0L)) {
|
||||
@@ -235,7 +241,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
|
||||
|
||||
q = rbp->bp_vend;
|
||||
end = (uint8_t *)&rbp[1];
|
||||
end = rbp->bp_vend + DHCP_OPT_LEN;
|
||||
memcpy(q, rfc1533_cookie, 4);
|
||||
q += 4;
|
||||
|
||||
@@ -336,6 +342,27 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
|
||||
/* this allows to support UEFI HTTP boot: according to the UEFI
|
||||
specification, DHCP server must send vendor class identifier option
|
||||
set to "HTTPClient" string, when responding to DHCP requests as part
|
||||
of the UEFI HTTP boot
|
||||
|
||||
we assume that, if the bootfile parameter was configured as an http
|
||||
URL, the user intends to perform UEFI HTTP boot, so send this option
|
||||
automatically */
|
||||
if (slirp->bootp_filename && g_str_has_prefix(slirp->bootp_filename, "http://")) {
|
||||
val = strlen(UEFI_HTTP_VENDOR_CLASS_ID);
|
||||
if (q + val + 2 >= end) {
|
||||
g_warning("DHCP packet size exceeded, "
|
||||
"omitting vendor class id option.");
|
||||
} else {
|
||||
*q++ = RFC2132_VENDOR_CLASS_ID;
|
||||
*q++ = val;
|
||||
memcpy(q, UEFI_HTTP_VENDOR_CLASS_ID, val);
|
||||
q += val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
static const char nak_msg[] = "requested address not available";
|
||||
|
||||
@@ -351,19 +378,21 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
q += sizeof(nak_msg) - 1;
|
||||
}
|
||||
assert(q < end);
|
||||
*q = RFC1533_END;
|
||||
*q++ = RFC1533_END;
|
||||
|
||||
daddr.sin_addr.s_addr = 0xffffffffu;
|
||||
|
||||
m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr);
|
||||
assert(q <= end);
|
||||
|
||||
m->m_len = sizeof(struct bootp_t) + (end - rbp->bp_vend) - sizeof(struct ip) - sizeof(struct udphdr);
|
||||
udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||
}
|
||||
|
||||
void bootp_input(struct mbuf *m)
|
||||
{
|
||||
struct bootp_t *bp = mtod(m, struct bootp_t *);
|
||||
struct bootp_t *bp = mtod_check(m, sizeof(struct bootp_t));
|
||||
|
||||
if (bp->bp_op == BOOTP_REQUEST) {
|
||||
bootp_reply(m->slirp, bp);
|
||||
if (!m->slirp->disable_dhcp && bp && bp->bp_op == BOOTP_REQUEST) {
|
||||
bootp_reply(m->slirp, bp, m_end(m));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user