diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-15 10:38:54 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-15 10:38:54 +0000 |
commit | e90c78820ddd3becb80642a373a4a3a9aad4eb4f (patch) | |
tree | 19f6137b3e431994da6f0786b1b5345ecce32e22 | |
parent | 25c386bd057ec8ca403e6ba7f1ff34541176e491 (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@
-rw-r--r-- | usr.sbin/vmd/packet.c | 30 |
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(ðer_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; |