This source file includes following definitions.
- print_icmph
- icmp_reply
- icmp_rcv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <linux/types.h>
46 #include <linux/sched.h>
47 #include <linux/kernel.h>
48 #include <linux/fcntl.h>
49 #include <linux/socket.h>
50 #include <netinet/in.h>
51 #include "timer.h"
52 #include "ip.h"
53 #include "tcp.h"
54 #include "sock.h"
55 #include <linux/errno.h>
56 #include <linux/timer.h>
57 #include <asm/system.h>
58 #include <asm/segment.h>
59 #include "icmp.h"
60 #ifdef PRINTK
61 #undef PRINTK
62 #endif
63
64 #undef ICMP_DEBUG
65 #ifdef ICMP_DEBUG
66 #define PRINTK printk
67 #else
68 #define PRINTK dummy_routine
69 #endif
70
71 #define min(a,b) ((a)<(b)?(a):(b))
72
73
74 struct icmp_err icmp_err_convert[]=
75 {
76 {ENETUNREACH, 1},
77 {EHOSTUNREACH, 1},
78 {ENOPROTOOPT, 1},
79 {ECONNREFUSED, 1},
80 {EOPNOTSUPP, 0},
81 {EOPNOTSUPP, 0},
82 {ENETUNREACH, 1},
83 {EHOSTDOWN, 1},
84 {ENONET, 1},
85 {ENETUNREACH, 1},
86 {EHOSTUNREACH, 1},
87 {EOPNOTSUPP, 0},
88 {EOPNOTSUPP, 0}
89 };
90
91 void
92 print_icmph (struct icmp_header *icmph)
93 {
94 PRINTK (" type = %d, code = %d, checksum = %X\n", icmph->type,
95 icmph->code, icmph->checksum);
96 PRINTK (" gateway = %X\n", icmph->un.gateway);
97 }
98
99
100 void
101 icmp_reply (struct sk_buff *skb_in, int type, int code, struct device *dev)
102 {
103 struct sk_buff *skb;
104 struct ip_header *iph;
105 int offset;
106 struct icmp_header *icmph;
107
108 int len;
109
110 len = sizeof (*skb) + 8 +
111 sizeof (struct icmp_header) +
112 64 +
113 dev->hard_header_len;
114
115 skb = kmalloc (len, GFP_ATOMIC);
116 if (skb == NULL) return;
117
118 skb->mem_addr = skb;
119 skb->mem_len = len;
120
121 len -= sizeof (*skb);
122
123
124 iph = (struct ip_header *)(skb_in+1);
125 iph = (struct ip_header *)((unsigned char *)iph + dev->hard_header_len);
126
127
128 offset = ip_build_header( skb, iph->daddr, iph->saddr,
129 &dev, IPPROTO_ICMP, NULL, len );
130
131 if (offset < 0)
132 {
133 skb->sk = NULL;
134 kfree_skb (skb, FREE_READ);
135 return;
136 }
137
138
139 skb->len = offset + sizeof (struct icmp_header) + 8;
140
141 icmph = (struct icmp_header *)((unsigned char *)(skb+1) + offset);
142 icmph->type = type;
143 icmph->code = code;
144 icmph->checksum = 0;
145 icmph->un.gateway = 0;
146 memcpy (icmph+1, iph+1, 8);
147
148 ip_queue_xmit (NULL, dev, skb, 1);
149
150 }
151
152
153
154 int
155 icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
156 unsigned long daddr, unsigned short len,
157 unsigned long saddr, int redo, struct ip_protocol *protocol )
158 {
159 int size, offset;
160 struct icmp_header *icmph, *icmphr;
161 struct sk_buff *skb;
162 unsigned char *buff;
163
164
165
166 if ((daddr & 0xff000000) == 0 || (daddr & 0xff000000) == 0xff000000)
167 {
168 skb1->sk = NULL;
169 kfree_skb (skb1, FREE_READ);
170 return (0);
171 }
172
173 buff = skb1->h.raw;
174
175 icmph = (struct icmp_header *)buff;
176
177
178 if( icmph->checksum )
179 {
180 if( ip_compute_csum( (unsigned char *)icmph, len ) )
181 {
182
183 PRINTK("ICMP ECHO failed checksum!\n");
184 skb1->sk = NULL;
185 kfree_skb (skb1, FREE_READ);
186 return (0);
187 }
188 }
189
190 print_icmph(icmph);
191
192
193 switch( icmph->type )
194 {
195 case ICMP_DEST_UNREACH:
196 case ICMP_SOURCE_QUENCH:
197 {
198 struct ip_header *iph;
199 struct ip_protocol *ipprot;
200 unsigned char hash;
201 int err;
202
203 err = icmph->type << 8 | icmph->code;
204
205
206
207 iph = (struct ip_header *)(icmph+1);
208
209
210 hash = iph->protocol & (MAX_IP_PROTOS -1 );
211 for (ipprot = ip_protos[hash]; ipprot != NULL; ipprot=ipprot->next)
212 {
213
214 ipprot->err_handler (err, (unsigned char *)iph+4*iph->ihl,
215 iph->daddr, iph->saddr, ipprot);
216 }
217 skb1->sk = NULL;
218 kfree_skb (skb1, FREE_READ);
219 return (0);
220 }
221
222 case ICMP_REDIRECT:
223 {
224
225 struct rtable *rt;
226 struct ip_header *iph;
227
228 iph = (struct ip_header *)(icmph+1);
229 rt = kmalloc (sizeof (*rt), GFP_ATOMIC);
230 if (rt != NULL)
231 {
232 rt->net = iph->daddr;
233
234
235 if ((icmph->code & 1) == 0) rt->net &= 0x00ffffff;
236 rt->dev = dev;
237 rt->router = icmph->un.gateway;
238 add_route (rt);
239 }
240 skb1->sk = NULL;
241 kfree_skb (skb1, FREE_READ);
242 return (0);
243 }
244
245 case ICMP_ECHO:
246
247
248
249 size = sizeof( struct sk_buff ) + dev->hard_header_len + 64 + len;
250 skb = kmalloc( size, GFP_ATOMIC );
251 if (skb == NULL)
252 {
253 skb1->sk = NULL;
254 kfree_skb (skb1, FREE_READ);
255 return (0);
256 }
257 skb->sk = NULL;
258 skb->mem_addr = skb;
259 skb->mem_len = size;
260
261
262 offset = ip_build_header( skb, daddr, saddr, &dev, IPPROTO_ICMP, opt, len );
263 if (offset < 0)
264 {
265
266 PRINTK("Could not build IP Header for ICMP ECHO Response\n");
267 kfree_s (skb->mem_addr, skb->mem_len);
268 skb1->sk = NULL;
269 kfree_skb (skb1, FREE_READ);
270 return( 0 );
271 }
272
273
274 skb->len = offset + len;
275
276
277 icmphr = (struct icmp_header *)( (char *)( skb + 1 ) + offset );
278 memcpy( (char *)icmphr, (char *)icmph, len );
279 icmphr->type = ICMP_ECHOREPLY;
280 icmphr->code = 0;
281 icmphr->checksum = 0;
282
283 if( icmph->checksum )
284 {
285 icmphr->checksum = ip_compute_csum( (void *)icmphr, len );
286 }
287
288
289 ip_queue_xmit( (volatile struct sock *)NULL, dev, skb, 1 );
290
291 skb1->sk = NULL;
292 kfree_skb (skb1, FREE_READ);
293 return( 0 );
294
295 default:
296 PRINTK("Unsupported ICMP type = x%x\n", icmph->type );
297 skb1->sk = NULL;
298 kfree_skb (skb1, FREE_READ);
299 return( 0 );
300 }
301
302
303 skb1->sk = NULL;
304 kfree_skb (skb1, FREE_READ);
305 return( 0 );
306 }
307