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