summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/ipxe/if_arp.h10
-rw-r--r--src/net/arp.c7
2 files changed, 17 insertions, 0 deletions
diff --git a/src/include/ipxe/if_arp.h b/src/include/ipxe/if_arp.h
index 4eb1f80b7..9d7b03fe8 100644
--- a/src/include/ipxe/if_arp.h
+++ b/src/include/ipxe/if_arp.h
@@ -99,4 +99,14 @@ static inline void * arp_target_pa ( struct arphdr *arphdr ) {
return ( arp_target_ha ( arphdr ) + arphdr->ar_hln );
}
+/** ARP packet length
+ *
+ * @v arphdr ARP header
+ * @ret len Length (including header)
+ */
+static inline size_t arp_len ( struct arphdr *arphdr ) {
+ return ( sizeof ( *arphdr ) +
+ ( 2 * ( arphdr->ar_hln + arphdr->ar_pln ) ) );
+}
+
#endif /* _IPXE_IF_ARP_H */
diff --git a/src/net/arp.c b/src/net/arp.c
index 1e27c44e7..c9b4109a9 100644
--- a/src/net/arp.c
+++ b/src/net/arp.c
@@ -139,8 +139,15 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
struct arp_net_protocol *arp_net_protocol;
struct net_protocol *net_protocol;
struct ll_protocol *ll_protocol;
+ size_t len = iob_len ( iobuf );
int rc;
+ /* Sanity check */
+ if ( ( len < sizeof ( *arphdr ) ) || ( len < arp_len ( arphdr ) ) ) {
+ rc = -EINVAL;
+ goto done;
+ }
+
/* Identify network-layer and link-layer protocols */
arp_net_protocol = arp_find_protocol ( arphdr->ar_pro );
if ( ! arp_net_protocol ) {