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