FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_icmp.c
1 /*
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
34 * $FreeBSD$
35 */
36
37 #include "opt_ipsec.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/mbuf.h>
42 #include <sys/protosw.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 #include <sys/kernel.h>
46 #include <sys/sysctl.h>
47
48 #include <net/if.h>
49 #include <net/if_types.h>
50 #include <net/route.h>
51
52 #define _IP_VHL
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/in_var.h>
56 #include <netinet/ip.h>
57 #include <netinet/ip_icmp.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/icmp_var.h>
60
61 #ifdef IPSEC
62 #include <netinet6/ipsec.h>
63 #include <netkey/key.h>
64 #endif
65
66 #ifdef FAST_IPSEC
67 #include <netipsec/ipsec.h>
68 #include <netipsec/key.h>
69 #define IPSEC
70 #endif
71
72 /*
73 * ICMP routines: error generation, receive packet processing, and
74 * routines to turnaround packets back to the originator, and
75 * host table maintenance routines.
76 */
77
78 static struct icmpstat icmpstat;
79 SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RW,
80 &icmpstat, icmpstat, "");
81
82 static int icmpmaskrepl = 0;
83 SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
84 &icmpmaskrepl, 0, "");
85
86 static int drop_redirect = 0;
87 SYSCTL_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW,
88 &drop_redirect, 0, "");
89
90 static int log_redirect = 0;
91 SYSCTL_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW,
92 &log_redirect, 0, "");
93
94 #ifdef ICMP_BANDLIM
95
96 /*
97 * ICMP error-response bandwidth limiting sysctl. If not enabled, sysctl
98 * variable content is -1 and read-only.
99 */
100
101 static int icmplim = 200;
102 SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW,
103 &icmplim, 0, "");
104 #else
105
106 static int icmplim = -1;
107 SYSCTL_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RD,
108 &icmplim, 0, "");
109
110 #endif
111
112 static int icmplim_output = 1;
113 SYSCTL_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW,
114 &icmplim_output, 0, "");
115
116 /*
117 * ICMP broadcast echo sysctl
118 */
119
120 static int icmpbmcastecho = 0;
121 SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW,
122 &icmpbmcastecho, 0, "");
123
124
125 #ifdef ICMPPRINTFS
126 int icmpprintfs = 0;
127 #endif
128
129 static void icmp_reflect __P((struct mbuf *));
130 static void icmp_send __P((struct mbuf *, struct mbuf *, struct route *));
131 static int ip_next_mtu __P((int, int));
132
133 extern struct protosw inetsw[];
134
135 /*
136 * Generate an error packet of type error
137 * in response to bad packet ip.
138 */
139 void
140 icmp_error(n, type, code, dest, destifp)
141 struct mbuf *n;
142 int type, code;
143 n_long dest;
144 struct ifnet *destifp;
145 {
146 register struct ip *oip = mtod(n, struct ip *), *nip;
147 register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2;
148 register struct icmp *icp;
149 register struct mbuf *m;
150 unsigned icmplen;
151
152 #ifdef ICMPPRINTFS
153 if (icmpprintfs)
154 printf("icmp_error(%p, %x, %d)\n", oip, type, code);
155 #endif
156 if (type != ICMP_REDIRECT)
157 icmpstat.icps_error++;
158 /*
159 * Don't send error if the original packet was encrypted.
160 * Don't send error if not the first fragment of message.
161 * Don't error if the old packet protocol was ICMP
162 * error message, only known informational types.
163 */
164 if (n->m_flags & M_DECRYPTED)
165 goto freeit;
166 if (oip->ip_off &~ (IP_MF|IP_DF))
167 goto freeit;
168 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
169 n->m_len >= oiplen + ICMP_MINLEN &&
170 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
171 icmpstat.icps_oldicmp++;
172 goto freeit;
173 }
174 /* Don't send error in response to a multicast or broadcast packet */
175 if (n->m_flags & (M_BCAST|M_MCAST))
176 goto freeit;
177 /*
178 * First, formulate icmp message
179 */
180 m = m_gethdr(M_DONTWAIT, MT_HEADER);
181 if (m == NULL)
182 goto freeit;
183 icmplen = min(oiplen + 8, oip->ip_len);
184 if (icmplen < sizeof(struct ip))
185 panic("icmp_error: bad length");
186 m->m_len = icmplen + ICMP_MINLEN;
187 MH_ALIGN(m, m->m_len);
188 icp = mtod(m, struct icmp *);
189 if ((u_int)type > ICMP_MAXTYPE)
190 panic("icmp_error");
191 icmpstat.icps_outhist[type]++;
192 icp->icmp_type = type;
193 if (type == ICMP_REDIRECT)
194 icp->icmp_gwaddr.s_addr = dest;
195 else {
196 icp->icmp_void = 0;
197 /*
198 * The following assignments assume an overlay with the
199 * zeroed icmp_void field.
200 */
201 if (type == ICMP_PARAMPROB) {
202 icp->icmp_pptr = code;
203 code = 0;
204 } else if (type == ICMP_UNREACH &&
205 code == ICMP_UNREACH_NEEDFRAG && destifp) {
206 icp->icmp_nextmtu = htons(destifp->if_mtu);
207 }
208 }
209
210 icp->icmp_code = code;
211 m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
212 nip = &icp->icmp_ip;
213
214 /*
215 * Convert fields to network representation.
216 */
217 HTONS(nip->ip_len);
218 HTONS(nip->ip_off);
219
220 /*
221 * Now, copy old ip header (without options)
222 * in front of icmp message.
223 */
224 if (m->m_data - sizeof(struct ip) < m->m_pktdat)
225 panic("icmp len");
226 m->m_data -= sizeof(struct ip);
227 m->m_len += sizeof(struct ip);
228 m->m_pkthdr.len = m->m_len;
229 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
230 nip = mtod(m, struct ip *);
231 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
232 nip->ip_len = m->m_len;
233 nip->ip_vhl = IP_VHL_BORING;
234 nip->ip_p = IPPROTO_ICMP;
235 nip->ip_tos = 0;
236 icmp_reflect(m);
237
238 freeit:
239 m_freem(n);
240 }
241
242 static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
243 static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
244 static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
245
246 /*
247 * Process a received ICMP message.
248 */
249 void
250 icmp_input(m, off, proto)
251 register struct mbuf *m;
252 int off, proto;
253 {
254 int hlen = off;
255 register struct icmp *icp;
256 register struct ip *ip = mtod(m, struct ip *);
257 int icmplen = ip->ip_len;
258 register int i;
259 struct in_ifaddr *ia;
260 void (*ctlfunc) __P((int, struct sockaddr *, void *));
261 int code;
262
263 /*
264 * Locate icmp structure in mbuf, and check
265 * that not corrupted and of at least minimum length.
266 */
267 #ifdef ICMPPRINTFS
268 if (icmpprintfs) {
269 char buf[4 * sizeof "123"];
270 strcpy(buf, inet_ntoa(ip->ip_src));
271 printf("icmp_input from %s to %s, len %d\n",
272 buf, inet_ntoa(ip->ip_dst), icmplen);
273 }
274 #endif
275 if (icmplen < ICMP_MINLEN) {
276 icmpstat.icps_tooshort++;
277 goto freeit;
278 }
279 i = hlen + min(icmplen, ICMP_ADVLENMIN);
280 if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
281 icmpstat.icps_tooshort++;
282 return;
283 }
284 ip = mtod(m, struct ip *);
285 m->m_len -= hlen;
286 m->m_data += hlen;
287 icp = mtod(m, struct icmp *);
288 if (in_cksum(m, icmplen)) {
289 icmpstat.icps_checksum++;
290 goto freeit;
291 }
292 m->m_len += hlen;
293 m->m_data -= hlen;
294
295 if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
296 /*
297 * Deliver very specific ICMP type only.
298 */
299 switch (icp->icmp_type) {
300 case ICMP_UNREACH:
301 case ICMP_TIMXCEED:
302 break;
303 default:
304 goto freeit;
305 }
306 }
307
308 #ifdef ICMPPRINTFS
309 if (icmpprintfs)
310 printf("icmp_input, type %d code %d\n", icp->icmp_type,
311 icp->icmp_code);
312 #endif
313
314 /*
315 * Message type specific processing.
316 */
317 if (icp->icmp_type > ICMP_MAXTYPE)
318 goto raw;
319 icmpstat.icps_inhist[icp->icmp_type]++;
320 code = icp->icmp_code;
321 switch (icp->icmp_type) {
322
323 case ICMP_UNREACH:
324 switch (code) {
325 case ICMP_UNREACH_NET:
326 case ICMP_UNREACH_HOST:
327 case ICMP_UNREACH_SRCFAIL:
328 case ICMP_UNREACH_NET_UNKNOWN:
329 case ICMP_UNREACH_HOST_UNKNOWN:
330 case ICMP_UNREACH_ISOLATED:
331 case ICMP_UNREACH_TOSNET:
332 case ICMP_UNREACH_TOSHOST:
333 case ICMP_UNREACH_HOST_PRECEDENCE:
334 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
335 code = PRC_UNREACH_NET;
336 break;
337
338 case ICMP_UNREACH_NEEDFRAG:
339 code = PRC_MSGSIZE;
340 break;
341
342 /*
343 * RFC 1122, Sections 3.2.2.1 and 4.2.3.9.
344 * Treat subcodes 2,3 as immediate RST
345 */
346 case ICMP_UNREACH_PROTOCOL:
347 case ICMP_UNREACH_PORT:
348 code = PRC_UNREACH_PORT;
349 break;
350
351 case ICMP_UNREACH_NET_PROHIB:
352 case ICMP_UNREACH_HOST_PROHIB:
353 case ICMP_UNREACH_FILTER_PROHIB:
354 code = PRC_UNREACH_ADMIN_PROHIB;
355 break;
356
357 default:
358 goto badcode;
359 }
360 goto deliver;
361
362 case ICMP_TIMXCEED:
363 if (code > 1)
364 goto badcode;
365 code += PRC_TIMXCEED_INTRANS;
366 goto deliver;
367
368 case ICMP_PARAMPROB:
369 if (code > 1)
370 goto badcode;
371 code = PRC_PARAMPROB;
372 goto deliver;
373
374 case ICMP_SOURCEQUENCH:
375 if (code)
376 goto badcode;
377 code = PRC_QUENCH;
378 deliver:
379 /*
380 * Problem with datagram; advise higher level routines.
381 */
382 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
383 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
384 icmpstat.icps_badlen++;
385 goto freeit;
386 }
387 NTOHS(icp->icmp_ip.ip_len);
388 /* Discard ICMP's in response to multicast packets */
389 if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr)))
390 goto badcode;
391 #ifdef ICMPPRINTFS
392 if (icmpprintfs)
393 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
394 #endif
395 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
396 #if 1
397 /*
398 * MTU discovery:
399 * If we got a needfrag and there is a host route to the
400 * original destination, and the MTU is not locked, then
401 * set the MTU in the route to the suggested new value
402 * (if given) and then notify as usual. The ULPs will
403 * notice that the MTU has changed and adapt accordingly.
404 * If no new MTU was suggested, then we guess a new one
405 * less than the current value. If the new MTU is
406 * unreasonably small (arbitrarily set at 296), then
407 * we reset the MTU to the interface value and enable the
408 * lock bit, indicating that we are no longer doing MTU
409 * discovery.
410 */
411 if (code == PRC_MSGSIZE) {
412 struct rtentry *rt;
413 int mtu;
414
415 rt = rtalloc1((struct sockaddr *)&icmpsrc, 0,
416 RTF_CLONING | RTF_PRCLONING);
417 if (rt && (rt->rt_flags & RTF_HOST)
418 && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
419 mtu = ntohs(icp->icmp_nextmtu);
420 if (!mtu)
421 mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu,
422 1);
423 #ifdef DEBUG_MTUDISC
424 printf("MTU for %s reduced to %d\n",
425 inet_ntoa(icmpsrc.sin_addr), mtu);
426 #endif
427 if (mtu < 296) {
428 /* rt->rt_rmx.rmx_mtu =
429 rt->rt_ifp->if_mtu; */
430 rt->rt_rmx.rmx_locks |= RTV_MTU;
431 } else if (rt->rt_rmx.rmx_mtu > mtu) {
432 rt->rt_rmx.rmx_mtu = mtu;
433 }
434 }
435 if (rt)
436 RTFREE(rt);
437 }
438
439 #endif
440 /*
441 * XXX if the packet contains [IPv4 AH TCP], we can't make a
442 * notification to TCP layer.
443 */
444 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
445 if (ctlfunc)
446 (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
447 (void *)&icp->icmp_ip);
448 break;
449
450 badcode:
451 icmpstat.icps_badcode++;
452 break;
453
454 case ICMP_ECHO:
455 if (!icmpbmcastecho
456 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
457 icmpstat.icps_bmcastecho++;
458 break;
459 }
460 icp->icmp_type = ICMP_ECHOREPLY;
461 #ifdef ICMP_BANDLIM
462 if (badport_bandlim(BANDLIM_ICMP_ECHO) < 0)
463 goto freeit;
464 else
465 #endif
466 goto reflect;
467
468 case ICMP_TSTAMP:
469 if (!icmpbmcastecho
470 && (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
471 icmpstat.icps_bmcasttstamp++;
472 break;
473 }
474 if (icmplen < ICMP_TSLEN) {
475 icmpstat.icps_badlen++;
476 break;
477 }
478 icp->icmp_type = ICMP_TSTAMPREPLY;
479 icp->icmp_rtime = iptime();
480 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
481 #ifdef ICMP_BANDLIM
482 if (badport_bandlim(BANDLIM_ICMP_TSTAMP) < 0)
483 goto freeit;
484 else
485 #endif
486 goto reflect;
487
488 case ICMP_MASKREQ:
489 if (icmpmaskrepl == 0)
490 break;
491 /*
492 * We are not able to respond with all ones broadcast
493 * unless we receive it over a point-to-point interface.
494 */
495 if (icmplen < ICMP_MASKLEN)
496 break;
497 switch (ip->ip_dst.s_addr) {
498
499 case INADDR_BROADCAST:
500 case INADDR_ANY:
501 icmpdst.sin_addr = ip->ip_src;
502 break;
503
504 default:
505 icmpdst.sin_addr = ip->ip_dst;
506 }
507 ia = (struct in_ifaddr *)ifaof_ifpforaddr(
508 (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
509 if (ia == 0)
510 break;
511 if (ia->ia_ifp == 0)
512 break;
513 icp->icmp_type = ICMP_MASKREPLY;
514 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
515 if (ip->ip_src.s_addr == 0) {
516 if (ia->ia_ifp->if_flags & IFF_BROADCAST)
517 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
518 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
519 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
520 }
521 reflect:
522 ip->ip_len += hlen; /* since ip_input deducts this */
523 icmpstat.icps_reflect++;
524 icmpstat.icps_outhist[icp->icmp_type]++;
525 icmp_reflect(m);
526 return;
527
528 case ICMP_REDIRECT:
529 if (log_redirect) {
530 u_long src, dst, gw;
531
532 src = ntohl(ip->ip_src.s_addr);
533 dst = ntohl(icp->icmp_ip.ip_dst.s_addr);
534 gw = ntohl(icp->icmp_gwaddr.s_addr);
535 printf("icmp redirect from %d.%d.%d.%d: "
536 "%d.%d.%d.%d => %d.%d.%d.%d\n",
537 (int)(src >> 24), (int)((src >> 16) & 0xff),
538 (int)((src >> 8) & 0xff), (int)(src & 0xff),
539 (int)(dst >> 24), (int)((dst >> 16) & 0xff),
540 (int)((dst >> 8) & 0xff), (int)(dst & 0xff),
541 (int)(gw >> 24), (int)((gw >> 16) & 0xff),
542 (int)((gw >> 8) & 0xff), (int)(gw & 0xff));
543 }
544 if (drop_redirect)
545 break;
546 if (code > 3)
547 goto badcode;
548 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
549 IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
550 icmpstat.icps_badlen++;
551 break;
552 }
553 /*
554 * Short circuit routing redirects to force
555 * immediate change in the kernel's routing
556 * tables. The message is also handed to anyone
557 * listening on a raw socket (e.g. the routing
558 * daemon for use in updating its tables).
559 */
560 icmpgw.sin_addr = ip->ip_src;
561 icmpdst.sin_addr = icp->icmp_gwaddr;
562 #ifdef ICMPPRINTFS
563 if (icmpprintfs) {
564 char buf[4 * sizeof "123"];
565 strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst));
566
567 printf("redirect dst %s to %s\n",
568 buf, inet_ntoa(icp->icmp_gwaddr));
569 }
570 #endif
571 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
572 rtredirect((struct sockaddr *)&icmpsrc,
573 (struct sockaddr *)&icmpdst,
574 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
575 (struct sockaddr *)&icmpgw, (struct rtentry **)0);
576 pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
577 #ifdef IPSEC
578 key_sa_routechange((struct sockaddr *)&icmpsrc);
579 #endif
580 break;
581
582 /*
583 * No kernel processing for the following;
584 * just fall through to send to raw listener.
585 */
586 case ICMP_ECHOREPLY:
587 case ICMP_ROUTERADVERT:
588 case ICMP_ROUTERSOLICIT:
589 case ICMP_TSTAMPREPLY:
590 case ICMP_IREQREPLY:
591 case ICMP_MASKREPLY:
592 default:
593 break;
594 }
595
596 raw:
597 rip_input(m, off, proto);
598 return;
599
600 freeit:
601 m_freem(m);
602 }
603
604 /*
605 * Reflect the ip packet back to the source
606 */
607 static void
608 icmp_reflect(m)
609 struct mbuf *m;
610 {
611 struct ip *ip = mtod(m, struct ip *);
612 struct ifaddr *ifa;
613 struct in_ifaddr *ia;
614 struct in_addr t;
615 struct mbuf *opts = 0;
616 int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip);
617 struct route *ro = NULL, rt;
618
619 if (!in_canforward(ip->ip_src) &&
620 ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
621 (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
622 m_freem(m); /* Bad return address */
623 icmpstat.icps_badaddr++;
624 goto done; /* Ip_output() will check for broadcast */
625 }
626 t = ip->ip_dst;
627 ip->ip_dst = ip->ip_src;
628 ro = &rt;
629 bzero(ro, sizeof(*ro));
630 /*
631 * If the incoming packet was addressed directly to us,
632 * use dst as the src for the reply. Otherwise (broadcast
633 * or anonymous), use the address which corresponds
634 * to the incoming interface.
635 */
636 LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash)
637 if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
638 goto match;
639 if (m->m_pkthdr.rcvif != NULL &&
640 m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
641 TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrhead, ifa_link) {
642 if (ifa->ifa_addr->sa_family != AF_INET)
643 continue;
644 ia = ifatoia(ifa);
645 if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
646 t.s_addr)
647 goto match;
648 }
649 }
650 ia = ip_rtaddr(ip->ip_dst, ro);
651 /* We need a route to do anything useful. */
652 if (ia == NULL) {
653 m_freem(m);
654 icmpstat.icps_noroute++;
655 goto done;
656 }
657 match:
658 t = IA_SIN(ia)->sin_addr;
659 ip->ip_src = t;
660 ip->ip_ttl = ip_defttl;
661
662 if (optlen > 0) {
663 register u_char *cp;
664 int opt, cnt;
665 u_int len;
666
667 /*
668 * Retrieve any source routing from the incoming packet;
669 * add on any record-route or timestamp options.
670 */
671 cp = (u_char *) (ip + 1);
672 if ((opts = ip_srcroute()) == 0 &&
673 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
674 opts->m_len = sizeof(struct in_addr);
675 mtod(opts, struct in_addr *)->s_addr = 0;
676 }
677 if (opts) {
678 #ifdef ICMPPRINTFS
679 if (icmpprintfs)
680 printf("icmp_reflect optlen %d rt %d => ",
681 optlen, opts->m_len);
682 #endif
683 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
684 opt = cp[IPOPT_OPTVAL];
685 if (opt == IPOPT_EOL)
686 break;
687 if (opt == IPOPT_NOP)
688 len = 1;
689 else {
690 if (cnt < IPOPT_OLEN + sizeof(*cp))
691 break;
692 len = cp[IPOPT_OLEN];
693 if (len < IPOPT_OLEN + sizeof(*cp) ||
694 len > cnt)
695 break;
696 }
697 /*
698 * Should check for overflow, but it "can't happen"
699 */
700 if (opt == IPOPT_RR || opt == IPOPT_TS ||
701 opt == IPOPT_SECURITY) {
702 bcopy((caddr_t)cp,
703 mtod(opts, caddr_t) + opts->m_len, len);
704 opts->m_len += len;
705 }
706 }
707 /* Terminate & pad, if necessary */
708 cnt = opts->m_len % 4;
709 if (cnt) {
710 for (; cnt < 4; cnt++) {
711 *(mtod(opts, caddr_t) + opts->m_len) =
712 IPOPT_EOL;
713 opts->m_len++;
714 }
715 }
716 #ifdef ICMPPRINTFS
717 if (icmpprintfs)
718 printf("%d\n", opts->m_len);
719 #endif
720 }
721 /*
722 * Now strip out original options by copying rest of first
723 * mbuf's data back, and adjust the IP length.
724 */
725 ip->ip_len -= optlen;
726 ip->ip_vhl = IP_VHL_BORING;
727 m->m_len -= optlen;
728 if (m->m_flags & M_PKTHDR)
729 m->m_pkthdr.len -= optlen;
730 optlen += sizeof(struct ip);
731 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
732 (unsigned)(m->m_len - sizeof(struct ip)));
733 }
734 m->m_flags &= ~(M_BCAST|M_MCAST);
735 icmp_send(m, opts, ro);
736 done:
737 if (opts)
738 (void)m_free(opts);
739 if (ro && ro->ro_rt)
740 RTFREE(ro->ro_rt);
741 }
742
743 /*
744 * Send an icmp packet back to the ip level,
745 * after supplying a checksum.
746 */
747 static void
748 icmp_send(m, opts, rt)
749 register struct mbuf *m;
750 struct mbuf *opts;
751 struct route *rt;
752 {
753 register struct ip *ip = mtod(m, struct ip *);
754 register int hlen;
755 register struct icmp *icp;
756
757 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
758 m->m_data += hlen;
759 m->m_len -= hlen;
760 icp = mtod(m, struct icmp *);
761 icp->icmp_cksum = 0;
762 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
763 m->m_data -= hlen;
764 m->m_len += hlen;
765 m->m_pkthdr.rcvif = (struct ifnet *)0;
766 #ifdef ICMPPRINTFS
767 if (icmpprintfs) {
768 char buf[4 * sizeof "123"];
769 strcpy(buf, inet_ntoa(ip->ip_dst));
770 printf("icmp_send dst %s src %s\n",
771 buf, inet_ntoa(ip->ip_src));
772 }
773 #endif
774 (void) ip_output(m, opts, rt, 0, NULL, NULL);
775 }
776
777 n_time
778 iptime()
779 {
780 struct timeval atv;
781 u_long t;
782
783 getmicrotime(&atv);
784 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
785 return (htonl(t));
786 }
787
788 #if 1
789 /*
790 * Return the next larger or smaller MTU plateau (table from RFC 1191)
791 * given current value MTU. If DIR is less than zero, a larger plateau
792 * is returned; otherwise, a smaller value is returned.
793 */
794 static int
795 ip_next_mtu(mtu, dir)
796 int mtu;
797 int dir;
798 {
799 static int mtutab[] = {
800 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296,
801 68, 0
802 };
803 int i;
804
805 for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) {
806 if (mtu >= mtutab[i])
807 break;
808 }
809
810 if (dir < 0) {
811 if (i == 0) {
812 return 0;
813 } else {
814 return mtutab[i - 1];
815 }
816 } else {
817 if (mtutab[i] == 0) {
818 return 0;
819 } else if(mtu > mtutab[i]) {
820 return mtutab[i];
821 } else {
822 return mtutab[i + 1];
823 }
824 }
825 }
826 #endif
827
828 #ifdef ICMP_BANDLIM
829
830 /*
831 * badport_bandlim() - check for ICMP bandwidth limit
832 *
833 * Return 0 if it is ok to send an ICMP error response, -1 if we have
834 * hit our bandwidth limit and it is not ok.
835 *
836 * If icmplim is <= 0, the feature is disabled and 0 is returned.
837 *
838 * For now we separate the TCP and UDP subsystems w/ different 'which'
839 * values. We may eventually remove this separation (and simplify the
840 * code further).
841 *
842 * Note that the printing of the error message is delayed so we can
843 * properly print the icmp error rate that the system was trying to do
844 * (i.e. 22000/100 pps, etc...). This can cause long delays in printing
845 * the 'final' error, but it doesn't make sense to solve the printing
846 * delay with more complex code.
847 */
848
849 int
850 badport_bandlim(int which)
851 {
852 static int lticks[BANDLIM_MAX + 1];
853 static int lpackets[BANDLIM_MAX + 1];
854 int dticks;
855 const char *bandlimittype[] = {
856 "Limiting icmp unreach response",
857 "Limiting icmp ping response",
858 "Limiting icmp tstamp response",
859 "Limiting closed port RST response",
860 "Limiting open port RST response"
861 };
862
863 /*
864 * Return ok status if feature disabled or argument out of
865 * ranage.
866 */
867
868 if (icmplim <= 0 || which > BANDLIM_MAX || which < 0)
869 return(0);
870 dticks = ticks - lticks[which];
871
872 /*
873 * reset stats when cumulative dt exceeds one second.
874 */
875
876 if ((unsigned int)dticks > hz) {
877 if (lpackets[which] > icmplim && icmplim_output) {
878 printf("%s from %d to %d packets per second\n",
879 bandlimittype[which],
880 lpackets[which],
881 icmplim
882 );
883 }
884 lticks[which] = ticks;
885 lpackets[which] = 0;
886 }
887
888 /*
889 * bump packet count
890 */
891
892 if (++lpackets[which] > icmplim) {
893 return(-1);
894 }
895 return(0);
896 }
897
898 #endif
899
900
Cache object: ab6917a842aa7b3425daac76891b2cca
|