?? icmp.c
字號(hào):
224 printk("ICMP: cannot handle TOS redirects yet!\n");
225 break;
226 default:
227 DPRINTF((DBG_ICMP, "ICMP: Unreach: CODE=%d\n",
228 (icmph->code & 7)));
229 break;
230 }
231 skb->sk = NULL;
232 kfree_skb(skb, FREE_READ);
233 }
234
235
236 /* Handle ICMP_ECHO ("ping") requests. */
237 static void
238 icmp_echo(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
239 unsigned long saddr, unsigned long daddr, int len,
240 struct options *opt)
241 {
242 struct icmphdr *icmphr;
243 struct sk_buff *skb2;
244 int size, offset;
245
246 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
247 skb2 = alloc_skb(size, GFP_ATOMIC);
248 if (skb2 == NULL) {
249 skb->sk = NULL;
250 kfree_skb(skb, FREE_READ);
251 return;
252 }
253 skb2->sk = NULL;
254 skb2->mem_addr = skb2;
255 skb2->mem_len = size;
256 skb2->free = 1;
257
258 /* Build Layer 2-3 headers for message back to source */
259 offset = ip_build_header(skb2, daddr, saddr, &dev,
260 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
261 if (offset < 0) {
262 printk("ICMP: Could not build IP Header for ICMP ECHO Response\n");
263 kfree_skb(skb2,FREE_WRITE);
264 skb->sk = NULL;
265 kfree_skb(skb, FREE_READ);
266 return;
267 }
268
269 /* Re-adjust length according to actual IP header size. */
270 skb2->len = offset + len;
271
272 /* Build ICMP_ECHO Response message. */
273 icmphr = (struct icmphdr *) (skb2->data + offset);
274 memcpy((char *) icmphr, (char *) icmph, len);
275 icmphr->type = ICMP_ECHOREPLY;
276 icmphr->code = 0;
277 icmphr->checksum = 0;
278 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
279
280 /* Ship it out - free it when done */
281 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
282
283 skb->sk = NULL;
284 kfree_skb(skb, FREE_READ);
285 }
286
287
288 /* Handle the ICMP INFORMATION REQUEST. */
289 static void
290 icmp_info(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
291 unsigned long saddr, unsigned long daddr, int len,
292 struct options *opt)
293 {
294 /* NOT YET */
295 skb->sk = NULL;
296 kfree_skb(skb, FREE_READ);
297 }
298
299
300 /* Handle ICMP_ADRESS_MASK requests. */
301 static void
302 icmp_address(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev,
303 unsigned long saddr, unsigned long daddr, int len,
304 struct options *opt)
305 {
306 struct icmphdr *icmphr;
307 struct sk_buff *skb2;
308 int size, offset;
309
310 size = sizeof(struct sk_buff) + dev->hard_header_len + 64 + len;
311 skb2 = alloc_skb(size, GFP_ATOMIC);
312 if (skb2 == NULL) {
313 skb->sk = NULL;
314 kfree_skb(skb, FREE_READ);
315 return;
316 }
317 skb2->sk = NULL;
318 skb2->mem_addr = skb2;
319 skb2->mem_len = size;
320 skb2->free = 1;
321
322 /* Build Layer 2-3 headers for message back to source */
323 offset = ip_build_header(skb2, daddr, saddr, &dev,
324 IPPROTO_ICMP, opt, len, skb->ip_hdr->tos,255);
325 if (offset < 0) {
326 printk("ICMP: Could not build IP Header for ICMP ADDRESS Response\n");
327 kfree_skb(skb2,FREE_WRITE);
328 skb->sk = NULL;
329 kfree_skb(skb, FREE_READ);
330 return;
331 }
332
333 /* Re-adjust length according to actual IP header size. */
334 skb2->len = offset + len;
335
336 /* Build ICMP ADDRESS MASK Response message. */
337 icmphr = (struct icmphdr *) (skb2->data + offset);
338 icmphr->type = ICMP_ADDRESSREPLY;
339 icmphr->code = 0;
340 icmphr->checksum = 0;
341 icmphr->un.echo.id = icmph->un.echo.id;
342 icmphr->un.echo.sequence = icmph->un.echo.sequence;
343 memcpy((char *) (icmphr + 1), (char *) &dev->pa_mask, sizeof(dev->pa_mask));
344
345 icmphr->checksum = ip_compute_csum((unsigned char *)icmphr, len);
346
347 /* Ship it out - free it when done */
348 ip_queue_xmit((struct sock *)NULL, dev, skb2, 1);
349
350 skb->sk = NULL;
351 kfree_skb(skb, FREE_READ);
352 }
353
354
355 /* Deal with incoming ICMP packets. */
356 int
357 icmp_rcv(struct sk_buff *skb1, struct device *dev, struct options *opt,
358 unsigned long daddr, unsigned short len,
359 unsigned long saddr, int redo, struct inet_protocol *protocol)
360 {
361 struct icmphdr *icmph;
362 unsigned char *buff;
363
364 /* Drop broadcast packets. */
365 if (chk_addr(daddr) == IS_BROADCAST) {
366 DPRINTF((DBG_ICMP, "ICMP: Discarded broadcast from %s\n",
367 in_ntoa(saddr)));
368 skb1->sk = NULL;
369 kfree_skb(skb1, FREE_READ);
370 return(0);
371 }
372
373 buff = skb1->h.raw;
374 icmph = (struct icmphdr *) buff;
375
376 /* Validate the packet first */
377 if (ip_compute_csum((unsigned char *) icmph, len)) {
378 /* Failed checksum! */
379 printk("ICMP: failed checksum from %s!\n", in_ntoa(saddr));
380 skb1->sk = NULL;
381 kfree_skb(skb1, FREE_READ);
382 return(0);
383 }
384 print_icmp(icmph);
385
386 /* Parse the ICMP message */
387 switch(icmph->type) {
388 case ICMP_TIME_EXCEEDED:
389 case ICMP_DEST_UNREACH:
390 case ICMP_SOURCE_QUENCH:
391 icmp_unreach(icmph, skb1);
392 return(0);
393 case ICMP_REDIRECT:
394 icmp_redirect(icmph, skb1, dev);
395 return(0);
396 case ICMP_ECHO:
397 icmp_echo(icmph, skb1, dev, saddr, daddr, len, opt);
398 return 0;
399 case ICMP_ECHOREPLY:
400 skb1->sk = NULL;
401 kfree_skb(skb1, FREE_READ);
402 return(0);
403 case ICMP_INFO_REQUEST:
404 icmp_info(icmph, skb1, dev, saddr, daddr, len, opt);
405 return 0;
406 case ICMP_INFO_REPLY:
407 skb1->sk = NULL;
408 kfree_skb(skb1, FREE_READ);
409 return(0);
410 case ICMP_ADDRESS:
411 icmp_address(icmph, skb1, dev, saddr, daddr, len, opt);
412 return 0;
413 case ICMP_ADDRESSREPLY:
414 skb1->sk = NULL;
415 kfree_skb(skb1, FREE_READ);
416 return(0);
417 default:
418 DPRINTF((DBG_ICMP,
419 "ICMP: Unsupported ICMP from %s, type = 0x%X\n",
420 in_ntoa(saddr), icmph->type));
421 skb1->sk = NULL;
422 kfree_skb(skb1, FREE_READ);
423 return(0);
424 }
425 /*NOTREACHED*/
426 skb1->sk = NULL;
427 kfree_skb(skb1, FREE_READ);
428 return(-1);
429 }
430
431
432 /* Perform any ICMP-related I/O control requests. */
433 int
434 icmp_ioctl(struct sock *sk, int cmd, unsigned long arg)
435 {
436 switch(cmd) {
437 case DDIOCSDBG:
438 return(dbg_ioctl((void *) arg, DBG_ICMP));
439 default:
440 return(-EINVAL);
441 }
442 return(0);
443 }
444
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -