1: /* 2: * Copyright (c) 1982, 1986 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: * 12: * @(#)ip_icmp.c 7.7.2 (2.11BSD GTE) 1995/10/10 13: */ 14: 15: #include "param.h" 16: #include "systm.h" 17: #include "mbuf.h" 18: #include "protosw.h" 19: #include "socket.h" 20: #include "time.h" 21: #include "kernel.h" 22: #include "errno.h" 23: 24: #include "../net/route.h" 25: #include "../net/if.h" 26: 27: #include "domain.h" 28: #include "in.h" 29: #include "in_systm.h" 30: #include "in_var.h" 31: #include "ip.h" 32: #include "ip_icmp.h" 33: #include "icmp_var.h" 34: 35: extern int icmpmaskrepl; 36: #ifdef ICMPPRINTFS 37: /* 38: * ICMP routines: error generation, receive packet processing, and 39: * routines to turnaround packets back to the originator, and 40: * host table maintenance routines. 41: */ 42: int icmpprintfs = 0; 43: #endif 44: 45: /* 46: * Generate an error packet of type error 47: * in response to bad packet ip. 48: */ 49: /*VARARGS4*/ 50: icmp_error(oip, type, code, ifp, dest) 51: struct ip *oip; 52: int type, code; 53: struct ifnet *ifp; 54: struct in_addr dest; 55: { 56: register unsigned oiplen = oip->ip_hl << 2; 57: register struct icmp *icp; 58: struct mbuf *m; 59: struct ip *nip; 60: unsigned icmplen; 61: 62: #ifdef ICMPPRINTFS 63: if (icmpprintfs) 64: printf("icmp_error(%x, %d, %d)\n", oip, type, code); 65: #endif 66: if (type != ICMP_REDIRECT) 67: icmpstat.icps_error++; 68: /* 69: * Don't send error if not the first fragment of message. 70: * Don't error if the old packet protocol was ICMP 71: * error message, only known informational types. 72: */ 73: if (oip->ip_off &~ (IP_MF|IP_DF)) 74: goto free; 75: if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && 76: !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) { 77: icmpstat.icps_oldicmp++; 78: goto free; 79: } 80: 81: /* 82: * First, formulate icmp message 83: */ 84: m = m_get(M_DONTWAIT, MT_HEADER); 85: if (m == NULL) 86: goto free; 87: icmplen = oiplen + MIN(8, oip->ip_len); 88: m->m_len = icmplen + ICMP_MINLEN; 89: m->m_off = MMAXOFF - m->m_len; 90: icp = mtod(m, struct icmp *); 91: if ((u_int)type > ICMP_MAXTYPE) 92: panic("icmp_error"); 93: icmpstat.icps_outhist[type]++; 94: icp->icmp_type = type; 95: if (type == ICMP_REDIRECT) 96: icp->icmp_gwaddr = dest; 97: else 98: icp->icmp_void = 0; 99: if (type == ICMP_PARAMPROB) { 100: icp->icmp_pptr = code; 101: code = 0; 102: } 103: icp->icmp_code = code; 104: bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen); 105: nip = &icp->icmp_ip; 106: nip->ip_len += oiplen; 107: nip->ip_len = htons((u_short)nip->ip_len); 108: 109: /* 110: * Now, copy old ip header in front of icmp message. 111: */ 112: if (m->m_len + oiplen > MLEN) 113: oiplen = sizeof(struct ip); 114: if (m->m_len + oiplen > MLEN) 115: panic("icmp len"); 116: m->m_off -= oiplen; 117: m->m_len += oiplen; 118: nip = mtod(m, struct ip *); 119: bcopy((caddr_t)oip, (caddr_t)nip, oiplen); 120: nip->ip_len = m->m_len; 121: nip->ip_p = IPPROTO_ICMP; 122: icmp_reflect(nip, ifp); 123: 124: free: 125: m_freem(dtom(oip)); 126: } 127: 128: static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP }; 129: static struct sockaddr_in icmpsrc = { AF_INET }; 130: static struct sockaddr_in icmpdst = { AF_INET }; 131: static struct sockaddr_in icmpgw = { AF_INET }; 132: struct in_ifaddr *ifptoia(); 133: 134: /* 135: * Process a received ICMP message. 136: */ 137: icmp_input(m, ifp) 138: register struct mbuf *m; 139: struct ifnet *ifp; 140: { 141: register struct icmp *icp; 142: register struct ip *ip = mtod(m, struct ip *); 143: int icmplen = ip->ip_len, hlen = ip->ip_hl << 2; 144: register int i; 145: struct in_ifaddr *ia; 146: int (*ctlfunc)(), code; 147: extern u_char ip_protox[]; 148: extern struct in_addr in_makeaddr(); 149: 150: /* 151: * Locate icmp structure in mbuf, and check 152: * that not corrupted and of at least minimum length. 153: */ 154: #ifdef ICMPPRINTFS 155: if (icmpprintfs) 156: printf("icmp_input src %X len %d", ntohl(ip->ip_src), icmplen); 157: #endif 158: if (icmplen < ICMP_MINLEN) { 159: icmpstat.icps_tooshort++; 160: goto free; 161: } 162: i = hlen + MIN(icmplen, ICMP_ADVLENMIN); 163: if ((m->m_off > MMAXOFF || m->m_len < i) && 164: (m = m_pullup(m, i)) == 0) { 165: icmpstat.icps_tooshort++; 166: return; 167: } 168: ip = mtod(m, struct ip *); 169: m->m_len -= hlen; 170: m->m_off += hlen; 171: icp = mtod(m, struct icmp *); 172: if (in_cksum(m, icmplen)) { 173: icmpstat.icps_checksum++; 174: goto free; 175: } 176: m->m_len += hlen; 177: m->m_off -= hlen; 178: 179: #ifdef ICMPPRINTFS 180: /* 181: * Message type specific processing. 182: */ 183: if (icmpprintfs) 184: printf("icmp_input, type %d code %d\n", icp->icmp_type, 185: icp->icmp_code); 186: #endif 187: if (icp->icmp_type > ICMP_MAXTYPE) 188: goto raw; 189: icmpstat.icps_inhist[icp->icmp_type]++; 190: code = icp->icmp_code; 191: switch (icp->icmp_type) { 192: 193: case ICMP_UNREACH: 194: if (code > 5) 195: goto badcode; 196: code += PRC_UNREACH_NET; 197: goto deliver; 198: 199: case ICMP_TIMXCEED: 200: if (code > 1) 201: goto badcode; 202: code += PRC_TIMXCEED_INTRANS; 203: goto deliver; 204: 205: case ICMP_PARAMPROB: 206: if (code) 207: goto badcode; 208: code = PRC_PARAMPROB; 209: goto deliver; 210: 211: case ICMP_SOURCEQUENCH: 212: if (code) 213: goto badcode; 214: code = PRC_QUENCH; 215: deliver: 216: /* 217: * Problem with datagram; advise higher level routines. 218: */ 219: icp->icmp_ip.ip_len = ntohs((u_short)icp->icmp_ip.ip_len); 220: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { 221: icmpstat.icps_badlen++; 222: goto free; 223: } 224: #ifdef ICMPPRINTFS 225: if (icmpprintfs) 226: printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); 227: #endif 228: icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 229: if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput) 230: (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, 231: (caddr_t)&icp->icmp_ip); 232: break; 233: 234: badcode: 235: icmpstat.icps_badcode++; 236: break; 237: 238: case ICMP_ECHO: 239: icp->icmp_type = ICMP_ECHOREPLY; 240: goto reflect; 241: 242: case ICMP_TSTAMP: 243: if (icmplen < ICMP_TSLEN) { 244: icmpstat.icps_badlen++; 245: break; 246: } 247: icp->icmp_type = ICMP_TSTAMPREPLY; 248: icp->icmp_rtime = iptime(); 249: icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 250: goto reflect; 251: 252: case ICMP_IREQ: 253: #define satosin(sa) ((struct sockaddr_in *)(sa)) 254: if (in_netof(ip->ip_src) == 0 && (ia = ifptoia(ifp))) 255: ip->ip_src = in_makeaddr(in_netof(IA_SIN(ia)->sin_addr), 256: in_lnaof(ip->ip_src)); 257: icp->icmp_type = ICMP_IREQREPLY; 258: goto reflect; 259: 260: case ICMP_MASKREQ: 261: if (icmpmaskrepl == 0) 262: break; 263: /* 264: * We are not able to respond with all ones broadcast 265: * unless we receive it over a point-to-point interface. 266: * This check is a 'switch' in 4.4BSD but 2.11's C compiler 267: * does not allow "long"s in a switch statement. 268: */ 269: if (icmplen < ICMP_MASKLEN || (ia = ifptoia(ifp)) == 0) 270: break; 271: if ((ip->ip_dst.s_addr == INADDR_BROADCAST || 272: ip->ip_dst.s_addr == INADDR_ANY)) 273: icmpdst.sin_addr = ip->ip_src; 274: else 275: icmpdst.sin_addr = ip->ip_dst; 276: icp->icmp_type = ICMP_MASKREPLY; 277: icp->icmp_mask = htonl(ia->ia_subnetmask); 278: if (ip->ip_src.s_addr == 0) { 279: if (ia->ia_ifp->if_flags & IFF_BROADCAST) 280: ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr; 281: else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT) 282: ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr; 283: } 284: reflect: 285: ip->ip_len += hlen; /* since ip_input deducts this */ 286: icmpstat.icps_reflect++; 287: icmpstat.icps_outhist[icp->icmp_type]++; 288: icmp_reflect(ip, ifp); 289: return; 290: 291: case ICMP_REDIRECT: 292: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { 293: icmpstat.icps_badlen++; 294: break; 295: } 296: /* 297: * Short circuit routing redirects to force 298: * immediate change in the kernel's routing 299: * tables. The message is also handed to anyone 300: * listening on a raw socket (e.g. the routing 301: * daemon for use in updating its tables). 302: */ 303: icmpgw.sin_addr = ip->ip_src; 304: icmpdst.sin_addr = icp->icmp_gwaddr; 305: #ifdef ICMPPRINTFS 306: if (icmpprintfs) 307: printf("redirect dst %X to %X\n", ntohl(icp->icmp_ip.ip_dst), 308: ntohl(icp->icmp_gwaddr)); 309: #endif 310: if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) { 311: icmpsrc.sin_addr = 312: in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY); 313: rtredirect((struct sockaddr *)&icmpsrc, 314: (struct sockaddr *)&icmpdst, RTF_GATEWAY, 315: (struct sockaddr *)&icmpgw); 316: icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 317: pfctlinput(PRC_REDIRECT_NET, 318: (struct sockaddr *)&icmpsrc); 319: } else { 320: icmpsrc.sin_addr = icp->icmp_ip.ip_dst; 321: rtredirect((struct sockaddr *)&icmpsrc, 322: (struct sockaddr *)&icmpdst, RTF_GATEWAY | RTF_HOST, 323: (struct sockaddr *)&icmpgw); 324: pfctlinput(PRC_REDIRECT_HOST, 325: (struct sockaddr *)&icmpsrc); 326: } 327: break; 328: 329: /* 330: * No kernel processing for the following; 331: * just fall through to send to raw listener. 332: */ 333: case ICMP_ECHOREPLY: 334: case ICMP_TSTAMPREPLY: 335: case ICMP_IREQREPLY: 336: case ICMP_MASKREPLY: 337: default: 338: break; 339: } 340: 341: raw: 342: icmpsrc.sin_addr = ip->ip_src; 343: icmpdst.sin_addr = ip->ip_dst; 344: raw_input(m, &icmproto, (struct sockaddr *)&icmpsrc, 345: (struct sockaddr *)&icmpdst); 346: return; 347: 348: free: 349: m_freem(m); 350: } 351: 352: /* 353: * Reflect the ip packet back to the source 354: */ 355: icmp_reflect(ip, ifp) 356: register struct ip *ip; 357: struct ifnet *ifp; 358: { 359: register struct in_ifaddr *ia; 360: struct in_addr t; 361: struct mbuf *opts = 0, *ip_srcroute(); 362: int optlen = (ip->ip_hl << 2) - sizeof(struct ip); 363: 364: t = ip->ip_dst; 365: ip->ip_dst = ip->ip_src; 366: /* 367: * If the incoming packet was addressed directly to us, 368: * use dst as the src for the reply. Otherwise (broadcast 369: * or anonymous), use the address which corresponds 370: * to the incoming interface. 371: */ 372: for (ia = in_ifaddr; ia; ia = ia->ia_next) { 373: if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) 374: break; 375: if ((ia->ia_ifp->if_flags & IFF_BROADCAST) && 376: t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr) 377: break; 378: } 379: if (ia == (struct in_ifaddr *)0) 380: ia = ifptoia(ifp); 381: if (ia == (struct in_ifaddr *)0) 382: ia = in_ifaddr; 383: t = IA_SIN(ia)->sin_addr; 384: ip->ip_src = t; 385: ip->ip_ttl = MAXTTL; 386: 387: if (optlen > 0) { 388: /* 389: * Retrieve any source routing from the incoming packet 390: * and strip out other options. Adjust the IP length. 391: */ 392: opts = ip_srcroute(); 393: ip->ip_len -= optlen; 394: ip_stripoptions(ip, (struct mbuf *)0); 395: } 396: icmp_send(ip, opts); 397: if (opts) 398: (void)m_free(opts); 399: } 400: 401: struct in_ifaddr * 402: ifptoia(ifp) 403: struct ifnet *ifp; 404: { 405: register struct in_ifaddr *ia; 406: 407: for (ia = in_ifaddr; ia; ia = ia->ia_next) 408: if (ia->ia_ifp == ifp) 409: return (ia); 410: return ((struct in_ifaddr *)0); 411: } 412: 413: /* 414: * Send an icmp packet back to the ip level, 415: * after supplying a checksum. 416: */ 417: icmp_send(ip, opts) 418: register struct ip *ip; 419: struct mbuf *opts; 420: { 421: register int hlen; 422: register struct icmp *icp; 423: register struct mbuf *m; 424: 425: m = dtom(ip); 426: hlen = ip->ip_hl << 2; 427: m->m_off += hlen; 428: m->m_len -= hlen; 429: icp = mtod(m, struct icmp *); 430: icp->icmp_cksum = 0; 431: icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); 432: m->m_off -= hlen; 433: m->m_len += hlen; 434: #ifdef ICMPPRINTFS 435: if (icmpprintfs) 436: printf("icmp_send dst %X src %X\n", ntohl(ip->ip_dst.s_addr), ntohl(ip->ip_src.s_addr)); 437: #endif 438: (void) ip_output(m, opts, (struct route *)0, 0); 439: } 440: 441: n_time 442: iptime() 443: { 444: struct timeval atv; 445: int s = splhigh(); 446: u_long t; 447: extern struct timeval time; 448: extern int lbolt, hz; 449: 450: cpfromkern(&time, &atv, sizeof(struct timeval)); 451: t = (atv.tv_sec % (24L*60L*60L)) * 1000L 452: + (long)mfkd(&lbolt) * 1000L / (long)hz; 453: splx(s); 454: return (htonl(t)); 455: } 456: 457: int 458: icmp_sysctl(name, namelen, oldp, oldlenp, newp, newlen) 459: int *name; 460: u_int namelen; 461: void *oldp; 462: size_t *oldlenp; 463: void *newp; 464: size_t newlen; 465: { 466: 467: /* All sysctl names at this level are terminal. */ 468: if (namelen != 1) 469: return (ENOTDIR); 470: 471: switch (name[0]) { 472: case ICMPCTL_MASKREPL: 473: return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl)); 474: default: 475: return (ENOPROTOOPT); 476: } 477: /* NOTREACHED */ 478: }