diff options
author | marius <marius@FreeBSD.org> | 2009-03-07 19:08:58 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2009-03-07 19:08:58 +0000 |
commit | 74f63d4ce14b7d970f6fe45d8d855faaaf5f7ed5 (patch) | |
tree | 25a76694bea3791d223804b5dab3dae47761145d /sys/netinet | |
parent | 09f1ec373e0d13417810ac3620b458cf50cd65d7 (diff) | |
download | FreeBSD-src-74f63d4ce14b7d970f6fe45d8d855faaaf5f7ed5.zip FreeBSD-src-74f63d4ce14b7d970f6fe45d8d855faaaf5f7ed5.tar.gz |
On architectures with strict alignment requirements compensate
the misalignment of the IP header that prepending the EtherIP
header might have caused.
PR: 131921
MFC after: 1 week
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in_gif.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index 9bcb09e..a05c04b 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -102,7 +102,7 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m) struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst; struct ip iphdr; /* capsule IP header, host byte ordered */ struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t tos; GIF_LOCK_ASSERT(sc); @@ -186,13 +186,27 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m) &iphdr.ip_tos, &tos); /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip)) - m = m_pullup(m, sizeof(struct ip)); + len = sizeof(struct ip); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); M_SETFIB(m, sc->gif_fibnum); |