X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/5d5c5d0d5b79ade9a973d55186ffda2638ba2b6e..c910b4d9d2451126ae3917b931cd4390c11e1d52:/bsd/netinet/ip_icmp.c diff --git a/bsd/netinet/ip_icmp.c b/bsd/netinet/ip_icmp.c index ce8b8e5ed..995ca8346 100644 --- a/bsd/netinet/ip_icmp.c +++ b/bsd/netinet/ip_icmp.c @@ -1,31 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2008 Apple Inc. All rights reserved. * - * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ + * @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 - * compliance with the License. The rights granted to you under the - * License may not be used to create, or enable the creation or - * redistribution of, 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, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * 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 + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * 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, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * 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_LICENSE_OSREFERENCE_HEADER_END@ + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -61,6 +59,12 @@ * * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94 */ +/* + * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. + */ #include #include @@ -104,7 +108,11 @@ */ #ifndef M_SKIP_FIREWALL #define M_SKIP_FIREWALL 0x4000 -#endif +#endif + +#if CONFIG_MACF_NET +#include +#endif /* MAC_NET */ /* * ICMP routines: error generation, receive packet processing, and @@ -181,10 +189,10 @@ icmp_error( n_long dest, struct ifnet *destifp) { - register struct ip *oip = mtod(n, struct ip *), *nip; - register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; - register struct icmp *icp; - register struct mbuf *m; + struct ip *oip = mtod(n, struct ip *), *nip; + unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2; + struct icmp *icp; + struct mbuf *m; unsigned icmplen; #if ICMPPRINTFS @@ -212,15 +220,18 @@ icmp_error( /* * First, formulate icmp message */ - m = m_gethdr(M_DONTWAIT, MT_HEADER); + m = m_gethdr(M_DONTWAIT, MT_HEADER); /* MAC-OK */ if (m == NULL) goto freeit; - if (n->m_flags & M_SKIP_FIREWALL) { + if (n->m_flags & M_SKIP_FIREWALL) { /* set M_SKIP_FIREWALL to skip firewall check, since we're called from firewall */ m->m_flags |= M_SKIP_FIREWALL; } +#if CONFIG_MACF_NET + mac_mbuf_label_associate_netlayer(n, m); +#endif icmplen = min(oiplen + 8, oip->ip_len); if (icmplen < sizeof(struct ip)) { printf("icmp_error: bad length\n"); @@ -271,7 +282,6 @@ icmp_error( m->m_len += sizeof(struct ip); m->m_pkthdr.len = m->m_len; m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; - m->m_pkthdr.aux = NULL; /* for IPsec */ nip = mtod(m, struct ip *); bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip)); nip->ip_len = m->m_len; @@ -284,26 +294,26 @@ freeit: m_freem(n); } -static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; -static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; +static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET, + 0 , { 0 }, { 0,0,0,0,0,0,0,0 } }; +static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET, + 0 , { 0 }, { 0,0,0,0,0,0,0,0 } }; +static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET, + 0 , { 0 }, { 0,0,0,0,0,0,0,0 } }; /* * Process a received ICMP message. */ void -icmp_input(m, hlen) - register struct mbuf *m; - int hlen; +icmp_input(struct mbuf *m, int hlen) { - register struct icmp *icp; - register struct ip *ip = mtod(m, struct ip *); + struct icmp *icp; + struct ip *ip = mtod(m, struct ip *); int icmplen = ip->ip_len; - register int i; + int i; struct in_ifaddr *ia; void (*ctlfunc)(int, struct sockaddr *, void *); int code; - char ipv4str[MAX_IPv4_STR_LEN]; /* * Locate icmp structure in mbuf, and check @@ -312,6 +322,7 @@ icmp_input(m, hlen) #if ICMPPRINTFS if (icmpprintfs) { char buf[MAX_IPv4_STR_LEN]; + char ipv4str[MAX_IPv4_STR_LEN]; printf("icmp_input from %s to %s, len %d\n", inet_ntop(AF_INET, &ip->ip_src, buf, sizeof(buf)), @@ -566,7 +577,7 @@ icmp_input(m, hlen) break; if (ia->ia_ifp == 0) { ifafree(&ia->ia_ifa); - ia = 0; + ia = NULL; break; } icp->icmp_type = ICMP_MASKREPLY; @@ -630,10 +641,9 @@ reflect: } #endif icmpsrc.sin_addr = icp->icmp_ip.ip_dst; - rtredirect((struct sockaddr *)&icmpsrc, - (struct sockaddr *)&icmpdst, - (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, - (struct sockaddr *)&icmpgw, (struct rtentry **)0); + rtredirect(m->m_pkthdr.rcvif, (struct sockaddr *)&icmpsrc, + (struct sockaddr *)&icmpdst, NULL, RTF_GATEWAY | RTF_HOST, + (struct sockaddr *)&icmpgw, NULL); pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); #if IPSEC key_sa_routechange((struct sockaddr *)&icmpsrc); @@ -666,13 +676,12 @@ freeit: * Reflect the ip packet back to the source */ static void -icmp_reflect(m) - struct mbuf *m; +icmp_reflect(struct mbuf *m) { - register struct ip *ip = mtod(m, struct ip *); - register struct in_ifaddr *ia; + struct ip *ip = mtod(m, struct ip *); + struct in_ifaddr *ia; struct in_addr t; - struct mbuf *opts = 0; + struct mbuf *opts = NULL; int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip); if (!in_canforward(ip->ip_src) && @@ -717,6 +726,9 @@ icmp_reflect(m) ifaref(&ia->ia_ifa); } lck_mtx_unlock(rt_mtx); +#if CONFIG_MACF_NET + mac_netinet_icmp_reply(m); +#endif t = IA_SIN(ia)->sin_addr; ip->ip_src = t; ip->ip_ttl = ip_defttl; @@ -724,7 +736,7 @@ icmp_reflect(m) ia = NULL; if (optlen > 0) { - register u_char *cp; + u_char *cp; int opt, cnt; u_int len; @@ -734,7 +746,7 @@ icmp_reflect(m) */ cp = (u_char *) (ip + 1); if ((opts = ip_srcroute()) == 0 && - (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { + (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { /* MAC-OK */ opts->m_len = sizeof(struct in_addr); mtod(opts, struct in_addr *)->s_addr = 0; } @@ -807,15 +819,16 @@ done: * after supplying a checksum. */ static void -icmp_send(m, opts) - register struct mbuf *m; - struct mbuf *opts; +icmp_send(struct mbuf *m, struct mbuf *opts) { - register struct ip *ip = mtod(m, struct ip *); - register int hlen; - register struct icmp *icp; + struct ip *ip = mtod(m, struct ip *); + int hlen; + struct icmp *icp; struct route ro; - char ipv4str[MAX_IPv4_STR_LEN]; + struct ip_out_args ipoa = { IFSCOPE_NONE }; + + if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.rcvif != NULL) + ipoa.ipoa_ifscope = m->m_pkthdr.rcvif->if_index; hlen = IP_VHL_HL(ip->ip_vhl) << 2; m->m_data += hlen; @@ -825,13 +838,13 @@ icmp_send(m, opts) icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); m->m_data -= hlen; m->m_len += hlen; - m->m_pkthdr.rcvif = 0; - m->m_pkthdr.aux = NULL; + m->m_pkthdr.rcvif = NULL; m->m_pkthdr.csum_data = 0; m->m_pkthdr.csum_flags = 0; #if ICMPPRINTFS if (icmpprintfs) { char buf[MAX_IPv4_STR_LEN]; + char ipv4str[MAX_IPv4_STR_LEN]; printf("icmp_send dst %s src %s\n", inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)), @@ -839,13 +852,15 @@ icmp_send(m, opts) } #endif bzero(&ro, sizeof ro); - (void) ip_output(m, opts, &ro, 0, NULL); - if (ro.ro_rt) + (void) ip_output(m, opts, &ro, IP_OUTARGS, NULL, &ipoa); + if (ro.ro_rt) { rtfree(ro.ro_rt); + ro.ro_rt = NULL; + } } n_time -iptime() +iptime(void) { struct timeval atv; u_long t; @@ -862,9 +877,7 @@ iptime() * is returned; otherwise, a smaller value is returned. */ static int -ip_next_mtu(mtu, dir) - int mtu; - int dir; +ip_next_mtu(int mtu, int dir) { static int mtutab[] = { 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296, @@ -1011,10 +1024,10 @@ __private_extern__ struct pr_usrreqs icmp_dgram_usrreqs = { /* Like rip_attach but without root privilege enforcement */ __private_extern__ int -icmp_dgram_attach(struct socket *so, int proto, struct proc *p) +icmp_dgram_attach(struct socket *so, __unused int proto, struct proc *p) { struct inpcb *inp; - int error, s; + int error; inp = sotoinpcb(so); if (inp) @@ -1023,9 +1036,7 @@ icmp_dgram_attach(struct socket *so, int proto, struct proc *p) error = soreserve(so, rip_sendspace, rip_recvspace); if (error) return error; - s = splnet(); error = in_pcballoc(so, &ripcbinfo, p); - splx(s); if (error) return error; inp = (struct inpcb *)so->so_pcb; @@ -1041,8 +1052,7 @@ icmp_dgram_attach(struct socket *so, int proto, struct proc *p) __private_extern__ int icmp_dgram_ctloutput(struct socket *so, struct sockopt *sopt) { - struct inpcb *inp = sotoinpcb(so); - int error, optval; + int error; if (sopt->sopt_level != IPPROTO_IP) return (EINVAL); @@ -1070,6 +1080,10 @@ icmp_dgram_ctloutput(struct socket *so, struct sockopt *sopt) #endif case IP_STRIPHDR: case IP_RECVTTL: + case IP_BOUND_IF: +#if CONFIG_FORCE_OUT_IFP + case IP_FORCE_OUT_IFP: +#endif error = rip_ctloutput(so, sopt); break; @@ -1172,4 +1186,3 @@ bad: } #endif /* __APPLE__ */ -