1 | #define _POSIX_C_SOURCE 199309 |
1 | #define _POSIX_C_SOURCE 199309 |
2 | #define _GNU_SOURCE 1 |
2 | #define _GNU_SOURCE 1 |
3 | |
3 | |
4 | #define IPV6 1 |
4 | #define IPV6 1 // if you get compilation problems try to disable IPv6 |
5 | |
5 | |
6 | #include "EXTERN.h" |
6 | #include "EXTERN.h" |
7 | #include "perl.h" |
7 | #include "perl.h" |
8 | #include "XSUB.h" |
8 | #include "XSUB.h" |
9 | |
9 | |
… | |
… | |
99 | |
99 | |
100 | typedef struct { |
100 | typedef struct { |
101 | uint8_t type, code; |
101 | uint8_t type, code; |
102 | uint16_t cksum; |
102 | uint16_t cksum; |
103 | uint16_t id, seq; |
103 | uint16_t id, seq; |
|
|
104 | uint32_t payload; |
104 | tstamp stamp; // be careful when accessing this |
105 | tstamp stamp; // be careful when accessing this |
105 | uint32_t payload; |
|
|
106 | } PKT; |
106 | } PKT; |
107 | |
107 | |
108 | pthread_t pthrid; |
108 | pthread_t pthrid; |
109 | int thr_send[2]; // send to worker |
109 | int thr_send[2]; // send to worker |
110 | int thr_recv[2]; // receive from worker |
110 | int thr_recv[2]; // receive from worker |
111 | |
111 | |
112 | int icmp4_fd, icmp6_fd; |
112 | int icmp4_fd, icmp6_fd; |
113 | |
113 | |
114 | uint16_t |
114 | static uint16_t |
115 | icmp_cksum (void *data, unsigned int len) |
115 | icmp_cksum (void *data, unsigned int len) |
116 | { |
116 | { |
117 | register int sum = 0; |
117 | register int sum = 0; |
118 | uint16_t *wp; |
118 | uint16_t *wp; |
119 | |
119 | |
… | |
… | |
157 | |
157 | |
158 | memset (&pkt, 0, sizeof (pkt)); |
158 | memset (&pkt, 0, sizeof (pkt)); |
159 | |
159 | |
160 | memset (&sa4, 0, sizeof (sa4)); |
160 | memset (&sa4, 0, sizeof (sa4)); |
161 | sa4.sin_family = AF_INET; |
161 | sa4.sin_family = AF_INET; |
162 | sa4.sin_port = 0; // unused |
162 | sa4.sin_port = IPPROTO_ICMP; |
163 | #if IPV6 |
163 | #if IPV6 |
164 | memset (&sa6, 0, sizeof (sa6)); |
164 | memset (&sa6, 0, sizeof (sa6)); |
165 | sa6.sin6_family = AF_INET6; |
165 | sa6.sin6_family = AF_INET6; |
166 | sa6.sin6_port = 0; // unused |
166 | sa6.sin6_port = IPPROTO_ICMPV6; |
167 | #endif |
167 | #endif |
168 | |
168 | |
169 | for (;;) |
169 | for (;;) |
170 | { |
170 | { |
171 | REQ *req; |
171 | REQ *req; |
… | |
… | |
225 | pkt.cksum = 0; |
225 | pkt.cksum = 0; |
226 | |
226 | |
227 | if (range->family == AF_INET) |
227 | if (range->family == AF_INET) |
228 | { |
228 | { |
229 | pkt.type = ICMP4_ECHO; |
229 | pkt.type = ICMP4_ECHO; |
230 | pkt.cksum = icmp_cksum (&pkt, sizeof (pkt)); |
230 | pkt.cksum = icmp_cksum (&pkt, sizeof (pkt));//D |
231 | |
231 | |
232 | memcpy (&sa4.sin_addr, |
232 | memcpy (&sa4.sin_addr, |
233 | sizeof (addr_t) - sizeof (sa4.sin_addr) + (char *)&range->lo, |
233 | sizeof (addr_t) - sizeof (sa4.sin_addr) + (char *)&range->lo, |
234 | sizeof (sa4.sin_addr)); |
234 | sizeof (sa4.sin_addr)); |
235 | |
235 | |
… | |
… | |
312 | |
312 | |
313 | if (pipe (thr_recv) < 0) |
313 | if (pipe (thr_recv) < 0) |
314 | croak ("Net::FPing: unable to create receive pipe"); |
314 | croak ("Net::FPing: unable to create receive pipe"); |
315 | |
315 | |
316 | icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); |
316 | icmp4_fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); |
|
|
317 | |
|
|
318 | #ifdef ICMP_FILTER |
|
|
319 | { |
|
|
320 | icmp_filter oval; |
|
|
321 | oval.data = 0xffffffff & ~(1 << ICMP4_ECHO); |
|
|
322 | setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval); |
|
|
323 | } |
|
|
324 | #endif |
|
|
325 | |
317 | #if IPV6 |
326 | #if IPV6 |
318 | icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); |
327 | icmp6_fd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); |
319 | #endif |
328 | #endif |
320 | |
329 | |
321 | pthread_attr_init (&attr); |
330 | pthread_attr_init (&attr); |
… | |
… | |
341 | } |
350 | } |
342 | |
351 | |
343 | MODULE = Net::FPing PACKAGE = Net::FPing |
352 | MODULE = Net::FPing PACKAGE = Net::FPing |
344 | |
353 | |
345 | BOOT: |
354 | BOOT: |
|
|
355 | { |
|
|
356 | HV *stash = gv_stashpv ("Net::FPing", 1); |
|
|
357 | |
346 | boot (); |
358 | boot (); |
347 | |
359 | |
|
|
360 | newCONSTSUB (stash, "ipv4_supported", newSViv (icmp4_fd >= 0)); |
|
|
361 | newCONSTSUB (stash, "ipv6_supported", newSViv (icmp6_fd >= 0)); |
|
|
362 | |
|
|
363 | newCONSTSUB (stash, "ipv4_pktsize", newSViv (HDR_SIZE_IP4 + sizeof (PKT))); |
|
|
364 | newCONSTSUB (stash, "ipv6_pktsize", newSViv (HDR_SIZE_IP6 + sizeof (PKT))); |
|
|
365 | } |
|
|
366 | |
348 | PROTOTYPES: DISABLE |
367 | PROTOTYPES: DISABLE |
349 | |
368 | |
350 | SV * |
369 | SV * |
351 | _req_ranges4 (SV *ranges, NV interval, U32 payload, SV *id) |
370 | _req_icmp_ping (SV *ranges, NV interval, U32 payload, SV *id) |
352 | CODE: |
371 | CODE: |
353 | { |
372 | { |
354 | if (!SvROK (ranges) || SvTYPE (SvRV (ranges)) != SVt_PVAV) |
373 | if (!SvROK (ranges) || SvTYPE (SvRV (ranges)) != SVt_PVAV) |
355 | croak ("address ranges must be given as arrayref with lo, hi pairs"); |
374 | croak ("address ranges must be given as arrayref with lo, hi pairs"); |
356 | |
375 | |