diff options
author | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2015-03-20 10:41:16 +0000 |
---|---|---|
committer | Mike Belopuhov <mikeb@cvs.openbsd.org> | 2015-03-20 10:41:16 +0000 |
commit | c1dfca4bc32d96d4ae0c01ac57ddc82c65289642 (patch) | |
tree | f20879279fc4c1ea6a774ee76aa2eab864fffb18 /sys | |
parent | 477cf2c45b4f87e43500e8d612d09b3865f2524b (diff) |
Re-apply -r1.115 that got accidentally reverted and brought to my
attention and fix re-tested by Kapetanakis Giannis. Thanks a lot!
Original commit message:
When setting up advanced TX descriptor use m_getptr to locate the IP
or IPv6 header instead of assuming contiguousness of the target buffer
across Ethernet and IP/IPv6 headers.
Tested by Kapetanakis Giannis <bilias at edu ! physics ! uoc ! gr>,
thanks! Problem analysis and initial diff by dlg@.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/if_ix.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 042bd6c6a6f..a05c836f9f4 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.c,v 1.117 2015/02/12 04:58:59 dlg Exp $ */ +/* $OpenBSD: if_ix.c,v 1.118 2015/03/20 10:41:15 mikeb Exp $ */ /****************************************************************************** @@ -2049,6 +2049,8 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, #ifdef notyet struct ip6_hdr *ip6; #endif + struct mbuf *m; + int ipoff; uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0; int ehdrlen, ip_hlen = 0; uint16_t etype; @@ -2094,9 +2096,13 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, * Jump over vlan headers if already present, * helpful for QinQ too. */ + if (mp->m_len < sizeof(struct ether_header)) + return (1); #if NVLAN > 0 eh = mtod(mp, struct ether_vlan_header *); if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) { + if (mp->m_len < sizeof(struct ether_vlan_header)) + return (1); etype = ntohs(eh->evl_proto); ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN; } else { @@ -2114,15 +2120,23 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp, switch (etype) { case ETHERTYPE_IP: - ip = (struct ip *)(mp->m_data + ehdrlen); + if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip)) + return (1); + m = m_getptr(mp, ehdrlen, &ipoff); + KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip)); + ip = (struct ip *)(m->m_data + ipoff); ip_hlen = ip->ip_hl << 2; ipproto = ip->ip_p; type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; break; #ifdef notyet case ETHERTYPE_IPV6: - ip6 = (struct ip6_hdr *)(mp->m_data + ehdrlen); - ip_hlen = sizeof(struct ip6_hdr); + if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip6)) + return (1); + m = m_getptr(mp, ehdrlen, &ipoff); + KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip6)); + ip6 = (struct ip6 *)(m->m_data + ipoff); + ip_hlen = sizeof(*ip6); /* XXX-BZ this will go badly in case of ext hdrs. */ ipproto = ip6->ip6_nxt; type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6; |