/*
- * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
+ *
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
- *
+ *
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
+ *
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
- *
+ *
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
*
* @(#)udp_var.h 8.1 (Berkeley) 6/10/93
*/
-
-#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/if_types.h>
#include <net/ntstat.h>
#include <net/dlil.h>
+#include <net/net_api_stats.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
static int udp6_abort(struct socket *);
static int udp6_attach(struct socket *, int, struct proc *);
static int udp6_bind(struct socket *, struct sockaddr *, struct proc *);
-static int udp6_connectx(struct socket *, struct sockaddr_list **,
- struct sockaddr_list **, struct proc *, uint32_t, sae_associd_t,
+static int udp6_connectx(struct socket *, struct sockaddr *,
+ struct sockaddr *, struct proc *, uint32_t, sae_associd_t,
sae_connid_t *, uint32_t, void *, uint32_t, struct uio *, user_ssize_t *);
static int udp6_detach(struct socket *);
static int udp6_disconnect(struct socket *);
struct sockaddr_in6 *, struct mbuf *, int, struct ifnet *);
static int udp6_input_checksum(struct mbuf *, struct udphdr *, int, int);
-#if IPFIREWALL
-extern int fw_verbose;
-extern void ipfwsyslog( int level, const char *format,...);
-extern void ipfw_stealth_stats_incr_udpv6(void);
-
-/* Apple logging, log to ipfw.log */
-#define log_in_vain_log(a) { \
- if ((udp_log_in_vain == 3) && (fw_verbose == 2)) { \
- ipfwsyslog a; \
- } else if ((udp_log_in_vain == 4) && (fw_verbose == 2)) { \
- ipfw_stealth_stats_incr_udpv6(); \
- } else { \
- log a; \
- } \
-}
-#else /* !IPFIREWALL */
-#define log_in_vain_log( a ) { log a; }
-#endif /* !IPFIREWALL */
-
struct pr_usrreqs udp6_usrreqs = {
.pru_abort = udp6_abort,
.pru_attach = udp6_attach,
if (nstat_collect) {
INP_ADD_STAT(last, cell, wifi, wired, rxpackets, 1);
INP_ADD_STAT(last, cell, wifi, wired, rxbytes, n->m_pkthdr.len);
+ inp_set_activity_bitmap(last);
}
so_recv_data_stat(last->in6p_socket, n, 0);
if (sbappendaddr(&last->in6p_socket->so_rcv,
mcaddr.sin6_addr = ip6->ip6_dst;
blocked = im6o_mc_filter(imo, ifp,
- (struct sockaddr *)&mcaddr,
- (struct sockaddr *)&fromsa);
+ &mcaddr, &fromsa);
IM6O_UNLOCK(imo);
if (blocked != MCAST_PASS) {
udp_unlock(in6p->in6p_socket, 1, 0);
ntohs(uh->uh_sport));
} else if (!(m->m_flags & (M_BCAST | M_MCAST)) &&
!IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &ip6->ip6_src)) {
- log_in_vain_log((LOG_INFO, "Connection attempt "
+ log(LOG_INFO, "Connection attempt "
"to UDP %s:%d from %s:%d\n", buf,
ntohs(uh->uh_dport),
ip6_sprintf(&ip6->ip6_src),
- ntohs(uh->uh_sport)));
+ ntohs(uh->uh_sport));
}
}
udpstat.udps_noport++;
if (nstat_collect) {
INP_ADD_STAT(in6p, cell, wifi, wired, rxpackets, 1);
INP_ADD_STAT(in6p, cell, wifi, wired, rxbytes, m->m_pkthdr.len);
+ inp_set_activity_bitmap(in6p);
}
so_recv_data_stat(in6p->in6p_socket, m, 0);
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
}
void
-udp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
+udp6_ctlinput(int cmd, struct sockaddr *sa, void *d, __unused struct ifnet *ifp)
{
struct udphdr uh;
struct ip6_hdr *ip6;
struct mbuf *m;
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
+ struct icmp6_hdr *icmp6 = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
void (*notify)(struct inpcb *, int) = udp_notify;
struct udp_portonly {
if ((unsigned)cmd >= PRC_NCMDS)
return;
- if (PRC_IS_REDIRECT(cmd))
- notify = in6_rtchange, d = NULL;
- else if (cmd == PRC_HOSTDEAD)
+ if (PRC_IS_REDIRECT(cmd)) {
+ notify = in6_rtchange;
+ d = NULL;
+ } else if (cmd == PRC_HOSTDEAD)
d = NULL;
else if (inet6ctlerrmap[cmd] == 0)
return;
/* if the parameter is from icmp6, decode it. */
if (d != NULL) {
ip6cp = (struct ip6ctlparam *)d;
+ icmp6 = ip6cp->ip6c_icmp6;
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
* XXX: We assume that when IPV6 is non NULL,
* M and OFF are valid.
*/
-
/* check if we can safely examine src and dst ports */
if (m->m_pkthdr.len < off + sizeof (*uhp))
return;
if (inp->inp_faddr.s_addr != INADDR_ANY)
return (EISCONN);
+
+ if (!(so->so_flags1 & SOF1_CONNECT_COUNTED)) {
+ so->so_flags1 |= SOF1_CONNECT_COUNTED;
+ INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_inet_dgram_connected);
+ }
+
in6_sin6_2_sin(&sin, sin6_p);
#if defined(NECP) && defined(FLOW_DIVERT)
if (should_use_flow_divert) {
error = in_pcbconnect(inp, (struct sockaddr *)&sin,
p, IFSCOPE_NONE, NULL);
if (error == 0) {
+#if NECP
+ /* Update NECP client with connected five-tuple */
+ if (!uuid_is_null(inp->necp_client_uuid)) {
+ socket_unlock(so, 0);
+ necp_client_assign_from_socket(so->last_pid, inp->necp_client_uuid, inp);
+ socket_lock(so, 0);
+ }
+#endif /* NECP */
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
soisconnected(so);
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
return (EISCONN);
+ if (!(so->so_flags1 & SOF1_CONNECT_COUNTED)) {
+ so->so_flags1 |= SOF1_CONNECT_COUNTED;
+ INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_inet6_dgram_connected);
+ }
+
#if defined(NECP) && defined(FLOW_DIVERT)
do_flow_divert:
if (should_use_flow_divert) {
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
}
+#if NECP
+ /* Update NECP client with connected five-tuple */
+ if (!uuid_is_null(inp->necp_client_uuid)) {
+ socket_unlock(so, 0);
+ necp_client_assign_from_socket(so->last_pid, inp->necp_client_uuid, inp);
+ socket_lock(so, 0);
+ }
+#endif /* NECP */
soisconnected(so);
if (inp->inp_flowhash == 0)
inp->inp_flowhash = inp_calc_flowhash(inp);
}
static int
-udp6_connectx(struct socket *so, struct sockaddr_list **src_sl,
- struct sockaddr_list **dst_sl, struct proc *p, uint32_t ifscope,
+udp6_connectx(struct socket *so, struct sockaddr *src,
+ struct sockaddr *dst, struct proc *p, uint32_t ifscope,
sae_associd_t aid, sae_connid_t *pcid, uint32_t flags, void *arg,
uint32_t arglen, struct uio *uio, user_ssize_t *bytes_written)
{
- return (udp_connectx_common(so, AF_INET6, src_sl, dst_sl,
+ return (udp_connectx_common(so, AF_INET6, src, dst,
p, ifscope, aid, pcid, flags, arg, arglen, uio, bytes_written));
}
inp->in6p_laddr = in6addr_any;
inp->in6p_last_outifp = NULL;
+
so->so_state &= ~SS_ISCONNECTED; /* XXX */
return (0);
}
uh->uh_sum == 0) {
/* UDP/IPv6 checksum is mandatory (RFC2460) */
- /*
+ /*
* If checksum was already validated, ignore this check.
- * This is necessary for transport-mode ESP, which may be
+ * This is necessary for transport-mode ESP, which may be
* getting UDP payloads without checksums when the network
* has a NAT64.
*/
if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
uh->uh_sum = m->m_pkthdr.csum_rx_val;
} else {
- uint16_t sum = m->m_pkthdr.csum_rx_val;
- uint16_t start = m->m_pkthdr.csum_rx_start;
+ uint32_t sum = m->m_pkthdr.csum_rx_val;
+ uint32_t start = m->m_pkthdr.csum_rx_start;
+ int32_t trailer = (m_pktlen(m) - (off + ulen));
/*
* Perform 1's complement adjustment of octets
* that got included/excluded in the hardware-
- * calculated checksum value.
+ * calculated checksum value. Also take care
+ * of any trailing bytes and subtract out
+ * their partial sum.
*/
+ ASSERT(trailer >= 0);
if ((m->m_pkthdr.csum_flags & CSUM_PARTIAL) &&
- start != off) {
- uint16_t s, d;
+ (start != off || trailer != 0)) {
+ uint32_t swbytes = (uint32_t)trailer;
+ uint16_t s = 0, d = 0;
if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
s = ip6->ip6_src.s6_addr16[1];
}
/* callee folds in sum */
- sum = m_adj_sum16(m, start, off, sum);
+ sum = m_adj_sum16(m, start, off, ulen, sum);
+ if (off > start)
+ swbytes += (off - start);
+ else
+ swbytes += (start - off);
if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
ip6->ip6_src.s6_addr16[1] = s;
if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
ip6->ip6_dst.s6_addr16[1] = d;
+
+ if (swbytes != 0)
+ udp_in_cksum_stats(swbytes);
+ if (trailer != 0)
+ m_adj(m, -trailer);
}
uh->uh_sum = in6_pseudo(&ip6->ip6_src, &ip6->ip6_dst,