inet: Make IN6_IS_ADDR_UNSPECIFIED etc. usable with POSIX [BZ #16421]
Previously, under some feature test macros and compilers, the
macros were defined, but references undefined struct members
in their implementation.
2016-11-25 Carlos O'Donell <carlos@redhat.com>
Florian Weimer <fweimer@redhat.com>
[BZ #16421]
* inet/netinet/in.h (struct in6_addr): Always define __u6_addr16
and __u6_addr32 members.
(IN6_IS_ADDR_UNSPECIFIED, IN6_IS_ADDR_LOOPBACK)
(IN6_IS_ADDR_LINKLOCAL, IN6_IS_ADDR_SITELOCAL)
(IN6_IS_ADDR_V4MAPPED, IN6_IS_ADDR_V4COMPAT, IN6_ARE_ADDR_EQUAL):
Use __u6_addr32.
* inet/tst-checks-posix.c: New file.
* inet/Makefile (tests): Add it.
(CFLAGS-tst-checks-posix.c): Compile in C99 mode.
* test-skeleton.c (xasprintf, struct temp_name_list)
(temp_name_list, add_temp_file, delete_temp_files)
(create_temp_file): Define only under _GNU_SOURCE.
(usage): Add argv parameter.
(main): Call usage with argv argument. Register delete_temp_files
and log temporary files only under _GNU_SOURCE. Explicitly retry
waitpid.
@@ -51,8 +51,8 @@ aux := check_pf check_native ifreq
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
- tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-sockaddr \
- tst-inet6_scopeid_pton
+ tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \
+ tst-sockaddr tst-inet6_scopeid_pton
include ../Rules
@@ -86,6 +86,7 @@ CFLAGS-either_hton.c = -fexceptions
CFLAGS-getnetgrent.c = -fexceptions
CFLAGS-getnetgrent_r.c = -fexceptions
+CFLAGS-tst-checks-posix.c = -std=c99
CFLAGS-tst-sockaddr.c = -fno-strict-aliasing
endif
@@ -213,10 +213,8 @@ struct in6_addr
union
{
uint8_t __u6_addr8[16];
-#ifdef __USE_MISC
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
-#endif
} __in6_u;
#define s6_addr __in6_u.__u6_addr8
#ifdef __USE_MISC
@@ -411,52 +409,52 @@ extern uint16_t htons (uint16_t __hostshort)
# define IN6_IS_ADDR_UNSPECIFIED(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- __a->s6_addr32[0] == 0 \
- && __a->s6_addr32[1] == 0 \
- && __a->s6_addr32[2] == 0 \
- && __a->s6_addr32[3] == 0; }))
+ __a->__in6_u.__u6_addr32[0] == 0 \
+ && __a->__in6_u.__u6_addr32[1] == 0 \
+ && __a->__in6_u.__u6_addr32[2] == 0 \
+ && __a->__in6_u.__u6_addr32[3] == 0; }))
# define IN6_IS_ADDR_LOOPBACK(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- __a->s6_addr32[0] == 0 \
- && __a->s6_addr32[1] == 0 \
- && __a->s6_addr32[2] == 0 \
- && __a->s6_addr32[3] == htonl (1); }))
+ __a->__in6_u.__u6_addr32[0] == 0 \
+ && __a->__in6_u.__u6_addr32[1] == 0 \
+ && __a->__in6_u.__u6_addr32[2] == 0 \
+ && __a->__in6_u.__u6_addr32[3] == htonl (1); }))
# define IN6_IS_ADDR_LINKLOCAL(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- (__a->s6_addr32[0] & htonl (0xffc00000)) == htonl (0xfe800000); }))
+ (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000)) == htonl (0xfe800000); }))
# define IN6_IS_ADDR_SITELOCAL(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- (__a->s6_addr32[0] & htonl (0xffc00000)) == htonl (0xfec00000); }))
+ (__a->__in6_u.__u6_addr32[0] & htonl (0xffc00000)) == htonl (0xfec00000); }))
# define IN6_IS_ADDR_V4MAPPED(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- __a->s6_addr32[0] == 0 \
- && __a->s6_addr32[1] == 0 \
- && __a->s6_addr32[2] == htonl (0xffff); }))
+ __a->__in6_u.__u6_addr32[0] == 0 \
+ && __a->__in6_u.__u6_addr32[1] == 0 \
+ && __a->__in6_u.__u6_addr32[2] == htonl (0xffff); }))
# define IN6_IS_ADDR_V4COMPAT(a) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
- __a->s6_addr32[0] == 0 \
- && __a->s6_addr32[1] == 0 \
- && __a->s6_addr32[2] == 0 \
- && ntohl (__a->s6_addr32[3]) > 1; }))
+ __a->__in6_u.__u6_addr32[0] == 0 \
+ && __a->__in6_u.__u6_addr32[1] == 0 \
+ && __a->__in6_u.__u6_addr32[2] == 0 \
+ && ntohl (__a->__in6_u.__u6_addr32[3]) > 1; }))
# define IN6_ARE_ADDR_EQUAL(a,b) \
(__extension__ \
({ const struct in6_addr *__a = (const struct in6_addr *) (a); \
const struct in6_addr *__b = (const struct in6_addr *) (b); \
- __a->s6_addr32[0] == __b->s6_addr32[0] \
- && __a->s6_addr32[1] == __b->s6_addr32[1] \
- && __a->s6_addr32[2] == __b->s6_addr32[2] \
- && __a->s6_addr32[3] == __b->s6_addr32[3]; }))
+ __a->__in6_u.__u6_addr32[0] == __b->__in6_u.__u6_addr32[0] \
+ && __a->__in6_u.__u6_addr32[1] == __b->__in6_u.__u6_addr32[1] \
+ && __a->__in6_u.__u6_addr32[2] == __b->__in6_u.__u6_addr32[2] \
+ && __a->__in6_u.__u6_addr32[3] == __b->__in6_u.__u6_addr32[3]; }))
#else
# define IN6_IS_ADDR_UNSPECIFIED(a) \
(((const uint32_t *) (a))[0] == 0 \
new file mode 100644
@@ -0,0 +1,25 @@
+/* Test IPv6 classification macros in POSIX mode.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Process tst-checks.c in POSIX mode. POSIX 2008 is required by the
+ test skeleton. */
+#undef _GNU_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#define _ISOMAC
+
+#include "tst-checks.c"
@@ -149,6 +149,7 @@ xrealloc (void *p, size_t n)
return result;
}
+#ifdef __USE_GNU
/* Call asprintf with error checking. */
__attribute__ ((always_inline, format (printf, 1, 2)))
static __inline__ char *
@@ -162,6 +163,7 @@ xasprintf (const char *format, ...)
}
return result;
}
+#endif /* __USE_GNU */
/* Write a message to standard output. Can be used in signal
handlers. */
@@ -173,6 +175,7 @@ write_message (const char *message)
unused = write (STDOUT_FILENO, message, strlen (message));
}
+#ifdef __USE_GNU
/* List of temporary files. */
struct temp_name_list
{
@@ -247,6 +250,7 @@ create_temp_file (const char *base, char **filename)
return fd;
}
+#endif/* __USE_GNU */
/* Timeout handler. We kill the child and exit with an error. */
static void
@@ -351,7 +355,7 @@ set_fortify_handler (void (*handler) (int sig))
/* Show people how to run the program. */
static void
-usage (void)
+usage (char **argv)
{
size_t i;
@@ -361,7 +365,7 @@ usage (void)
" TIMEOUTFACTOR An integer used to scale the timeout\n"
" TMPDIR Where to place temporary files\n"
"\n",
- program_invocation_short_name);
+ argv[0]);
printf ("Options:\n");
for (i = 0; options[i].name; ++i)
{
@@ -407,7 +411,7 @@ main (int argc, char *argv[])
switch (opt)
{
case '?':
- usage ();
+ usage (argv);
exit (1);
case OPT_DIRECT:
direct = 1;
@@ -454,8 +458,10 @@ main (int argc, char *argv[])
/* Make sure we see all message, even those on stdout. */
setvbuf (stdout, NULL, _IONBF, 0);
+#ifdef __USE_GNU
/* Make sure temporary files are deleted. */
atexit (delete_temp_files);
+#endif
/* Correct for the possible parameters. */
argv[optind - 1] = argv[0];
@@ -493,6 +499,7 @@ main (int argc, char *argv[])
}
#endif
+#ifdef __USE_GNU
if (temp_name_list != NULL)
{
struct temp_name_list *n;
@@ -503,6 +510,7 @@ main (int argc, char *argv[])
fprintf (f, " '%s'\n", n->name);
fprintf (f, ")\n");
}
+#endif /* __USE_GNU */
fclose (f);
direct = 1;
@@ -551,7 +559,9 @@ main (int argc, char *argv[])
signal (SIGINT, signal_handler);
/* Wait for the regular termination. */
- termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+ do
+ termpid = waitpid (pid, &status, 0);
+ while (termpid == -1 && errno == EINTR);
if (termpid == -1)
{
printf ("Waiting for test program failed: %m\n");