免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3745 | 回复: 4

ipv6的icmp ping,有什么可用的模块么? [复制链接]

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
发表于 2013-12-05 18:39 |显示全部楼层
最好是支持event的,不过
anyevent之下,好像没有做v6 ping的

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
发表于 2013-12-06 16:36 |显示全部楼层
好失败呀.尝试了io::socket:inet6和io::socket::ip都不行...
直接换成socket看看,
5.14以上的socket应该可以支持ipv6了呀.

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
发表于 2013-12-09 14:34 |显示全部楼层
本帖最后由 laputa73 于 2013-12-09 16:09 编辑

倒腾了2天,照葫芦画瓢, 搞出个勉强可用的版本.

1.改造Anyevent:ing模块,另存存为一个新的Ping6模块
  1. #package AnyEvent::Ping6;

  2. #use 5.008_001;
  3. use 5.014;  #need socket version of perl 5.14
  4. use strict;
  5. use warnings;


  6. our $VERSION = 0.001;  #new version num


  7. use Time::HiRes 'time';
  8. use IO::Socket::IP qw/SOCK_RAW PF_INET6 AF_INET6 pack_sockaddr_in6 inet_pton/;
  9. #use IO::Socket::INET qw/sockaddr_in inet_aton/;
  10. use List::Util ();
  11. use AnyEvent::Handle;
  12. require Carp;

  13. #my $ICMP_PING = 'ccnnnA*';
  14. my $ICMP_PING = 'CcnnnA*';   #C means unsigned char,supporting 128,129.

  15. #my $ICMP_ECHOREPLY     = 0;     # Echo Reply
  16. my $ICMP_ECHOREPLY     = 129;     # Echo Reply of icmpv6
  17. my $ICMP_DEST_UNREACH  = 3;     # Destination Unreachable
  18. my $ICMP_SOURCE_QUENCH = 4;     # Source Quench
  19. my $ICMP_REDIRECT      = 5;     # Redirect (change route)
  20. #my $ICMP_ECHO          = 8;     # Echo Request
  21. my $ICMP_ECHO          = 128;     # Echo Request of icmpv6
  22. my $ICMP_TIME_EXCEEDED = 11;    # Time Exceeded

  23. sub new {
  24.     my ($class, %args) = @_;

  25.     my $interval = $args{interval};
  26.     $interval = 0.2 unless defined $interval;

  27.     my $timeout = $args{timeout};
  28.     $timeout = 5 unless defined $timeout;

  29.     my $self = bless {interval => $interval, timeout => $timeout}, $class;

  30.     # Create RAW socket
  31.     my $socket = IO::Socket::IP->new(
  32.         Family  => PF_INET6,
  33.         Proto    => 58,   #IPPROTO_ICMPV6 = 58
  34.         Type     => SOCK_RAW,
  35.         Blocking => 0
  36.     ) or Carp::croak "Unable to create icmp socket : $!";


  37.    
  38.     $self->{_socket} = $socket;

  39.     # Create Poll object
  40.     $self->{_poll_read} = AnyEvent->io(
  41.         fh   => $socket,
  42.         poll => 'r',
  43.         cb   => sub { $self->_on_read },
  44.     );

  45.     # Ping tasks
  46.     $self->{_tasks}     = [];
  47.     $self->{_tasks_out} = [];

  48.     return $self;
  49. }

  50. sub interval { @_ > 1 ? $_[0]->{interval} = $_[1] : $_[0]->{interval} }

  51. sub timeout { @_ > 1 ? $_[0]->{timeout} = $_[1] : $_[0]->{timeout} }

  52. sub error { $_[0]->{error} }

  53. sub ping {
  54.     my ($self, $host, $times, $cb) = @_;

  55.     my $socket = $self->{_socket};

  56.     #my $ip = inet_aton($host);
  57.     my $ip = inet_pton(AF_INET6,$host);  #ipv6 addr,16bytes

  58.     my $request = {
  59.         host        => $host,
  60.         times       => $times,
  61.         results     => [],
  62.         cb          => $cb,
  63.         identifier  => int(rand 0x10000),  #may collision?
  64.         #destination => scalar sockaddr_in(0, $ip),
  65.         destination => scalar pack_sockaddr_in6(0, $ip),    #$sockaddr = pack_sockaddr_in6 $port, $ip6_address, [$scope_id, [$flowinfo]]
  66.     };

  67.     push @{$self->{_tasks}}, $request;

  68.     push @{$self->{_tasks_out}}, $request;

  69.     $self->_add_write_poll;

  70.     return $self;
  71. }

  72. sub _add_write_poll {
  73.     my $self = shift;

  74.     return if exists $self->{_poll_write};

  75.     $self->{_poll_write} = AnyEvent->io(
  76.         fh   => $self->{_socket},
  77.         poll => 'w',
  78.         cb   => sub { $self->_send_requests },
  79.     );
  80. }

  81. sub _send_requests {
  82.     my $self = shift;

  83.     foreach my $request (@{$self->{_tasks_out}}) {
  84.         $self->_send_request($request);
  85.     }

  86.     $self->{_tasks_out} = [];
  87.     delete $self->{_poll_write};
  88. }

  89. sub _on_read {
  90.     my $self = shift;

  91.     my $socket = $self->{_socket};
  92.     $socket->sysread(my $chunk, 4194304, 0);

  93.     #ipv4
  94.     #my $icmp_msg = substr $chunk, 20;
  95.     #ipv6  参考ping.py.v6少了20byte的头
  96.     my $icmp_msg = substr $chunk, 0;
  97.    
  98.     my ($type, $identifier, $sequence, $data);

  99.     #$type = unpack 'c', $icmp_msg;
  100.     $type = unpack 'C', $icmp_msg;
  101.     #print ("====got type=$type.\n");
  102.     if ($type == $ICMP_ECHOREPLY) {
  103.         ($type, $identifier, $sequence, $data) =
  104.           (unpack $ICMP_PING, $icmp_msg)[0, 3, 4, 5];
  105.     }
  106.     elsif ($type == $ICMP_DEST_UNREACH || $type == $ICMP_TIME_EXCEEDED) {
  107.         ($identifier, $sequence) = unpack('nn', substr($chunk, 52));
  108.     }
  109.     else {

  110.         # Don't mind
  111.         return;
  112.     }

  113.     # Find our task
  114.     my $request =
  115.       List::Util::first { $identifier == $_->{identifier} }
  116.     @{$self->{_tasks}};

  117.     return unless $request;

  118.     # Is it response to our latest message?
  119.     return unless $sequence == @{$request->{results}} + 1;

  120.     if ($type == $ICMP_ECHOREPLY) {

  121.         # Check data
  122.         if ($data eq $request->{data}) {
  123.             $self->_store_result($request, 'OK');
  124.         }
  125.         else {
  126.             $self->_store_result($request, 'MALFORMED');
  127.         }
  128.     }
  129.     elsif ($type == $ICMP_DEST_UNREACH) {
  130.         $self->_store_result($request, 'DEST_UNREACH');
  131.     }
  132.     elsif ($type == $ICMP_TIME_EXCEEDED) {
  133.         $self->_store_result($request, 'TIMEOUT');
  134.     }
  135. }

  136. sub _store_result {
  137.     my ($self, $request, $result) = @_;

  138.     my $results = $request->{results};

  139.     # Clear request specific data
  140.     delete $request->{timer};

  141.     push @$results, [$result, time - $request->{start}];

  142.     if (@$results == $request->{times} || $result eq 'ERROR') {

  143.         # Cleanup
  144.         my $tasks = $self->{_tasks};
  145.         for my $i (0 .. scalar @$tasks) {
  146.             if ($tasks->[$i] == $request) {
  147.                 splice @$tasks, $i, 1;
  148.                 last;
  149.             }
  150.         }

  151.         # Testing done
  152.         $request->{cb}->($results);

  153.         undef $request;
  154.     }

  155.     # Perform another check
  156.     else {

  157.         # Setup interval timer before next request
  158.         my $w;
  159.         $w = AnyEvent->timer(
  160.             after => $self->interval,
  161.             cb    => sub {
  162.                 undef $w;
  163.                 push @{$self->{_tasks_out}}, $request;
  164.                 $self->_add_write_poll;
  165.             }
  166.         );
  167.     }
  168. }

  169. sub _send_request {
  170.     my ($self, $request) = @_;

  171.     my $checksum   = 0x0000;
  172.     my $identifier = $request->{identifier};
  173.     my $sequence   = @{$request->{results}} + 1;
  174.     my $data       = 'abcdef';  #test payload.should store starttime better.

  175.     my $msg = pack $ICMP_PING,
  176.       $ICMP_ECHO, 0x00, $checksum,
  177.       $identifier, $sequence, $data;

  178.     $checksum = $self->_icmp_checksum($msg);

  179.     $msg = pack $ICMP_PING,
  180.       $ICMP_ECHO, 0x00, $checksum,
  181.       $identifier, $sequence, $data;

  182.     $request->{data} = $data;

  183.     $request->{start} = time;

  184.     $request->{timer} = AnyEvent->timer(
  185.         after => $self->timeout,
  186.         cb    => sub {
  187.             $self->_store_result($request, 'TIMEOUT');
  188.         }
  189.     );

  190.     my $socket = $self->{_socket};

  191.     $socket->send($msg, 0, $request->{destination}) or
  192.         $self->_store_result($request, "ERROR($!)");
  193. }

  194. sub _icmp_checksum {
  195.     my ($self, $msg) = @_;

  196.     my $res = 0;
  197.     foreach my $int (unpack "n*", $msg) {
  198.         $res += $int;
  199.     }

  200.     # Add possible odd byte
  201.     $res += unpack('C', substr($msg, -1, 1)) << 8
  202.       if length($msg) % 2;

  203.     # Fold high into low
  204.     $res = ($res >> 16) + ($res & 0xffff);

  205.     # Two times
  206.     $res = ($res >> 16) + ($res & 0xffff);

  207.     return ~$res;
  208. }

  209. 1;
  210. __END__

  211. =head1 NAME

  212. AnyEvent::Ping - ping hosts with AnyEvent

  213. =head1 SYNOPSIS

  214.     use AnyEvent;
  215.     use AnyEvent::Ping;

  216.     my $c = AnyEvent->condvar;

  217.     my $ping = AnyEvent::Ping->new;

  218.     $ping->ping('google.com', 1, sub {
  219.         my $result = shift;
  220.         print "Result: ", $result->[0][0],
  221.           " in ", $result->[0][1], " seconds\n";
  222.         $c->send;
  223.     });

  224.     $c->recv;

  225. =head1 DESCRIPTION

  226. L<AnyEvent::Ping> is an asynchronous AnyEvent pinger.

  227. =head1 ATTRIBUTES

  228. L<AnyEvent::Ping> implements the following attributes.

  229. =head2 C<interval>

  230.     my $interval = $ping->interval;
  231.     $ping->interval(1);

  232. Interval between pings, defaults to 0.2 seconds.

  233. =head2 C<timeout>
  234.    
  235.     my $timeout = $ping->timeout;
  236.     $ping->timeout(3);

  237. Maximum response time, defaults to 5 seconds.

  238. =head2 C<error>

  239.     my $error = $ping->error;

  240. Last error message.

  241. =head1 METHODS

  242. L<AnyEvent::Ping> implements the following methods.

  243. =head2 C<ping>

  244.     $ping->ping($ip, $n => sub {
  245.         my $result = shift;
  246.     });

  247. Perform a ping of a given $ip address $n times.

  248. =head1 SEE ALSO

  249. L<AnyEvent>, L<AnyEvent::FastPing>

  250. =head1 AUTHOR

  251. Sergey Zasenko, C<undef@cpan.org>.

  252. =head1 COPYRIGHT AND LICENSE

  253. Copyright (C) 2012, Sergey Zasenko

  254. This program is free software, you can redistribute it and/or modify it under
  255. the same terms as Perl 5.12.

  256. =cut
