X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/58bca61d95cf59937d54f0a2863a67e3ad6db420..7985f2abad4958a0f6ef93ad1df40487ba6ff5a8:/usr/src/sys/netinet/ip_input.c diff --git a/usr/src/sys/netinet/ip_input.c b/usr/src/sys/netinet/ip_input.c index 53f47f8c84..c0488df76c 100644 --- a/usr/src/sys/netinet/ip_input.c +++ b/usr/src/sys/netinet/ip_input.c @@ -1,9 +1,20 @@ /* - * Copyright (c) 1982 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. * - * @(#)ip_input.c 6.23 (Berkeley) %G% + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)ip_input.c 7.10 (Berkeley) %G% */ #include "param.h" @@ -224,43 +235,53 @@ next: ours: /* - * Look for queue of fragments - * of this datagram. + * If offset or IP_MF are set, must reassemble. + * Otherwise, nothing need be done. + * (We could look in the reassembly queue to see + * if the packet was previously fragmented, + * but it's not worth the time; just let them time out.) */ - for (fp = ipq.next; fp != &ipq; fp = fp->next) - if (ip->ip_id == fp->ipq_id && - ip->ip_src.s_addr == fp->ipq_src.s_addr && - ip->ip_dst.s_addr == fp->ipq_dst.s_addr && - ip->ip_p == fp->ipq_p) - goto found; - fp = 0; + if (ip->ip_off &~ IP_DF) { + /* + * Look for queue of fragments + * of this datagram. + */ + for (fp = ipq.next; fp != &ipq; fp = fp->next) + if (ip->ip_id == fp->ipq_id && + ip->ip_src.s_addr == fp->ipq_src.s_addr && + ip->ip_dst.s_addr == fp->ipq_dst.s_addr && + ip->ip_p == fp->ipq_p) + goto found; + fp = 0; found: - /* - * Adjust ip_len to not reflect header, - * set ip_mff if more fragments are expected, - * convert offset of this to bytes. - */ - ip->ip_len -= hlen; - ((struct ipasfrag *)ip)->ipf_mff = 0; - if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff = 1; - ip->ip_off <<= 3; + /* + * Adjust ip_len to not reflect header, + * set ip_mff if more fragments are expected, + * convert offset of this to bytes. + */ + ip->ip_len -= hlen; + ((struct ipasfrag *)ip)->ipf_mff = 0; + if (ip->ip_off & IP_MF) + ((struct ipasfrag *)ip)->ipf_mff = 1; + ip->ip_off <<= 3; - /* - * If datagram marked as having more fragments - * or if this is not the first fragment, - * attempt reassembly; if it succeeds, proceed. - */ - if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { - ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp); - if (ip == 0) - goto next; - m = dtom(ip); + /* + * If datagram marked as having more fragments + * or if this is not the first fragment, + * attempt reassembly; if it succeeds, proceed. + */ + if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { + ipstat.ips_fragments++; + ip = ip_reass((struct ipasfrag *)ip, fp); + if (ip == 0) + goto next; + m = dtom(ip); + } else + if (fp) + ip_freef(fp); } else - if (fp) - ip_freef(fp); + ip->ip_len -= hlen; /* * Switch out to protocol's input routine. @@ -300,7 +321,7 @@ ip_reass(ip, fp) * If first fragment to arrive, create a reassembly queue. */ if (fp == 0) { - if ((t = m_get(M_WAIT, MT_FTABLE)) == NULL) + if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) goto dropfrag; fp = mtod(t, struct ipq *); insque(fp, &ipq); @@ -488,6 +509,7 @@ ip_drain() } } +extern struct in_ifaddr *ifptoia(); struct in_ifaddr *ip_rtaddr(); /* @@ -593,14 +615,14 @@ ip_dooptions(ip, ifp) off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) break; - bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, + bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, sizeof(ipaddr.sin_addr)); /* * locate outgoing interface */ if ((ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; - code = ICMP_UNREACH_SRCFAIL; + code = ICMP_UNREACH_HOST; goto bad; } bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), @@ -618,7 +640,7 @@ ip_dooptions(ip, ifp) goto bad; break; } - sin = (struct in_addr *)(cp+cp[IPOPT_OFFSET]-1); + sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: @@ -628,21 +650,20 @@ ip_dooptions(ip, ifp) if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; - if (in_ifaddr == 0) - goto bad; /* ??? */ - bcopy((caddr_t)&IA_SIN(in_ifaddr)->sin_addr, + ia = ifptoia(ifp); + bcopy((caddr_t)&IA_SIN(ia)->sin_addr, (caddr_t)sin, sizeof(struct in_addr)); - sin++; + ipt->ipt_ptr += sizeof(struct in_addr); break; 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, sizeof(struct in_addr)); if (ifa_ifwithaddr((struct sockaddr *)&ipaddr) == 0) continue; - if (ipt->ipt_ptr + sizeof(n_time) + - sizeof(struct in_addr) > ipt->ipt_len) - goto bad; ipt->ipt_ptr += sizeof(struct in_addr); break; @@ -650,7 +671,8 @@ ip_dooptions(ip, ifp) goto bad; } ntime = iptime(); - bcopy((caddr_t)&ntime, (caddr_t)sin, sizeof(n_time)); + bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1, + sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); } } @@ -729,7 +751,9 @@ ip_srcroute() if (ip_nhops == 0) return ((struct mbuf *)0); - m = m_get(M_WAIT, MT_SOOPTS); + 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; /* @@ -839,7 +863,7 @@ ip_forward(ip, ifp) return; #endif } - if (ip->ip_ttl < IPTTLDEC) { + if (ip->ip_ttl <= IPTTLDEC) { type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS; goto sendicmp; } @@ -868,11 +892,15 @@ ip_forward(ip, ifp) * perhaps should send a redirect to sender to shortcut a hop. * Only send redirect if source is sending directly to us, * 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)) { struct in_ifaddr *ia; - extern struct in_ifaddr *ifptoia(); u_long src = ntohl(ip->ip_src.s_addr); u_long dst = ntohl(ip->ip_dst.s_addr); @@ -929,7 +957,10 @@ ip_forward(ip, ifp) case ENETUNREACH: case ENETDOWN: - code = ICMP_UNREACH_NET; + if (in_localaddr(ip->ip_dst)) + code = ICMP_UNREACH_HOST; + else + code = ICMP_UNREACH_NET; break; case EMSGSIZE: