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