ip_icmp.c revision 1.39 1 /* $NetBSD: ip_icmp.c,v 1.39 2000/01/25 17:07:56 sommerfeld Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1998 The NetBSD Foundation, Inc.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to The NetBSD Foundation
37 * by Public Access Networks Corporation ("Panix"). It was developed under
38 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the NetBSD
51 * Foundation, Inc. and its contributors.
52 * 4. Neither the name of The NetBSD Foundation nor the names of its
53 * contributors may be used to endorse or promote products derived
54 * from this software without specific prior written permission.
55 *
56 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
57 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
58 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
59 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
60 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
61 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
62 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
63 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
64 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
65 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66 * POSSIBILITY OF SUCH DAMAGE.
67 */
68
69 /*
70 * Copyright (c) 1982, 1986, 1988, 1993
71 * The Regents of the University of California. All rights reserved.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions
75 * are met:
76 * 1. Redistributions of source code must retain the above copyright
77 * notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce the above copyright
79 * notice, this list of conditions and the following disclaimer in the
80 * documentation and/or other materials provided with the distribution.
81 * 3. All advertising materials mentioning features or use of this software
82 * must display the following acknowledgement:
83 * This product includes software developed by the University of
84 * California, Berkeley and its contributors.
85 * 4. Neither the name of the University nor the names of its contributors
86 * may be used to endorse or promote products derived from this software
87 * without specific prior written permission.
88 *
89 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
90 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
91 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
92 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
93 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
94 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
95 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
96 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
97 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
98 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
99 * SUCH DAMAGE.
100 *
101 * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
102 */
103
104 #include "opt_ipsec.h"
105
106 #include <sys/param.h>
107 #include <sys/systm.h>
108 #include <sys/malloc.h>
109 #include <sys/mbuf.h>
110 #include <sys/protosw.h>
111 #include <sys/socket.h>
112 #include <sys/time.h>
113 #include <sys/kernel.h>
114 #include <sys/proc.h>
115
116 #include <vm/vm.h>
117 #include <sys/sysctl.h>
118
119 #include <net/if.h>
120 #include <net/route.h>
121
122 #include <netinet/in.h>
123 #include <netinet/in_systm.h>
124 #include <netinet/in_var.h>
125 #include <netinet/ip.h>
126 #include <netinet/ip_icmp.h>
127 #include <netinet/ip_var.h>
128 #include <netinet/in_pcb.h>
129 #include <netinet/icmp_var.h>
130
131 #ifdef IPSEC
132 #include <netinet6/ipsec.h>
133 #include <netkey/key.h>
134 #include <netkey/key_debug.h>
135 #endif
136
137 #include <machine/stdarg.h>
138
139 /*
140 * ICMP routines: error generation, receive packet processing, and
141 * routines to turnaround packets back to the originator, and
142 * host table maintenance routines.
143 */
144
145 int icmpmaskrepl = 0;
146 #ifdef ICMPPRINTFS
147 int icmpprintfs = 0;
148 #endif
149
150 #if 0
151 static int ip_next_mtu __P((int, int));
152 #else
153 /*static*/ int ip_next_mtu __P((int, int));
154 #endif
155
156 extern struct protosw inetsw[];
157
158 static void icmp_mtudisc __P((struct icmp *));
159 static void icmp_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
160
161 /*
162 * Generate an error packet of type error
163 * in response to bad packet ip.
164 */
165 void
166 icmp_error(n, type, code, dest, destifp)
167 struct mbuf *n;
168 int type, code;
169 n_long dest;
170 struct ifnet *destifp;
171 {
172 register struct ip *oip = mtod(n, struct ip *), *nip;
173 register unsigned oiplen = oip->ip_hl << 2;
174 register struct icmp *icp;
175 register struct mbuf *m;
176 unsigned icmplen;
177
178 #ifdef ICMPPRINTFS
179 if (icmpprintfs)
180 printf("icmp_error(%x, %d, %d)\n", oip, type, code);
181 #endif
182 if (type != ICMP_REDIRECT)
183 icmpstat.icps_error++;
184 /*
185 * Don't send error if not the first fragment of message.
186 * Don't error if the old packet protocol was ICMP
187 * error message, only known informational types.
188 */
189 if (oip->ip_off &~ (IP_MF|IP_DF))
190 goto freeit;
191 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
192 n->m_len >= oiplen + ICMP_MINLEN &&
193 !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
194 icmpstat.icps_oldicmp++;
195 goto freeit;
196 }
197 /* Don't send error in response to a multicast or broadcast packet */
198 if (n->m_flags & (M_BCAST|M_MCAST))
199 goto freeit;
200 /*
201 * First, formulate icmp message
202 */
203 m = m_gethdr(M_DONTWAIT, MT_HEADER);
204 if (m == NULL)
205 goto freeit;
206 icmplen = oiplen + min(8, oip->ip_len - oiplen);
207 m->m_len = icmplen + ICMP_MINLEN;
208 MH_ALIGN(m, m->m_len);
209 icp = mtod(m, struct icmp *);
210 if ((u_int)type > ICMP_MAXTYPE)
211 panic("icmp_error");
212 icmpstat.icps_outhist[type]++;
213 icp->icmp_type = type;
214 if (type == ICMP_REDIRECT)
215 icp->icmp_gwaddr.s_addr = dest;
216 else {
217 icp->icmp_void = 0;
218 /*
219 * The following assignments assume an overlay with the
220 * zeroed icmp_void field.
221 */
222 if (type == ICMP_PARAMPROB) {
223 icp->icmp_pptr = code;
224 code = 0;
225 } else if (type == ICMP_UNREACH &&
226 code == ICMP_UNREACH_NEEDFRAG && destifp)
227 icp->icmp_nextmtu = htons(destifp->if_mtu);
228 }
229
230 HTONS(oip->ip_off);
231 HTONS(oip->ip_len);
232 icp->icmp_code = code;
233 bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
234 nip = &icp->icmp_ip;
235
236 /*
237 * Now, copy old ip header (without options)
238 * in front of icmp message.
239 */
240 if (m->m_data - sizeof(struct ip) < m->m_pktdat)
241 panic("icmp len");
242 m->m_data -= sizeof(struct ip);
243 m->m_len += sizeof(struct ip);
244 m->m_pkthdr.len = m->m_len;
245 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
246 nip = mtod(m, struct ip *);
247 bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
248 nip->ip_len = m->m_len;
249 nip->ip_hl = sizeof(struct ip) >> 2;
250 nip->ip_p = IPPROTO_ICMP;
251 nip->ip_tos = 0;
252 icmp_reflect(m);
253
254 freeit:
255 m_freem(n);
256 }
257
258 static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
259 static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
260 static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
261 struct sockaddr_in icmpmask = { 8, 0 };
262
263 /*
264 * Process a received ICMP message.
265 */
266 void
267 #if __STDC__
268 icmp_input(struct mbuf *m, ...)
269 #else
270 icmp_input(m, va_alist)
271 struct mbuf *m;
272 va_dcl
273 #endif
274 {
275 int proto;
276 register struct icmp *icp;
277 register struct ip *ip = mtod(m, struct ip *);
278 int icmplen;
279 register int i;
280 struct in_ifaddr *ia;
281 void *(*ctlfunc) __P((int, struct sockaddr *, void *));
282 int code;
283 extern u_char ip_protox[];
284 int hlen;
285 va_list ap;
286
287 va_start(ap, m);
288 hlen = va_arg(ap, int);
289 proto = va_arg(ap, int);
290 va_end(ap);
291
292 /*
293 * Locate icmp structure in mbuf, and check
294 * that not corrupted and of at least minimum length.
295 */
296 icmplen = ip->ip_len - hlen;
297 #ifdef ICMPPRINTFS
298 if (icmpprintfs)
299 printf("icmp_input from %x to %x, len %d\n",
300 ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr),
301 icmplen);
302 #endif
303 if (icmplen < ICMP_MINLEN) {
304 icmpstat.icps_tooshort++;
305 goto freeit;
306 }
307 i = hlen + min(icmplen, ICMP_ADVLENMIN);
308 if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
309 icmpstat.icps_tooshort++;
310 return;
311 }
312 ip = mtod(m, struct ip *);
313 m->m_len -= hlen;
314 m->m_data += hlen;
315 icp = mtod(m, struct icmp *);
316 if (in_cksum(m, icmplen)) {
317 icmpstat.icps_checksum++;
318 goto freeit;
319 }
320 m->m_len += hlen;
321 m->m_data -= hlen;
322
323 #ifdef ICMPPRINTFS
324 /*
325 * Message type specific processing.
326 */
327 if (icmpprintfs)
328 printf("icmp_input, type %d code %d\n", icp->icmp_type,
329 icp->icmp_code);
330 #endif
331 #ifdef IPSEC
332 /* drop it if it does not match the policy */
333 if (ipsec4_in_reject(m, NULL)) {
334 ipsecstat.in_polvio++;
335 goto freeit;
336 }
337 #endif
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_PROTOCOL:
349 case ICMP_UNREACH_PORT:
350 case ICMP_UNREACH_SRCFAIL:
351 code += PRC_UNREACH_NET;
352 break;
353
354 case ICMP_UNREACH_NEEDFRAG:
355 code = PRC_MSGSIZE;
356 break;
357
358 case ICMP_UNREACH_NET_UNKNOWN:
359 case ICMP_UNREACH_NET_PROHIB:
360 case ICMP_UNREACH_TOSNET:
361 code = PRC_UNREACH_NET;
362 break;
363
364 case ICMP_UNREACH_HOST_UNKNOWN:
365 case ICMP_UNREACH_ISOLATED:
366 case ICMP_UNREACH_HOST_PROHIB:
367 case ICMP_UNREACH_TOSHOST:
368 code = PRC_UNREACH_HOST;
369 break;
370
371 default:
372 goto badcode;
373 }
374 goto deliver;
375
376 case ICMP_TIMXCEED:
377 if (code > 1)
378 goto badcode;
379 code += PRC_TIMXCEED_INTRANS;
380 goto deliver;
381
382 case ICMP_PARAMPROB:
383 if (code > 1)
384 goto badcode;
385 code = PRC_PARAMPROB;
386 goto deliver;
387
388 case ICMP_SOURCEQUENCH:
389 if (code)
390 goto badcode;
391 code = PRC_QUENCH;
392 goto deliver;
393
394 deliver:
395 /*
396 * Problem with datagram; advise higher level routines.
397 */
398 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
399 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
400 icmpstat.icps_badlen++;
401 goto freeit;
402 }
403 if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr))
404 goto badcode;
405 NTOHS(icp->icmp_ip.ip_len);
406 #ifdef ICMPPRINTFS
407 if (icmpprintfs)
408 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
409 #endif
410 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
411 if (code == PRC_MSGSIZE && ip_mtudisc)
412 icmp_mtudisc(icp);
413 /*
414 * XXX if the packet contains [IPv4 AH TCP], we can't make a
415 * notification to TCP layer.
416 */
417 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
418 if (ctlfunc)
419 (*ctlfunc)(code, sintosa(&icmpsrc), &icp->icmp_ip);
420 break;
421
422 badcode:
423 icmpstat.icps_badcode++;
424 break;
425
426 case ICMP_ECHO:
427 icp->icmp_type = ICMP_ECHOREPLY;
428 goto reflect;
429
430 case ICMP_TSTAMP:
431 if (icmplen < ICMP_TSLEN) {
432 icmpstat.icps_badlen++;
433 break;
434 }
435 icp->icmp_type = ICMP_TSTAMPREPLY;
436 icp->icmp_rtime = iptime();
437 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
438 goto reflect;
439
440 case ICMP_MASKREQ:
441 if (icmpmaskrepl == 0)
442 break;
443 /*
444 * We are not able to respond with all ones broadcast
445 * unless we receive it over a point-to-point interface.
446 */
447 if (icmplen < ICMP_MASKLEN) {
448 icmpstat.icps_badlen++;
449 break;
450 }
451 if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
452 in_nullhost(ip->ip_dst))
453 icmpdst.sin_addr = ip->ip_src;
454 else
455 icmpdst.sin_addr = ip->ip_dst;
456 ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
457 m->m_pkthdr.rcvif));
458 if (ia == 0)
459 break;
460 icp->icmp_type = ICMP_MASKREPLY;
461 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
462 if (in_nullhost(ip->ip_src)) {
463 if (ia->ia_ifp->if_flags & IFF_BROADCAST)
464 ip->ip_src = ia->ia_broadaddr.sin_addr;
465 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
466 ip->ip_src = ia->ia_dstaddr.sin_addr;
467 }
468 reflect:
469 icmpstat.icps_reflect++;
470 icmpstat.icps_outhist[icp->icmp_type]++;
471 icmp_reflect(m);
472 return;
473
474 case ICMP_REDIRECT:
475 if (code > 3)
476 goto badcode;
477 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
478 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
479 icmpstat.icps_badlen++;
480 break;
481 }
482 /*
483 * Short circuit routing redirects to force
484 * immediate change in the kernel's routing
485 * tables. The message is also handed to anyone
486 * listening on a raw socket (e.g. the routing
487 * daemon for use in updating its tables).
488 */
489 icmpgw.sin_addr = ip->ip_src;
490 icmpdst.sin_addr = icp->icmp_gwaddr;
491 #ifdef ICMPPRINTFS
492 if (icmpprintfs)
493 printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst,
494 icp->icmp_gwaddr);
495 #endif
496 icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
497 rtredirect(sintosa(&icmpsrc), sintosa(&icmpdst),
498 (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
499 sintosa(&icmpgw), (struct rtentry **)0);
500 pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
501 #ifdef IPSEC
502 key_sa_routechange((struct sockaddr *)&icmpsrc);
503 #endif
504 break;
505
506 /*
507 * No kernel processing for the following;
508 * just fall through to send to raw listener.
509 */
510 case ICMP_ECHOREPLY:
511 case ICMP_ROUTERADVERT:
512 case ICMP_ROUTERSOLICIT:
513 case ICMP_TSTAMPREPLY:
514 case ICMP_IREQREPLY:
515 case ICMP_MASKREPLY:
516 default:
517 break;
518 }
519
520 raw:
521 rip_input(m, hlen, proto);
522 return;
523
524 freeit:
525 m_freem(m);
526 return;
527 }
528
529 /*
530 * Reflect the ip packet back to the source
531 */
532 void
533 icmp_reflect(m)
534 struct mbuf *m;
535 {
536 register struct ip *ip = mtod(m, struct ip *);
537 register struct in_ifaddr *ia;
538 register struct ifaddr *ifa;
539 struct sockaddr_in *sin = 0;
540 struct in_addr t;
541 struct mbuf *opts = 0;
542 int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
543
544 if (!in_canforward(ip->ip_src) &&
545 ((ip->ip_src.s_addr & IN_CLASSA_NET) !=
546 htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
547 m_freem(m); /* Bad return address */
548 goto done; /* ip_output() will check for broadcast */
549 }
550 t = ip->ip_dst;
551 ip->ip_dst = ip->ip_src;
552 /*
553 * If the incoming packet was addressed directly to us, use
554 * dst as the src for the reply. Otherwise (broadcast or
555 * anonymous), use an address which corresponds to the
556 * incoming interface, with a preference for the address which
557 * corresponds to the route to the destination of the ICMP.
558 */
559
560 /* Look for packet addressed to us */
561 INADDR_TO_IA(t, ia);
562
563 /* look for packet sent to broadcast address */
564 if (ia == NULL && (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) {
565 for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
566 ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
567 if (ifa->ifa_addr->sa_family != AF_INET)
568 continue;
569 if (in_hosteq(t,ifatoia(ifa)->ia_broadaddr.sin_addr)) {
570 ia = ifatoia(ifa);
571 break;
572 }
573 }
574 }
575
576 if (ia)
577 sin = &ia->ia_addr;
578
579 icmpdst.sin_addr = t;
580
581 /* if the packet is addressed somewhere else, compute the
582 source address for packets routed back to the source, and
583 use that, if it's an address on the interface which
584 received the packet */
585 if (sin == (struct sockaddr_in *)0) {
586 struct sockaddr_in sin_dst;
587 struct route icmproute;
588 int errornum;
589
590 sin_dst.sin_family = AF_INET;
591 sin_dst.sin_len = sizeof(struct sockaddr_in);
592 sin_dst.sin_addr = ip->ip_dst;
593 bzero(&icmproute, sizeof(icmproute));
594 errornum = 0;
595 sin = in_selectsrc(&sin_dst, &icmproute, 0, NULL, &errornum);
596 /* errornum is never used */
597 if (icmproute.ro_rt)
598 RTFREE(icmproute.ro_rt);
599 /* check to make sure sin is a source address on rcvif */
600 if (sin) {
601 t = sin->sin_addr;
602 sin = (struct sockaddr_in *)0;
603 INADDR_TO_IA(t, ia);
604 while (ia) {
605 if (ia->ia_ifp == m->m_pkthdr.rcvif) {
606 sin = &ia->ia_addr;
607 break;
608 }
609 NEXT_IA_WITH_SAME_ADDR(ia);
610 }
611 }
612 }
613
614 /* if it was not addressed to us, but the route doesn't go out
615 the source interface, pick an address on the source
616 interface. This can happen when routing is asymmetric, or
617 when the incoming packet was encapsulated */
618 if (sin == (struct sockaddr_in *)0) {
619 for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
620 ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
621 if (ifa->ifa_addr->sa_family != AF_INET)
622 continue;
623 sin = &(ifatoia(ifa)->ia_addr);
624 break;
625 }
626 }
627
628 /*
629 * The following happens if the packet was not addressed to us,
630 * and was received on an interface with no IP address:
631 * We find the first AF_INET address on the first non-loopback
632 * interface.
633 */
634 if (sin == (struct sockaddr_in *)0)
635 for (ia = in_ifaddr.tqh_first; ia != NULL;
636 ia = ia->ia_list.tqe_next) {
637 if (ia->ia_ifp->if_flags & IFF_LOOPBACK)
638 continue;
639 sin = &ia->ia_addr;
640 break;
641 }
642
643 /*
644 * If we still didn't find an address, punt. We could have an
645 * interface up (and receiving packets) with no address.
646 */
647 if (sin == (struct sockaddr_in *)0) {
648 m_freem(m);
649 goto done;
650 }
651
652 ip->ip_src = sin->sin_addr;
653 ip->ip_ttl = MAXTTL;
654
655 if (optlen > 0) {
656 register u_char *cp;
657 int opt, cnt;
658 u_int len;
659
660 /*
661 * Retrieve any source routing from the incoming packet;
662 * add on any record-route or timestamp options.
663 */
664 cp = (u_char *) (ip + 1);
665 if ((opts = ip_srcroute()) == 0 &&
666 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
667 opts->m_len = sizeof(struct in_addr);
668 *mtod(opts, struct in_addr *) = zeroin_addr;
669 }
670 if (opts) {
671 #ifdef ICMPPRINTFS
672 if (icmpprintfs)
673 printf("icmp_reflect optlen %d rt %d => ",
674 optlen, opts->m_len);
675 #endif
676 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
677 opt = cp[IPOPT_OPTVAL];
678 if (opt == IPOPT_EOL)
679 break;
680 if (opt == IPOPT_NOP)
681 len = 1;
682 else {
683 len = cp[IPOPT_OLEN];
684 if (len <= 0 || len > cnt)
685 break;
686 }
687 /*
688 * Should check for overflow, but it "can't happen"
689 */
690 if (opt == IPOPT_RR || opt == IPOPT_TS ||
691 opt == IPOPT_SECURITY) {
692 bcopy((caddr_t)cp,
693 mtod(opts, caddr_t) + opts->m_len, len);
694 opts->m_len += len;
695 }
696 }
697 /* Terminate & pad, if necessary */
698 if ((cnt = opts->m_len % 4) != 0) {
699 for (; cnt < 4; cnt++) {
700 *(mtod(opts, caddr_t) + opts->m_len) =
701 IPOPT_EOL;
702 opts->m_len++;
703 }
704 }
705 #ifdef ICMPPRINTFS
706 if (icmpprintfs)
707 printf("%d\n", opts->m_len);
708 #endif
709 }
710 /*
711 * Now strip out original options by copying rest of first
712 * mbuf's data back, and adjust the IP length.
713 */
714 ip->ip_len -= optlen;
715 ip->ip_hl = sizeof(struct ip) >> 2;
716 m->m_len -= optlen;
717 if (m->m_flags & M_PKTHDR)
718 m->m_pkthdr.len -= optlen;
719 optlen += sizeof(struct ip);
720 bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
721 (unsigned)(m->m_len - sizeof(struct ip)));
722 }
723 m->m_flags &= ~(M_BCAST|M_MCAST);
724 icmp_send(m, opts);
725 done:
726 if (opts)
727 (void)m_free(opts);
728 }
729
730 /*
731 * Send an icmp packet back to the ip level,
732 * after supplying a checksum.
733 */
734 void
735 icmp_send(m, opts)
736 register struct mbuf *m;
737 struct mbuf *opts;
738 {
739 register struct ip *ip = mtod(m, struct ip *);
740 register int hlen;
741 register struct icmp *icp;
742
743 hlen = ip->ip_hl << 2;
744 m->m_data += hlen;
745 m->m_len -= hlen;
746 icp = mtod(m, struct icmp *);
747 icp->icmp_cksum = 0;
748 icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
749 m->m_data -= hlen;
750 m->m_len += hlen;
751 #ifdef ICMPPRINTFS
752 if (icmpprintfs)
753 printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src);
754 #endif
755 #ifdef IPSEC
756 m->m_pkthdr.rcvif = NULL;
757 #endif /*IPSEC*/
758 (void) ip_output(m, opts, NULL, 0, NULL);
759 }
760
761 n_time
762 iptime()
763 {
764 struct timeval atv;
765 u_long t;
766
767 microtime(&atv);
768 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
769 return (htonl(t));
770 }
771
772 int
773 icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
774 int *name;
775 u_int namelen;
776 void *oldp;
777 size_t *oldlenp;
778 void *newp;
779 size_t newlen;
780 {
781
782 /* All sysctl names at this level are terminal. */
783 if (namelen != 1)
784 return (ENOTDIR);
785
786 switch (name[0]) {
787 case ICMPCTL_MASKREPL:
788 return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl));
789 default:
790 return (ENOPROTOOPT);
791 }
792 /* NOTREACHED */
793 }
794
795 static void
796 icmp_mtudisc(icp)
797 struct icmp *icp;
798 {
799 struct rtentry *rt;
800 struct sockaddr *dst = sintosa(&icmpsrc);
801 u_long mtu = ntohs(icp->icmp_nextmtu); /* Why a long? IPv6 */
802 int error;
803
804 /* Table of common MTUs: */
805
806 static u_long mtu_table[] = {65535, 65280, 32000, 17914, 9180, 8166,
807 4352, 2002, 1492, 1006, 508, 296, 68, 0};
808
809 rt = rtalloc1(dst, 1);
810 if (rt == 0)
811 return;
812
813 /* If we didn't get a host route, allocate one */
814
815 if ((rt->rt_flags & RTF_HOST) == 0) {
816 struct rtentry *nrt;
817
818 error = rtrequest((int) RTM_ADD, dst,
819 (struct sockaddr *) rt->rt_gateway,
820 (struct sockaddr *) 0,
821 RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC, &nrt);
822 if (error) {
823 rtfree(rt);
824 rtfree(nrt);
825 return;
826 }
827 nrt->rt_rmx = rt->rt_rmx;
828 rtfree(rt);
829 rt = nrt;
830 }
831 error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q);
832 if (error) {
833 rtfree(rt);
834 return;
835 }
836
837 if (mtu == 0) {
838 int i = 0;
839
840 mtu = icp->icmp_ip.ip_len; /* NTOHS happened in deliver: */
841 /* Some 4.2BSD-based routers incorrectly adjust the ip_len */
842 if (mtu > rt->rt_rmx.rmx_mtu && rt->rt_rmx.rmx_mtu != 0)
843 mtu -= (icp->icmp_ip.ip_hl << 2);
844
845 /* If we still can't guess a value, try the route */
846
847 if (mtu == 0) {
848 mtu = rt->rt_rmx.rmx_mtu;
849
850 /* If no route mtu, default to the interface mtu */
851
852 if (mtu == 0)
853 mtu = rt->rt_ifp->if_mtu;
854 }
855
856 for (i = 0; i < sizeof(mtu_table) / sizeof(mtu_table[0]); i++)
857 if (mtu > mtu_table[i]) {
858 mtu = mtu_table[i];
859 break;
860 }
861 }
862
863 /*
864 * XXX: RTV_MTU is overloaded, since the admin can set it
865 * to turn off PMTU for a route, and the kernel can
866 * set it to indicate a serious problem with PMTU
867 * on a route. We should be using a separate flag
868 * for the kernel to indicate this.
869 */
870
871 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
872 if (mtu < 296 || mtu > rt->rt_ifp->if_mtu)
873 rt->rt_rmx.rmx_locks |= RTV_MTU;
874 else if (rt->rt_rmx.rmx_mtu > mtu ||
875 rt->rt_rmx.rmx_mtu == 0)
876 rt->rt_rmx.rmx_mtu = mtu;
877 }
878
879 if (rt)
880 rtfree(rt);
881 }
882
883 /*
884 * Return the next larger or smaller MTU plateau (table from RFC 1191)
885 * given current value MTU. If DIR is less than zero, a larger plateau
886 * is returned; otherwise, a smaller value is returned.
887 */
888 int
889 ip_next_mtu(mtu, dir) /* XXX */
890 int mtu;
891 int dir;
892 {
893 static int mtutab[] = {
894 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296,
895 68, 0
896 };
897 int i;
898
899 for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) {
900 if (mtu >= mtutab[i])
901 break;
902 }
903
904 if (dir < 0) {
905 if (i == 0) {
906 return 0;
907 } else {
908 return mtutab[i - 1];
909 }
910 } else {
911 if (mtutab[i] == 0) {
912 return 0;
913 } else if(mtu > mtutab[i]) {
914 return mtutab[i];
915 } else {
916 return mtutab[i + 1];
917 }
918 }
919 }
920
921
922 static void
923 icmp_mtudisc_timeout(rt, r)
924 struct rtentry *rt;
925 struct rttimer *r;
926 {
927 if (rt == NULL)
928 panic("icmp_mtudisc_timeout: bad route to timeout");
929 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) ==
930 (RTF_DYNAMIC | RTF_HOST)) {
931 rtrequest((int) RTM_DELETE, (struct sockaddr *)rt_key(rt),
932 rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
933 } else {
934 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) {
935 rt->rt_rmx.rmx_mtu = 0;
936 }
937 }
938 }
939