ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FastPing/FPing.xs
(Generate patch)

Comparing AnyEvent-FastPing/FPing.xs (file contents):
Revision 1.4 by root, Fri May 4 15:16:14 2007 UTC vs.
Revision 1.6 by root, Fri May 4 15:44:06 2007 UTC

28#include <netinet/in.h> 28#include <netinet/in.h>
29#include <arpa/inet.h> 29#include <arpa/inet.h>
30 30
31#ifdef __linux 31#ifdef __linux
32# include <linux/icmp.h> 32# include <linux/icmp.h>
33#endif
34#if IPV6
35# include <netinet/icmp6.h>
33#endif 36#endif
34 37
35#define ICMP4_ECHO 8 38#define ICMP4_ECHO 8
36#define ICMP4_ECHO_REPLY 0 39#define ICMP4_ECHO_REPLY 0
37#define ICMP6_ECHO 128 40#define ICMP6_ECHO 128
194 pkt.payload = req->payload; 197 pkt.payload = req->payload;
195 198
196 tstamp now = NOW (); 199 tstamp now = NOW ();
197 tstamp next = now; 200 tstamp next = now;
198 201
202 {
203 int r;
204 for (r = req->nranges; r--; )
205 inc_addr (&req->ranges [r].hi);
206 }
207
199 while (req->nranges) 208 while (req->nranges)
200 { 209 {
201 RANGE *range = req->ranges; 210 RANGE *range = req->ranges;
202 211
203 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t))) 212 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t)))
347 356
348 if (pipe (thr_recv) < 0) 357 if (pipe (thr_recv) < 0)
349 croak ("Net::FPing: unable to create receive pipe"); 358 croak ("Net::FPing: unable to create receive pipe");
350 359
351 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 360 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
352#if IPV6
353 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
354#endif
355
356#ifdef ICMP_FILTER 361#ifdef ICMP_FILTER
357 { 362 {
358 struct icmp_filter oval; 363 struct icmp_filter oval;
359 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY); 364 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY);
360 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); 365 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
361 } 366 }
367#endif
368
369#if IPV6
370 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
371# ifdef ICMP6_FILTER
372 {
373 struct icmp6_filter oval;
374 ICMP6_FILTER_SETBLOCKALL (&oval);
375 ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &oval);
376 setsockopt (icmp6_fd, IPPROTO_ICMPV6, ICMP6_FILTER, &oval, sizeof oval);
377 }
378# endif
362#endif 379#endif
363 380
364 pthread_attr_init (&attr); 381 pthread_attr_init (&attr);
365 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); 382 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
366#ifdef PTHREAD_SCOPE_PROCESS 383#ifdef PTHREAD_SCOPE_PROCESS
523 CODE: 540 CODE:
524{ 541{
525 char buf [512]; 542 char buf [512];
526 struct sockaddr_in sa; 543 struct sockaddr_in sa;
527 socklen_t sl = sizeof (sa); 544 socklen_t sl = sizeof (sa);
528 AV *res_av = newAV (); 545 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ());
529 SV *res_rv = sv_2mortal (newRV_noinc ((SV *)res_av));
530 tstamp now = NOW (); 546 tstamp now = NOW ();
531 547
532 for (;;) 548 for (;;)
533 { 549 {
534 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 550 int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl);
540 556
541 int hdrlen = (iphdr->version_ihl & 15) * 4; 557 int hdrlen = (iphdr->version_ihl & 15) * 4;
542 int totlen = ntohs (iphdr->tot_len); 558 int totlen = ntohs (iphdr->tot_len);
543 559
544 // packet corrupt? 560 // packet corrupt?
561 if (!res_av
545 if (totlen > len 562 || totlen > len
546 || iphdr->protocol != IPPROTO_ICMP 563 || iphdr->protocol != IPPROTO_ICMP
547 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) 564 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen)
548 continue; 565 continue;
549 566
550 PKT *pkt = (PKT *)(buf + hdrlen); 567 PKT *pkt = (PKT *)(buf + hdrlen);
561 av_push (av, newSVuv (pkt->payload)); 578 av_push (av, newSVuv (pkt->payload));
562 579
563 av_push (res_av, newRV_noinc ((SV *)av)); 580 av_push (res_av, newRV_noinc ((SV *)av));
564 } 581 }
565 582
583 if (res_av)
566 feed_reply (res_av); 584 feed_reply (res_av);
567} 585}
568 586
569void 587void
570_recv_icmp6 (...) 588_recv_icmp6 (...)
571 CODE: 589 CODE:
572{ 590{
573 struct sockaddr_in6 sa; 591 struct sockaddr_in6 sa;
574 socklen_t sl = sizeof (sa); 592 socklen_t sl = sizeof (sa);
575 AV *res_av = (AV *)sv_2mortal ((SV *)newAV ()); 593 AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ());
576 PKT pkt; 594 PKT pkt;
577 tstamp now = NOW (); 595 tstamp now = NOW ();
578 596
579 for (;;) 597 for (;;)
580 { 598 {
581 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 599 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl);
582 600
583 if (len != sizeof (PKT)) 601 if (len != sizeof (PKT))
584 break; 602 break;
585 603
604 if (!res_av
586 if (pkt.type != ICMP6_ECHO_REPLY 605 || pkt.type != ICMP6_ECHO_REPLY
587 || pkt.id != (uint16_t) MAGIC 606 || pkt.id != (uint16_t) MAGIC
588 || pkt.seq != (uint16_t)~MAGIC 607 || pkt.seq != (uint16_t)~MAGIC
589 || !isnormal (pkt.stamp)) 608 || !isnormal (pkt.stamp))
590 continue; 609 continue;
591 610
595 av_push (av, newSVuv (pkt.payload)); 614 av_push (av, newSVuv (pkt.payload));
596 615
597 av_push (res_av, newRV_noinc ((SV *)av)); 616 av_push (res_av, newRV_noinc ((SV *)av));
598 } 617 }
599 618
619 if (res_av)
600 feed_reply (res_av); 620 feed_reply (res_av);
601} 621}
602 622

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines