dpz@rutgers.rutgers.edu (David P. Zimmerman) (01/09/89)
The problem: 4.3BSD drops the IP options on the floor when it turns an ICMP request into a reply. This doesn't make things easy, especially for doing useful things like ping with record route. The fix: Apply these two patches. The first is for sys/netinet/ip_input.c, the second is for sys/netinet/ip_icmp.c. No, it isn't backwards compatible with the original way ip_stripoptions(ip, real_mbuf) worked, but nothing was using it that way anyway. Looked like a half-solution waiting for a problem. ip_stripoptions(ip, (struct mbuf *)0)) still works normally. David : This is a shell archive. : Remove everything above this line and : run the following text with /bin/sh to create: : ip_input.c.diff : ip_icmp.c.diff : This archive created: Mon Jan 9 05:51:11 1989 cat << 'SHAR_EOF' > ip_input.c.diff *** /tmp/geta4604 Mon Jan 9 05:10:02 1989 --- /tmp/getb4604 Mon Jan 9 05:10:02 1989 *************** *** 783,798 **** register int i; register struct mbuf *m; register caddr_t opts; ! int olen; olen = (ip->ip_hl<<2) - sizeof (struct ip); m = dtom(ip); opts = (caddr_t)(ip + 1); if (mopt) { ! mopt->m_len = olen; ! mopt->m_off = MMINOFF; ! bcopy(opts, mtod(mopt, caddr_t), (unsigned)olen); ! } i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; --- 783,834 ---- register int i; register struct mbuf *m; register caddr_t opts; ! int olen, optsoff = 0; olen = (ip->ip_hl<<2) - sizeof (struct ip); m = dtom(ip); opts = (caddr_t)(ip + 1); + if (mopt) { ! ! /* If m_len is 0, we're dealing with an option set which ip_srcroute ! ** found no source routing in. So, we've got an empty mbuf, into the ! ** beginning of which we have to coerce a "first hop" address. In a ! ** packet with no source routing, this would be the destination ! ** address. Otherwise, m_len is real, and we're just appending to ! ** the mbuf coming out of ip_srcroute. */ ! ! if (!mopt->m_len) { ! mopt->m_len = sizeof(struct in_addr); ! bcopy(&ip->ip_dst, mtod(mopt, caddr_t), mopt->m_len); ! } ! ! /* Push the rest of the options in. We don't have to worry about the ! ** other IP level options like we do the source routing, so just ! ** search for them and insert them into the mbuf. Notice that ! ** anything dealing with source routing is ignored, since you would ! ** want to do that in ip_srcroute instead. */ ! ! while (optsoff + 1 <= olen) ! switch(opts[optsoff]) { ! case IPOPT_LSRR: ! case IPOPT_SSRR: ! optsoff += opts[optsoff + IPOPT_OLEN]; ! break; ! case IPOPT_EOL: ! case IPOPT_NOP: ! mopt->m_dat[mopt->m_len++] = opts[optsoff++]; ! break; ! default: ! bcopy(&opts[optsoff], &mopt->m_dat[mopt->m_len], ! opts[optsoff + IPOPT_OLEN]); ! mopt->m_len += opts[optsoff + IPOPT_OLEN]; ! optsoff += opts[optsoff + IPOPT_OLEN]; ! break; ! } ! mopt->m_off = MMINOFF; ! } ! i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; SHAR_EOF cat << 'SHAR_EOF' > ip_icmp.c.diff *** /tmp/geta4590 Mon Jan 9 05:09:27 1989 --- /tmp/getb4590 Mon Jan 9 05:09:27 1989 *************** *** 376,386 **** if (optlen > 0) { /* * Retrieve any source routing from the incoming packet ! * and strip out other options. Adjust the IP length. */ opts = ip_srcroute(); ip->ip_len -= optlen; - ip_stripoptions(ip, (struct mbuf *)0); } icmp_send(ip, opts); if (opts) --- 376,393 ---- if (optlen > 0) { /* * Retrieve any source routing from the incoming packet ! * and merge in the other non-routing options. ! * Adjust the IP length. */ opts = ip_srcroute(); + if (!opts) + if (opts = m_get(M_DONTWAIT, MT_SOOPTS)) + opts->m_len = 0; + if (opts) + ip_stripoptions(ip, opts); + else /* admit defeat */ + ip_stripoptions(ip, (struct mbuf *)0); ip->ip_len -= optlen; } icmp_send(ip, opts); if (opts) SHAR_EOF : End of shell archive exit 0 -- David P. Zimmerman, the Dorm Networking Pilot Project, the UUCP Project, etc dpz@dorm.rutgers.edu rutgers!dpz dpzimmerman@zodiac.bitnet