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.98 retrieving revision 1.103 diff -u -p -r1.98 -r1.103 --- src/sys/netinet/ip_input.c 2000/02/12 17:45:44 1.98 +++ src/sys/netinet/ip_input.c 2000/03/01 12:49:33 1.103 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.98 2000/02/12 17:45:44 thorpej Exp $ */ +/* $NetBSD: ip_input.c,v 1.103 2000/03/01 12:49:33 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -194,8 +194,6 @@ int ipprintfs = 0; struct rttimer_queue *ip_mtudisc_timeout_q = NULL; extern struct domain inetdomain; -extern struct protosw inetsw[]; -u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddr; struct in_ifaddrhashhead *in_ifaddrhashtbl; @@ -348,6 +346,7 @@ ip_input(struct mbuf *m) register struct ifaddr *ifa; struct ipqent *ipqe; int hlen = 0, mff, len; + int downmatch; #ifdef PFIL_HOOKS struct packet_filter_hook *pfh; struct mbuf *m0; @@ -399,7 +398,7 @@ ip_input(struct mbuf *m) } /* - * RFC1112: packets with a multicast source address are + * RFC1122: packets with a multicast source address are * not allowed. */ if (IN_MULTICAST(ip->ip_src.s_addr)) { @@ -465,9 +464,11 @@ ip_input(struct mbuf *m) * in the list may have previously cleared it. */ m0 = m; - for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next) + pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh); + for (; pfh; pfh = pfh->pfil_link.tqe_next) if (pfh->pfil_func) { - rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0); + rv = pfh->pfil_func(ip, hlen, + m->m_pkthdr.rcvif, 0, &m0); if (rv) return; m = m0; @@ -489,18 +490,20 @@ ip_input(struct mbuf *m) /* * Check our list of addresses, to see if the packet is for us. + * + * Traditional 4.4BSD did not consult IFF_UP at all. + * The behavior here is to treat addresses on !IFF_UP interface + * as not mine. */ + downmatch = 0; for (ia = IN_IFADDR_HASH(ip->ip_dst.s_addr).lh_first; ia != NULL; ia = ia->ia_hash.le_next) { if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) { if ((ia->ia_ifp->if_flags & IFF_UP) != 0) break; - else { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, - 0, m->m_pkthdr.rcvif); - return; - } + else + downmatch++; } } if (ia != NULL) @@ -591,8 +594,20 @@ ip_input(struct mbuf *m) if (ipforwarding == 0) { ipstat.ips_cantforward++; m_freem(m); - } else + } else { + /* + * If ip_dst matched any of my address on !IFF_UP interface, + * and there's no IFF_UP interface that matches ip_dst, + * send icmp unreach. Forwarding it will result in in-kernel + * forwarding loop till TTL goes to 0. + */ + if (downmatch) { + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); + ipstat.ips_cantforward++; + return; + } ip_forward(m, 0); + } return; ours: @@ -1388,8 +1403,9 @@ ip_forward(m, srcrt) } #ifdef IPSEC - m->m_pkthdr.rcvif = NULL; -#endif /*IPSEC*/ + /* Don't lookup socket in forwading case */ + ipsec_setsocket(m, NULL); +#endif error = ip_output(m, (struct mbuf *)0, &ipforward_rt, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), 0); if (error)