1 /* $OpenBSD: ip_icmp.c,v 1.123 2014/07/13 13:57:56 mpi Exp $ */ 2 /* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 33 * 34 * NRL grants permission for redistribution and use in source and binary 35 * forms, with or without modification, of the software and documentation 36 * created at NRL provided that the following conditions are met: 37 * 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgements: 45 * This product includes software developed by the University of 46 * California, Berkeley and its contributors. 47 * This product includes software developed at the Information 48 * Technology Division, US Naval Research Laboratory. 49 * 4. Neither the name of the NRL nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS 54 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 56 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR 57 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 59 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 * 65 * The views and conclusions contained in the software and documentation 66 * are those of the authors and should not be interpreted as representing 67 * official policies, either expressed or implied, of the US Naval 68 * Research Laboratory (NRL). 69 */ 70 71 #include "carp.h" 72 #include "pf.h" 73 74 #include <sys/param.h> 75 #include <sys/systm.h> 76 #include <sys/mbuf.h> 77 #include <sys/protosw.h> 78 #include <sys/socket.h> 79 #include <sys/proc.h> 80 #include <sys/sysctl.h> 81 82 #include <net/if.h> 83 #include <net/route.h> 84 85 #include <netinet/in.h> 86 #include <netinet/in_systm.h> 87 #include <netinet/in_var.h> 88 #include <netinet/ip.h> 89 #include <netinet/ip_icmp.h> 90 #include <netinet/ip_var.h> 91 #include <netinet/icmp_var.h> 92 93 #if NCARP > 0 94 #include <net/if_types.h> 95 #include <netinet/ip_carp.h> 96 #endif 97 98 #if NPF > 0 99 #include <net/pfvar.h> 100 #endif 101 102 /* 103 * ICMP routines: error generation, receive packet processing, and 104 * routines to turnaround packets back to the originator, and 105 * host table maintenance routines. 106 */ 107 108 #ifdef ICMPPRINTFS 109 int icmpprintfs = 0; /* Settable from ddb */ 110 #endif 111 112 /* values controllable via sysctl */ 113 int icmpmaskrepl = 0; 114 int icmpbmcastecho = 0; 115 int icmptstamprepl = 1; 116 int icmperrppslim = 100; 117 int icmp_rediraccept = 0; 118 int icmp_redirtimeout = 10 * 60; 119 120 static int icmperrpps_count = 0; 121 static struct timeval icmperrppslim_last; 122 123 static struct rttimer_queue *icmp_redirect_timeout_q = NULL; 124 struct icmpstat icmpstat; 125 126 int *icmpctl_vars[ICMPCTL_MAXID] = ICMPCTL_VARS; 127 128 void icmp_mtudisc_timeout(struct rtentry *, struct rttimer *); 129 int icmp_ratelimit(const struct in_addr *, const int, const int); 130 void icmp_redirect_timeout(struct rtentry *, struct rttimer *); 131 132 void 133 icmp_init(void) 134 { 135 /* 136 * This is only useful if the user initializes redirtimeout to 137 * something other than zero. 138 */ 139 if (icmp_redirtimeout != 0) { 140 icmp_redirect_timeout_q = 141 rt_timer_queue_create(icmp_redirtimeout); 142 } 143 } 144 145 struct mbuf * 146 icmp_do_error(struct mbuf *n, int type, int code, u_int32_t dest, int destmtu) 147 { 148 struct ip *oip = mtod(n, struct ip *), *nip; 149 unsigned oiplen = oip->ip_hl << 2; 150 struct icmp *icp; 151 struct mbuf *m; 152 unsigned icmplen, mblen; 153 154 #ifdef ICMPPRINTFS 155 if (icmpprintfs) 156 printf("icmp_error(%x, %d, %d)\n", oip, type, code); 157 #endif 158 if (type != ICMP_REDIRECT) 159 icmpstat.icps_error++; 160 /* 161 * Don't send error if not the first fragment of message. 162 * Don't error if the old packet protocol was ICMP 163 * error message, only known informational types. 164 */ 165 if (oip->ip_off & htons(IP_OFFMASK)) 166 goto freeit; 167 if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 168 n->m_len >= oiplen + ICMP_MINLEN && 169 !ICMP_INFOTYPE(((struct icmp *) 170 ((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 /* 179 * First, do a rate limitation check. 180 */ 181 if (icmp_ratelimit(&oip->ip_src, type, code)) { 182 icmpstat.icps_toofreq++; 183 goto freeit; 184 } 185 186 /* 187 * Now, formulate icmp message 188 */ 189 icmplen = oiplen + min(8, ntohs(oip->ip_len)); 190 /* 191 * Defend against mbuf chains shorter than oip->ip_len: 192 */ 193 mblen = 0; 194 for (m = n; m && (mblen < icmplen); m = m->m_next) 195 mblen += m->m_len; 196 icmplen = min(mblen, icmplen); 197 198 /* 199 * As we are not required to return everything we have, 200 * we return whatever we can return at ease. 201 * 202 * Note that ICMP datagrams longer than 576 octets are out of spec 203 * according to RFC1812; 204 */ 205 206 KASSERT(ICMP_MINLEN <= MCLBYTES); 207 208 if (icmplen + ICMP_MINLEN > MCLBYTES) 209 icmplen = MCLBYTES - ICMP_MINLEN - sizeof (struct ip); 210 211 m = m_gethdr(M_DONTWAIT, MT_HEADER); 212 if (m && (sizeof (struct ip) + icmplen + ICMP_MINLEN > MHLEN)) { 213 MCLGET(m, M_DONTWAIT); 214 if ((m->m_flags & M_EXT) == 0) { 215 m_freem(m); 216 m = NULL; 217 } 218 } 219 if (m == NULL) 220 goto freeit; 221 /* keep in same rtable */ 222 m->m_pkthdr.ph_rtableid = n->m_pkthdr.ph_rtableid; 223 m->m_len = icmplen + ICMP_MINLEN; 224 if ((m->m_flags & M_EXT) == 0) 225 MH_ALIGN(m, m->m_len); 226 icp = mtod(m, struct icmp *); 227 if ((u_int)type > ICMP_MAXTYPE) 228 panic("icmp_error"); 229 icmpstat.icps_outhist[type]++; 230 icp->icmp_type = type; 231 if (type == ICMP_REDIRECT) 232 icp->icmp_gwaddr.s_addr = dest; 233 else { 234 icp->icmp_void = 0; 235 /* 236 * The following assignments assume an overlay with the 237 * zeroed icmp_void field. 238 */ 239 if (type == ICMP_PARAMPROB) { 240 icp->icmp_pptr = code; 241 code = 0; 242 } else if (type == ICMP_UNREACH && 243 code == ICMP_UNREACH_NEEDFRAG && destmtu) 244 icp->icmp_nextmtu = htons(destmtu); 245 } 246 247 icp->icmp_code = code; 248 m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip); 249 250 /* 251 * Now, copy old ip header (without options) 252 * in front of icmp message. 253 */ 254 if ((m->m_flags & M_EXT) == 0 && 255 m->m_data - sizeof(struct ip) < m->m_pktdat) 256 panic("icmp len"); 257 m->m_data -= sizeof(struct ip); 258 m->m_len += sizeof(struct ip); 259 m->m_pkthdr.len = m->m_len; 260 m->m_pkthdr.rcvif = n->m_pkthdr.rcvif; 261 nip = mtod(m, struct ip *); 262 /* ip_v set in ip_output */ 263 nip->ip_hl = sizeof(struct ip) >> 2; 264 nip->ip_tos = 0; 265 nip->ip_len = htons(m->m_len); 266 /* ip_id set in ip_output */ 267 nip->ip_off = 0; 268 /* ip_ttl set in icmp_reflect */ 269 nip->ip_p = IPPROTO_ICMP; 270 nip->ip_src = oip->ip_src; 271 nip->ip_dst = oip->ip_dst; 272 273 /* move PF_GENERATED to new packet, if existent XXX preserve more? */ 274 if (n->m_pkthdr.pf.flags & PF_TAG_GENERATED) 275 m->m_pkthdr.pf.flags |= PF_TAG_GENERATED; 276 277 m_freem(n); 278 return (m); 279 280 freeit: 281 m_freem(n); 282 return (NULL); 283 } 284 285 /* 286 * Generate an error packet of type error 287 * in response to bad packet ip. 288 * 289 * The ip packet inside has ip_off and ip_len in host byte order. 290 */ 291 void 292 icmp_error(struct mbuf *n, int type, int code, u_int32_t dest, int destmtu) 293 { 294 struct mbuf *m; 295 296 m = icmp_do_error(n, type, code, dest, destmtu); 297 if (m != NULL) 298 if (!icmp_reflect(m, NULL, NULL)) 299 icmp_send(m, NULL); 300 } 301 302 /* 303 * Process a received ICMP message. 304 */ 305 void 306 icmp_input(struct mbuf *m, ...) 307 { 308 struct ifnet *ifp; 309 struct icmp *icp; 310 struct ip *ip = mtod(m, struct ip *); 311 struct sockaddr_in sin; 312 int icmplen, i, code, hlen; 313 struct in_ifaddr *ia; 314 void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); 315 va_list ap; 316 struct mbuf *opts; 317 318 va_start(ap, m); 319 hlen = va_arg(ap, int); 320 va_end(ap); 321 322 ifp = m->m_pkthdr.rcvif; 323 324 /* 325 * Locate icmp structure in mbuf, and check 326 * that not corrupted and of at least minimum length. 327 */ 328 icmplen = ntohs(ip->ip_len) - hlen; 329 #ifdef ICMPPRINTFS 330 if (icmpprintfs) { 331 char dst[INET_ADDRSTRLEN], src[INET_ADDRSTRLEN]; 332 333 inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); 334 inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); 335 336 printf("icmp_input from %s to %s, len %d\n", src, dst, icmplen); 337 } 338 #endif 339 if (icmplen < ICMP_MINLEN) { 340 icmpstat.icps_tooshort++; 341 goto freeit; 342 } 343 i = hlen + min(icmplen, ICMP_ADVLENMIN); 344 if (m->m_len < i && (m = m_pullup(m, i)) == NULL) { 345 icmpstat.icps_tooshort++; 346 return; 347 } 348 ip = mtod(m, struct ip *); 349 if (in4_cksum(m, 0, hlen, icmplen)) { 350 icmpstat.icps_checksum++; 351 goto freeit; 352 } 353 354 icp = (struct icmp *)(mtod(m, caddr_t) + hlen); 355 #ifdef ICMPPRINTFS 356 /* 357 * Message type specific processing. 358 */ 359 if (icmpprintfs) 360 printf("icmp_input, type %d code %d\n", icp->icmp_type, 361 icp->icmp_code); 362 #endif 363 if (icp->icmp_type > ICMP_MAXTYPE) 364 goto raw; 365 #if NPF > 0 366 if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) { 367 switch (icp->icmp_type) { 368 /* 369 * These ICMP types map to other connections. They must be 370 * delivered to pr_ctlinput() also for diverted connections. 371 */ 372 case ICMP_UNREACH: 373 case ICMP_TIMXCEED: 374 case ICMP_PARAMPROB: 375 case ICMP_SOURCEQUENCH: 376 break; 377 /* 378 * Although pf_icmp_mapping() considers redirects belonging 379 * to a diverted connection, we must process it here anyway. 380 */ 381 case ICMP_REDIRECT: 382 break; 383 default: 384 goto raw; 385 } 386 } 387 #endif /* NPF */ 388 icmpstat.icps_inhist[icp->icmp_type]++; 389 code = icp->icmp_code; 390 switch (icp->icmp_type) { 391 392 case ICMP_UNREACH: 393 switch (code) { 394 case ICMP_UNREACH_NET: 395 case ICMP_UNREACH_HOST: 396 case ICMP_UNREACH_PROTOCOL: 397 case ICMP_UNREACH_PORT: 398 case ICMP_UNREACH_SRCFAIL: 399 code += PRC_UNREACH_NET; 400 break; 401 402 case ICMP_UNREACH_NEEDFRAG: 403 code = PRC_MSGSIZE; 404 break; 405 406 case ICMP_UNREACH_NET_UNKNOWN: 407 case ICMP_UNREACH_NET_PROHIB: 408 case ICMP_UNREACH_TOSNET: 409 code = PRC_UNREACH_NET; 410 break; 411 412 case ICMP_UNREACH_HOST_UNKNOWN: 413 case ICMP_UNREACH_ISOLATED: 414 case ICMP_UNREACH_HOST_PROHIB: 415 case ICMP_UNREACH_TOSHOST: 416 case ICMP_UNREACH_FILTER_PROHIB: 417 case ICMP_UNREACH_HOST_PRECEDENCE: 418 case ICMP_UNREACH_PRECEDENCE_CUTOFF: 419 code = PRC_UNREACH_HOST; 420 break; 421 422 default: 423 goto badcode; 424 } 425 goto deliver; 426 427 case ICMP_TIMXCEED: 428 if (code > 1) 429 goto badcode; 430 code += PRC_TIMXCEED_INTRANS; 431 goto deliver; 432 433 case ICMP_PARAMPROB: 434 if (code > 1) 435 goto badcode; 436 code = PRC_PARAMPROB; 437 goto deliver; 438 439 case ICMP_SOURCEQUENCH: 440 if (code) 441 goto badcode; 442 code = PRC_QUENCH; 443 deliver: 444 /* Free packet atttributes */ 445 if (m->m_flags & M_PKTHDR) 446 m_tag_delete_chain(m); 447 448 /* 449 * Problem with datagram; advise higher level routines. 450 */ 451 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 452 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { 453 icmpstat.icps_badlen++; 454 goto freeit; 455 } 456 if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr)) 457 goto badcode; 458 #ifdef INET6 459 /* Get more contiguous data for a v6 in v4 ICMP message. */ 460 if (icp->icmp_ip.ip_p == IPPROTO_IPV6) { 461 if (icmplen < ICMP_V6ADVLENMIN || 462 icmplen < ICMP_V6ADVLEN(icp)) { 463 icmpstat.icps_badlen++; 464 goto freeit; 465 } else { 466 if ((m = m_pullup(m, (ip->ip_hl << 2) + 467 ICMP_V6ADVLEN(icp))) == NULL) { 468 icmpstat.icps_tooshort++; 469 return; 470 } 471 ip = mtod(m, struct ip *); 472 icp = (struct icmp *) 473 (m->m_data + (ip->ip_hl << 2)); 474 } 475 } 476 #endif /* INET6 */ 477 #ifdef ICMPPRINTFS 478 if (icmpprintfs) 479 printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); 480 #endif 481 memset(&sin, 0, sizeof(sin)); 482 sin.sin_family = AF_INET; 483 sin.sin_len = sizeof(struct sockaddr_in); 484 sin.sin_addr = icp->icmp_ip.ip_dst; 485 #if NCARP > 0 486 if (ifp->if_type == IFT_CARP && 487 carp_lsdrop(m, AF_INET, &sin.sin_addr.s_addr, 488 &ip->ip_dst.s_addr)) 489 goto freeit; 490 #endif 491 /* 492 * XXX if the packet contains [IPv4 AH TCP], we can't make a 493 * notification to TCP layer. 494 */ 495 ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput; 496 if (ctlfunc) 497 (*ctlfunc)(code, sintosa(&sin), m->m_pkthdr.ph_rtableid, 498 &icp->icmp_ip); 499 break; 500 501 badcode: 502 icmpstat.icps_badcode++; 503 break; 504 505 case ICMP_ECHO: 506 if (!icmpbmcastecho && 507 (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 508 icmpstat.icps_bmcastecho++; 509 break; 510 } 511 icp->icmp_type = ICMP_ECHOREPLY; 512 goto reflect; 513 514 case ICMP_TSTAMP: 515 if (icmptstamprepl == 0) 516 break; 517 518 if (!icmpbmcastecho && 519 (m->m_flags & (M_MCAST | M_BCAST)) != 0) { 520 icmpstat.icps_bmcastecho++; 521 break; 522 } 523 if (icmplen < ICMP_TSLEN) { 524 icmpstat.icps_badlen++; 525 break; 526 } 527 icp->icmp_type = ICMP_TSTAMPREPLY; 528 icp->icmp_rtime = iptime(); 529 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 530 goto reflect; 531 532 case ICMP_MASKREQ: 533 if (icmpmaskrepl == 0) 534 break; 535 if (icmplen < ICMP_MASKLEN) { 536 icmpstat.icps_badlen++; 537 break; 538 } 539 /* 540 * We are not able to respond with all ones broadcast 541 * unless we receive it over a point-to-point interface. 542 */ 543 memset(&sin, 0, sizeof(sin)); 544 sin.sin_family = AF_INET; 545 sin.sin_len = sizeof(struct sockaddr_in); 546 if (ip->ip_dst.s_addr == INADDR_BROADCAST || 547 ip->ip_dst.s_addr == INADDR_ANY) 548 sin.sin_addr = ip->ip_src; 549 else 550 sin.sin_addr = ip->ip_dst; 551 if (ifp == NULL) 552 break; 553 ia = ifatoia(ifaof_ifpforaddr(sintosa(&sin), ifp)); 554 if (ia == 0) 555 break; 556 icp->icmp_type = ICMP_MASKREPLY; 557 icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr; 558 if (ip->ip_src.s_addr == 0) { 559 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 560 if (ia->ia_broadaddr.sin_addr.s_addr) 561 ip->ip_src = ia->ia_broadaddr.sin_addr; 562 else 563 ip->ip_src.s_addr = INADDR_BROADCAST; 564 } 565 else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 566 ip->ip_src = ia->ia_dstaddr.sin_addr; 567 } 568 reflect: 569 #if NCARP > 0 570 if (ifp->if_type == IFT_CARP && 571 carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, 572 &ip->ip_dst.s_addr)) 573 goto freeit; 574 #endif 575 /* Free packet atttributes */ 576 if (m->m_flags & M_PKTHDR) 577 m_tag_delete_chain(m); 578 579 icmpstat.icps_reflect++; 580 icmpstat.icps_outhist[icp->icmp_type]++; 581 if (!icmp_reflect(m, &opts, NULL)) 582 icmp_send(m, opts); 583 return; 584 585 case ICMP_REDIRECT: 586 { 587 struct sockaddr_in sdst; 588 struct sockaddr_in sgw; 589 struct sockaddr_in ssrc; 590 struct rtentry *newrt = NULL; 591 592 /* Free packet atttributes */ 593 if (m->m_flags & M_PKTHDR) 594 m_tag_delete_chain(m); 595 if (icmp_rediraccept == 0 || ipforwarding == 1) 596 goto freeit; 597 if (code > 3) 598 goto badcode; 599 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || 600 icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { 601 icmpstat.icps_badlen++; 602 break; 603 } 604 /* 605 * Short circuit routing redirects to force 606 * immediate change in the kernel's routing 607 * tables. The message is also handed to anyone 608 * listening on a raw socket (e.g. the routing 609 * daemon for use in updating its tables). 610 */ 611 memset(&sdst, 0, sizeof(sdst)); 612 memset(&sgw, 0, sizeof(sgw)); 613 memset(&ssrc, 0, sizeof(ssrc)); 614 sdst.sin_family = sgw.sin_family = ssrc.sin_family = AF_INET; 615 sdst.sin_len = sgw.sin_len = ssrc.sin_len = sizeof(sdst); 616 memcpy(&sdst.sin_addr, &icp->icmp_ip.ip_dst, 617 sizeof(sdst.sin_addr)); 618 memcpy(&sgw.sin_addr, &icp->icmp_gwaddr, 619 sizeof(sgw.sin_addr)); 620 memcpy(&ssrc.sin_addr, &ip->ip_src, 621 sizeof(ssrc.sin_addr)); 622 623 #ifdef ICMPPRINTFS 624 if (icmpprintfs) { 625 char gw[INET_ADDRSTRLEN], dst[INET_ADDRSTRLEN]; 626 627 inet_ntop(AF_INET, &icp->icmp_gwaddr, gw, sizeof(gw)); 628 inet_ntop(AF_INET, &icp->icmp_ip.ip_dst, 629 dst, sizeof(dst)); 630 631 printf("redirect dst %s to %s\n", dst, gw); 632 } 633 #endif 634 635 #if NCARP > 0 636 if (ifp->if_type == IFT_CARP && 637 carp_lsdrop(m, AF_INET, &sdst.sin_addr.s_addr, 638 &ip->ip_dst.s_addr)) 639 goto freeit; 640 #endif 641 rtredirect(sintosa(&sdst), sintosa(&sgw), NULL, 642 RTF_GATEWAY | RTF_HOST, sintosa(&ssrc), 643 &newrt, m->m_pkthdr.ph_rtableid); 644 if (newrt != NULL && icmp_redirtimeout != 0) { 645 (void)rt_timer_add(newrt, icmp_redirect_timeout, 646 icmp_redirect_timeout_q, m->m_pkthdr.ph_rtableid); 647 } 648 if (newrt != NULL) 649 rtfree(newrt); 650 pfctlinput(PRC_REDIRECT_HOST, sintosa(&sdst)); 651 break; 652 } 653 /* 654 * No kernel processing for the following; 655 * just fall through to send to raw listener. 656 */ 657 case ICMP_ECHOREPLY: 658 case ICMP_ROUTERADVERT: 659 case ICMP_ROUTERSOLICIT: 660 case ICMP_TSTAMPREPLY: 661 case ICMP_IREQREPLY: 662 case ICMP_MASKREPLY: 663 case ICMP_TRACEROUTE: 664 case ICMP_DATACONVERR: 665 case ICMP_MOBILE_REDIRECT: 666 case ICMP_IPV6_WHEREAREYOU: 667 case ICMP_IPV6_IAMHERE: 668 case ICMP_MOBILE_REGREQUEST: 669 case ICMP_MOBILE_REGREPLY: 670 case ICMP_PHOTURIS: 671 default: 672 break; 673 } 674 675 raw: 676 rip_input(m); 677 return; 678 679 freeit: 680 m_freem(m); 681 } 682 683 /* 684 * Reflect the ip packet back to the source 685 */ 686 int 687 icmp_reflect(struct mbuf *m, struct mbuf **op, struct in_ifaddr *ia) 688 { 689 struct ip *ip = mtod(m, struct ip *); 690 struct in_addr t; 691 struct mbuf *opts = 0; 692 int optlen = (ip->ip_hl << 2) - sizeof(struct ip); 693 694 if (!in_canforward(ip->ip_src) && 695 ((ip->ip_src.s_addr & IN_CLASSA_NET) != 696 htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) { 697 m_freem(m); /* Bad return address */ 698 return (EHOSTUNREACH); 699 } 700 701 #if NPF > 0 702 pf_pkt_addr_changed(m); 703 #endif 704 t = ip->ip_dst; 705 ip->ip_dst = ip->ip_src; 706 /* 707 * If the incoming packet was addressed directly to us, 708 * use dst as the src for the reply. For broadcast, use 709 * the address which corresponds to the incoming interface. 710 */ 711 if (ia == NULL) { 712 TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { 713 if (ia->ia_ifp->if_rdomain != 714 rtable_l2(m->m_pkthdr.ph_rtableid)) 715 continue; 716 if (t.s_addr == ia->ia_addr.sin_addr.s_addr) 717 break; 718 if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && 719 ia->ia_broadaddr.sin_addr.s_addr != 0 && 720 t.s_addr == ia->ia_broadaddr.sin_addr.s_addr) 721 break; 722 } 723 } 724 /* 725 * The following happens if the packet was not addressed to us. 726 * Use the new source address and do a route lookup. If it fails 727 * drop the packet as there is no path to the host. 728 */ 729 if (ia == NULL) { 730 struct sockaddr_in *dst; 731 struct route ro; 732 733 memset(&ro, 0, sizeof(ro)); 734 ro.ro_tableid = m->m_pkthdr.ph_rtableid; 735 dst = satosin(&ro.ro_dst); 736 dst->sin_family = AF_INET; 737 dst->sin_len = sizeof(*dst); 738 dst->sin_addr = ip->ip_src; 739 740 /* keep packet in the original virtual instance */ 741 ro.ro_rt = rtalloc1(&ro.ro_dst, RT_REPORT, 742 m->m_pkthdr.ph_rtableid); 743 if (ro.ro_rt == 0) { 744 ipstat.ips_noroute++; 745 m_freem(m); 746 return (EHOSTUNREACH); 747 } 748 749 ia = ifatoia(ro.ro_rt->rt_ifa); 750 ro.ro_rt->rt_use++; 751 RTFREE(ro.ro_rt); 752 } 753 754 t = ia->ia_addr.sin_addr; 755 ip->ip_src = t; 756 ip->ip_ttl = MAXTTL; 757 758 if (optlen > 0) { 759 u_char *cp; 760 int opt, cnt; 761 u_int len; 762 763 /* 764 * Retrieve any source routing from the incoming packet; 765 * add on any record-route or timestamp options. 766 */ 767 cp = (u_char *) (ip + 1); 768 if (op && (opts = ip_srcroute(m)) == NULL && 769 (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) { 770 opts->m_len = sizeof(struct in_addr); 771 mtod(opts, struct in_addr *)->s_addr = 0; 772 } 773 if (op && opts) { 774 #ifdef ICMPPRINTFS 775 if (icmpprintfs) 776 printf("icmp_reflect optlen %d rt %d => ", 777 optlen, opts->m_len); 778 #endif 779 for (cnt = optlen; cnt > 0; cnt -= len, cp += len) { 780 opt = cp[IPOPT_OPTVAL]; 781 if (opt == IPOPT_EOL) 782 break; 783 if (opt == IPOPT_NOP) 784 len = 1; 785 else { 786 if (cnt < IPOPT_OLEN + sizeof(*cp)) 787 break; 788 len = cp[IPOPT_OLEN]; 789 if (len < IPOPT_OLEN + sizeof(*cp) || 790 len > cnt) 791 break; 792 } 793 /* 794 * Should check for overflow, but it 795 * "can't happen" 796 */ 797 if (opt == IPOPT_RR || opt == IPOPT_TS || 798 opt == IPOPT_SECURITY) { 799 memcpy(mtod(opts, caddr_t) + 800 opts->m_len, cp, len); 801 opts->m_len += len; 802 } 803 } 804 /* Terminate & pad, if necessary */ 805 if ((cnt = opts->m_len % 4) != 0) 806 for (; cnt < 4; cnt++) { 807 *(mtod(opts, caddr_t) + opts->m_len) = 808 IPOPT_EOL; 809 opts->m_len++; 810 } 811 #ifdef ICMPPRINTFS 812 if (icmpprintfs) 813 printf("%d\n", opts->m_len); 814 #endif 815 } 816 ip_stripoptions(m); 817 } 818 m->m_flags &= ~(M_BCAST|M_MCAST); 819 if (op) 820 *op = opts; 821 822 return (0); 823 } 824 825 /* 826 * Send an icmp packet back to the ip level 827 */ 828 void 829 icmp_send(struct mbuf *m, struct mbuf *opts) 830 { 831 struct ip *ip = mtod(m, struct ip *); 832 int hlen; 833 struct icmp *icp; 834 835 hlen = ip->ip_hl << 2; 836 icp = (struct icmp *)(mtod(m, caddr_t) + hlen); 837 icp->icmp_cksum = 0; 838 m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; 839 #ifdef ICMPPRINTFS 840 if (icmpprintfs) { 841 char dst[INET_ADDRSTRLEN], src[INET_ADDRSTRLEN]; 842 843 inet_ntop(AF_INET, &ip->ip_dst, dst, sizeof(dst)); 844 inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)); 845 846 printf("icmp_send dst %s src %s\n", dst, src); 847 } 848 #endif 849 ip_output(m, opts, NULL, 0, NULL, NULL, 0); 850 } 851 852 u_int32_t 853 iptime(void) 854 { 855 struct timeval atv; 856 u_long t; 857 858 microtime(&atv); 859 t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000; 860 return (htonl(t)); 861 } 862 863 int 864 icmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, 865 size_t newlen) 866 { 867 int s, error; 868 869 /* All sysctl names at this level are terminal. */ 870 if (namelen != 1) 871 return (ENOTDIR); 872 873 s = splsoftnet(); 874 switch (name[0]) { 875 case ICMPCTL_REDIRTIMEOUT: 876 877 error = sysctl_int(oldp, oldlenp, newp, newlen, 878 &icmp_redirtimeout); 879 if (icmp_redirect_timeout_q != NULL) { 880 if (icmp_redirtimeout == 0) { 881 rt_timer_queue_destroy(icmp_redirect_timeout_q); 882 icmp_redirect_timeout_q = NULL; 883 } else 884 rt_timer_queue_change(icmp_redirect_timeout_q, 885 icmp_redirtimeout); 886 } else if (icmp_redirtimeout > 0) { 887 icmp_redirect_timeout_q = 888 rt_timer_queue_create(icmp_redirtimeout); 889 } 890 break; 891 892 case ICMPCTL_STATS: 893 if (newp != NULL) { 894 error = EPERM; 895 break; 896 } 897 error = sysctl_struct(oldp, oldlenp, newp, newlen, 898 &icmpstat, sizeof(icmpstat)); 899 break; 900 901 default: 902 if (name[0] < ICMPCTL_MAXID) { 903 error = sysctl_int_arr(icmpctl_vars, name, namelen, 904 oldp, oldlenp, newp, newlen); 905 break; 906 } 907 error = ENOPROTOOPT; 908 break; 909 } 910 splx(s); 911 912 return (error); 913 } 914 915 916 struct rtentry * 917 icmp_mtudisc_clone(struct in_addr dst, u_int rtableid) 918 { 919 struct sockaddr_in *sin; 920 struct route ro; 921 struct rtentry *rt; 922 int error; 923 924 memset(&ro, 0, sizeof(ro)); 925 ro.ro_tableid = rtableid; 926 sin = satosin(&ro.ro_dst); 927 sin->sin_family = AF_INET; 928 sin->sin_len = sizeof(*sin); 929 sin->sin_addr = dst; 930 931 rt = rtalloc1(&ro.ro_dst, RT_REPORT, rtableid); 932 if (rt == NULL) 933 return (NULL); 934 935 /* Check if the route is actually usable */ 936 if (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE) || 937 (rt->rt_flags & RTF_UP) == 0) 938 return (NULL); 939 940 /* If we didn't get a host route, allocate one */ 941 942 if ((rt->rt_flags & RTF_HOST) == 0) { 943 struct rtentry *nrt; 944 struct rt_addrinfo info; 945 946 memset(&info, 0, sizeof(info)); 947 info.rti_info[RTAX_DST] = sintosa(sin); 948 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 949 info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; 950 951 error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &nrt, rtableid); 952 if (error) { 953 rtfree(rt); 954 return (NULL); 955 } 956 nrt->rt_rmx = rt->rt_rmx; 957 rtfree(rt); 958 rt = nrt; 959 } 960 error = rt_timer_add(rt, icmp_mtudisc_timeout, ip_mtudisc_timeout_q, 961 rtableid); 962 if (error) { 963 rtfree(rt); 964 return (NULL); 965 } 966 967 return (rt); 968 } 969 970 /* Table of common MTUs: */ 971 static const u_short mtu_table[] = { 972 65535, 65280, 32000, 17914, 9180, 8166, 973 4352, 2002, 1492, 1006, 508, 296, 68, 0 974 }; 975 976 void 977 icmp_mtudisc(struct icmp *icp, u_int rtableid) 978 { 979 struct rtentry *rt; 980 u_long mtu = ntohs(icp->icmp_nextmtu); /* Why a long? IPv6 */ 981 982 rt = icmp_mtudisc_clone(icp->icmp_ip.ip_dst, rtableid); 983 if (rt == 0) 984 return; 985 986 if (mtu == 0) { 987 int i = 0; 988 989 mtu = ntohs(icp->icmp_ip.ip_len); 990 /* Some 4.2BSD-based routers incorrectly adjust the ip_len */ 991 if (mtu > rt->rt_rmx.rmx_mtu && rt->rt_rmx.rmx_mtu != 0) 992 mtu -= (icp->icmp_ip.ip_hl << 2); 993 994 /* If we still can't guess a value, try the route */ 995 if (mtu == 0) { 996 mtu = rt->rt_rmx.rmx_mtu; 997 998 /* If no route mtu, default to the interface mtu */ 999 1000 if (mtu == 0) 1001 mtu = rt->rt_ifp->if_mtu; 1002 } 1003 1004 for (i = 0; i < nitems(mtu_table); i++) 1005 if (mtu > mtu_table[i]) { 1006 mtu = mtu_table[i]; 1007 break; 1008 } 1009 } 1010 1011 /* 1012 * XXX: RTV_MTU is overloaded, since the admin can set it 1013 * to turn off PMTU for a route, and the kernel can 1014 * set it to indicate a serious problem with PMTU 1015 * on a route. We should be using a separate flag 1016 * for the kernel to indicate this. 1017 */ 1018 1019 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) { 1020 if (mtu < 296 || mtu > rt->rt_ifp->if_mtu) 1021 rt->rt_rmx.rmx_locks |= RTV_MTU; 1022 else if (rt->rt_rmx.rmx_mtu > mtu || 1023 rt->rt_rmx.rmx_mtu == 0) 1024 rt->rt_rmx.rmx_mtu = mtu; 1025 } 1026 1027 rtfree(rt); 1028 } 1029 1030 void 1031 icmp_mtudisc_timeout(struct rtentry *rt, struct rttimer *r) 1032 { 1033 if (rt == NULL) 1034 panic("icmp_mtudisc_timeout: bad route to timeout"); 1035 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) == 1036 (RTF_DYNAMIC | RTF_HOST)) { 1037 void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); 1038 struct sockaddr_in sa; 1039 struct rt_addrinfo info; 1040 1041 memset(&info, 0, sizeof(info)); 1042 info.rti_info[RTAX_DST] = rt_key(rt); 1043 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1044 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1045 info.rti_flags = rt->rt_flags; 1046 1047 sa = *(struct sockaddr_in *)rt_key(rt); 1048 rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL, 1049 r->rtt_tableid); 1050 1051 /* Notify TCP layer of increased Path MTU estimate */ 1052 ctlfunc = inetsw[ip_protox[IPPROTO_TCP]].pr_ctlinput; 1053 if (ctlfunc) 1054 (*ctlfunc)(PRC_MTUINC,(struct sockaddr *)&sa, 1055 r->rtt_tableid, NULL); 1056 } else 1057 if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0) 1058 rt->rt_rmx.rmx_mtu = 0; 1059 } 1060 1061 /* 1062 * Perform rate limit check. 1063 * Returns 0 if it is okay to send the icmp packet. 1064 * Returns 1 if the router SHOULD NOT send this icmp packet due to rate 1065 * limitation. 1066 * 1067 * XXX per-destination/type check necessary? 1068 */ 1069 int 1070 icmp_ratelimit(const struct in_addr *dst, const int type, const int code) 1071 { 1072 /* PPS limit */ 1073 if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count, 1074 icmperrppslim)) 1075 return 1; /* The packet is subject to rate limit */ 1076 return 0; /* okay to send */ 1077 } 1078 1079 void 1080 icmp_redirect_timeout(struct rtentry *rt, struct rttimer *r) 1081 { 1082 if (rt == NULL) 1083 panic("icmp_redirect_timeout: bad route to timeout"); 1084 if ((rt->rt_flags & (RTF_DYNAMIC | RTF_HOST)) == 1085 (RTF_DYNAMIC | RTF_HOST)) { 1086 struct rt_addrinfo info; 1087 1088 memset(&info, 0, sizeof(info)); 1089 info.rti_info[RTAX_DST] = rt_key(rt); 1090 info.rti_info[RTAX_NETMASK] = rt_mask(rt); 1091 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; 1092 info.rti_flags = rt->rt_flags; 1093 1094 rtrequest1(RTM_DELETE, &info, rt->rt_priority, NULL, 1095 r->rtt_tableid); 1096 } 1097 } 1098 1099 int 1100 icmp_do_exthdr(struct mbuf *m, u_int16_t class, u_int8_t ctype, void *buf, 1101 size_t len) 1102 { 1103 struct ip *ip = mtod(m, struct ip *); 1104 int hlen, off; 1105 struct mbuf *n; 1106 struct icmp *icp; 1107 struct icmp_ext_hdr *ieh; 1108 struct { 1109 struct icmp_ext_hdr ieh; 1110 struct icmp_ext_obj_hdr ieo; 1111 } hdr; 1112 1113 hlen = ip->ip_hl << 2; 1114 icp = (struct icmp *)(mtod(m, caddr_t) + hlen); 1115 if (icp->icmp_type != ICMP_TIMXCEED && icp->icmp_type != ICMP_UNREACH && 1116 icp->icmp_type != ICMP_PARAMPROB) 1117 /* exthdr not supported */ 1118 return (0); 1119 1120 if (icp->icmp_length != 0) 1121 /* exthdr already present, giving up */ 1122 return (0); 1123 1124 /* the actual offset starts after the common ICMP header */ 1125 hlen += ICMP_MINLEN; 1126 /* exthdr must start on a word boundary */ 1127 off = roundup(ntohs(ip->ip_len) - hlen, sizeof(u_int32_t)); 1128 /* ... and at an offset of ICMP_EXT_OFFSET or bigger */ 1129 off = max(off, ICMP_EXT_OFFSET); 1130 icp->icmp_length = off / sizeof(u_int32_t); 1131 1132 memset(&hdr, 0, sizeof(hdr)); 1133 hdr.ieh.ieh_version = ICMP_EXT_HDR_VERSION; 1134 hdr.ieo.ieo_length = htons(sizeof(struct icmp_ext_obj_hdr) + len); 1135 hdr.ieo.ieo_cnum = class; 1136 hdr.ieo.ieo_ctype = ctype; 1137 1138 if (m_copyback(m, hlen + off, sizeof(hdr), &hdr, M_NOWAIT) || 1139 m_copyback(m, hlen + off + sizeof(hdr), len, buf, M_NOWAIT)) { 1140 m_freem(m); 1141 return (ENOBUFS); 1142 } 1143 1144 /* calculate checksum */ 1145 n = m_getptr(m, hlen + off, &off); 1146 if (n == NULL) 1147 panic("icmp_do_exthdr: m_getptr failure"); 1148 ieh = (struct icmp_ext_hdr *)(mtod(n, caddr_t) + off); 1149 ieh->ieh_cksum = in4_cksum(n, 0, off, sizeof(hdr) + len); 1150 1151 ip->ip_len = htons(m->m_pkthdr.len); 1152 1153 return (0); 1154 } 1155