bostic@OKEEFFE.BERKELEY.EDU.UUCP (09/18/87)
Subject: IP options Index: sys/netinet/ip_input.c 4.3BSD Description: There are a few oddities in the IP options code in 4.3BSD. The record route option looked up a garbage address and would drop the packet if it failed. The other bug of interest was in the IP timestamp handling. Here is a set of diffs to fix the record route bug and several other minor things. Repeat-By: Use a 4.3BSD gateway to forward packets with a record route option. Note that the packets are either dropped or have the wrong route address. Fix: Apply the following patch. *** /nbsd/usr/src.4.3/sys/netinet/ip_input.c Thu Jun 5 00:28:15 1986 --- ip_input.c Mon Sep 14 14:59:07 1987 *************** *** 5,7 **** * ! * @(#)ip_input.c 7.1 (Berkeley) 6/5/86 */ --- 5,7 ---- * ! * @(#)ip_input.c 7.6.1.2 (Berkeley) 9/14/87 */ *************** *** 302,304 **** if (fp == 0) { ! if ((t = m_get(M_WAIT, MT_FTABLE)) == NULL) goto dropfrag; --- 302,304 ---- if (fp == 0) { ! if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) goto dropfrag; *************** *** 490,491 **** --- 490,492 ---- + extern struct in_ifaddr *ifptoia(); struct in_ifaddr *ip_rtaddr(); *************** *** 595,597 **** break; ! bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); --- 596,598 ---- break; ! bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); *************** *** 602,604 **** type = ICMP_UNREACH; ! code = ICMP_UNREACH_SRCFAIL; goto bad; --- 603,605 ---- type = ICMP_UNREACH; ! code = ICMP_UNREACH_HOST; goto bad; *************** *** 620,622 **** } ! sin = (struct in_addr *)(cp+cp[IPOPT_OFFSET]-1); switch (ipt->ipt_flg) { --- 621,623 ---- } ! sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { *************** *** 630,636 **** goto bad; ! if (in_ifaddr == 0) ! goto bad; /* ??? */ ! bcopy((caddr_t)&IA_SIN(in_ifaddr)->sin_addr, (caddr_t)sin, sizeof(struct in_addr)); ! sin++; break; --- 631,636 ---- goto bad; ! ia = ifptoia(ifp); ! bcopy((caddr_t)&IA_SIN(ia)->sin_addr, (caddr_t)sin, sizeof(struct in_addr)); ! ipt->ipt_ptr += sizeof(struct in_addr); break; *************** *** 638,639 **** --- 638,642 ---- case IPOPT_TS_PRESPEC: + if (ipt->ipt_ptr + sizeof(n_time) + + sizeof(struct in_addr) > ipt->ipt_len) + goto bad; bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, *************** *** 642,646 **** continue; - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; ipt->ipt_ptr += sizeof(struct in_addr); --- 645,646 ---- *************** *** 652,654 **** ntime = iptime(); ! bcopy((caddr_t)&ntime, (caddr_t)sin, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); --- 652,655 ---- ntime = iptime(); ! bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, ! sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); *************** *** 731,733 **** return ((struct mbuf *)0); ! m = m_get(M_WAIT, MT_SOOPTS); m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1; --- 732,736 ---- return ((struct mbuf *)0); ! m = m_get(M_DONTWAIT, MT_SOOPTS); ! if (m == 0) ! return ((struct mbuf *)0); m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1; *************** *** 841,843 **** } ! if (ip->ip_ttl < IPTTLDEC) { type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS; --- 844,846 ---- } ! if (ip->ip_ttl <= IPTTLDEC) { type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS; *************** *** 870,873 **** --- 873,881 ---- * and if packet was not source routed (or has any options). + * Also, don't send redirect if forwarding using a default route + * or a route modfied by a redirect. */ + #define satosin(sa) ((struct sockaddr_in *)(sa)) if (ipforward_rt.ro_rt && ipforward_rt.ro_rt->rt_ifp == ifp && + (ipforward_rt.ro_rt->rt_flags & RTF_DYNAMIC) == 0 && + satosin(&ipforward_rt.ro_rt->rt_dst)->sin_addr.s_addr != 0 && ipsendredirects && ip->ip_hl == (sizeof(struct ip) >> 2)) { *************** *** 874,876 **** struct in_ifaddr *ia; - extern struct in_ifaddr *ifptoia(); u_long src = ntohl(ip->ip_src.s_addr); --- 882,883 ----