Update libslirp to 4.7.0 with our customizations

This commit is contained in:
Jasmine Iwanek
2023-02-06 12:46:37 -05:00
parent 0daee20e8b
commit 3b5cfe8bfc
50 changed files with 2071 additions and 441 deletions

View File

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