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.3 by root, Fri May 4 13:50:02 2007 UTC vs.
Revision 1.5 by root, Fri May 4 15:33:56 2007 UTC

26#include <sys/socket.h> 26#include <sys/socket.h>
27 27
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
32# include <linux/icmp.h>
33#endif
34#if IPV6
35# include <netinet/icmp6.h>
36#endif
37
31#define ICMP4_ECHO 8 38#define ICMP4_ECHO 8
39#define ICMP4_ECHO_REPLY 0
32#define ICMP6_ECHO 128 40#define ICMP6_ECHO 128
41#define ICMP6_ECHO_REPLY 129
33 42
34#define DRAIN_INTERVAL .000001 // how long to wait when sendto returns ENOBUFS, in seconds 43#define DRAIN_INTERVAL .000001 // how long to wait when sendto returns ENOBUFS, in seconds
35#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds 44#define MIN_INTERVAL .000001 // minimum packet send interval, in seconds
36 45
37#define HDR_SIZE_IP4 20 46#define HDR_SIZE_IP4 20
185 pkt.code = 0; 194 pkt.code = 0;
186 pkt.id = (uint16_t)MAGIC; 195 pkt.id = (uint16_t)MAGIC;
187 pkt.seq = (uint16_t)~MAGIC; 196 pkt.seq = (uint16_t)~MAGIC;
188 pkt.payload = req->payload; 197 pkt.payload = req->payload;
189 198
190 tstamp next = NOW (); 199 tstamp now = NOW ();
200 tstamp next = now;
201
202 {
203 int r;
204 for (r = req->nranges; r--; )
205 inc_addr (&req->ranges [r].hi);
206 }
191 207
192 while (req->nranges) 208 while (req->nranges)
193 { 209 {
194 RANGE *range = req->ranges; 210 RANGE *range = req->ranges;
195 211
196 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t))) 212 if (!memcmp (&range->lo, &range->hi, sizeof (addr_t)))
197 req->ranges [0] = req->ranges [--req->nranges]; 213 req->ranges [0] = req->ranges [--req->nranges];
198 else 214 else
199 { 215 {
200 tstamp now = NOW ();
201
202 // ranges [0] is always the next range to ping 216 // ranges [0] is always the next range to ping
203 tstamp wait = range->next - now; 217 tstamp wait = range->next - now;
204 218
205 // compare with the global frequency limit 219 // compare with the global frequency limit
206 { 220 {
219 ts.tv_sec = wait; 233 ts.tv_sec = wait;
220 ts.tv_nsec = (wait - ts.tv_sec) * 1000000000.; 234 ts.tv_nsec = (wait - ts.tv_sec) * 1000000000.;
221 235
222 nanosleep (&ts, 0); 236 nanosleep (&ts, 0);
223 } 237 }
238
239 now = NOW ();
224 240
225 pkt.stamp = now; 241 pkt.stamp = now;
226 pkt.cksum = 0; 242 pkt.cksum = 0;
227 243
228 if (range->family == AF_INET) 244 if (range->family == AF_INET)
340 356
341 if (pipe (thr_recv) < 0) 357 if (pipe (thr_recv) < 0)
342 croak ("Net::FPing: unable to create receive pipe"); 358 croak ("Net::FPing: unable to create receive pipe");
343 359
344 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 360 icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
361#ifdef ICMP_FILTER
362 {
363 struct icmp_filter oval;
364 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO_REPLY);
365 setsockopt (icmp4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
366 }
367#endif
368
345#if IPV6 369#if IPV6
346 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); 370 icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
347#endif
348
349#ifdef ICMP_FILTER 371# ifdef ICMP6_FILTER
350 { 372 {
351 icmp_filter oval; 373 struct icmp6_filter oval;
352 oval.data = 0xffffffff & ~(1 << ICMP4_ECHO); 374 ICMP6_FILTER_SETBLOCKALL (&oval);
375 ICMP6_FILTER_SETPASS (ICMP6_ECHO_REPLY, &oval);
353 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); 376 setsockopt (icmp6_fd, IPPROTO_ICMPV6, ICMP6_FILTER, &oval, sizeof oval);
354 } 377 }
378# endif
355#endif 379#endif
356 380
357 pthread_attr_init (&attr); 381 pthread_attr_init (&attr);
358 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); 382 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
359#ifdef PTHREAD_SCOPE_PROCESS 383#ifdef PTHREAD_SCOPE_PROCESS
387 boot (); 411 boot ();
388 412
389 newCONSTSUB (stash, "ipv4_supported", newSViv (icmp4_fd >= 0)); 413 newCONSTSUB (stash, "ipv4_supported", newSViv (icmp4_fd >= 0));
390 newCONSTSUB (stash, "ipv6_supported", newSViv (icmp6_fd >= 0)); 414 newCONSTSUB (stash, "ipv6_supported", newSViv (icmp6_fd >= 0));
391 415
392 newCONSTSUB (stash, "ipv4_pktsize", newSViv (HDR_SIZE_IP4 + sizeof (PKT))); 416 newCONSTSUB (stash, "icmp4_pktsize", newSViv (HDR_SIZE_IP4 + sizeof (PKT)));
393 newCONSTSUB (stash, "ipv6_pktsize", newSViv (HDR_SIZE_IP6 + sizeof (PKT))); 417 newCONSTSUB (stash, "icmp6_pktsize", newSViv (HDR_SIZE_IP6 + sizeof (PKT)));
394} 418}
395 419
396PROTOTYPES: DISABLE 420PROTOTYPES: DISABLE
397 421
398SV * 422SV *
540 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) 564 || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen)
541 continue; 565 continue;
542 566
543 PKT *pkt = (PKT *)(buf + hdrlen); 567 PKT *pkt = (PKT *)(buf + hdrlen);
544 568
569 if (pkt->type != ICMP4_ECHO_REPLY
545 if (pkt->id != (uint16_t)MAGIC 570 || pkt->id != (uint16_t) MAGIC
546 || pkt->seq != (uint16_t)~MAGIC 571 || pkt->seq != (uint16_t)~MAGIC
547 || pkt->type != ICMP4_ECHO
548 || !isnormal (pkt->stamp)) 572 || !isnormal (pkt->stamp))
549 continue; 573 continue;
550 574
551 AV *av = newAV (); 575 AV *av = newAV ();
552 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4)); 576 av_push (av, newSVpvn ((char *)&sa.sin_addr, 4));
574 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); 598 int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl);
575 599
576 if (len != sizeof (PKT)) 600 if (len != sizeof (PKT))
577 break; 601 break;
578 602
579 if (pkt.type != ICMP6_ECHO 603 if (pkt.type != ICMP6_ECHO_REPLY
580 || pkt.id != (uint16_t)MAGIC 604 || pkt.id != (uint16_t) MAGIC
581 || pkt.seq != (uint16_t)~MAGIC 605 || pkt.seq != (uint16_t)~MAGIC
582 || !isnormal (pkt.stamp)) 606 || !isnormal (pkt.stamp))
583 continue; 607 continue;
584 608
585 AV *av = newAV (); 609 AV *av = newAV ();

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines