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.4.10 retrieving revision 1.337.2.1 diff -u -p -r1.319.4.10 -r1.337.2.1 --- src/sys/netinet/ip_input.c 2017/08/28 17:53:12 1.319.4.10 +++ src/sys/netinet/ip_input.c 2016/08/06 00:19:10 1.337.2.1 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.319.4.10 2017/08/28 17:53:12 skrll Exp $ */ +/* $NetBSD: ip_input.c,v 1.337.2.1 2016/08/06 00:19:10 pgoyette Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,16 +91,16 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.319.4.10 2017/08/28 17:53:12 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.337.2.1 2016/08/06 00:19:10 pgoyette Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" +#include "opt_compat_netbsd.h" #include "opt_gateway.h" #include "opt_ipsec.h" #include "opt_mrouting.h" #include "opt_mbuftrace.h" #include "opt_inet_csum.h" -#include "opt_net_mpsafe.h" #endif #include "arp.h" @@ -173,6 +173,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ #endif +#ifdef COMPAT_50 +#include +#include +#endif + /* * Note: DIRECTED_BROADCAST is handled this way so that previous * configuration using this option will Just Work. @@ -220,7 +225,7 @@ pfil_head_t * inet_pfil_hook __read_mo ipid_state_t * ip_ids __read_mostly; percpu_t * ipstat_percpu __read_mostly; -static percpu_t *ipforward_rt_percpu __cacheline_aligned; +static struct route ipforward_rt __cacheline_aligned; uint16_t ip_id; @@ -247,23 +252,30 @@ EVCNT_ATTACH_STATIC(ip_swcsum); #endif /* INET_CSUM_COUNTERS */ /* - * Used to save the IP options in case a protocol wants to respond + * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing. This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */ -struct ip_srcrt { - int isr_nhops; /* number of hops */ - struct in_addr isr_dst; /* final destination */ - char isr_nop; /* one NOP to align */ - char isr_hdr[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN & OFFSET */ - struct in_addr isr_routes[MAX_IPOPTLEN/sizeof(struct in_addr)]; -}; + +static int ip_nhops = 0; + +static struct ip_srcrt { + struct in_addr dst; /* final destination */ + char nop; /* one NOP to align */ + char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ + struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; +} ip_srcrt; static int ip_drainwanted; -static void save_rte(struct mbuf *, u_char *, struct in_addr); +struct sockaddr_in ipaddr = { + .sin_len = sizeof(ipaddr), + .sin_family = AF_INET, +}; + +static void save_rte(u_char *, struct in_addr); #ifdef MBUFTRACE struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx"); @@ -274,7 +286,7 @@ static void ipintr(void *); static void ip_input(struct mbuf *); static void ip_forward(struct mbuf *, int, struct ifnet *); static bool ip_dooptions(struct mbuf *); -static struct in_ifaddr *ip_rtaddr(struct in_addr, struct psref *); +static struct in_ifaddr *ip_rtaddr(struct in_addr); static void sysctl_net_inet_ip_setup(struct sysctllog **); static struct in_ifaddr *ip_match_our_address(struct ifnet *, struct ip *, @@ -282,13 +294,9 @@ static struct in_ifaddr *ip_match_our_ad static struct in_ifaddr *ip_match_our_address_broadcast(struct ifnet *, struct ip *); -#ifdef NET_MPSAFE -#define SOFTNET_LOCK() mutex_enter(softnet_lock) -#define SOFTNET_UNLOCK() mutex_exit(softnet_lock) -#else +/* XXX: Not yet enabled. */ #define SOFTNET_LOCK() KASSERT(mutex_owned(softnet_lock)) #define SOFTNET_UNLOCK() KASSERT(mutex_owned(softnet_lock)) -#endif /* * IP initialization: fill in IP protocol switch table. @@ -322,6 +330,7 @@ ip_init(void) ip_ids = ip_id_init(); ip_id = time_uptime & 0xfffff; + ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); #ifdef GATEWAY ipflow_init(); #endif @@ -336,8 +345,6 @@ ip_init(void) #endif /* MBUFTRACE */ ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS); - ipforward_rt_percpu = percpu_alloc(sizeof(struct route)); - ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); } static struct in_ifaddr * @@ -371,8 +378,7 @@ ip_match_our_address(struct ifnet *ifp, continue; if (checkif && ia->ia_ifp != ifp) continue; - if ((ia->ia_ifp->if_flags & IFF_UP) != 0 && - (ia->ia4_flags & IN_IFF_DETACHED) == 0) + if ((ia->ia_ifp->if_flags & IFF_UP) != 0) break; else (*downmatch)++; @@ -392,7 +398,7 @@ ip_match_our_address_broadcast(struct if if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); - if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) + 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) || @@ -426,15 +432,11 @@ ipintr(void *arg __unused) KASSERT(cpu_softintr_p()); -#ifndef NET_MPSAFE mutex_enter(softnet_lock); -#endif while ((m = pktq_dequeue(ip_pktq)) != NULL) { ip_input(m); } -#ifndef NET_MPSAFE mutex_exit(softnet_lock); -#endif } /* @@ -607,9 +609,10 @@ ip_input(struct mbuf *m) struct in_addr odst = ip->ip_dst; bool freed; + SOFTNET_LOCK(); freed = pfil_run_hooks(inet_pfil_hook, &m, ifp, PFIL_IN) != 0; + SOFTNET_UNLOCK(); if (freed || m == NULL) { - m = NULL; goto out; } ip = mtod(m, struct ip *); @@ -639,7 +642,6 @@ ip_input(struct mbuf *m) if ((*altq_input)(m, AF_INET) == 0) { /* Packet dropped by traffic conditioner. */ SOFTNET_UNLOCK(); - m = NULL; goto out; } SOFTNET_UNLOCK(); @@ -652,10 +654,9 @@ ip_input(struct mbuf *m) * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ - if (hlen > sizeof (struct ip) && ip_dooptions(m)) { - m = NULL; + ip_nhops = 0; /* for source routed packets */ + if (hlen > sizeof (struct ip) && ip_dooptions(m)) goto out; - } /* * Check our list of addresses, to see if the packet is for us. @@ -752,12 +753,15 @@ ip_input(struct mbuf *m) return; } #ifdef IPSEC - /* Check the security policy (SP) for the packet */ + /* Perform IPsec, if any. */ if (ipsec_used) { + SOFTNET_LOCK(); if (ipsec4_input(m, IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)) != 0) { + SOFTNET_UNLOCK(); goto out; } + SOFTNET_UNLOCK(); } #endif ip_forward(m, srcrt, ifp); @@ -800,9 +804,12 @@ ours: */ if (ipsec_used && (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) { + SOFTNET_LOCK(); if (ipsec4_input(m, 0) != 0) { + SOFTNET_UNLOCK(); goto out; } + SOFTNET_UNLOCK(); } #endif @@ -817,7 +824,7 @@ ours: * is expensive, so explore ia here again. */ s = pserialize_read_enter(); - _ia = in_get_ia(ip->ip_dst); + _ia = in_get_ia(ip->ip_dst.s_addr); _ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len); pserialize_read_exit(s); } @@ -844,17 +851,13 @@ void ip_slowtimo(void) { -#ifndef NET_MPSAFE mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); -#endif ip_reass_slowtimo(); -#ifndef NET_MPSAFE KERNEL_UNLOCK_ONE(NULL); mutex_exit(softnet_lock); -#endif } /* @@ -886,7 +889,7 @@ ip_dooptions(struct mbuf *m) int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr dst; n_time ntime; - struct ifaddr *ifa = NULL; + struct ifaddr *ifa; int s; dst = ip->ip_dst; @@ -924,13 +927,7 @@ ip_dooptions(struct mbuf *m) * address is on directly accessible net. */ case IPOPT_LSRR: - case IPOPT_SSRR: { - struct psref psref; - struct sockaddr_in ipaddr = { - .sin_len = sizeof(ipaddr), - .sin_family = AF_INET, - }; - + case IPOPT_SSRR: if (ip_allowsrcrt == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_NET_PROHIB; @@ -968,7 +965,7 @@ ip_dooptions(struct mbuf *m) /* * End of source route. Should be for us. */ - save_rte(m, cp, ip->ip_src); + save_rte(cp, ip->ip_src); break; } /* @@ -976,40 +973,34 @@ ip_dooptions(struct mbuf *m) */ memcpy((void *)&ipaddr.sin_addr, (void *)(cp + off), sizeof(ipaddr.sin_addr)); + s = pserialize_read_enter(); if (opt == IPOPT_SSRR) { - ifa = ifa_ifwithladdr_psref(sintosa(&ipaddr), - &psref); + ifa = ifa_ifwithladdr(sintosa(&ipaddr)); if (ifa != NULL) ia = ifatoia(ifa); else ia = NULL; } else { - ia = ip_rtaddr(ipaddr.sin_addr, &psref); + ia = ip_rtaddr(ipaddr.sin_addr); } if (ia == NULL) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; + pserialize_read_exit(s); goto bad; } ip->ip_dst = ipaddr.sin_addr; bcopy((void *)&ia->ia_addr.sin_addr, (void *)(cp + off), sizeof(struct in_addr)); - ia4_release(ia, &psref); + pserialize_read_exit(s); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Let ip_intr's mcast routing check handle mcast pkts */ forward = !IN_MULTICAST(ip->ip_dst.s_addr); break; - } - - case IPOPT_RR: { - struct psref psref; - struct sockaddr_in ipaddr = { - .sin_len = sizeof(ipaddr), - .sin_family = AF_INET, - }; + case IPOPT_RR: if (optlen < IPOPT_OFFSET + sizeof(*cp)) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; @@ -1030,10 +1021,12 @@ ip_dooptions(struct mbuf *m) * locate outgoing interface; if we're the destination, * use the incoming interface (should be same). */ - ifa = ifa_ifwithaddr_psref(sintosa(&ipaddr), &psref); + s = pserialize_read_enter(); + ifa = ifa_ifwithaddr(sintosa(&ipaddr)); if (ifa == NULL) { - ia = ip_rtaddr(ipaddr.sin_addr, &psref); + ia = ip_rtaddr(ipaddr.sin_addr); if (ia == NULL) { + pserialize_read_exit(s); type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; @@ -1043,10 +1036,9 @@ ip_dooptions(struct mbuf *m) } bcopy((void *)&ia->ia_addr.sin_addr, (void *)(cp + off), sizeof(struct in_addr)); - ia4_release(ia, &psref); + pserialize_read_exit(s); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; - } case IPOPT_TS: code = cp - (u_char *)ip; @@ -1076,10 +1068,6 @@ ip_dooptions(struct mbuf *m) case IPOPT_TS_TSANDADDR: { struct ifnet *rcvif; int _s, _ss; - struct sockaddr_in ipaddr = { - .sin_len = sizeof(ipaddr), - .sin_family = AF_INET, - }; if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) { @@ -1090,10 +1078,7 @@ ip_dooptions(struct mbuf *m) ipaddr.sin_addr = dst; _ss = pserialize_read_enter(); rcvif = m_get_rcvif(m, &_s); - if (__predict_true(rcvif != NULL)) { - ifa = ifaof_ifpforaddr(sintosa(&ipaddr), - rcvif); - } + ifa = ifaof_ifpforaddr(sintosa(&ipaddr), rcvif); m_put_rcvif(rcvif, &_s); if (ifa == NULL) { pserialize_read_exit(_ss); @@ -1107,12 +1092,7 @@ ip_dooptions(struct mbuf *m) break; } - case IPOPT_TS_PRESPEC: { - struct sockaddr_in ipaddr = { - .sin_len = sizeof(ipaddr), - .sin_family = AF_INET, - }; - + case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) { code = (u_char *)&ipt->ipt_ptr - @@ -1130,7 +1110,6 @@ ip_dooptions(struct mbuf *m) pserialize_read_exit(s); ipt->ipt_ptr += sizeof(struct in_addr); break; - } default: /* XXX can't take &ipt->ipt_flg */ @@ -1177,27 +1156,21 @@ bad: * return internet address info of interface to be used to get there. */ static struct in_ifaddr * -ip_rtaddr(struct in_addr dst, struct psref *psref) +ip_rtaddr(struct in_addr dst) { struct rtentry *rt; union { struct sockaddr dst; struct sockaddr_in dst4; } u; - struct route *ro; sockaddr_in_init(&u.dst4, &dst, 0); - ro = percpu_getref(ipforward_rt_percpu); - rt = rtcache_lookup(ro, &u.dst); - if (rt == NULL) { - percpu_putref(ipforward_rt_percpu); + SOFTNET_LOCK(); + rt = rtcache_lookup(&ipforward_rt, &u.dst); + SOFTNET_UNLOCK(); + if (rt == NULL) return NULL; - } - - ia4_acquire(ifatoia(rt->rt_ifa), psref); - rtcache_unref(rt, ro); - percpu_putref(ipforward_rt_percpu); return ifatoia(rt->rt_ifa); } @@ -1207,25 +1180,16 @@ ip_rtaddr(struct in_addr dst, struct psr * up later by ip_srcroute if the receiver is interested. */ static void -save_rte(struct mbuf *m, u_char *option, struct in_addr dst) +save_rte(u_char *option, struct in_addr dst) { - struct ip_srcrt *isr; - struct m_tag *mtag; unsigned olen; olen = option[IPOPT_OLEN]; - if (olen > sizeof(isr->isr_hdr) + sizeof(isr->isr_routes)) - return; - - mtag = m_tag_get(PACKET_TAG_SRCROUTE, sizeof(*isr), M_NOWAIT); - if (mtag == NULL) + if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) return; - isr = (struct ip_srcrt *)(mtag + 1); - - memcpy(isr->isr_hdr, option, olen); - isr->isr_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); - isr->isr_dst = dst; - m_tag_prepend(m, mtag); + memcpy((void *)ip_srcrt.srcopt, (void *)option, olen); + ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); + ip_srcrt.dst = dst; } /* @@ -1234,43 +1198,36 @@ save_rte(struct mbuf *m, u_char *option, * The first hop is placed before the options, will be removed later. */ struct mbuf * -ip_srcroute(struct mbuf *m0) +ip_srcroute(void) { struct in_addr *p, *q; struct mbuf *m; - struct ip_srcrt *isr; - struct m_tag *mtag; - - mtag = m_tag_find(m0, PACKET_TAG_SRCROUTE, NULL); - if (mtag == NULL) - return NULL; - isr = (struct ip_srcrt *)(mtag + 1); - if (isr->isr_nhops == 0) + if (ip_nhops == 0) return NULL; - m = m_get(M_DONTWAIT, MT_SOOPTS); - if (m == NULL) + if (m == 0) return NULL; MCLAIM(m, &inetdomain.dom_mowner); -#define OPTSIZ (sizeof(isr->isr_nop) + sizeof(isr->isr_hdr)) +#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) - /* length is (nhops+1)*sizeof(addr) + sizeof(nop + header) */ - m->m_len = (isr->isr_nhops + 1) * sizeof(struct in_addr) + OPTSIZ; + /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ + m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + + OPTSIZ; /* * First save first hop for return route */ - p = &(isr->isr_routes[isr->isr_nhops - 1]); + p = &ip_srcrt.route[ip_nhops - 1]; *(mtod(m, struct in_addr *)) = *p--; /* * Copy option fields and padding (nop) to mbuf. */ - isr->isr_nop = IPOPT_NOP; - isr->isr_hdr[IPOPT_OFFSET] = IPOPT_MINOFF; - memmove(mtod(m, char *) + sizeof(struct in_addr), &isr->isr_nop, + ip_srcrt.nop = IPOPT_NOP; + ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; + memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop, OPTSIZ); q = (struct in_addr *)(mtod(m, char *) + sizeof(struct in_addr) + OPTSIZ); @@ -1279,15 +1236,14 @@ ip_srcroute(struct mbuf *m0) * Record return path as an IP source route, * reversing the path (pointers are now aligned). */ - while (p >= isr->isr_routes) { + while (p >= ip_srcrt.route) { *q++ = *p--; } /* * Last hop goes to final destination. */ - *q = isr->isr_dst; - m_tag_delete(m0, mtag); - return m; + *q = ip_srcrt.dst; + return (m); } const int inetctlerrmap[PRC_NCMDS] = { @@ -1344,7 +1300,6 @@ ip_forward(struct mbuf *m, int srcrt, st struct sockaddr_in dst4; } u; uint64_t *ips; - struct route *ro; KASSERTMSG(cpu_softintr_p(), "ip_forward: not in the software " "interrupt handler; synchronization assumptions violated"); @@ -1366,18 +1321,19 @@ ip_forward(struct mbuf *m, int srcrt, st return; } + SOFTNET_LOCK(); + if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); + SOFTNET_UNLOCK(); return; } sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); - ro = percpu_getref(ipforward_rt_percpu); - rt = rtcache_lookup(ro, &u.dst); - if (rt == NULL) { - percpu_putref(ipforward_rt_percpu); + if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); + SOFTNET_UNLOCK(); return; } @@ -1419,9 +1375,8 @@ ip_forward(struct mbuf *m, int srcrt, st code = ICMP_REDIRECT_HOST; } } - rtcache_unref(rt, ro); - error = ip_output(m, NULL, ro, + error = ip_output(m, NULL, &ipforward_rt, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL); @@ -1443,18 +1398,18 @@ ip_forward(struct mbuf *m, int srcrt, st if (mcopy) { #ifdef GATEWAY if (mcopy->m_flags & M_CANFASTFWD) - ipflow_create(ro, mcopy); + ipflow_create(&ipforward_rt, mcopy); #endif m_freem(mcopy); } - percpu_putref(ipforward_rt_percpu); + SOFTNET_UNLOCK(); return; redirect: error: if (mcopy == NULL) { - percpu_putref(ipforward_rt_percpu); + SOFTNET_UNLOCK(); return; } @@ -1477,10 +1432,8 @@ error: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; - if ((rt = rtcache_validate(ro)) != NULL) { + if ((rt = rtcache_validate(&ipforward_rt)) != NULL) destmtu = rt->rt_ifp->if_mtu; - rtcache_unref(rt, ro); - } #ifdef IPSEC if (ipsec_used) (void)ipsec4_forward(mcopy, &destmtu); @@ -1497,11 +1450,11 @@ error: */ if (mcopy) m_freem(mcopy); - percpu_putref(ipforward_rt_percpu); + SOFTNET_UNLOCK(); return; } icmp_error(mcopy, type, code, dest, destmtu); - percpu_putref(ipforward_rt_percpu); + SOFTNET_UNLOCK(); } void @@ -1509,39 +1462,46 @@ ip_savecontrol(struct inpcb *inp, struct struct mbuf *m) { struct socket *so = inp->inp_socket; + ifnet_t *ifp; int inpflags = inp->inp_flags; + struct psref psref; - if (SOOPT_TIMESTAMP(so->so_options)) - mp = sbsavetimestamp(so->so_options, m, mp); + ifp = m_get_rcvif_psref(m, &psref); + if (__predict_false(ifp == NULL)) + return; /* XXX should report error? */ - if (inpflags & INP_RECVDSTADDR) { - *mp = sbcreatecontrol(&ip->ip_dst, - sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); + if (so->so_options & SO_TIMESTAMP +#ifdef SO_OTIMESTAMP + || so->so_options & SO_OTIMESTAMP +#endif + ) { + struct timeval tv; + + microtime(&tv); +#ifdef SO_OTIMESTAMP + if (so->so_options & SO_OTIMESTAMP) { + struct timeval50 tv50; + timeval_to_timeval50(&tv, &tv50); + *mp = sbcreatecontrol((void *) &tv50, sizeof(tv50), + SCM_OTIMESTAMP, SOL_SOCKET); + } else +#endif + *mp = sbcreatecontrol((void *) &tv, sizeof(tv), + SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } - - if (inpflags & INP_RECVTTL) { - *mp = sbcreatecontrol(&ip->ip_ttl, - sizeof(uint8_t), IP_RECVTTL, IPPROTO_IP); + if (inpflags & INP_RECVDSTADDR) { + *mp = sbcreatecontrol((void *) &ip->ip_dst, + sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } - - struct psref psref; - ifnet_t *ifp = m_get_rcvif_psref(m, &psref); - if (__predict_false(ifp == NULL)) { -#ifdef DIAGNOSTIC - printf("%s: missing receive interface\n", __func__); -#endif - return; /* XXX should report error? */ - } - if (inpflags & INP_RECVPKTINFO) { struct in_pktinfo ipi; ipi.ipi_addr = ip->ip_src; ipi.ipi_ifindex = ifp->if_index; - *mp = sbcreatecontrol(&ipi, + *mp = sbcreatecontrol((void *) &ipi, sizeof(ipi), IP_RECVPKTINFO, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; @@ -1550,7 +1510,7 @@ ip_savecontrol(struct inpcb *inp, struct struct in_pktinfo ipi; ipi.ipi_addr = ip->ip_dst; ipi.ipi_ifindex = ifp->if_index; - *mp = sbcreatecontrol(&ipi, + *mp = sbcreatecontrol((void *) &ipi, sizeof(ipi), IP_PKTINFO, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; @@ -1564,6 +1524,12 @@ ip_savecontrol(struct inpcb *inp, struct if (*mp) mp = &(*mp)->m_next; } + if (inpflags & INP_RECVTTL) { + *mp = sbcreatecontrol((void *) &ip->ip_ttl, + sizeof(uint8_t), IP_RECVTTL, IPPROTO_IP); + if (*mp) + mp = &(*mp)->m_next; + } m_put_rcvif_psref(ifp, &psref); } @@ -1603,25 +1569,23 @@ sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS int error, tmp; struct sysctlnode node; - icmp_mtudisc_lock(); - node = *rnode; tmp = ip_mtudisc_timeout; node.sysctl_data = &tmp; error = sysctl_lookup(SYSCTLFN_CALL(&node)); if (error || newp == NULL) - goto out; - if (tmp < 0) { - error = EINVAL; - goto out; - } + return (error); + if (tmp < 0) + return (EINVAL); + + mutex_enter(softnet_lock); ip_mtudisc_timeout = tmp; rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); - error = 0; -out: - icmp_mtudisc_unlock(); - return error; + + mutex_exit(softnet_lock); + + return (0); } static int