summaryrefslogtreecommitdiff
path: root/usr.sbin/vmd
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2021-06-15 10:38:54 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2021-06-15 10:38:54 +0000
commite90c78820ddd3becb80642a373a4a3a9aad4eb4f (patch)
tree19f6137b3e431994da6f0786b1b5345ecce32e22 /usr.sbin/vmd
parent25c386bd057ec8ca403e6ba7f1ff34541176e491 (diff)
Filter out packets that are not IPv4. This code came from dhcp programs
where this filtering was done in bpf but here vmd needs to make sure to not look at non IPv4 packets. OK florian@ and dv@
Diffstat (limited to 'usr.sbin/vmd')
-rw-r--r--usr.sbin/vmd/packet.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/usr.sbin/vmd/packet.c b/usr.sbin/vmd/packet.c
index 1bf5d28f9da..645015fe450 100644
--- a/usr.sbin/vmd/packet.c
+++ b/usr.sbin/vmd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.2 2021/05/23 22:43:36 dv Exp $ */
+/* $OpenBSD: packet.c,v 1.3 2021/06/15 10:38:53 claudio Exp $ */
/* Packet assembly code, originally contributed by Archie Cobbs. */
@@ -169,6 +169,8 @@ decode_hw_header(unsigned char *buf, size_t buflen,
size_t offset, struct packet_ctx *pc, unsigned int intfhtype)
{
u_int32_t ip_len;
+ u_int16_t ether_type;
+ struct ether_header *eh;
struct ip *ip;
switch (intfhtype) {
@@ -196,9 +198,14 @@ decode_hw_header(unsigned char *buf, size_t buflen,
if (buflen < offset + ETHER_HDR_LEN)
return (-1);
- memcpy(pc->pc_dmac, buf + offset, ETHER_ADDR_LEN);
- memcpy(pc->pc_smac, buf + offset + ETHER_ADDR_LEN,
- ETHER_ADDR_LEN);
+ eh = (struct ether_header *)(buf + offset);
+ memcpy(pc->pc_dmac, eh->ether_dhost, ETHER_ADDR_LEN);
+ memcpy(pc->pc_smac, eh->ether_shost, ETHER_ADDR_LEN);
+ memcpy(&ether_type, &eh->ether_type, sizeof(ether_type));
+
+ if (ether_type != htons(ETHERTYPE_IP))
+ return (-1);
+
offset += ETHER_HDR_LEN;
pc->pc_htype = ARPHRD_ETHER;
@@ -225,18 +232,20 @@ decode_udp_ip_header(unsigned char *buf, size_t buflen,
/* Assure that an entire IP header is within the buffer. */
if (buflen < offset + sizeof(*ip))
return (-1);
- ip_len = (buf[offset] & 0xf) << 2;
- if (buflen < offset + ip_len)
+ ip = (struct ip *)(buf + offset);
+ if (ip->ip_v != IPVERSION)
+ return (-1);
+ ip_len = ip->ip_hl << 2;
+ if (ip_len < sizeof(struct ip) ||
+ buflen < offset + ip_len)
return (-1);
- ip = (struct ip *)(buf + offset);
if (ip->ip_p != IPPROTO_UDP)
return (-1);
/* Check the IP header checksum - it should be zero. */
- if (wrapsum(checksum(buf + offset, ip_len, 0)) != 0) {
+ if (wrapsum(checksum(buf + offset, ip_len, 0)) != 0)
return (-1);
- }
pc->pc_src.ss_len = sizeof(struct sockaddr_in);
pc->pc_src.ss_family = AF_INET;
@@ -288,9 +297,8 @@ decode_udp_ip_header(unsigned char *buf, size_t buflen,
2 * sizeof(ip->ip_src),
IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)))));
- if (usum && usum != sum) {
+ if (usum && usum != sum)
return (-1);
- }
ss2sin(&pc->pc_src)->sin_port = udp->uh_sport;
ss2sin(&pc->pc_dst)->sin_port = udp->uh_dport;