4.2BSD as Gateway bug
ron at brl-tgr.UUCP
ron at brl-tgr.UUCP
Wed May 16 03:40:52 AEST 1984
Subject: 4.2BSD as Gateway bug
Newsgroups: net.bugs.4bsd
Subject: Fragmentation bug on packet forwarding
Index: sys/netinet/ip_output.c 4.2BSD
Description:
When the packets are being forwarded through a 4.2 BSD system
a problem sometimes shows up that results in lost packets and
transmission of illegally formatted internet packets. The
problem occurs when a 4.2 BSD system is gatewaying from nets
that have unequal Maximum Transfer Units (MTU). When a fragmented
packet arriving from an outside source must be fragmented again
the MORE FRAGMENTS bit is never set on the last fragment even
though it may be required. When other than the last fragment of
the original packet is fragmented, the MORE FRAGMENTS bit must be
set to indicate that the subsequent fragments of the original packet
still follow (got that?). This problem does not happen when you
are not playing gateway because ip_output does not get passed
already fragmented packets in that situation. Example: Host
X sends ip packet A to BSD-HOST in two fragments, A1 and A2.
BSD-HOST must then fragment A1 into A1a and A1b. A1b should have
MF set because fragment A2 still follows.
Repeat-By:
Set the MTU on you host to some small number, and then try to
forward already fragmented packets through it.
Fix:
Set the bit on the last fragment to what it was on the packet
before fragmenting began. Below is the fragmentation code from
ip_ouptut():
/*
* Discard IP header from logical mbuf for m_copy's sake.
* Loop through length of segment, make a copy of each
* part and output.
*/
m->m_len -= sizeof (struct ip);
m->m_off += sizeof (struct ip);
for (off = 0; off < ip->ip_len-hlen; off += len) {
struct mbuf *mh = m_get(M_DONTWAIT, MT_HEADER);
struct ip *mhip;
if (mh == 0) {
error = ENOBUFS;
goto bad;
}
mh->m_off = MMAXOFF - hlen;
mhip = mtod(mh, struct ip *);
*mhip = *ip;
if (hlen > sizeof (struct ip)) {
int olen = ip_optcopy(ip, mhip, off);
mh->m_len = sizeof (struct ip) + olen;
} else
mh->m_len = sizeof (struct ip);
mhip->ip_off = off >> 3;
/*******************************************************\
|* *|
|* A D D T H I S L I N E *|
|* *|
|* If the packet we're fragmenting has fragments from *|
|* other systems, propagate the MORE_FRAGMENTS flag. *|
\*******************************************************/
if(ip->ip_off & IP_MF) mhip->ip_off |= IP_MF;
if (off + len >= ip->ip_len-hlen)
len = mhip->ip_len = ip->ip_len - hlen - off;
else {
mhip->ip_len = len;
mhip->ip_off |= IP_MF;
}
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list