Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.12 retrieving revision 1.13 diff -u -p -r1.12 -r1.13 --- src/sys/netinet/ip_input.c 1994/02/14 21:45:53 1.12 +++ src/sys/netinet/ip_input.c 1994/05/13 06:06:21 1.13 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1982, 1986, 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)ip_input.c 7.19 (Berkeley) 5/25/91 - * $Id: ip_input.c,v 1.12 1994/02/14 21:45:53 mycroft Exp $ + * from: @(#)ip_input.c 8.2 (Berkeley) 1/4/94 + * $Id: ip_input.c,v 1.13 1994/05/13 06:06:21 mycroft Exp $ */ #include @@ -55,7 +55,6 @@ #include #include #include -#include #ifndef IPFORWARDING #ifdef GATEWAY @@ -69,6 +68,7 @@ #endif int ipforwarding = IPFORWARDING; int ipsendredirects = IPSENDREDIRECTS; +int ip_defttl = IPDEFTTL; #ifdef DIAGNOSTIC int ipprintfs = 0; #endif @@ -78,6 +78,7 @@ extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddr *in_ifaddr; /* first inet address */ +struct ifqueue ipintrq; /* * We need to save the IP options in case a protocol wants to respond @@ -99,9 +100,7 @@ extern int if_index; u_long *ip_ifmatrix; #endif -static void ip_forward __P((struct mbuf *, int)); -static void save_rte __P((u_char *, struct in_addr)); - +static void save_rte __P((u_char *, struct in_addr)); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. @@ -127,12 +126,11 @@ ip_init() ipintrq.ifq_maxlen = ipqmaxlen; #ifdef GATEWAY i = (if_index + 1) * (if_index + 1) * sizeof (u_long); - if ((ip_ifmatrix = (u_long *) malloc(i, M_RTABLE, M_WAITOK)) == 0) - panic("no memory for ip_ifmatrix"); + ip_ifmatrix = (u_long *) malloc(i, M_RTABLE, M_WAITOK); + bzero((char *)ip_ifmatrix, i); #endif } -struct ip *ip_reass(); struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; struct route ipforward_rt; @@ -148,13 +146,7 @@ ipintr() register struct ipq *fp; register struct in_ifaddr *ia; int hlen, s; -#ifdef DIAGNOSTIC - static int busy = 0; - if (busy) - panic("ipintr: called recursively\n"); - ++busy; -#endif next: /* * Get next datagram off input queue and get IP header @@ -163,12 +155,8 @@ next: s = splimp(); IF_DEQUEUE(&ipintrq, m); splx(s); - if (m == 0) { -#ifdef DIAGNOSTIC - --busy; -#endif + if (m == 0) return; - } #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ipintr no HDR"); @@ -186,6 +174,10 @@ next: goto next; } ip = mtod(m, struct ip *); + if (ip->ip_v != IPVERSION) { + ipstat.ips_badvers++; + goto bad; + } hlen = ip->ip_hl << 2; if (hlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; @@ -300,7 +292,8 @@ next: * ip_output().) */ ip->ip_id = htons(ip->ip_id); - if (ip_mforward(ip, m->m_pkthdr.rcvif, m) != 0) { + if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) { + ipstat.ips_cantforward++; m_freem(m); goto next; } @@ -313,6 +306,7 @@ next: */ if (ip->ip_p == IPPROTO_IGMP) goto ours; + ipstat.ips_forward++; } #endif /* @@ -321,6 +315,7 @@ next: */ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); if (inm == NULL) { + ipstat.ips_cantforward++; m_freem(m); goto next; } @@ -376,9 +371,9 @@ found: * convert offset of this to bytes. */ ip->ip_len -= hlen; - ((struct ipasfrag *)ip)->ipf_mff = 0; + ((struct ipasfrag *)ip)->ipf_mff &= ~1; if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff = 1; + ((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_off <<= 3; /* @@ -386,13 +381,12 @@ found: * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ - if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { + if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { ipstat.ips_fragments++; ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) goto next; - else - ipstat.ips_reassembled++; + ipstat.ips_reassembled++; m = dtom(ip); } else if (fp) @@ -505,7 +499,7 @@ insert: return (0); next += q->ip_len; } - if (q->ipf_prev->ipf_mff) + if (q->ipf_prev->ipf_mff & 1) return (0); /* @@ -531,6 +525,7 @@ insert: */ ip = fp->ipq_next; ip->ip_len = next; + ip->ipf_mff &= ~1; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; remque(fp); @@ -639,9 +634,6 @@ ip_drain() } } -extern struct in_ifaddr *ifptoia(); -struct in_ifaddr *ip_rtaddr(); - /* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, @@ -658,9 +650,10 @@ ip_dooptions(m) register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; - struct in_addr *sin; + struct in_addr *sin, dst; n_time ntime; + dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { @@ -728,7 +721,7 @@ ip_dooptions(m) #define INA struct in_ifaddr * #define SA struct sockaddr * if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) - ia = in_iaonnetof(in_netof(ipaddr.sin_addr)); + ia = (INA)ifa_ifwithnet((SA)&ipaddr); } else ia = ip_rtaddr(ipaddr.sin_addr); if (ia == 0) { @@ -740,7 +733,10 @@ ip_dooptions(m) bcopy((caddr_t)&(IA_SIN(ia)->sin_addr), (caddr_t)(cp + off), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); - forward = 1; + /* + * Let ip_intr's mcast routing check handle mcast pkts + */ + forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); break; case IPOPT_RR: @@ -791,7 +787,11 @@ ip_dooptions(m) if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; - ia = ifptoia(m->m_pkthdr.rcvif); + ipaddr.sin_addr = dst; + ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, + m->m_pkthdr.rcvif); + if (ia == 0) + continue; bcopy((caddr_t)&IA_SIN(ia)->sin_addr, (caddr_t)sin, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); @@ -820,13 +820,12 @@ ip_dooptions(m) if (forward) { ip_forward(m, 1); return (1); - } else - return (0); + } + return (0); bad: - { - register struct in_addr foo = {}; - icmp_error(m, type, code, foo); - } + ip->ip_len -= ip->ip_hl << 2; /* XXX icmp_error adds in hdr length */ + icmp_error(m, type, code, 0, 0); + ipstat.ips_badoptions++; return (1); } @@ -862,7 +861,7 @@ ip_rtaddr(dst) * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ -static void +void save_rte(option, dst) u_char *option; struct in_addr dst; @@ -898,7 +897,7 @@ ip_srcroute() if (m == 0) return ((struct mbuf *)0); -#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) +#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + @@ -1000,7 +999,7 @@ u_char inetctlerrmap[PRC_NCMDS] = { * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ -static void +void ip_forward(m, srcrt) struct mbuf *m; int srcrt; @@ -1010,9 +1009,10 @@ ip_forward(m, srcrt) register struct rtentry *rt; int error, type = 0, code; struct mbuf *mcopy; - struct in_addr dest; + n_long dest; + struct ifnet *destifp; - dest.s_addr = 0; + dest = 0; #ifdef DIAGNOSTIC if (ipprintfs) printf("forward: src %x dst %x ttl %x\n", ip->ip_src, @@ -1025,7 +1025,7 @@ ip_forward(m, srcrt) } HTONS(ip->ip_id); if (ip->ip_ttl <= IPTTLDEC) { - icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest); + icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); return; } ip->ip_ttl -= IPTTLDEC; @@ -1043,7 +1043,7 @@ ip_forward(m, srcrt) rtalloc(&ipforward_rt); if (ipforward_rt.ro_rt == 0) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest); + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } rt = ipforward_rt.ro_rt; @@ -1072,44 +1072,30 @@ ip_forward(m, srcrt) (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt) { - struct in_ifaddr *ia; +#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) u_long src = ntohl(ip->ip_src.s_addr); - u_long dst = ntohl(ip->ip_dst.s_addr); - if ((ia = ifptoia(m->m_pkthdr.rcvif)) && - (src & ia->ia_subnetmask) == ia->ia_subnet) { + if (RTA(rt) && + (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { if (rt->rt_flags & RTF_GATEWAY) - dest = satosin(rt->rt_gateway)->sin_addr; + dest = satosin(rt->rt_gateway)->sin_addr.s_addr; else - dest = ip->ip_dst; - /* - * If the destination is reached by a route to host, - * is on a subnet of a local net, or is directly - * on the attached net (!), use host redirect. - * (We may be the correct first hop for other subnets.) - */ -#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) + dest = ip->ip_dst.s_addr; + /* Router requirements says to only send host redirects */ type = ICMP_REDIRECT; - if ((rt->rt_flags & RTF_HOST) || - (rt->rt_flags & RTF_GATEWAY) == 0) - code = ICMP_REDIRECT_HOST; - else if (RTA(rt)->ia_subnetmask != RTA(rt)->ia_netmask && - (dst & RTA(rt)->ia_netmask) == RTA(rt)->ia_net) - code = ICMP_REDIRECT_HOST; - else - code = ICMP_REDIRECT_NET; + code = ICMP_REDIRECT_HOST; #ifdef DIAGNOSTIC if (ipprintfs) - printf("redirect (%d) to %x\n", code, dest.s_addr); + printf("redirect (%d) to %lx\n", code, (u_long)dest); #endif } } - error = ip_output(m, NULL, &ipforward_rt, IP_FORWARDING + error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING #ifdef DIRECTED_BROADCAST - | IP_ALLOWBROADCAST + | IP_ALLOWBROADCAST #endif - , NULL); + , 0); if (error) ipstat.ips_cantforward++; else { @@ -1124,6 +1110,8 @@ ip_forward(m, srcrt) } if (mcopy == NULL) return; + destifp = NULL; + switch (error) { case 0: /* forwarded, but need redirect */ @@ -1142,6 +1130,8 @@ ip_forward(m, srcrt) case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; + if (ipforward_rt.ro_rt) + destifp = ipforward_rt.ro_rt->rt_ifp; ipstat.ips_cantfrag++; break; @@ -1150,5 +1140,36 @@ ip_forward(m, srcrt) code = 0; break; } - icmp_error(mcopy, type, code, dest); + icmp_error(mcopy, type, code, dest, destifp); +} + +int +ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen) + int *name; + u_int namelen; + void *oldp; + size_t *oldlenp; + void *newp; + size_t newlen; +{ + /* All sysctl names at this level are terminal. */ + if (namelen != 1) + return (ENOTDIR); + + switch (name[0]) { + case IPCTL_FORWARDING: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding)); + case IPCTL_SENDREDIRECTS: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ipsendredirects)); + case IPCTL_DEFTTL: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl)); +#ifdef notyet + case IPCTL_DEFMTU: + return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu)); +#endif + default: + return (EOPNOTSUPP); + } + /* NOTREACHED */ }