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.319.10.1 retrieving revision 1.331 diff -u -p -r1.319.10.1 -r1.331 --- src/sys/netinet/ip_input.c 2018/02/09 14:05:29 1.319.10.1 +++ src/sys/netinet/ip_input.c 2016/06/30 06:48:58 1.331 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.319.10.1 2018/02/09 14:05:29 martin Exp $ */ +/* $NetBSD: ip_input.c,v 1.331 2016/06/30 06:48:58 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,8 +91,9 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.319.10.1 2018/02/09 14:05:29 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.331 2016/06/30 06:48:58 ozaki-r Exp $"); +#ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_compat_netbsd.h" #include "opt_gateway.h" @@ -100,6 +101,9 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include "opt_mrouting.h" #include "opt_mbuftrace.h" #include "opt_inet_csum.h" +#endif + +#include "arp.h" #include #include @@ -157,10 +161,10 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #define IPSENDREDIRECTS 1 #endif #ifndef IPFORWSRCRT -#define IPFORWSRCRT 0 /* forward source-routed packets */ +#define IPFORWSRCRT 1 /* forward source-routed packets */ #endif #ifndef IPALLOWSRCRT -#define IPALLOWSRCRT 0 /* allow source-routed packets */ +#define IPALLOWSRCRT 1 /* allow source-routed packets */ #endif #ifndef IPMTUDISC #define IPMTUDISC 1 @@ -280,7 +284,7 @@ struct mowner ip_tx_mowner = MOWNER_INIT static void ipintr(void *); static void ip_input(struct mbuf *); -static void ip_forward(struct mbuf *, int); +static void ip_forward(struct mbuf *, int, struct ifnet *); static bool ip_dooptions(struct mbuf *); static struct in_ifaddr *ip_rtaddr(struct in_addr); static void sysctl_net_inet_ip_setup(struct sysctllog **); @@ -319,7 +323,7 @@ ip_init(void) ip_reass_init(); ip_ids = ip_id_init(); - ip_id = time_second & 0xfffff; + ip_id = time_uptime & 0xfffff; ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); #ifdef GATEWAY @@ -370,13 +374,17 @@ ip_input(struct mbuf *m) int checkif; int srcrt = 0; ifnet_t *ifp; + struct psref psref; KASSERTMSG(cpu_softintr_p(), "ip_input: not in the software " "interrupt handler; synchronization assumptions violated"); MCLAIM(m, &ip_rx_mowner); KASSERT((m->m_flags & M_PKTHDR) != 0); - ifp = m->m_pkthdr.rcvif; + + ifp = m_get_rcvif_psref(m, &psref); + if (__predict_false(ifp == NULL)) + goto bad; /* * If no IP addresses have been set yet but the interfaces @@ -399,12 +407,12 @@ ip_input(struct mbuf *m) (max_linkhdr + 3) & ~3)) == NULL) { /* XXXJRT new stat, please */ IP_STATINC(IP_STAT_TOOSMALL); - return; + goto out; } } else if (__predict_false(m->m_len < sizeof (struct ip))) { if ((m = m_pullup(m, sizeof (struct ip))) == NULL) { IP_STATINC(IP_STAT_TOOSMALL); - return; + goto out; } } ip = mtod(m, struct ip *); @@ -420,7 +428,7 @@ ip_input(struct mbuf *m) if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == NULL) { IP_STATINC(IP_STAT_BADHLEN); - return; + goto out; } ip = mtod(m, struct ip *); } @@ -524,7 +532,7 @@ ip_input(struct mbuf *m) freed = pfil_run_hooks(inet_pfil_hook, &m, ifp, PFIL_IN) != 0; SOFTNET_UNLOCK(); if (freed || m == NULL) { - return; + goto out; } ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; @@ -553,7 +561,7 @@ ip_input(struct mbuf *m) if ((*altq_input)(m, AF_INET) == 0) { /* Packet dropped by traffic conditioner. */ SOFTNET_UNLOCK(); - return; + goto out; } SOFTNET_UNLOCK(); } @@ -567,7 +575,7 @@ ip_input(struct mbuf *m) */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) - return; + goto out; /* * Enable a consistency check between the destination address @@ -593,11 +601,13 @@ ip_input(struct mbuf *m) * * Traditional 4.4BSD did not consult IFF_UP at all. * The behavior here is to treat addresses on !IFF_UP interface - * as not mine. + * or IN_IFF_NOTREADY addresses as not mine. */ downmatch = 0; LIST_FOREACH(ia, &IN_IFADDR_HASH(ip->ip_dst.s_addr), ia_hash) { if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) { + if (ia->ia4_flags & IN_IFF_NOTREADY) + continue; if (checkif && ia->ia_ifp != ifp) continue; if ((ia->ia_ifp->if_flags & IFF_UP) != 0) @@ -613,6 +623,8 @@ ip_input(struct mbuf *m) if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); + if (ia->ia4_flags & IN_IFF_NOTREADY) + continue; if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || /* @@ -651,8 +663,7 @@ ip_input(struct mbuf *m) if (ip_mforward(m, ifp) != 0) { SOFTNET_UNLOCK(); IP_STATINC(IP_STAT_CANTFORWARD); - m_freem(m); - return; + goto bad; } SOFTNET_UNLOCK(); @@ -673,8 +684,7 @@ ip_input(struct mbuf *m) */ if (!in_multi_group(ip->ip_dst, ifp, 0)) { IP_STATINC(IP_STAT_CANTFORWARD); - m_freem(m); - return; + goto bad; } goto ours; } @@ -686,6 +696,7 @@ ip_input(struct mbuf *m) * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { + m_put_rcvif_psref(ifp, &psref); IP_STATINC(IP_STAT_CANTFORWARD); m_freem(m); } else { @@ -696,6 +707,7 @@ ip_input(struct mbuf *m) * forwarding loop till TTL goes to 0. */ if (downmatch) { + m_put_rcvif_psref(ifp, &psref); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); IP_STATINC(IP_STAT_CANTFORWARD); return; @@ -712,11 +724,15 @@ ip_input(struct mbuf *m) SOFTNET_UNLOCK(); } #endif - ip_forward(m, srcrt); + ip_forward(m, srcrt, ifp); + m_put_rcvif_psref(ifp, &psref); } return; ours: + m_put_rcvif_psref(ifp, &psref); + ifp = NULL; + /* * If offset or IP_MF are set, must reassemble. */ @@ -773,12 +789,17 @@ ours: SOFTNET_UNLOCK(); return; bad: + m_put_rcvif_psref(ifp, &psref); m_freem(m); return; badcsum: + m_put_rcvif_psref(ifp, &psref); IP_STATINC(IP_STAT_BADSUM); m_freem(m); + return; +out: + m_put_rcvif_psref(ifp, &psref); } /* @@ -980,7 +1001,10 @@ ip_dooptions(struct mbuf *m) case IPOPT_TS_TSONLY: break; - case IPOPT_TS_TSANDADDR: + case IPOPT_TS_TSANDADDR: { + struct ifnet *rcvif; + int s; + if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) { code = (u_char *)&ipt->ipt_ptr - @@ -988,14 +1012,17 @@ ip_dooptions(struct mbuf *m) goto bad; } ipaddr.sin_addr = dst; + rcvif = m_get_rcvif(m, &s); ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr), - m->m_pkthdr.rcvif)); + rcvif)); + m_put_rcvif(rcvif, &s); if (ia == 0) continue; bcopy(&ia->ia_addr.sin_addr, cp0, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; + } case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr - 1 + sizeof(n_time) + @@ -1026,12 +1053,23 @@ ip_dooptions(struct mbuf *m) } } if (forward) { + struct ifnet *rcvif; + struct psref psref; + if (ip_forwsrcrt == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } - ip_forward(m, 1); + + rcvif = m_get_rcvif_psref(m, &psref); + if (__predict_false(rcvif == NULL)) { + type = ICMP_UNREACH; + code = ICMP_UNREACH_HOST; + goto bad; + } + ip_forward(m, 1, rcvif); + m_put_rcvif_psref(rcvif, &psref); return true; } return false; @@ -1178,7 +1216,7 @@ ip_drainstub(void) * via a source route. */ static void -ip_forward(struct mbuf *m, int srcrt) +ip_forward(struct mbuf *m, int srcrt, struct ifnet *rcvif) { struct ip *ip = mtod(m, struct ip *); struct rtentry *rt; @@ -1189,6 +1227,7 @@ ip_forward(struct mbuf *m, int srcrt) struct sockaddr dst; struct sockaddr_in dst4; } u; + uint64_t *ips; KASSERTMSG(cpu_softintr_p(), "ip_forward: not in the software " "interrupt handler; synchronization assumptions violated"); @@ -1245,7 +1284,7 @@ ip_forward(struct mbuf *m, int srcrt) * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. */ - if (rt->rt_ifp == m->m_pkthdr.rcvif && + if (rt->rt_ifp == rcvif && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && !in_nullhost(satocsin(rt_getkey(rt))->sin_addr) && ipsendredirects && !srcrt) { @@ -1269,27 +1308,34 @@ ip_forward(struct mbuf *m, int srcrt) (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL); - if (error) + if (error) { IP_STATINC(IP_STAT_CANTFORWARD); - else { - uint64_t *ips = IP_STAT_GETREF(); - ips[IP_STAT_FORWARD]++; - if (type) { - ips[IP_STAT_REDIRECTSENT]++; - IP_STAT_PUTREF(); - } else { - IP_STAT_PUTREF(); - if (mcopy) { + goto error; + } + + ips = IP_STAT_GETREF(); + ips[IP_STAT_FORWARD]++; + + if (type) { + ips[IP_STAT_REDIRECTSENT]++; + IP_STAT_PUTREF(); + goto redirect; + } + + IP_STAT_PUTREF(); + if (mcopy) { #ifdef GATEWAY - if (mcopy->m_flags & M_CANFASTFWD) - ipflow_create(&ipforward_rt, mcopy); + if (mcopy->m_flags & M_CANFASTFWD) + ipflow_create(&ipforward_rt, mcopy); #endif - m_freem(mcopy); - } - SOFTNET_UNLOCK(); - return; - } + m_freem(mcopy); } + + SOFTNET_UNLOCK(); + return; + +redirect: +error: if (mcopy == NULL) { SOFTNET_UNLOCK(); return; @@ -1344,8 +1390,13 @@ ip_savecontrol(struct inpcb *inp, struct struct mbuf *m) { struct socket *so = inp->inp_socket; - ifnet_t *ifp = m->m_pkthdr.rcvif; + ifnet_t *ifp; int inpflags = inp->inp_flags; + struct psref psref; + + ifp = m_get_rcvif_psref(m, &psref); + if (__predict_false(ifp == NULL)) + return; /* XXX should report error? */ if (so->so_options & SO_TIMESTAMP #ifdef SO_OTIMESTAMP @@ -1407,6 +1458,7 @@ ip_savecontrol(struct inpcb *inp, struct if (*mp) mp = &(*mp)->m_next; } + m_put_rcvif_psref(ifp, &psref); } /* @@ -1568,15 +1620,6 @@ sysctl_net_inet_ip_setup(struct sysctllo sysctl_net_inet_ip_pmtudto, 0, (void *)&ip_mtudisc_timeout, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_MTUDISCTIMEOUT, CTL_EOL); -#if NGIF > 0 - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READWRITE, - CTLTYPE_INT, "gifttl", - SYSCTL_DESCR("Default TTL for a gif tunnel datagram"), - NULL, 0, &ip_gif_ttl, 0, - CTL_NET, PF_INET, IPPROTO_IP, - IPCTL_GIF_TTL, CTL_EOL); -#endif /* NGIF */ #ifndef IPNOPRIVPORTS sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, @@ -1633,6 +1676,16 @@ sysctl_net_inet_ip_setup(struct sysctllo sysctl_net_inet_ip_stats, 0, NULL, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS, CTL_EOL); +#if NARP + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "dad_count", + SYSCTL_DESCR("Number of Duplicate Address Detection " + "probes to send"), + NULL, 0, &ip_dad_count, 0, + CTL_NET, PF_INET, IPPROTO_IP, + IPCTL_DAD_COUNT, CTL_EOL); +#endif /* anonportalgo RFC6056 subtree */ const struct sysctlnode *portalgo_node;