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