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.292 retrieving revision 1.308 diff -u -p -r1.292 -r1.308 --- src/sys/netinet/ip_input.c 2010/12/11 22:37:46 1.292 +++ src/sys/netinet/ip_input.c 2013/06/29 21:06:58 1.308 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.292 2010/12/11 22:37:46 matt Exp $ */ +/* $NetBSD: ip_input.c,v 1.308 2013/06/29 21:06:58 rmind Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,12 +91,11 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.292 2010/12/11 22:37:46 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.308 2013/06/29 21:06:58 rmind Exp $"); #include "opt_inet.h" #include "opt_compat_netbsd.h" #include "opt_gateway.h" -#include "opt_pfil_hooks.h" #include "opt_ipsec.h" #include "opt_mrouting.h" #include "opt_mbuftrace.h" @@ -139,16 +138,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #ifdef MROUTING #include #endif +#include #ifdef IPSEC -#include -#include -#include -#endif -#ifdef FAST_IPSEC #include -#include -#endif /* FAST_IPSEC*/ +#endif #ifndef IPFORWARDING #ifdef GATEWAY @@ -221,7 +215,6 @@ int ip_checkinterface = 0; struct rttimer_queue *ip_mtudisc_timeout_q = NULL; -int ipqmaxlen = IFQ_MAXLEN; u_long in_ifaddrhash; /* size of hash table - 1 */ int in_ifaddrentries; /* total number of addrs */ struct in_ifaddrhead in_ifaddrhead; @@ -236,9 +229,7 @@ uint16_t ip_id; percpu_t *ipstat_percpu; -#ifdef PFIL_HOOKS -struct pfil_head inet_pfil_hook; -#endif +pfil_head_t *inet_pfil_hook; struct pool inmulti_pool; @@ -279,6 +270,8 @@ static struct ip_srcrt { struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; } ip_srcrt; +static int ip_drainwanted; + static void save_rte(u_char *, struct in_addr); #ifdef MBUFTRACE @@ -319,7 +312,7 @@ ip_init(void) ip_ids = ip_id_init(); ip_id = time_second & 0xfffff; - ipintrq.ifq_maxlen = ipqmaxlen; + ipintrq.ifq_maxlen = IFQ_MAXLEN; TAILQ_INIT(&in_ifaddrhead); in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, true, @@ -331,15 +324,9 @@ ip_init(void) ipflow_init(ip_hashsize); #endif -#ifdef PFIL_HOOKS /* Register our Packet Filter hook. */ - inet_pfil_hook.ph_type = PFIL_TYPE_AF; - inet_pfil_hook.ph_af = AF_INET; - i = pfil_head_register(&inet_pfil_hook); - if (i != 0) - printf("ip_init: WARNING: unable to register pfil hook, " - "error %d\n", i); -#endif /* PFIL_HOOKS */ + inet_pfil_hook = pfil_head_create(PFIL_TYPE_AF, (void *)AF_INET); + KASSERT(inet_pfil_hook != NULL); #ifdef MBUFTRACE MOWNER_ATTACH(&ip_tx_mowner); @@ -366,7 +353,6 @@ ipintr(void) struct ifqueue lcl_intrq; memset(&lcl_intrq, 0, sizeof(lcl_intrq)); - ipintrq.ifq_maxlen = ipqmaxlen; mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); @@ -390,9 +376,7 @@ ipintr(void) IF_DEQUEUE(&lcl_intrq, m); if (m == NULL) break; - KERNEL_UNLOCK_ONE(NULL); ip_input(m); - KERNEL_LOCK(1, NULL); } mutex_exit(softnet_lock); } @@ -411,12 +395,6 @@ ip_input(struct mbuf *m) int downmatch; int checkif; int srcrt = 0; -#ifdef FAST_IPSEC - struct m_tag *mtag; - struct tdb_ident *tdbi; - struct secpolicy *sp; - int error, s; -#endif /* FAST_IPSEC */ MCLAIM(m, &ip_rx_mowner); KASSERT((m->m_flags & M_PKTHDR) != 0); @@ -458,7 +436,7 @@ ip_input(struct mbuf *m) goto bad; } if (hlen > m->m_len) { - if ((m = m_pullup(m, hlen)) == 0) { + if ((m = m_pullup(m, hlen)) == NULL) { IP_STATINC(IP_STAT_BADHLEN); return; } @@ -538,18 +516,12 @@ ip_input(struct mbuf *m) m_adj(m, len - m->m_pkthdr.len); } -#if defined(IPSEC) - /* ipflow (IP fast forwarding) is not compatible with IPsec. */ - m->m_flags &= ~M_CANFASTFWD; -#else /* * Assume that we can create a fast-forward IP flow entry * based on this packet. */ m->m_flags |= M_CANFASTFWD; -#endif -#ifdef PFIL_HOOKS /* * Run through list of hooks for input packets. If there are any * filters which require that additional packets in the flow are @@ -561,9 +533,7 @@ ip_input(struct mbuf *m) * let ipfilter look at packet on the wire, * not the decapsulated packet. */ -#ifdef IPSEC - if (!ipsec_getnhist(m)) -#elif defined(FAST_IPSEC) +#if defined(IPSEC) if (!ipsec_indone(m)) #else if (1) @@ -572,7 +542,7 @@ ip_input(struct mbuf *m) struct in_addr odst; odst = ip->ip_dst; - if (pfil_run_hooks(&inet_pfil_hook, &m, m->m_pkthdr.rcvif, + if (pfil_run_hooks(inet_pfil_hook, &m, m->m_pkthdr.rcvif, PFIL_IN) != 0) return; if (m == NULL) @@ -595,7 +565,6 @@ ip_input(struct mbuf *m) */ srcrt = (odst.s_addr != ip->ip_dst.s_addr); } -#endif /* PFIL_HOOKS */ #ifdef ALTQ /* XXX Temporary until ALTQ is changed to use a pfil hook */ @@ -746,60 +715,12 @@ ip_input(struct mbuf *m) return; } #ifdef IPSEC - if (ipsec4_in_reject(m, NULL)) { - IPSEC_STATINC(IPSEC_STAT_IN_POLVIO); + /* Perform IPsec, if any. */ + if (ipsec4_input(m, IP_FORWARDING | (ip_directedbcast ? + IP_ALLOWBROADCAST : 0)) != 0) { goto bad; } #endif -#ifdef FAST_IPSEC - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - s = splsoftnet(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp == NULL) { /* NB: can happen if error */ - splx(s); - /*XXX error stat???*/ - DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/ - goto bad; - } - - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - splx(s); - if (error) { - IP_STATINC(IP_STAT_CANTFORWARD); - goto bad; - } - - /* - * Peek at the outbound SP for this packet to determine if - * it's a Fast Forward candidate. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL); - if (mtag != NULL) - m->m_flags &= ~M_CANFASTFWD; - else { - s = splsoftnet(); - sp = ipsec4_checkpolicy(m, IPSEC_DIR_OUTBOUND, - (IP_FORWARDING | - (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), - &error, NULL); - if (sp != NULL) { - m->m_flags &= ~M_CANFASTFWD; - KEY_FREESP(&sp); - } - splx(s); - } -#endif /* FAST_IPSEC */ - ip_forward(m, srcrt); } return; @@ -828,56 +749,18 @@ ours: hlen = ip->ip_hl << 2; } -#if defined(IPSEC) - /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. - */ - if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 && - ipsec4_in_reject(m, NULL)) { - IPSEC_STATINC(IPSEC_STAT_IN_POLVIO); - goto bad; - } -#endif -#ifdef FAST_IPSEC +#ifdef IPSEC /* - * enforce IPsec policy checking if we are seeing last header. - * note that we do not visit this with protocols with pcb layer - * code - like udp/tcp/raw ip. + * Enforce IPsec policy checking if we are seeing last header. + * Note that we do not visit this with protocols with PCB layer + * code - like UDP/TCP/raw IP. */ if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) { - /* - * Check if the packet has already had IPsec processing - * done. If so, then just pass it along. This tag gets - * set during AH, ESP, etc. input handling, before the - * packet is returned to the ip input queue for delivery. - */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - s = splsoftnet(); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } - if (sp != NULL) { - /* - * Check security policy against packet attributes. - */ - error = ipsec_in_reject(sp, m); - KEY_FREESP(&sp); - } else { - /* XXX error stat??? */ - error = EINVAL; -DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ - } - splx(s); - if (error) + if (ipsec4_input(m, 0) != 0) { goto bad; + } } -#endif /* FAST_IPSEC */ +#endif /* * Switch out to protocol's input routine. @@ -1286,6 +1169,21 @@ const int inetctlerrmap[PRC_NCMDS] = { [PRC_PARAMPROB] = ENOPROTOOPT, }; +void +ip_fasttimo(void) +{ + if (ip_drainwanted) { + ip_drain(); + ip_drainwanted = 0; + } +} + +void +ip_drainstub(void) +{ + ip_drainwanted = 1; +} + /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful @@ -1392,7 +1290,7 @@ ip_forward(struct mbuf *m, int srcrt) error = ip_output(m, NULL, &ipforward_rt, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), - (struct ip_moptions *)NULL, (struct socket *)NULL); + NULL, NULL); if (error) IP_STATINC(IP_STAT_CANTFORWARD); @@ -1438,57 +1336,9 @@ ip_forward(struct mbuf *m, int srcrt) if ((rt = rtcache_validate(&ipforward_rt)) != NULL) destmtu = rt->rt_ifp->if_mtu; - -#if defined(IPSEC) || defined(FAST_IPSEC) - { - /* - * If the packet is routed over IPsec tunnel, tell the - * originator the tunnel MTU. - * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz - * XXX quickhack!!! - */ - - struct secpolicy *sp; - int ipsecerror; - size_t ipsechdr; - struct route *ro; - - sp = ipsec4_getpolicybyaddr(mcopy, - IPSEC_DIR_OUTBOUND, IP_FORWARDING, - &ipsecerror); - - if (sp != NULL) { - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, NULL); - - /* - * find the correct route for outer IPv4 - * header, compute tunnel MTU. - */ - - if (sp->req != NULL - && sp->req->sav != NULL - && sp->req->sav->sah != NULL) { - ro = &sp->req->sav->sah->sa_route; - rt = rtcache_validate(ro); - if (rt && rt->rt_ifp) { - destmtu = - rt->rt_rmx.rmx_mtu ? - rt->rt_rmx.rmx_mtu : - rt->rt_ifp->if_mtu; - destmtu -= ipsechdr; - } - } - -#ifdef IPSEC - key_freesp(sp); -#else - KEY_FREESP(&sp); +#ifdef IPSEC + (void)ipsec4_forward(mcopy, &destmtu); #endif - } - } -#endif /*defined(IPSEC) || defined(FAST_IPSEC)*/ IP_STATINC(IP_STAT_CANTFRAG); break; @@ -1544,6 +1394,24 @@ ip_savecontrol(struct inpcb *inp, struct if (*mp) mp = &(*mp)->m_next; } + if (inp->inp_flags & INP_RECVPKTINFO) { + struct in_pktinfo ipi; + ipi.ipi_addr = ip->ip_src; + ipi.ipi_ifindex = m->m_pkthdr.rcvif->if_index; + *mp = sbcreatecontrol((void *) &ipi, + sizeof(ipi), IP_RECVPKTINFO, IPPROTO_IP); + if (*mp) + mp = &(*mp)->m_next; + } + if (inp->inp_flags & INP_PKTINFO) { + struct in_pktinfo ipi; + ipi.ipi_addr = ip->ip_dst; + ipi.ipi_ifindex = m->m_pkthdr.rcvif->if_index; + *mp = sbcreatecontrol((void *) &ipi, + sizeof(ipi), IP_PKTINFO, IPPROTO_IP); + if (*mp) + mp = &(*mp)->m_next; + } #ifdef notyet /* * XXX @@ -1816,7 +1684,7 @@ sysctl_net_inet_ip_setup(struct sysctllo CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "mtudisctimeout", SYSCTL_DESCR("Lifetime of a Path MTU Discovered route"), - sysctl_net_inet_ip_pmtudto, 0, &ip_mtudisc_timeout, 0, + sysctl_net_inet_ip_pmtudto, 0, (void *)&ip_mtudisc_timeout, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_MTUDISCTIMEOUT, CTL_EOL); #ifdef GATEWAY @@ -1907,6 +1775,33 @@ 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); + + /* anonportalgo RFC6056 subtree */ + const struct sysctlnode *portalgo_node; + sysctl_createv(clog, 0, NULL, &portalgo_node, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "anonportalgo", + SYSCTL_DESCR("Anonymous Port Algorithm Selection (RFC 6056)"), + NULL, 0, NULL, 0, + CTL_NET, PF_INET, IPPROTO_IP, CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &portalgo_node, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_STRING, "available", + SYSCTL_DESCR("available algorithms"), + sysctl_portalgo_available, 0, NULL, PORTALGO_MAXLEN, + CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &portalgo_node, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_STRING, "selected", + SYSCTL_DESCR("selected algorithm"), + sysctl_portalgo_selected4, 0, NULL, PORTALGO_MAXLEN, + CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &portalgo_node, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_STRUCT, "reserve", + SYSCTL_DESCR("bitmap of reserved ports"), + sysctl_portalgo_reserve4, 0, NULL, 0, + CTL_CREATE, CTL_EOL); } void