- Fix fallback to SO\_TIMESTAMP if SO\_TIMESTAMPNS is not available (#375, thanks
@auerswal)
+## New features
+
+- The -g, --generate option now also supports IPv6 addresses (#376,
+ thanks @auerswal)
+
fping 5.3 (2025-01-02)
======================
#!/usr/bin/perl -w
-use Test::Command tests => 102;
+use Test::Command tests => 146;
use Test::More;
use File::Temp;
$cmd->stderr_like(qr{can't parse address 127\.0\.0\.1:.*(not supported|not known)});
}
-# fping -g (range - no IPv6 generator)
+# fping -g (range - IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -g ::1 ::1");
- $cmd->exit_is_num(1);
- $cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->exit_is_num(0);
+ $cmd->stdout_is_eq("::1 is alive\n");
+ $cmd->stderr_is_eq("");
}
-# fping -g (empty range - no IPv6 generator)
+# fping -g (empty range - IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
my $cmd = Test::Command->new(cmd => "fping -g ::1 ::");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->stderr_is_eq("");
+}
+
+# fping -g (empty range - IPv6 - crossing 64 bit boundary)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -g 2001:db8:0:2:: 2001:db8:0:1:ffff:ffff:ffff:ffff");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
}
-# fping -6 -g (range - no IPv6 generator)
+# fping -6 -g (range - IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 ::1");
+ $cmd->exit_is_num(0);
+ $cmd->stdout_is_eq("::1 is alive\n");
+ $cmd->stderr_is_eq("");
+}
+
+# fping -g (range - scoped IPv6)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 1;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -i1 -t10 -r0 -g fe80::47%2 fe80::48%2");
+ $cmd->stdout_like(qr{fe80::47%2 is (alive|unreachable)\nfe80::48%2 is (alive|unreachable)\n});
+}
+
+# fping -g (range - scoped IPv6 - only start address is scoped)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -i1 -t10 -r0 -g fe80::47%2 fe80::48");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: different scopes for start and end addresses\n");
+}
+
+# fping -g (range - scoped IPv6 - only end address is scoped)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -i1 -t10 -r0 -g fe80::47 fe80::48%2");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: different scopes for start and end addresses\n");
+}
+
+# fping -g (range - inconsistently scoped IPv6)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -i1 -t10 -r0 -g fe80::47%2 fe80::48%3");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: different scopes for start and end addresses\n");
+}
+
+# fping -g (range - unreachable documentation addresses)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -r0 -i1 -g 2001:db8:1:2:3:4:5:6 2001:db8:1:2:3:4:5:7");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("2001:db8:1:2:3:4:5:6 is unreachable\n2001:db8:1:2:3:4:5:7 is unreachable\n");
+}
+
+# fping -g (range - unreachable documentation addresses - crossing 64 bit boundary)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -i1 -r0 -g 2001:db8:1:2:ffff:ffff:ffff:fffe 2001:db8:1:3::1");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("2001:db8:1:2:ffff:ffff:ffff:fffe is unreachable
+2001:db8:1:2:ffff:ffff:ffff:ffff is unreachable
+2001:db8:1:3:: is unreachable
+2001:db8:1:3::1 is unreachable\n");
+}
+
+# fping -g (range - too many addresses - lower 64 bit)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -i1 -r0 -g 2001:db8:1:2:3:4:0:1 2001:db8:1:2:3:4:ff:ffff");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (range - too many addresses - upper 64 bit)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -i1 -r0 -g 2001:db8:1:2::1 2001:db8:1:3::1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
}
-# fping -6 -g (range - no IPv6 generator - start address IPv6)
+# fping -6 -g (range - mixed address families - start address IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
my $cmd = Test::Command->new(cmd => "fping -6 -g ::1 127.0.0.1");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->stderr_like(qr{fping: can't parse address 127\.0\.0\.1: .*\n});
}
-# fping -g (range - no IPv6 generator - end address IPv6)
+# fping -g (range - mixed address families - end address IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
$cmd->stderr_like(qr{fping: can't parse address ::1: .*\n});
}
-# fping -6 -g (range - no IPv6 generator - end address IPv6)
+# fping -6 -g (range - mixed address families - end address IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
$cmd->stderr_like(qr{can't parse address 127\.0\.0\.1:.*(not supported|not known)});
}
-# fping -g (CIDR - no IPv6 generator)
+# fping -g (CIDR - IPv6)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
my $cmd = Test::Command->new(cmd => "fping -g ::1/128");
+ $cmd->exit_is_num(0);
+ $cmd->stdout_is_eq("::1 is alive\n");
+ $cmd->stderr_is_eq("");
+}
+
+# fping -6 -g (CIDR - IPv6)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128");
+ $cmd->exit_is_num(0);
+ $cmd->stdout_is_eq("::1 is alive\n");
+ $cmd->stderr_is_eq("");
+}
+
+# fping -g (CIDR - scoped IPv6)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 1;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -r0 -g fe80::4:3:2:1%2/128");
+ $cmd->stdout_like(qr{fe80::4:3:2:1%2 is (alive|unreachable)\n});
+}
+
+# fping -g (CIDR - scoped IPv6 - wrong syntax)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -r0 -g fe80::4:3:2:1/128%2");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->stderr_is_eq("fping: address scope must precede prefix length\n");
+}
+
+# fping -g (CIDR - IPv6 - unreachable documentation addresses - host prefix)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -r0 -g 2001:db8:abcd:1234:5678:9098:7654:4321/128");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("2001:db8:abcd:1234:5678:9098:7654:4321 is unreachable\n");
+}
+
+# fping -g (CIDR - IPv6 - unreachable documentation addresses - point-to-point prefix)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -r0 -g 2001:db8:abcd:1234:5678:9098:7654:4320/127");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("2001:db8:abcd:1234:5678:9098:7654:4320 is unreachable\n2001:db8:abcd:1234:5678:9098:7654:4321 is unreachable\n");
}
-# fping -6 -g (CIDR - no IPv6 generator)
+# fping -g (CIDR - IPv6 - unreachable documentation addresses - normal prefix)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 2;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -t10 -i1 -r0 -g 2001:db8:abcd:1234:5678:9098:7654:4320/126");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("2001:db8:abcd:1234:5678:9098:7654:4320 is unreachable
+2001:db8:abcd:1234:5678:9098:7654:4321 is unreachable
+2001:db8:abcd:1234:5678:9098:7654:4322 is unreachable
+2001:db8:abcd:1234:5678:9098:7654:4323 is unreachable\n");
+}
+
+# fping -g (CIDR - IPv6 - prefix too short)
SKIP: {
if($ENV{SKIP_IPV6}) {
skip 'Skip IPv6 tests', 3;
}
- my $cmd = Test::Command->new(cmd => "fping -6 -g ::1/128");
+ my $cmd = Test::Command->new(cmd => "fping -g 2001:db8::/64");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: netmask must be between 65 and 128 (is: 64)\n");
+}
+
+# fping -g (CIDR - IPv6 - too many addresses)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -g 2001:db8::/65");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (CIDR - IPv6 - too many addresses)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -g 2001:db8::/104");
+ $cmd->exit_is_num(1);
+ $cmd->stdout_is_eq("");
+ $cmd->stderr_is_eq("fping: -g parameter generates too many addresses\n");
+}
+
+# fping -g (CIDR - IPv6 - prefix too long)
+SKIP: {
+ if($ENV{SKIP_IPV6}) {
+ skip 'Skip IPv6 tests', 3;
+ }
+ my $cmd = Test::Command->new(cmd => "fping -g 2001:db8::/129");
$cmd->exit_is_num(1);
$cmd->stdout_is_eq("");
- $cmd->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+ $cmd->stderr_is_eq("fping: netmask must be between 65 and 128 (is: 129)\n");
}
# fping -H
my $cmd1 = Test::Command->new(cmd => "fping -a -g 2001:db8:120:4161::4/64");
$cmd1->exit_is_num(1);
$cmd1->stdout_is_eq("");
-$cmd1->stderr_is_eq("fping: -g works only with IPv4 addresses\n");
+$cmd1->stderr_is_eq("fping: netmask must be between 65 and 128 (is: 64)\n");
Generate a target list from a supplied IP netmask, or a starting and ending IP.
Specify the netmask or start/end in the targets portion of the command line. If
-a network with netmask is given, the network and broadcast addresses will be
-excluded. ex. To ping the network 192.168.1.0/24, the specified command line
-could look like either:
+an IPv4 network with netmask is given, the network and broadcast addresses will
+be excluded.
+
+Example: To ping the network 192.168.1.0/24, the specified command line could
+look like either:
$ fping -g 192.168.1.0/24
=head1 RESTRICTIONS
The number of addresses that can be generated using the C<-g>, C<--generate>
-option is limited to 131070 (the number of host addresses in one 15-bit IPv4
-prefix).
+option is limited to 131072 (the number of host addresses in one 111-bit IPv6
+prefix, two addresses more than the host addresses in one 15-bit IPv4 prefix).
If fping was configured with C<--enable-safe-limits>, the following values are
not allowed for non-root users:
#define SIZE_ICMP_HDR 8 /* from ip_icmp.h */
#define MAX_PING_DATA (MAX_IP_PACKET - SIZE_IP_HDR - SIZE_ICMP_HDR)
-#define MAX_GENERATE 131070 /* maximum number of hosts that -g can generate */
+#define MAX_GENERATE 131072 /* maximum number of hosts that -g can generate */
/* sized so as to be like traditional ping */
#define DEFAULT_PING_DATA_SIZE 56
void add_cidr_ipv4(unsigned long, unsigned long);
void add_range(char *, char *);
void add_addr_range_ipv4(unsigned long, unsigned long);
+#ifdef IPV6
+uint64_t be_octets_to_uint64(uint8_t*);
+void uint64_to_be_octets(uint64_t, uint8_t*);
+void add_cidr_ipv6(uint64_t, uint64_t, unsigned long, const char *);
+void add_addr_range_ipv6(uint64_t, uint64_t, uint64_t, uint64_t, const char *);
+#endif
void print_warning(char *fmt, ...);
int addr_cmp(struct sockaddr *a, struct sockaddr *b);
void host_add_ping_event(HOST_ENTRY *h, int index, int64_t ev_time);
struct addrinfo addr_hints;
struct addrinfo *addr_res;
unsigned long net_addr;
+#ifdef IPV6
+ uint64_t net_upper, net_lower;
+ char *scope_str;
+#endif /* IPV6 */
/* Split address from mask */
- addr_end = strchr(addr, '/');
+ addr_end = strrchr(addr, '/');
if (addr_end == NULL) {
usage(1);
}
- *addr_end = '\0';
mask_str = addr_end + 1;
+
+#ifdef IPV6
+ /* IPv6 addresses can have a scope */
+ scope_str = strchr(addr, '%');
+ if (scope_str && mask_str < scope_str) {
+ fprintf(stderr, "%s: address scope must precede prefix length\n", prog);
+ exit(1);
+ }
+#endif /*IPV6 */
+
+ *addr_end = '\0';
mask = atoi(mask_str);
- /* parse address (IPv4 only) */
+ /* parse address */
memset(&addr_hints, 0, sizeof(struct addrinfo));
addr_hints.ai_family = hints_ai_family;
addr_hints.ai_flags = AI_NUMERICHOST;
net_addr = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
add_cidr_ipv4(net_addr, mask);
+#ifdef IPV6
+ } else if (addr_res->ai_family == AF_INET6) {
+ uint8_t *ipv6_addr = ((struct sockaddr_in6*)addr_res->ai_addr)->sin6_addr.s6_addr;
+ net_upper = be_octets_to_uint64(ipv6_addr);
+ net_lower = be_octets_to_uint64(ipv6_addr + 8);
+ freeaddrinfo(addr_res);
+ add_cidr_ipv6(net_upper, net_lower, mask, scope_str);
+#endif /* IPV6 */
} else {
freeaddrinfo(addr_res);
- fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
+ fprintf(stderr, "%s: -g does not support this address family\n", prog);
exit(1);
}
}
add_addr_range_ipv4(net_addr, net_last);
}
+#ifdef IPV6
+void add_cidr_ipv6(uint64_t net_upper, uint64_t net_lower, unsigned long mask, const char *scope_str)
+{
+ uint64_t bitmask_lower;
+ uint64_t last_lower;
+
+ /* check mask -- 2^63 addresses should suffice for now */
+ if (mask < 65 || mask > 128) {
+ fprintf(stderr, "%s: netmask must be between 65 and 128 (is: %lu)\n", prog, mask);
+ exit(1);
+ }
+
+ /* convert mask integer from 65 to 128 to the lower part of a bitmask */
+ bitmask_lower = ((uint64_t)-1) << (128 - mask);
+
+ /* calculate network range */
+ net_lower &= bitmask_lower;
+ last_lower = net_lower + ((uint64_t)1 << (128 - mask)) - 1;
+
+ add_addr_range_ipv6(net_upper, net_lower, net_upper, last_lower, scope_str);
+}
+#endif /* IPV6 */
+
void add_range(char *start, char *end)
{
struct addrinfo addr_hints;
unsigned long start_long;
unsigned long end_long;
int ret;
-
- /* parse start address (IPv4 only) */
+#ifdef IPV6
+ uint64_t start_upper, start_lower;
+ uint64_t end_upper, end_lower;
+ char *start_scope_str, *end_scope_str;
+
+ /*
+ * The compiler does not know that setting the address family hint to
+ * ensure that start and end are from the same address family also
+ * ensures that either start_long and end_long are initialized and used,
+ * or start_upper, start_lower, end_upper, and end_lower are initialized
+ * and used. Thus initialize all variables when both IPv4 and IPv6 are
+ * supported to suppress compiler warnings.
+ */
+ start_long = -1;
+ end_long = 0;
+ start_upper = start_lower = -1;
+ end_upper = end_lower = 0;
+ start_scope_str = end_scope_str = NULL;
+#endif /* IPV6 */
+
+ /* parse start address */
memset(&addr_hints, 0, sizeof(struct addrinfo));
addr_hints.ai_family = hints_ai_family;
addr_hints.ai_flags = AI_NUMERICHOST;
if (addr_res->ai_family == AF_INET) {
start_long = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
+#ifdef IPV6
+ } else if (addr_res->ai_family == AF_INET6) {
+ uint8_t *ipv6_addr = ((struct sockaddr_in6*)addr_res->ai_addr)->sin6_addr.s6_addr;
+ start_upper = be_octets_to_uint64(ipv6_addr);
+ start_lower = be_octets_to_uint64(ipv6_addr + 8);
+ freeaddrinfo(addr_res);
+#endif /* IPV6 */
} else {
freeaddrinfo(addr_res);
- fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
+ fprintf(stderr, "%s: -g does not support this address family\n", prog);
exit(1);
}
- /* parse end address (IPv4 only) */
+ /* IPv6 addresses can have a scope */
+ if (hints_ai_family == AF_INET6) {
+ start_scope_str = strchr(start, '%');
+ end_scope_str = strchr(end, '%');
+ if ((!start_scope_str && end_scope_str) ||
+ (start_scope_str && !end_scope_str) ||
+ (start_scope_str && end_scope_str && strcmp(start_scope_str, end_scope_str) != 0)) {
+ fprintf(stderr, "%s: different scopes for start and end addresses\n", prog);
+ exit(1);
+ }
+ }
+
+ /* parse end address */
memset(&addr_hints, 0, sizeof(struct addrinfo));
addr_hints.ai_family = hints_ai_family;
addr_hints.ai_flags = AI_NUMERICHOST;
end_long = ntohl(((struct sockaddr_in*)addr_res->ai_addr)->sin_addr.s_addr);
freeaddrinfo(addr_res);
add_addr_range_ipv4(start_long, end_long);
+#ifdef IPV6
+ } else if (addr_res->ai_family == AF_INET6) {
+ uint8_t *ipv6_addr = ((struct sockaddr_in6*)addr_res->ai_addr)->sin6_addr.s6_addr;
+ end_upper = be_octets_to_uint64(ipv6_addr);
+ end_lower = be_octets_to_uint64(ipv6_addr + 8);
+ freeaddrinfo(addr_res);
+ add_addr_range_ipv6(start_upper, start_lower, end_upper, end_lower, start_scope_str);
+#endif /* IPV6 */
} else {
freeaddrinfo(addr_res);
- fprintf(stderr, "%s: -g works only with IPv4 addresses\n", prog);
+ fprintf(stderr, "%s: -g does not support this address family\n", prog);
exit(1);
}
}
}
}
+#ifdef IPV6
+uint64_t be_octets_to_uint64(uint8_t *be_octets)
+{
+ int i;
+ uint64_t ret = 0;
+ for (i = 0; i < 8; i++) {
+ ret |= (uint64_t)be_octets[7 - i] << (i * 8);
+ }
+ return ret;
+}
+
+void uint64_to_be_octets(uint64_t num, uint8_t *be_octets)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ be_octets[7 - i] = (uint8_t)((num >> (i * 8)) & 0xff);
+ }
+}
+
+void add_addr_range_ipv6(uint64_t start_upper, uint64_t start_lower,
+ uint64_t end_upper, uint64_t end_lower,
+ const char *scope_str)
+{
+ struct in6_addr in6_addr_tmp;
+ char buffer[100];
+
+ /* prevent generating too many addresses */
+ if ((start_upper + 1 < end_upper) ||
+ (start_upper + 1 == end_upper && end_lower >= start_lower) ||
+ (start_upper + 1 == end_upper && end_lower - MAX_GENERATE >= start_lower) ||
+ (start_upper == end_upper && end_lower - MAX_GENERATE >= start_lower &&
+ start_lower + MAX_GENERATE <= end_lower)) {
+ fprintf(stderr, "%s: -g parameter generates too many addresses\n", prog);
+ exit(1);
+ }
+
+ while ((start_upper < end_upper) ||
+ (start_upper == end_upper && start_lower <= end_lower)) {
+ uint64_to_be_octets(start_upper, in6_addr_tmp.s6_addr);
+ uint64_to_be_octets(start_lower, in6_addr_tmp.s6_addr + 8);
+ inet_ntop(AF_INET6, &in6_addr_tmp, buffer, sizeof(buffer));
+ if (scope_str) {
+ if (strlen(buffer) + strlen(scope_str) + 1 > sizeof(buffer)) {
+ fprintf(stderr, "%s: scope identifier is too long\n", prog);
+ exit(1);
+ }
+ strncat(buffer, scope_str, sizeof(buffer) - strlen(buffer) - 1);
+ }
+ add_name(buffer);
+ start_lower++;
+ if (start_lower == 0) {
+ start_upper++;
+ }
+ }
+}
+#endif /* IPv6 */
+
void main_loop()
{
int64_t lt;