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