|
|
1.1 ! root 1: /* ip_icmp.c 6.2 83/09/19 */ ! 2: ! 3: #include "../h/param.h" ! 4: #include "../h/systm.h" ! 5: #include "../h/mbuf.h" ! 6: #include "../h/protosw.h" ! 7: #include "../h/socket.h" ! 8: #include "../h/time.h" ! 9: #include "../h/kernel.h" ! 10: ! 11: #include "../net/route.h" ! 12: ! 13: #include "../netinet/in.h" ! 14: #include "../netinet/in_systm.h" ! 15: #include "../netinet/ip.h" ! 16: #include "../netinet/ip_icmp.h" ! 17: #include "../netinet/icmp_var.h" ! 18: ! 19: #ifdef ICMPPRINTFS ! 20: /* ! 21: * Changes: ! 22: * . (from Usenet) don't look at icmplen for ICMP_ECHOREPLY, ! 23: * ICMP_TSTAMPREPLY, and ICMP_IREQREPLY ! 24: * ! 25: * . (from Usenet) distinguish between net and host redirect ! 26: * ! 27: */ ! 28: /* ! 29: * ICMP routines: error generation, receive packet processing, and ! 30: * routines to turnaround packets back to the originator, and ! 31: * host table maintenance routines. ! 32: */ ! 33: int icmpprintfs = 0; ! 34: #endif ! 35: ! 36: /* ! 37: * Generate an error packet of type error ! 38: * in response to bad packet ip. ! 39: */ ! 40: icmp_error(oip, type, code) ! 41: struct ip *oip; ! 42: int type, code; ! 43: { ! 44: register unsigned oiplen = oip->ip_hl << 2; ! 45: register struct icmp *icp; ! 46: struct mbuf *m; ! 47: struct ip *nip; ! 48: ! 49: #ifdef ICMPPRINTFS ! 50: if (icmpprintfs) ! 51: printf("icmp_error(%x, %d, %d)\n", oip, type, code); ! 52: #endif ! 53: icmpstat.icps_error++; ! 54: /* ! 55: * Make sure that the old IP packet had 8 bytes of data to return; ! 56: * if not, don't bother. Also don't EVER error if the old ! 57: * packet protocol was ICMP. ! 58: */ ! 59: if (oip->ip_len < 8) { ! 60: icmpstat.icps_oldshort++; ! 61: goto free; ! 62: } ! 63: if (oip->ip_p == IPPROTO_ICMP) { ! 64: icmpstat.icps_oldicmp++; ! 65: goto free; ! 66: } ! 67: ! 68: /* ! 69: * First, formulate icmp message ! 70: */ ! 71: m = m_get(M_DONTWAIT, MT_HEADER); ! 72: MBUFNULL(6,m); /* for debugging */ ! 73: if (m == NULL) ! 74: goto free; ! 75: m->m_len = oiplen + 8 + ICMP_MINLEN; ! 76: m->m_off = MMAXOFF - m->m_len; ! 77: icp = mtod(m, struct icmp *); ! 78: if ((u_int)type > ICMP_IREQREPLY) ! 79: panic("icmp_error"); ! 80: icmpstat.icps_outhist[type]++; ! 81: icp->icmp_type = type; ! 82: icp->icmp_void = 0; ! 83: if (type == ICMP_PARAMPROB) { ! 84: icp->icmp_pptr = code; ! 85: code = 0; ! 86: } ! 87: icp->icmp_code = code; ! 88: bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, oiplen + 8); ! 89: nip = &icp->icmp_ip; ! 90: nip->ip_len += oiplen; ! 91: nip->ip_len = htons((u_short)nip->ip_len); ! 92: ! 93: /* ! 94: * Now, copy old ip header in front of icmp ! 95: * message. This allows us to reuse any source ! 96: * routing info present. ! 97: */ ! 98: m->m_off -= oiplen; ! 99: nip = mtod(m, struct ip *); ! 100: bcopy((caddr_t)oip, (caddr_t)nip, oiplen); ! 101: nip->ip_len = m->m_len + oiplen; ! 102: nip->ip_p = IPPROTO_ICMP; ! 103: /* icmp_send adds ip header to m_off and m_len, so we deduct here */ ! 104: m->m_off += oiplen; ! 105: icmp_reflect(nip); ! 106: ! 107: free: ! 108: m_freem(dtom(oip)); ! 109: } ! 110: ! 111: static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP }; ! 112: static struct sockaddr_in icmpsrc = { AF_INET }; ! 113: static struct sockaddr_in icmpdst = { AF_INET }; ! 114: ! 115: /* ! 116: * Process a received ICMP message. ! 117: */ ! 118: icmp_input(m) ! 119: struct mbuf *m; ! 120: { ! 121: register struct icmp *icp; ! 122: register struct ip *ip = mtod(m, struct ip *); ! 123: int icmplen = ip->ip_len, hlen = ip->ip_hl << 2; ! 124: int (*ctlfunc)(), code, i; ! 125: extern u_char ip_protox[]; ! 126: ! 127: /* ! 128: * Locate icmp structure in mbuf, and check ! 129: * that not corrupted and of at least minimum length. ! 130: */ ! 131: #ifdef ICMPPRINTFS ! 132: if (icmpprintfs) ! 133: printf("icmp_input from %x, len %d\n", ip->ip_src, icmplen); ! 134: #endif ! 135: if (icmplen < ICMP_MINLEN) { ! 136: icmpstat.icps_tooshort++; ! 137: goto free; ! 138: } ! 139: m->m_len -= hlen; ! 140: m->m_off += hlen; ! 141: /* need routine to make sure header is in this mbuf here */ ! 142: icp = mtod(m, struct icmp *); ! 143: i = icp->icmp_cksum; ! 144: icp->icmp_cksum = 0; ! 145: if (i != in_cksum(m, icmplen)) { ! 146: icmpstat.icps_checksum++; ! 147: goto free; ! 148: } ! 149: ! 150: #ifdef ICMPPRINTFS ! 151: /* ! 152: * Message type specific processing. ! 153: */ ! 154: if (icmpprintfs) ! 155: printf("icmp_input, type %d code %d\n", icp->icmp_type, ! 156: icp->icmp_code); ! 157: #endif ! 158: if (icp->icmp_type > ICMP_IREQREPLY) ! 159: goto free; ! 160: icmpstat.icps_inhist[icp->icmp_type]++; ! 161: code = icp->icmp_code; ! 162: switch (icp->icmp_type) { ! 163: ! 164: case ICMP_UNREACH: ! 165: if (code > 5) ! 166: goto badcode; ! 167: code += PRC_UNREACH_NET; ! 168: goto deliver; ! 169: ! 170: case ICMP_TIMXCEED: ! 171: if (code > 1) ! 172: goto badcode; ! 173: code += PRC_TIMXCEED_INTRANS; ! 174: goto deliver; ! 175: ! 176: case ICMP_PARAMPROB: ! 177: if (code) ! 178: goto badcode; ! 179: code = PRC_PARAMPROB; ! 180: goto deliver; ! 181: ! 182: case ICMP_SOURCEQUENCH: ! 183: if (code) ! 184: goto badcode; ! 185: code = PRC_QUENCH; ! 186: deliver: ! 187: /* ! 188: * Problem with datagram; advise higher level routines. ! 189: */ ! 190: icp->icmp_ip.ip_len = ntohs((u_short)icp->icmp_ip.ip_len); ! 191: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { ! 192: icmpstat.icps_badlen++; ! 193: goto free; ! 194: } ! 195: #ifdef ICMPPRINTFS ! 196: if (icmpprintfs) ! 197: printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); ! 198: #endif ! 199: if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput) ! 200: (*ctlfunc)(code, (caddr_t)icp); ! 201: goto free; ! 202: ! 203: badcode: ! 204: icmpstat.icps_badcode++; ! 205: goto free; ! 206: ! 207: case ICMP_ECHO: ! 208: icp->icmp_type = ICMP_ECHOREPLY; ! 209: goto reflect; ! 210: ! 211: case ICMP_TSTAMP: ! 212: if (icmplen < ICMP_TSLEN) { ! 213: icmpstat.icps_badlen++; ! 214: goto free; ! 215: } ! 216: icp->icmp_type = ICMP_TSTAMPREPLY; ! 217: icp->icmp_rtime = iptime(); ! 218: icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ ! 219: goto reflect; ! 220: ! 221: case ICMP_IREQ: ! 222: #ifdef notdef ! 223: /* fill in source address zero fields! */ ! 224: goto reflect; ! 225: #else ! 226: goto free; /* not yet implemented: ignore */ ! 227: #endif ! 228: ! 229: case ICMP_REDIRECT: ! 230: if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) { ! 231: icmpstat.icps_badlen++; ! 232: goto free; ! 233: } ! 234: /* ! 235: * Short circuit routing redirects to force ! 236: * immediate change in the kernel's routing ! 237: * tables. The message is also handed to anyone ! 238: * listening on a raw socket (e.g. the routing ! 239: * daemon for use in updating it's tables). ! 240: */ ! 241: icmpsrc.sin_addr = icp->icmp_ip.ip_dst; ! 242: icmpdst.sin_addr = icp->icmp_gwaddr; ! 243: rtredirect((struct sockaddr *)&icmpsrc, ! 244: (struct sockaddr *)&icmpdst, ! 245: (((code == ICMP_REDIRECT_NET) || ! 246: (code == ICMP_REDIRECT_TOSNET)) ? ! 247: RTF_GATEWAY: (RTF_GATEWAY|RTF_HOST))); ! 248: /* falls through */ ! 249: ! 250: case ICMP_ECHOREPLY: ! 251: case ICMP_TSTAMPREPLY: ! 252: case ICMP_IREQREPLY: ! 253: icmpsrc.sin_addr = ip->ip_src; ! 254: icmpdst.sin_addr = ip->ip_dst; ! 255: raw_input(dtom(icp), &icmproto, (struct sockaddr *)&icmpsrc, ! 256: (struct sockaddr *)&icmpdst); ! 257: return; ! 258: ! 259: default: ! 260: goto free; ! 261: } ! 262: reflect: ! 263: ip->ip_len += hlen; /* since ip_input deducts this */ ! 264: icmpstat.icps_reflect++; ! 265: icmp_reflect(ip); ! 266: return; ! 267: free: ! 268: m_freem(dtom(ip)); ! 269: } ! 270: ! 271: /* ! 272: * Reflect the ip packet back to the source ! 273: * TODO: rearrange ip source routing options. ! 274: */ ! 275: icmp_reflect(ip) ! 276: struct ip *ip; ! 277: { ! 278: struct in_addr t; ! 279: ! 280: t = ip->ip_dst; ! 281: ip->ip_dst = ip->ip_src; ! 282: ip->ip_src = t; ! 283: icmp_send(ip); ! 284: } ! 285: ! 286: /* ! 287: * Send an icmp packet back to the ip level, ! 288: * after supplying a checksum. ! 289: */ ! 290: icmp_send(ip) ! 291: struct ip *ip; ! 292: { ! 293: register int hlen; ! 294: register struct icmp *icp; ! 295: register struct mbuf *m; ! 296: ! 297: m = dtom(ip); ! 298: hlen = ip->ip_hl << 2; ! 299: icp = mtod(m, struct icmp *); ! 300: icp->icmp_cksum = 0; ! 301: icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen); ! 302: m->m_off -= hlen; ! 303: m->m_len += hlen; ! 304: #ifdef ICMPPRINTFS ! 305: if (icmpprintfs) ! 306: printf("icmp_send dst %x src %x\n", ip->ip_dst, ip->ip_src); ! 307: #endif ! 308: (void) ip_output(m, (struct mbuf *)0, (struct route *)0, 0); ! 309: } ! 310: ! 311: n_time ! 312: iptime() ! 313: { ! 314: int s = spl8(); ! 315: u_long t; ! 316: ! 317: t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000; ! 318: splx(s); ! 319: return (htonl(t)); ! 320: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.