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