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