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