1 /* ip_icmp.c 4.2 81/11/08 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/inaddr.h" 6 #include "../net/inet.h" 7 #include "../net/inet_systm.h" 8 #include "../net/ip.h" 9 #include "../net/ip_icmp.h" 10 11 /* 12 * ICMP routines: error generation, receive packet processing, and 13 * routines to turnaround packets back to the originator, and 14 * host table maintenance routines. 15 */ 16 17 /* 18 * Generate an error packet of type error in response to bad packet ip. 19 */ 20 icmp_error(oip, type, code) 21 struct ip *oip; 22 int type; 23 { 24 int oiplen = oip->ip_hl << 2; 25 struct icmp *icp = (struct icmp *)((int)oip + oiplen); 26 struct mbuf *m; 27 struct ip *nip; 28 29 /* 30 * Make sure that the old IP packet had 8 bytes of data to return; 31 * if not, don't bother. Also don't EVER error if the old 32 * packet protocol was ICMP. 33 */ 34 if (oip->ip_len - oiplen < 8 || oip->ip_p == IPPROTO_ICMP) 35 goto free; 36 37 /* 38 * Get a new mbuf, and fill in a ICMP header at the bottom 39 * of the mbuf, followed by the old IP header and 8 bytes 40 * of its data. 41 */ 42 m = m_get(0); 43 if (m == 0) 44 goto free; 45 m->m_off = MMAXOFF - (oiplen + 8); 46 icp->icmp_type = type; 47 if (type == ICMP_PARAMPROB) { 48 icp->icmp_code = 0; 49 icp->icmp_pptr = code; 50 } else 51 icp->icmp_code = code; 52 bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, oiplen + 8); 53 54 /* 55 * Now prepend an IP header and reflect this packet back to 56 * the source. 57 */ 58 m->m_off -= sizeof (struct ip); 59 m->m_len += sizeof (struct ip); 60 nip = (struct ip *)mtod(m, struct ip *); 61 *nip = *oip; 62 icmp_reflect(nip); 63 64 /* 65 * Discard mbufs of original datagram 66 */ 67 free: 68 m_freem(dtom(oip)); 69 } 70 71 /* 72 * Process a received ICMP message. 73 */ 74 icmp_input(m) 75 struct mbuf *m; 76 { 77 register struct icmp *icp; 78 register struct ip *ip = mtod(m, struct ip *); 79 int hlen = ip->ip_hl << 2; 80 int icmplen = ip->ip_len - hlen; 81 int i; 82 83 /* 84 * Locate icmp structure in mbuf, and check 85 * that not corrupted and of at least minimum length. 86 */ 87 m->m_len -= hlen; 88 m->m_off += hlen; 89 /* need routine to make sure header is in this mbuf here */ 90 icp = (struct icmp *)mtod(m, struct icmp *); 91 i = icp->icmp_cksum; 92 icp->icmp_cksum = 0; 93 if (i != inet_cksum(m, icmplen) || icmplen < ICMP_MINLEN) 94 goto free; 95 96 /* 97 * Message type specific processing. 98 */ 99 switch (icp->icmp_type) { 100 101 case ICMP_UNREACH: 102 case ICMP_TIMXCEED: 103 case ICMP_PARAMPROB: 104 case ICMP_SOURCEQUENCH: 105 case ICMP_REDIRECT: 106 /* 107 * Problem with previous datagram; advise 108 * higher level routines. 109 */ 110 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) 111 goto free; 112 icmp_advise(ip, icp); 113 goto free; 114 115 case ICMP_ECHO: 116 icp->icmp_type = ICMP_ECHOREPLY; 117 goto reflect; 118 119 case ICMP_TSTAMP: 120 if (icmplen < ICMP_TSLEN) 121 goto free; 122 icp->icmp_type = ICMP_TSTAMPREPLY; 123 ip_time(&icp->icmp_rtime); 124 icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ 125 goto reflect; 126 127 case ICMP_IREQ: 128 /* fill in source address zero fields! */ 129 goto reflect; 130 131 case ICMP_ECHOREPLY: 132 case ICMP_TSTAMPREPLY: 133 case ICMP_IREQREPLY: 134 if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) 135 goto free; 136 icmp_gotreply(icp); 137 goto free; 138 139 default: 140 goto free; 141 } 142 reflect: 143 icmp_reflect(ip); 144 free: 145 m_freem(dtom(ip)); 146 } 147 148 /* 149 * Reflect the ip packet back to the source 150 */ 151 icmp_reflect(ip) 152 struct ip *ip; 153 { 154 struct ip_addr t; 155 156 t = ip->ip_src; ip->ip_dst = ip->ip_src; ip->ip_src = t; 157 /* 158 * This is a little naive... do we have to munge the options 159 * to reverse source routing? 160 */ 161 icmp_send(ip); 162 } 163 164 /* 165 * Send an icmp packet back to the ip level, after 166 * supplying a checksum. 167 */ 168 icmp_send(ip, icp) 169 struct ip *ip; 170 struct icmp *icp; 171 { 172 173 icp->icmp_cksum = 0; 174 icp->icmp_inet_cksum = cksum(dtom(ip), 0); /* ### */ 175 /* what about ttl? */ 176 ip_output(ip); 177 } 178 179 /* 180 * Advise a higher level protocol of a problem reported by 181 * a gateway or another host. 182 */ 183 icmp_advise(ip, icp) 184 struct ip *ip; 185 struct icmp *icp; 186 { 187 188 /* pass through protocol specific switch */ 189 /* (*f)(ip, icp); */ 190 } 191 192 /* 193 * Got a reply, e.g. to an echo message or a timestamp 194 * message; nothing is done with these yet. 195 */ 196 /*ARGSUSED*/ 197 icmp_gotreply(icp) 198 struct icmp *icp; 199 { 200 201 } 202 203 icmp_drain() 204 { 205 206 } 207 208 ip_time() 209 { 210 211 } 212