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