/*
- * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2016 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@
*/
/*
#define _IP_VHL
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <netinet/in_tclass.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
* mbuf chain.
*/
void
-rip_input(m, iphlen)
- struct mbuf *m;
- int iphlen;
+rip_input(struct mbuf *m, int iphlen)
{
struct ip *ip = mtod(m, struct ip *);
struct inpcb *inp;
} else {
if (error) {
/* should notify about lost packet */
- kprintf("rip_input can't append to socket\n");
+ ipstat.ips_raw_sappend_fail++;
}
}
opts = 0;
if (ret != 0) {
m_freem(m);
m_freem(opts);
- goto unlock;
+ goto unlock;
}
}
if (last->inp_flags & INP_STRIPHDR) {
(struct sockaddr *)&ripsrc, m, opts, NULL) != 0) {
sorwakeup(last->inp_socket);
} else {
- kprintf("rip_input(2) can't append to socket\n");
+ ipstat.ips_raw_sappend_fail++;
}
} else {
m_freem(m);
}
unlock:
/*
- * Keep the list locked because socket filter may force the socket lock
+ * Keep the list locked because socket filter may force the socket lock
* to be released when calling sbappendaddr() -- see rdar://7627704
*/
lck_rw_done(ripcbinfo.ipi_lock);
struct inpcb *inp = sotoinpcb(so);
int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
struct ip_out_args ipoa =
- { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0 };
+ { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, 0, 0 };
struct ip_moptions *imo;
int error = 0;
- mbuf_svc_class_t msc = MBUF_SC_UNSPEC;
+ int sotc = SO_TC_UNSPEC;
+ int netsvctype = _NET_SERVICE_TYPE_UNSPEC;
if (control != NULL) {
- msc = mbuf_service_class_from_control(control);
+ sotc = so_tc_from_control(control, &netsvctype);
m_freem(control);
control = NULL;
}
+ if (sotc == SO_TC_UNSPEC) {
+ sotc = so->so_traffic_class;
+ netsvctype = so->so_netsvctype;
+ }
if (inp == NULL
#if NECP
ipoa.ipoa_flags |= IPOAF_NO_EXPENSIVE;
if (INP_AWDL_UNRESTRICTED(inp))
ipoa.ipoa_flags |= IPOAF_AWDL_UNRESTRICTED;
+ ipoa.ipoa_sotc = sotc;
+ ipoa.ipoa_netsvctype = netsvctype;
if (inp->inp_flowhash == 0)
inp->inp_flowhash = inp_calc_flowhash(inp);
{
necp_kernel_policy_id policy_id;
u_int32_t route_rule_id;
+
+ /*
+ * We need a route to perform NECP route rule checks
+ */
+ if (net_qos_policy_restricted != 0 &&
+ ROUTE_UNUSABLE(&inp->inp_route)) {
+ struct sockaddr_in to;
+ struct sockaddr_in from;
+ struct in_addr laddr = ip->ip_src;
+
+ ROUTE_RELEASE(&inp->inp_route);
+
+ bzero(&from, sizeof(struct sockaddr_in));
+ from.sin_family = AF_INET;
+ from.sin_len = sizeof(struct sockaddr_in);
+ from.sin_addr = laddr;
+
+ bzero(&to, sizeof(struct sockaddr_in));
+ to.sin_family = AF_INET;
+ to.sin_len = sizeof(struct sockaddr_in);
+ to.sin_addr.s_addr = ip->ip_dst.s_addr;
+
+ if ((error = in_pcbladdr(inp, (struct sockaddr *)&to,
+ &laddr, ipoa.ipoa_boundif, NULL, 1)) != 0) {
+ printf("%s in_pcbladdr(%p) error %d\n",
+ __func__, inp, error);
+ m_freem(m);
+ return (error);
+ }
+
+ inp_update_necp_policy(inp, (struct sockaddr *)&from,
+ (struct sockaddr *)&to, ipoa.ipoa_boundif);
+ inp->inp_policyresult.results.qos_marking_gencount = 0;
+ }
+
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);
}
necp_mark_packet_from_socket(m, inp, policy_id, route_rule_id);
+
+ if (net_qos_policy_restricted != 0) {
+ struct ifnet *rt_ifp = NULL;
+
+ if (inp->inp_route.ro_rt != NULL)
+ rt_ifp = inp->inp_route.ro_rt->rt_ifp;
+
+ printf("%s inp %p last_pid %u inp_boundifp %d inp_last_outifp %d rt_ifp %d route_rule_id %u\n",
+ __func__, inp,
+ inp->inp_socket != NULL ? inp->inp_socket->last_pid : -1,
+ inp->inp_boundifp != NULL ? inp->inp_boundifp->if_index : -1,
+ inp->inp_last_outifp != NULL ? inp->inp_last_outifp->if_index : -1,
+ rt_ifp != NULL ? rt_ifp->if_index : -1,
+ route_rule_id);
+ necp_socket_update_qos_marking(inp, inp->inp_route.ro_rt,
+ NULL, route_rule_id);
+ }
}
#endif /* NECP */
+ if ((so->so_flags1 & SOF1_QOSMARKING_ALLOWED))
+ ipoa.ipoa_flags |= IPOAF_QOSMARKING_ALLOWED;
#if IPSEC
if (inp->inp_sp != NULL && ipsec_setsocket(m, so) != 0) {
if (ROUTE_UNUSABLE(&inp->inp_route))
ROUTE_RELEASE(&inp->inp_route);
- set_packet_service_class(m, so, msc, 0);
+ set_packet_service_class(m, so, sotc, 0);
m->m_pkthdr.pkt_flowsrc = FLOWSRC_INPCB;
m->m_pkthdr.pkt_flowid = inp->inp_flowhash;
m->m_pkthdr.pkt_flags |= (PKTF_FLOW_ID | PKTF_FLOW_LOCALSRC |
load_ipfw(void)
{
kern_return_t err;
-
+
ipfw_init();
-
+
#if DUMMYNET
if (!DUMMYNET_LOADED)
ip_dn_init();
#endif /* DUMMYNET */
err = 0;
-
+
return err == 0 && ip_fw_ctl_ptr == NULL ? -1 : err;
}
#endif /* IPFIREWALL */
* Raw IP socket option processing.
*/
int
-rip_ctloutput(so, sopt)
- struct socket *so;
- struct sockopt *sopt;
+rip_ctloutput(struct socket *so, struct sockopt *sopt)
{
struct inpcb *inp = sotoinpcb(so);
int error, optval;
}
/* note: rip_unlock is called from different protos instead of the generic socket_unlock,
- * it will handle the socket dealloc on last reference
+ * it will handle the socket dealloc on last reference
* */
int
rip_unlock(struct socket *so, int refcount, void *debug)
*/
gencnt = ripcbinfo.ipi_gencnt;
n = ripcbinfo.ipi_count;
-
+
bzero(&xig, sizeof(xig));
xig.xig_len = sizeof xig;
xig.xig_count = n;
*/
if (n == 0) {
lck_rw_done(ripcbinfo.ipi_lock);
- return 0;
+ return 0;
}
inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK);
lck_rw_done(ripcbinfo.ipi_lock);
return ENOMEM;
}
-
+
for (inp = ripcbinfo.ipi_listhead->lh_first, i = 0; inp && i < n;
inp = inp->inp_list.le_next) {
if (inp->inp_gencnt <= gencnt && inp->inp_state != INPCB_STATE_DEAD)