]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/ip_icmp.c
xnu-1228.15.4.tar.gz
[apple/xnu.git] / bsd / netinet / ip_icmp.c
1 /*
2 * Copyright (c) 2000-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * Copyright (c) 1982, 1986, 1988, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
61 */
62 /*
63 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
64 * support for mandatory and extensible security protections. This notice
65 * is included in support of clause 2.2 (b) of the Apple Public License,
66 * Version 2.0.
67 */
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/mbuf.h>
72 #include <sys/protosw.h>
73 #include <sys/socket.h>
74 #include <sys/time.h>
75 #include <sys/kernel.h>
76 #include <sys/sysctl.h>
77
78 #include <net/if.h>
79 #include <net/route.h>
80
81 #define _IP_VHL
82 #include <netinet/in.h>
83 #include <netinet/in_systm.h>
84 #include <netinet/in_var.h>
85 #include <netinet/ip.h>
86 #include <netinet/ip_icmp.h>
87 #include <netinet/ip_var.h>
88 #include <netinet/icmp_var.h>
89 #include <netinet/tcp.h>
90 #include <netinet/tcp_fsm.h>
91 #include <netinet/tcp_seq.h>
92 #include <netinet/tcp_timer.h>
93 #include <netinet/tcp_var.h>
94 #include <netinet/tcpip.h>
95
96 #if IPSEC
97 #include <netinet6/ipsec.h>
98 #include <netkey/key.h>
99 #endif
100
101 #if defined(NFAITH) && NFAITH > 0
102 #include "faith.h"
103 #include <net/if_types.h>
104 #endif
105
106 /* XXX This one should go in sys/mbuf.h. It is used to avoid that
107 * a firewall-generated packet loops forever through the firewall.
108 */
109 #ifndef M_SKIP_FIREWALL
110 #define M_SKIP_FIREWALL 0x4000
111 #endif
112
113 #if CONFIG_MACF_NET
114 #include <security/mac_framework.h>
115 #endif /* MAC_NET */
116
117 /*
118 * ICMP routines: error generation, receive packet processing, and
119 * routines to turnaround packets back to the originator, and
120 * host table maintenance routines.
121 */
122
123 static struct icmpstat icmpstat;
124 SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RD,
125 &icmpstat, icmpstat, "");
126
127 static int icmpmaskrepl = 0;
128 SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
129 &icmpmaskrepl, 0, "");
130
131 static int icmptimestamp = 0;
132 SYSCTL_INT(_net_inet_icmp, ICMPCTL_TIMESTAMP, timestamp, CTLFLAG_RW,
133 &icmptimestamp, 0, "");
134
135 static int drop_redirect = 0;
136 SYSCTL_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW,
137 &drop_redirect, 0, "");
138
139 static int log_redirect = 0;
140 SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW,
141 &log_redirect, 0, "");
142
143 #if ICMP_BANDLIM
144
145 /*
146 * ICMP error-response bandwidth limiting sysctl. If not enabled, sysctl
147 * variable content is -1 and read-only.
148 */
149
150 static int icmplim = 250;
151 SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW,
152 &icmplim, 0, "");
153 #else
154
155 static int icmplim = -1;
156 SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD,
157 &icmplim, 0, "");
158
159 #endif
160
161 /*
162 * ICMP broadcast echo sysctl
163 */
164
165 static int icmpbmcastecho = 1;
166 SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW,
167 &icmpbmcastecho, 0, "");
168
169
170 #if ICMPPRINTFS
171 int icmpprintfs = 0;
172 #endif
173
174 static void icmp_reflect(struct mbuf *);
175 static void icmp_send(struct mbuf *, struct mbuf *);
176 static int ip_next_mtu(int, int);
177
178 extern struct protosw inetsw[];
179
180 /*
181 * Generate an error packet of type error
182 * in response to bad packet ip.
183 */
184 void
185 icmp_error(
186 struct mbuf *n,
187 int type,
188 int code,
189 n_long dest,
190 struct ifnet *destifp)
191 {
192 struct ip *oip = mtod(n, struct ip *), *nip;
193 unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2;
194 struct icmp *icp;
195 struct mbuf *m;
196 unsigned icmplen;
197
198 #if ICMPPRINTFS
199 if (icmpprintfs)
200 printf("icmp_error(%p, %x, %d)\n", oip, type, code);
201 #endif
202 if (type != ICMP_REDIRECT)
203 icmpstat.icps_error++;
204 /*
205 * Don't send error if not the first fragment of message.
206 * Don't error if the old packet protocol was ICMP
207 * error message, only known informational types.
208 */
209 if (oip->ip_off &~ (IP_MF|IP_DF))
210 goto freeit;
211 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
212 n->m_len >= oiplen + ICMP_MINLEN &&
213 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
214 icmpstat.icps_oldicmp++;
215 goto freeit;
216 }
217 /* Don't send error in response to a multicast or broadcast packet */
218 if (n->m_flags & (M_BCAST|M_MCAST))
219 goto freeit;
220 /*
221 * First, formulate icmp message
222 */
223 m = m_gethdr(M_DONTWAIT, MT_HEADER); /* MAC-OK */
224 if (m == NULL)
225 goto freeit;
226
227 if (n->m_flags & M_SKIP_FIREWALL) {
228 /* set M_SKIP_FIREWALL to skip firewall check, since we're called from firewall */
229 m->m_flags |= M_SKIP_FIREWALL;
230 }
231
232 #if CONFIG_MACF_NET
233 mac_mbuf_label_associate_netlayer(n, m);
234 #endif
235 icmplen = min(oiplen + 8, oip->ip_len);
236 if (icmplen < sizeof(struct ip)) {
237 printf("icmp_error: bad length\n");
238 m_free(m);
239 goto freeit;
240 }
241 m->m_len = icmplen + ICMP_MINLEN;
242 MH_ALIGN(m, m->m_len);
243 icp = mtod(m, struct icmp *);
244 if ((u_int)type > ICMP_MAXTYPE)
245 panic("icmp_error");
246 icmpstat.icps_outhist[type]++;
247 icp->icmp_type = type;
248 if (type == ICMP_REDIRECT)
249 icp->icmp_gwaddr.s_addr = dest;
250 else {
251 icp->icmp_void = 0;
252 /*
253 * The following assignments assume an overlay with the
254 * zeroed icmp_void field.
255 */
256 if (type == ICMP_PARAMPROB) {
257 icp->icmp_pptr = code;
258 code = 0;
259 } else if (type == ICMP_UNREACH &&
260 code == ICMP_UNREACH_NEEDFRAG && destifp) {
261 icp->icmp_nextmtu = htons(destifp->if_mtu);
262 }
263 }
264
265 icp->icmp_code = code;
266 m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
267 nip = &icp->icmp_ip;
268
269 /*
270 * Convert fields to network representation.
271 */
272 HTONS(nip->ip_len);
273 HTONS(nip->ip_off);
274
275 /*
276 * Now, copy old ip header (without options)
277 * in front of icmp message.
278 */
279 if (m->m_data - sizeof(struct ip) < m->m_pktdat)
280 panic("icmp len");
281 m->m_data -= sizeof(struct ip);
282 m->m_len += sizeof(struct ip);
283 m->m_pkthdr.len = m->m_len;
284 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
285 nip = mtod(m, struct ip *);
286 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
287 nip->ip_len = m->m_len;
288 nip->ip_vhl = IP_VHL_BORING;
289 nip->ip_p = IPPROTO_ICMP;
290 nip->ip_tos = 0;
291 icmp_reflect(m);
292
293 freeit:
294 m_freem(n);
295 }
296
297 static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET,
298 0 , { 0 }, { 0,0,0,0,0,0,0,0 } };
299 static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET,
300 0 , { 0 }, { 0,0,0,0,0,0,0,0 } };
301 static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET,
302 0 , { 0 }, { 0,0,0,0,0,0,0,0 } };
303
304 /*
305 * Process a received ICMP message.
306 */
307 void
308 icmp_input(struct mbuf *m, int hlen)
309 {
310 struct icmp *icp;
311 struct ip *ip = mtod(m, struct ip *);
312 int icmplen = ip->ip_len;
313 int i;
314 struct in_ifaddr *ia;
315 void (*ctlfunc)(int, struct sockaddr *, void *);
316 int code;
317
318 /*
319 * Locate icmp structure in mbuf, and check
320 * that not corrupted and of at least minimum length.
321 */
322 #if ICMPPRINTFS
323 if (icmpprintfs) {
324 char buf[MAX_IPv4_STR_LEN];
325 char ipv4str[MAX_IPv4_STR_LEN];
326
327 printf("icmp_input from %s to %s, len %d\n",
328 inet_ntop(AF_INET, &ip->ip_src, buf, sizeof(buf)),
329 inet_ntop(AF_INET, &ip->ip_dst, ipv4str, sizeof(ipv4str)),
330 icmplen);
331 }
332 #endif
333 if (icmplen < ICMP_MINLEN) {
334 icmpstat.icps_tooshort++;
335 goto freeit;
336 }
337 i = hlen + min(icmplen, ICMP_ADVLENMIN);
338 if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
339 icmpstat.icps_tooshort++;
340 return;
341 }
342 ip = mtod(m, struct ip *);
343 m->m_len -= hlen;
344 m->m_data += hlen;
345 icp = mtod(m, struct icmp *);
346 if (in_cksum(m, icmplen)) {
347 icmpstat.icps_checksum++;
348 goto freeit;
349 }
350 m->m_len += hlen;
351 m->m_data -= hlen;
352
353 #if defined(NFAITH) && 0 < NFAITH
354 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
355 /*
356 * Deliver very specific ICMP type only.
357 */
358 switch (icp->icmp_type) {
359 case ICMP_UNREACH:
360 case ICMP_TIMXCEED:
361 break;
362 default:
363 goto freeit;
364 }
365 }
366 #endif
367
368 #if ICMPPRINTFS
369 if (icmpprintfs)
370 printf("icmp_input, type %d code %d\n", icp->icmp_type,
371 icp->icmp_code);
372 #endif
373
374 /*
375 * Message type specific processing.
376 */
377 if (icp->icmp_type > ICMP_MAXTYPE)
378 goto raw;
379 icmpstat.icps_inhist[icp->icmp_type]++;
380 code = icp->icmp_code;
381 switch (icp->icmp_type) {
382
383 case ICMP_UNREACH:
384 switch (code) {
385 case ICMP_UNREACH_NET:
386 case ICMP_UNREACH_HOST:
387 case ICMP_UNREACH_SRCFAIL:
388 case ICMP_UNREACH_NET_UNKNOWN:
389 case ICMP_UNREACH_HOST_UNKNOWN:
390 case ICMP_UNREACH_ISOLATED:
391 case ICMP_UNREACH_TOSNET:
392 case ICMP_UNREACH_TOSHOST:
393 case ICMP_UNREACH_HOST_PRECEDENCE:
394 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
395 code = PRC_UNREACH_NET;
396 break;
397
398 case ICMP_UNREACH_NEEDFRAG:
399 code = PRC_MSGSIZE;
400 break;
401
402 /*
403 * RFC 1122, Sections 3.2.2.1 and 4.2.3.9.
404 * Treat subcodes 2,3 as immediate RST
405 */
406 case ICMP_UNREACH_PROTOCOL:
407 case ICMP_UNREACH_PORT:
408 code = PRC_UNREACH_PORT;
409 break;
410
411 case ICMP_UNREACH_NET_PROHIB:
412 case ICMP_UNREACH_HOST_PROHIB:
413 case ICMP_UNREACH_FILTER_PROHIB:
414 code = PRC_UNREACH_ADMIN_PROHIB;
415 break;
416
417 default:
418 goto badcode;
419 }
420 goto deliver;
421
422 case ICMP_TIMXCEED:
423 if (code > 1)
424 goto badcode;
425 code += PRC_TIMXCEED_INTRANS;
426 goto deliver;
427
428 case ICMP_PARAMPROB:
429 if (code > 1)
430 goto badcode;
431 code = PRC_PARAMPROB;
432 goto deliver;
433
434 case ICMP_SOURCEQUENCH:
435 if (code)
436 goto badcode;
437 code = PRC_QUENCH;
438 deliver:
439 /*
440 * Problem with datagram; advise higher level routines.
441 */
442 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
443 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
444 icmpstat.icps_badlen++;
445 goto freeit;
446 }
447 NTOHS(icp->icmp_ip.ip_len);
448 /* Discard ICMP's in response to multicast packets */
449 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr)))
450 goto badcode;
451 #if ICMPPRINTFS
452 if (icmpprintfs)
453 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
454 #endif
455 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
456 #if 1
457 /*
458 * MTU discovery:
459 * If we got a needfrag and there is a host route to the
460 * original destination, and the MTU is not locked, then
461 * set the MTU in the route to the suggested new value
462 * (if given) and then notify as usual. The ULPs will
463 * notice that the MTU has changed and adapt accordingly.
464 * If no new MTU was suggested, then we guess a new one
465 * less than the current value. If the new MTU is
466 * unreasonably small (defined by sysctl tcp_minmss), then
467 * we reset the MTU to the interface value and enable the
468 * lock bit, indicating that we are no longer doing MTU
469 * discovery.
470 */
471 if (code == PRC_MSGSIZE) {
472 struct rtentry *rt;
473 int mtu;
474
475 rt = rtalloc1((struct sockaddr *)&icmpsrc, 0,
476 RTF_CLONING | RTF_PRCLONING);
477 if (rt && (rt->rt_flags & RTF_HOST)
478 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
479 mtu = ntohs(icp->icmp_nextmtu);
480 if (!mtu)
481 mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu,
482 1);
483 #if DEBUG_MTUDISC
484 printf("MTU for %s reduced to %d\n",
485 inet_ntop(AF_INET, &icmpsrc.sin_addr, ipv4str,
486 sizeof(ipv4str)),
487 mtu);
488 #endif
489 if (mtu < max(296, (tcp_minmss + sizeof(struct tcpiphdr)))) {
490 /* rt->rt_rmx.rmx_mtu =
491 rt->rt_ifp->if_mtu; */
492 rt->rt_rmx.rmx_locks |= RTV_MTU;
493 } else if (rt->rt_rmx.rmx_mtu > mtu) {
494 rt->rt_rmx.rmx_mtu = mtu;
495 }
496 }
497 if (rt)
498 rtfree(rt);
499 }
500
501 #endif
502 /*
503 * XXX if the packet contains [IPv4 AH TCP], we can't make a
504 * notification to TCP layer.
505 */
506 ctlfunc = ip_protox[icp->icmp_ip.ip_p]->pr_ctlinput;
507 if (ctlfunc)
508 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
509 (void *)&icp->icmp_ip);
510 break;
511
512 badcode:
513 icmpstat.icps_badcode++;
514 break;
515
516 case ICMP_ECHO:
517 if (!icmpbmcastecho
518 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
519 icmpstat.icps_bmcastecho++;
520 break;
521 }
522 icp->icmp_type = ICMP_ECHOREPLY;
523 #if ICMP_BANDLIM
524 if (badport_bandlim(BANDLIM_ICMP_ECHO) < 0)
525 goto freeit;
526 else
527 #endif
528 goto reflect;
529
530 case ICMP_TSTAMP:
531
532 if (icmptimestamp == 0)
533 break;
534
535 if (!icmpbmcastecho
536 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
537 icmpstat.icps_bmcasttstamp++;
538 break;
539 }
540 if (icmplen < ICMP_TSLEN) {
541 icmpstat.icps_badlen++;
542 break;
543 }
544 icp->icmp_type = ICMP_TSTAMPREPLY;
545 icp->icmp_rtime = iptime();
546 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
547 #if ICMP_BANDLIM
548 if (badport_bandlim(BANDLIM_ICMP_TSTAMP) < 0)
549 goto freeit;
550 else
551 #endif
552 goto reflect;
553
554 case ICMP_MASKREQ:
555 #define satosin(sa) ((struct sockaddr_in *)(sa))
556 if (icmpmaskrepl == 0)
557 break;
558 /*
559 * We are not able to respond with all ones broadcast
560 * unless we receive it over a point-to-point interface.
561 */
562 if (icmplen < ICMP_MASKLEN)
563 break;
564 switch (ip->ip_dst.s_addr) {
565
566 case INADDR_BROADCAST:
567 case INADDR_ANY:
568 icmpdst.sin_addr = ip->ip_src;
569 break;
570
571 default:
572 icmpdst.sin_addr = ip->ip_dst;
573 }
574 ia = (struct in_ifaddr *)ifaof_ifpforaddr(
575 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
576 if (ia == 0)
577 break;
578 if (ia->ia_ifp == 0) {
579 ifafree(&ia->ia_ifa);
580 ia = NULL;
581 break;
582 }
583 icp->icmp_type = ICMP_MASKREPLY;
584 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
585 if (ip->ip_src.s_addr == 0) {
586 if (ia->ia_ifp->if_flags & IFF_BROADCAST)
587 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
588 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
589 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
590 }
591 ifafree(&ia->ia_ifa);
592 reflect:
593 ip->ip_len += hlen; /* since ip_input deducts this */
594 icmpstat.icps_reflect++;
595 icmpstat.icps_outhist[icp->icmp_type]++;
596 icmp_reflect(m);
597 return;
598
599 case ICMP_REDIRECT:
600 if (log_redirect) {
601 u_long src, dst, gw;
602
603 src = ntohl(ip->ip_src.s_addr);
604 dst = ntohl(icp->icmp_ip.ip_dst.s_addr);
605 gw = ntohl(icp->icmp_gwaddr.s_addr);
606 printf("icmp redirect from %d.%d.%d.%d: "
607 "%d.%d.%d.%d => %d.%d.%d.%d\n",
608 (int)(src >> 24), (int)((src >> 16) & 0xff),
609 (int)((src >> 8) & 0xff), (int)(src & 0xff),
610 (int)(dst >> 24), (int)((dst >> 16) & 0xff),
611 (int)((dst >> 8) & 0xff), (int)(dst & 0xff),
612 (int)(gw >> 24), (int)((gw >> 16) & 0xff),
613 (int)((gw >> 8) & 0xff), (int)(gw & 0xff));
614 }
615 if (drop_redirect)
616 break;
617 if (code > 3)
618 goto badcode;
619 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
620 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
621 icmpstat.icps_badlen++;
622 break;
623 }
624 /*
625 * Short circuit routing redirects to force
626 * immediate change in the kernel's routing
627 * tables. The message is also handed to anyone
628 * listening on a raw socket (e.g. the routing
629 * daemon for use in updating its tables).
630 */
631 icmpgw.sin_addr = ip->ip_src;
632 icmpdst.sin_addr = icp->icmp_gwaddr;
633 #if ICMPPRINTFS
634 if (icmpprintfs) {
635 char buf[MAX_IPv4_STR_LEN];
636
637 printf("redirect dst %s to %s\n",
638 inet_ntop(AF_INET, &icp->icmp_ip.ip_dst, buf, sizeof(buf)),
639 inet_ntop(AF_INET, &icp->icmp_gwaddr, ipv4str,
640 sizeof(ipv4str)));
641 }
642 #endif
643 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
644 rtredirect(m->m_pkthdr.rcvif, (struct sockaddr *)&icmpsrc,
645 (struct sockaddr *)&icmpdst, NULL, RTF_GATEWAY | RTF_HOST,
646 (struct sockaddr *)&icmpgw, NULL);
647 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
648 #if IPSEC
649 key_sa_routechange((struct sockaddr *)&icmpsrc);
650 #endif
651 break;
652
653 /*
654 * No kernel processing for the following;
655 * just fall through to send to raw listener.
656 */
657 case ICMP_ECHOREPLY:
658 case ICMP_ROUTERADVERT:
659 case ICMP_ROUTERSOLICIT:
660 case ICMP_TSTAMPREPLY:
661 case ICMP_IREQREPLY:
662 case ICMP_MASKREPLY:
663 default:
664 break;
665 }
666
667 raw:
668 rip_input(m, hlen);
669 return;
670
671 freeit:
672 m_freem(m);
673 }
674
675 /*
676 * Reflect the ip packet back to the source
677 */
678 static void
679 icmp_reflect(struct mbuf *m)
680 {
681 struct ip *ip = mtod(m, struct ip *);
682 struct in_ifaddr *ia;
683 struct in_addr t;
684 struct mbuf *opts = NULL;
685 int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip);
686
687 if (!in_canforward(ip->ip_src) &&
688 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
689 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
690 m_freem(m); /* Bad return address */
691 goto done; /* Ip_output() will check for broadcast */
692 }
693 t = ip->ip_dst;
694 ip->ip_dst = ip->ip_src;
695 /*
696 * If the incoming packet was addressed directly to us,
697 * use dst as the src for the reply. Otherwise (broadcast
698 * or anonymous), use the address which corresponds
699 * to the incoming interface.
700 */
701 lck_mtx_lock(rt_mtx);
702 for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) {
703 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
704 break;
705 if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) &&
706 t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
707 break;
708 }
709 if (ia)
710 ifaref(&ia->ia_ifa);
711 icmpdst.sin_addr = t;
712 if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif)
713 ia = (struct in_ifaddr *)ifaof_ifpforaddr(
714 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
715 /*
716 * The following happens if the packet was not addressed to us,
717 * and was received on an interface with no IP address.
718 */
719 if (ia == (struct in_ifaddr *)0) {
720 ia = in_ifaddrhead.tqh_first;
721 if (ia == (struct in_ifaddr *)0) {/* no address yet, bail out */
722 m_freem(m);
723 lck_mtx_unlock(rt_mtx);
724 goto done;
725 }
726 ifaref(&ia->ia_ifa);
727 }
728 lck_mtx_unlock(rt_mtx);
729 #if CONFIG_MACF_NET
730 mac_netinet_icmp_reply(m);
731 #endif
732 t = IA_SIN(ia)->sin_addr;
733 ip->ip_src = t;
734 ip->ip_ttl = ip_defttl;
735 ifafree(&ia->ia_ifa);
736 ia = NULL;
737
738 if (optlen > 0) {
739 u_char *cp;
740 int opt, cnt;
741 u_int len;
742
743 /*
744 * Retrieve any source routing from the incoming packet;
745 * add on any record-route or timestamp options.
746 */
747 cp = (u_char *) (ip + 1);
748 if ((opts = ip_srcroute()) == 0 &&
749 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { /* MAC-OK */
750 opts->m_len = sizeof(struct in_addr);
751 mtod(opts, struct in_addr *)->s_addr = 0;
752 }
753 if (opts) {
754 #if ICMPPRINTFS
755 if (icmpprintfs)
756 printf("icmp_reflect optlen %d rt %d => ",
757 optlen, opts->m_len);
758 #endif
759 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
760 opt = cp[IPOPT_OPTVAL];
761 if (opt == IPOPT_EOL)
762 break;
763 if (opt == IPOPT_NOP)
764 len = 1;
765 else {
766 if (cnt < IPOPT_OLEN + sizeof(*cp))
767 break;
768 len = cp[IPOPT_OLEN];
769 if (len < IPOPT_OLEN + sizeof(*cp) ||
770 len > cnt)
771 break;
772 }
773 /*
774 * Should check for overflow, but it "can't happen"
775 */
776 if (opt == IPOPT_RR || opt == IPOPT_TS ||
777 opt == IPOPT_SECURITY) {
778 bcopy((caddr_t)cp,
779 mtod(opts, caddr_t) + opts->m_len, len);
780 opts->m_len += len;
781 }
782 }
783 /* Terminate & pad, if necessary */
784 cnt = opts->m_len % 4;
785 if (cnt) {
786 for (; cnt < 4; cnt++) {
787 *(mtod(opts, caddr_t) + opts->m_len) =
788 IPOPT_EOL;
789 opts->m_len++;
790 }
791 }
792 #if ICMPPRINTFS
793 if (icmpprintfs)
794 printf("%d\n", opts->m_len);
795 #endif
796 }
797 /*
798 * Now strip out original options by copying rest of first
799 * mbuf's data back, and adjust the IP length.
800 */
801 ip->ip_len -= optlen;
802 ip->ip_vhl = IP_VHL_BORING;
803 m->m_len -= optlen;
804 if (m->m_flags & M_PKTHDR)
805 m->m_pkthdr.len -= optlen;
806 optlen += sizeof(struct ip);
807 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
808 (unsigned)(m->m_len - sizeof(struct ip)));
809 }
810 m->m_flags &= ~(M_BCAST|M_MCAST);
811 icmp_send(m, opts);
812 done:
813 if (opts)
814 (void)m_free(opts);
815 }
816
817 /*
818 * Send an icmp packet back to the ip level,
819 * after supplying a checksum.
820 */
821 static void
822 icmp_send(struct mbuf *m, struct mbuf *opts)
823 {
824 struct ip *ip = mtod(m, struct ip *);
825 int hlen;
826 struct icmp *icp;
827 struct route ro;
828 struct ip_out_args ipoa = { IFSCOPE_NONE };
829
830 if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.rcvif != NULL)
831 ipoa.ipoa_ifscope = m->m_pkthdr.rcvif->if_index;
832
833 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
834 m->m_data += hlen;
835 m->m_len -= hlen;
836 icp = mtod(m, struct icmp *);
837 icp->icmp_cksum = 0;
838 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
839 m->m_data -= hlen;
840 m->m_len += hlen;
841 m->m_pkthdr.rcvif = NULL;
842 m->m_pkthdr.csum_data = 0;
843 m->m_pkthdr.csum_flags = 0;
844 #if ICMPPRINTFS
845 if (icmpprintfs) {
846 char buf[MAX_IPv4_STR_LEN];
847 char ipv4str[MAX_IPv4_STR_LEN];
848
849 printf("icmp_send dst %s src %s\n",
850 inet_ntop(AF_INET, &ip->ip_dst, buf, sizeof(buf)),
851 inet_ntop(AF_INET, &ip->ip_src, ipv4str, sizeof(ipv4str)));
852 }
853 #endif
854 bzero(&ro, sizeof ro);
855 (void) ip_output(m, opts, &ro, IP_OUTARGS, NULL, &ipoa);
856 if (ro.ro_rt) {
857 rtfree(ro.ro_rt);
858 ro.ro_rt = NULL;
859 }
860 }
861
862 n_time
863 iptime(void)
864 {
865 struct timeval atv;
866 u_long t;
867
868 microtime(&atv);
869 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
870 return (htonl(t));
871 }
872
873 #if 1
874 /*
875 * Return the next larger or smaller MTU plateau (table from RFC 1191)
876 * given current value MTU. If DIR is less than zero, a larger plateau
877 * is returned; otherwise, a smaller value is returned.
878 */
879 static int
880 ip_next_mtu(int mtu, int dir)
881 {
882 static int mtutab[] = {
883 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296,
884 68, 0
885 };
886 int i;
887
888 for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) {
889 if (mtu >= mtutab[i])
890 break;
891 }
892
893 if (dir < 0) {
894 if (i == 0) {
895 return 0;
896 } else {
897 return mtutab[i - 1];
898 }
899 } else {
900 if (mtutab[i] == 0) {
901 return 0;
902 } else if(mtu > mtutab[i]) {
903 return mtutab[i];
904 } else {
905 return mtutab[i + 1];
906 }
907 }
908 }
909 #endif
910
911 #if ICMP_BANDLIM
912
913 /*
914 * badport_bandlim() - check for ICMP bandwidth limit
915 *
916 * Return 0 if it is ok to send an ICMP error response, -1 if we have
917 * hit our bandwidth limit and it is not ok.
918 *
919 * If icmplim is <= 0, the feature is disabled and 0 is returned.
920 *
921 * For now we separate the TCP and UDP subsystems w/ different 'which'
922 * values. We may eventually remove this separation (and simplify the
923 * code further).
924 *
925 * Note that the printing of the error message is delayed so we can
926 * properly print the icmp error rate that the system was trying to do
927 * (i.e. 22000/100 pps, etc...). This can cause long delays in printing
928 * the 'final' error, but it doesn't make sense to solve the printing
929 * delay with more complex code.
930 */
931
932 int
933 badport_bandlim(int which)
934 {
935 static struct timeval lticks[BANDLIM_MAX + 1];
936 static int lpackets[BANDLIM_MAX + 1];
937 struct timeval time;
938 int secs;
939
940 const char *bandlimittype[] = {
941 "Limiting icmp unreach response",
942 "Limiting icmp ping response",
943 "Limiting icmp tstamp response",
944 "Limiting closed port RST response",
945 "Limiting open port RST response"
946 };
947
948 /*
949 * Return ok status if feature disabled or argument out of
950 * ranage.
951 */
952
953 if (icmplim <= 0 || which > BANDLIM_MAX || which < 0)
954 return(0);
955
956 getmicrouptime(&time);
957
958 secs = time.tv_sec - lticks[which].tv_sec ;
959
960 /*
961 * reset stats when cumulative delta exceeds one second.
962 */
963
964 if ((secs > 1) || (secs == 1 && (lticks[which].tv_usec > time.tv_usec))) {
965 if (lpackets[which] > icmplim) {
966 printf("%s from %d to %d packets per second\n",
967 bandlimittype[which],
968 lpackets[which],
969 icmplim
970 );
971 }
972 lticks[which].tv_sec = time.tv_sec;
973 lticks[which].tv_usec = time.tv_usec;
974 lpackets[which] = 0;
975 }
976
977 /*
978 * bump packet count
979 */
980
981 if (++lpackets[which] > icmplim) {
982 return(-1);
983 }
984 return(0);
985 }
986
987 #endif
988
989 #if __APPLE__
990
991 /*
992 * Non-privileged ICMP socket operations
993 * - send ICMP echo request
994 * - all ICMP
995 * - limited socket options
996 */
997
998 #include <netinet/ip_icmp.h>
999 #include <netinet/in_pcb.h>
1000
1001 extern struct domain inetdomain;
1002 extern u_long rip_sendspace;
1003 extern u_long rip_recvspace;
1004 extern struct inpcbinfo ripcbinfo;
1005
1006 int rip_abort(struct socket *);
1007 int rip_bind(struct socket *, struct sockaddr *, struct proc *);
1008 int rip_connect(struct socket *, struct sockaddr *, struct proc *);
1009 int rip_detach(struct socket *);
1010 int rip_disconnect(struct socket *);
1011 int rip_shutdown(struct socket *);
1012
1013 __private_extern__ int icmp_dgram_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p);
1014 __private_extern__ int icmp_dgram_attach(struct socket *so, int proto, struct proc *p);
1015 __private_extern__ int icmp_dgram_ctloutput(struct socket *so, struct sockopt *sopt);
1016
1017 __private_extern__ struct pr_usrreqs icmp_dgram_usrreqs = {
1018 rip_abort, pru_accept_notsupp, icmp_dgram_attach, rip_bind, rip_connect,
1019 pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
1020 pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
1021 pru_rcvoob_notsupp, icmp_dgram_send, pru_sense_null, rip_shutdown,
1022 in_setsockaddr, sosend, soreceive, pru_sopoll_notsupp
1023 };
1024
1025 /* Like rip_attach but without root privilege enforcement */
1026 __private_extern__ int
1027 icmp_dgram_attach(struct socket *so, __unused int proto, struct proc *p)
1028 {
1029 struct inpcb *inp;
1030 int error;
1031
1032 inp = sotoinpcb(so);
1033 if (inp)
1034 panic("icmp_dgram_attach");
1035
1036 error = soreserve(so, rip_sendspace, rip_recvspace);
1037 if (error)
1038 return error;
1039 error = in_pcballoc(so, &ripcbinfo, p);
1040 if (error)
1041 return error;
1042 inp = (struct inpcb *)so->so_pcb;
1043 inp->inp_vflag |= INP_IPV4;
1044 inp->inp_ip_p = IPPROTO_ICMP;
1045 inp->inp_ip_ttl = ip_defttl;
1046 return 0;
1047 }
1048
1049 /*
1050 * Raw IP socket option processing.
1051 */
1052 __private_extern__ int
1053 icmp_dgram_ctloutput(struct socket *so, struct sockopt *sopt)
1054 {
1055 int error;
1056
1057 if (sopt->sopt_level != IPPROTO_IP)
1058 return (EINVAL);
1059
1060 switch (sopt->sopt_name) {
1061 case IP_OPTIONS:
1062 case IP_HDRINCL:
1063 case IP_TOS:
1064 case IP_TTL:
1065 case IP_RECVOPTS:
1066 case IP_RECVRETOPTS:
1067 case IP_RECVDSTADDR:
1068 case IP_RETOPTS:
1069 case IP_MULTICAST_IF:
1070 case IP_MULTICAST_TTL:
1071 case IP_MULTICAST_LOOP:
1072 case IP_ADD_MEMBERSHIP:
1073 case IP_DROP_MEMBERSHIP:
1074 case IP_MULTICAST_VIF:
1075 case IP_PORTRANGE:
1076 case IP_RECVIF:
1077 case IP_IPSEC_POLICY:
1078 #if defined(NFAITH) && NFAITH > 0
1079 case IP_FAITH:
1080 #endif
1081 case IP_STRIPHDR:
1082 case IP_RECVTTL:
1083 case IP_BOUND_IF:
1084 #if CONFIG_FORCE_OUT_IFP
1085 case IP_FORCE_OUT_IFP:
1086 #endif
1087 error = rip_ctloutput(so, sopt);
1088 break;
1089
1090 default:
1091 error = EINVAL;
1092 break;
1093 }
1094
1095 return (error);
1096 }
1097
1098 __private_extern__ int
1099 icmp_dgram_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
1100 struct mbuf *control, struct proc *p)
1101 {
1102 struct ip *ip;
1103 struct inpcb *inp = sotoinpcb(so);
1104 int hlen;
1105 struct icmp *icp;
1106 struct in_ifaddr *ia = NULL;
1107 int icmplen;
1108
1109 if ((inp->inp_flags & INP_HDRINCL) != 0) {
1110 /*
1111 * This is not raw IP, we liberal only for fields TOS, id and TTL
1112 */
1113 ip = mtod(m, struct ip *);
1114
1115 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
1116 /* Some sanity checks */
1117 if (m->m_pkthdr.len < hlen + ICMP_MINLEN) {
1118 goto bad;
1119 }
1120 /* Only IPv4 */
1121 if (IP_VHL_V(ip->ip_vhl) != 4)
1122 goto bad;
1123 if (hlen < 20 || hlen > 40 || ip->ip_len != m->m_pkthdr.len)
1124 goto bad;
1125 /* Bogus fragments can tie up peer resources */
1126 if (ip->ip_off != 0)
1127 goto bad;
1128 /* Allow only ICMP even for user provided IP header */
1129 if (ip->ip_p != IPPROTO_ICMP)
1130 goto bad;
1131 /* To prevent spoofing, specified source address must be one of ours */
1132 if (ip->ip_src.s_addr != INADDR_ANY) {
1133 socket_unlock(so, 0);
1134 lck_mtx_lock(rt_mtx);
1135 if (TAILQ_EMPTY(&in_ifaddrhead)) {
1136 lck_mtx_unlock(rt_mtx);
1137 socket_lock(so, 0);
1138 goto bad;
1139 }
1140 TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
1141 if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_src.s_addr) {
1142 lck_mtx_unlock(rt_mtx);
1143 socket_lock(so, 0);
1144 goto ours;
1145 }
1146 }
1147 lck_mtx_unlock(rt_mtx);
1148 socket_lock(so, 0);
1149 goto bad;
1150 }
1151 ours:
1152 /* Do not trust we got a valid checksum */
1153 ip->ip_sum = 0;
1154
1155 icp = (struct icmp *)(((char *)m->m_data) + hlen);
1156 icmplen = m->m_pkthdr.len - hlen;
1157 } else {
1158 if ((icmplen = m->m_pkthdr.len) < ICMP_MINLEN) {
1159 goto bad;
1160 }
1161 icp = mtod(m, struct icmp *);
1162 }
1163 /*
1164 * Allow only to send request types with code 0
1165 */
1166 if (icp->icmp_code != 0)
1167 goto bad;
1168 switch (icp->icmp_type) {
1169 case ICMP_ECHO:
1170 break;
1171 case ICMP_TSTAMP:
1172 if (icmplen != 20)
1173 goto bad;
1174 break;
1175 case ICMP_MASKREQ:
1176 if (icmplen != 12)
1177 goto bad;
1178 break;
1179 default:
1180 goto bad;
1181 }
1182 return rip_send(so, flags, m, nam, control, p);
1183 bad:
1184 m_freem(m);
1185 return EINVAL;
1186 }
1187
1188 #endif /* __APPLE__ */