复制代码
2.测试程序
  1. #!/usr/bin/perl
  2. use 5.014;
  3. use AnyEvent;
  4.     use AnyEvent::Ping6;

  5.     my $c = AnyEvent->condvar;

  6.     my $ping = AnyEvent::Ping6->new;

  7.     $ping->ping('::1', 1, sub {
  8.         my $result = shift;
  9.         print "Result: ", $result->[0][0],
  10.           " in ", $result->[0][1], " seconds\n";
  11.         $c->send;
  12.     });

  13.     $c->recv;
复制代码
小结,5.14以后,Socket已经可以支持ipv6.原来的Socket6和io::socket::inet6基本就废弃了.
   改为新的io::socket::IP.

论坛徽章:
3
未羊
日期:2013-11-18 15:17:06酉鸡
日期:2013-12-06 17:07:16天蝎座
日期:2014-06-11 12:37:07
发表于 2013-12-10 09:38 |显示全部楼层
  神一样的人。。。

论坛徽章:
42
19周年集字徽章-周
日期:2019-10-14 14:35:31平安夜徽章
日期:2015-12-26 00:06:30数据库技术版块每日发帖之星
日期:2015-12-01 06:20:002015亚冠之首尔
日期:2015-11-04 22:25:43IT运维版块每日发帖之星
日期:2015-08-17 06:20:00寅虎
日期:2014-06-04 16:25:27狮子座
日期:2014-05-12 11:00:00辰龙
日期:2013-12-20 17:07:19射手座
日期:2013-10-24 21:01:23CU十二周年纪念徽章
日期:2013-10-24 15:41:34IT运维版块每日发帖之星
日期:2016-01-27 06:20:0015-16赛季CBA联赛之新疆
日期:2016-06-07 14:10:01
发表于 2013-12-10 11:10 |显示全部楼层
依葫芦画瓢而已,程序员的基本技能...
做运维网管也许用得到.
ps.
好久没有得徽章了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP