X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..4bd07ac2140668789aa3ee8ec4dde4a3e0a3bba5:/bsd/netinet/raw_ip.c diff --git a/bsd/netinet/raw_ip.c b/bsd/netinet/raw_ip.c index 89d1a5f3a..c2b41a365 100644 --- a/bsd/netinet/raw_ip.c +++ b/bsd/netinet/raw_ip.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Apple Inc. All rights reserved. + * Copyright (c) 2000-2014 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -93,7 +93,6 @@ #include #include #include -#include #if INET6 #include @@ -120,10 +119,6 @@ int rip_disconnect(struct socket *); int rip_bind(struct socket *, struct sockaddr *, struct proc *); int rip_connect(struct socket *, struct sockaddr *, struct proc *); int rip_shutdown(struct socket *); - -#if IPSEC -extern int ipsec_bypass; -#endif struct inpcbhead ripcb; struct inpcbinfo ripcbinfo; @@ -231,29 +226,21 @@ rip_input(m, iphlen) if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; - - if (inp_restricted(inp, ifp)) - continue; - - if (ifp != NULL && IFNET_IS_CELLULAR(ifp) && - (inp->inp_flags & INP_NO_IFT_CELLULAR)) + if (inp_restricted_recv(inp, ifp)) continue; - if (last) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); - + skipit = 0; -#if IPSEC - /* check AH/ESP integrity. */ - if (ipsec_bypass == 0 && n) { - if (ipsec4_in_reject_so(n, last->inp_socket)) { - m_freem(n); - IPSEC_STAT_INCREMENT(ipsecstat.in_polvio); - /* do not inject data to pcb */ - skipit = 1; - } - } -#endif /*IPSEC*/ + +#if NECP + if (n && !necp_socket_is_allowed_to_send_recv_v4(last, 0, 0, + &ip->ip_dst, &ip->ip_src, ifp, NULL, NULL)) { + m_freem(n); + /* do not inject data to pcb */ + skipit = 1; + } +#endif /* NECP */ #if CONFIG_MACF_NET if (n && skipit == 0) { if (mac_inpcb_check_deliver(last, n, AF_INET, @@ -299,18 +286,15 @@ rip_input(m, iphlen) } skipit = 0; -#if IPSEC - /* check AH/ESP integrity. */ - if (ipsec_bypass == 0 && last) { - if (ipsec4_in_reject_so(m, last->inp_socket)) { - m_freem(m); - IPSEC_STAT_INCREMENT(ipsecstat.in_polvio); - OSAddAtomic(1, &ipstat.ips_delivered); - /* do not inject data to pcb */ - skipit = 1; - } - } -#endif /*IPSEC*/ +#if NECP + if (last && !necp_socket_is_allowed_to_send_recv_v4(last, 0, 0, + &ip->ip_dst, &ip->ip_src, ifp, NULL, NULL)) { + m_freem(m); + OSAddAtomic(1, &ipstat.ips_delivered); + /* do not inject data to pcb */ + skipit = 1; + } +#endif /* NECP */ #if CONFIG_MACF_NET if (last && skipit == 0) { if (mac_inpcb_check_deliver(last, m, AF_INET, SOCK_RAW) != 0) { @@ -384,7 +368,11 @@ rip_output( control = NULL; } - if (inp == NULL || (inp->inp_flags2 & INP2_WANT_FLOW_DIVERT)) { + if (inp == NULL +#if NECP + || (necp_socket_should_use_flow_divert(inp)) +#endif /* NECP */ + ) { if (m != NULL) m_freem(m); VERIFY(control == NULL); @@ -397,8 +385,12 @@ rip_output( ipoa.ipoa_boundif = inp->inp_boundifp->if_index; ipoa.ipoa_flags |= IPOAF_BOUND_IF; } - if (inp->inp_flags & INP_NO_IFT_CELLULAR) + if (INP_NO_CELLULAR(inp)) ipoa.ipoa_flags |= IPOAF_NO_CELLULAR; + if (INP_NO_EXPENSIVE(inp)) + ipoa.ipoa_flags |= IPOAF_NO_EXPENSIVE; + if (INP_AWDL_UNRESTRICTED(inp)) + ipoa.ipoa_flags |= IPOAF_AWDL_UNRESTRICTED; if (inp->inp_flowhash == 0) inp->inp_flowhash = inp_calc_flowhash(inp); @@ -412,7 +404,7 @@ rip_output( m_freem(m); return(EMSGSIZE); } - M_PREPEND(m, sizeof(struct ip), M_WAIT); + M_PREPEND(m, sizeof(struct ip), M_WAIT, 1); if (m == NULL) return ENOBUFS; ip = mtod(m, struct ip *); @@ -448,8 +440,22 @@ rip_output( if (inp->inp_laddr.s_addr != INADDR_ANY) ipoa.ipoa_flags |= IPOAF_BOUND_SRCADDR; +#if NECP + { + necp_kernel_policy_id policy_id; + u_int32_t route_rule_id; + if (!necp_socket_is_allowed_to_send_recv_v4(inp, 0, 0, + &ip->ip_src, &ip->ip_dst, NULL, &policy_id, &route_rule_id)) { + m_freem(m); + return(EHOSTUNREACH); + } + + necp_mark_packet_from_socket(m, inp, policy_id, route_rule_id); + } +#endif /* NECP */ + #if IPSEC - if (ipsec_bypass == 0 && ipsec_setsocket(m, so) != 0) { + if (inp->inp_sp != NULL && ipsec_setsocket(m, so) != 0) { m_freem(m); return ENOBUFS; } @@ -477,6 +483,7 @@ rip_output( * to pass the PCB cached route pointer directly to IP and * the modules beneath it. */ + // TODO: PASS DOWN ROUTE RULE ID error = ip_output(m, inp->inp_options, &inp->inp_route, flags, imo, &ipoa); @@ -511,11 +518,11 @@ rip_output( } /* - * If output interface was cellular, and this socket is denied - * access to it, generate an event. + * If output interface was cellular/expensive, and this socket is + * denied access to it, generate an event. */ if (error != 0 && (ipoa.ipoa_retflags & IPOARF_IFDENIED) && - (inp->inp_flags & INP_NO_IFT_CELLULAR)) + (INP_NO_CELLULAR(inp) || INP_NO_EXPENSIVE(inp))) soevent(so, (SO_FILT_HINT_LOCKED|SO_FILT_HINT_IFDENIED)); return (error); @@ -595,19 +602,6 @@ rip_ctloutput(so, sopt) break ; #endif /* DUMMYNET */ -#if MROUTING - case MRT_INIT: - case MRT_DONE: - case MRT_ADD_VIF: - case MRT_DEL_VIF: - case MRT_ADD_MFC: - case MRT_DEL_MFC: - case MRT_VERSION: - case MRT_ASSERT: - error = ip_mrouter_get(so, sopt); - break; -#endif /* MROUTING */ - default: error = ip_ctloutput(so, sopt); break; @@ -671,36 +665,6 @@ rip_ctloutput(so, sopt) break ; #endif -#if MROUTING - case IP_RSVP_ON: - error = ip_rsvp_init(so); - break; - - case IP_RSVP_OFF: - error = ip_rsvp_done(); - break; - - /* XXX - should be combined */ - case IP_RSVP_VIF_ON: - error = ip_rsvp_vif_init(so, sopt); - break; - - case IP_RSVP_VIF_OFF: - error = ip_rsvp_vif_done(so, sopt); - break; - - case MRT_INIT: - case MRT_DONE: - case MRT_ADD_VIF: - case MRT_DEL_VIF: - case MRT_ADD_MFC: - case MRT_DEL_MFC: - case MRT_VERSION: - case MRT_ASSERT: - error = ip_mrouter_set(so, sopt); - break; -#endif /* MROUTING */ - case SO_FLUSH: if ((error = sooptcopyin(sopt, &optval, sizeof (optval), sizeof (optval))) != 0) @@ -854,13 +818,6 @@ rip_detach(struct socket *so) inp = sotoinpcb(so); if (inp == 0) panic("rip_detach"); -#if MROUTING - if (so == ip_mrouter) - ip_mrouter_done(); - ip_rsvp_force_done(so); - if (so == ip_rsvpd) - ip_rsvp_done(); -#endif /* MROUTING */ in_pcbdetach(inp); return 0; } @@ -889,7 +846,11 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct proc *p) struct ifaddr *ifa = NULL; struct ifnet *outif = NULL; - if (inp == NULL || (inp->inp_flags2 & INP2_WANT_FLOW_DIVERT)) + if (inp == NULL +#if NECP + || (necp_socket_should_use_flow_divert(inp)) +#endif /* NECP */ + ) return (inp == NULL ? EINVAL : EPROTOTYPE); if (nam->sa_len != sizeof (struct sockaddr_in)) @@ -930,7 +891,11 @@ rip_connect(struct socket *so, struct sockaddr *nam, __unused struct proc *p) struct inpcb *inp = sotoinpcb(so); struct sockaddr_in *addr = (struct sockaddr_in *)(void *)nam; - if (inp == NULL || (inp->inp_flags2 & INP2_WANT_FLOW_DIVERT)) + if (inp == NULL +#if NECP + || (necp_socket_should_use_flow_divert(inp)) +#endif /* NECP */ + ) return (inp == NULL ? EINVAL : EPROTOTYPE); if (nam->sa_len != sizeof(*addr)) return EINVAL; @@ -961,8 +926,15 @@ rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, u_int32_t dst; int error = 0; - if (inp == NULL || (inp->inp_flags2 & INP2_WANT_FLOW_DIVERT)) { - error = (inp == NULL ? EINVAL : EPROTOTYPE); + if (inp == NULL +#if NECP + || (necp_socket_should_use_flow_divert(inp) && (error = EPROTOTYPE)) +#endif /* NECP */ + ) { + if (inp == NULL) + error = EINVAL; + else + error = EPROTOTYPE; goto bad; } @@ -1135,7 +1107,8 @@ rip_pcblist SYSCTL_HANDLER_ARGS return error; } -SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, +SYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, rip_pcblist, "S,xinpcb", "List of active raw IP sockets"); @@ -1237,7 +1210,8 @@ rip_pcblist64 SYSCTL_HANDLER_ARGS return error; } -SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist64, CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, +SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist64, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, rip_pcblist64, "S,xinpcb64", "List of active raw IP sockets"); @@ -1253,7 +1227,8 @@ rip_pcblist_n SYSCTL_HANDLER_ARGS return error; } -SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist_n, CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, +SYSCTL_PROC(_net_inet_raw, OID_AUTO, pcblist_n, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, rip_pcblist_n, "S,xinpcb_n", "List of active raw IP sockets"); struct pr_usrreqs rip_usrreqs = {