|
|
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.