math: Improve fmodf
[glibc.git] / inet / tst-inet6_scopeid_pton.c
blob6984e3b5ede311d4cb7627378c2383e2ef348fc9
1 /* Tests for __inet6_scopeid_pton and IPv6 scopes in getaddrinfo.
2 Copyright (C) 2016-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <arpa/inet.h>
20 #include <inttypes.h>
21 #include <net-internal.h>
22 #include <net/if.h>
23 #include <netdb.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <support/check.h>
28 #include <support/support.h>
29 #include <support/test-driver.h>
31 /* An interface which is known to the system. */
32 static const char *interface_name;
33 static uint32_t interface_index;
35 /* Initiale the variables above. */
36 static void
37 setup_interface (void)
39 struct if_nameindex *list = if_nameindex ();
40 if (list != NULL && list[0].if_index != 0 && list[0].if_name[0] != '\0')
42 interface_name = list[0].if_name;
43 interface_index = list[0].if_index;
47 /* Convert ADDRESS to struct in6_addr. */
48 static struct in6_addr
49 from_string (const char *address)
51 struct in6_addr addr;
52 if (inet_pton (AF_INET6, address, &addr) != 1)
53 FAIL_EXIT1 ("inet_pton (\"%s\")", address);
54 return addr;
57 /* Invoke getaddrinfo to parse ADDRESS%SCOPE. Return true if
58 getaddrinfo was successful. */
59 static bool
60 call_gai (int family, const char *address, const char *scope,
61 struct sockaddr_in6 *result)
63 struct addrinfo hints =
65 .ai_family = family,
66 .ai_flags = AI_NUMERICHOST,
67 .ai_socktype = SOCK_DGRAM,
68 .ai_protocol = IPPROTO_UDP,
70 char *fulladdr = xasprintf ("%s%%%s", address, scope);
71 struct addrinfo *ai = NULL;
72 int ret = getaddrinfo (fulladdr, NULL, &hints, &ai);
73 if (ret == EAI_ADDRFAMILY || ret == EAI_NONAME)
75 if (test_verbose > 0)
76 printf ("info: getaddrinfo (\"%s\"): %s (%d)\n",
77 fulladdr, gai_strerror (ret), ret);
78 free (fulladdr);
79 return false;
81 if (ret != 0)
82 FAIL_EXIT1 ("getaddrinfo (\"%s\"): %s (%d)\n",
83 fulladdr, gai_strerror (ret), ret);
84 TEST_VERIFY_EXIT (ai != NULL);
85 TEST_VERIFY_EXIT (ai->ai_addrlen == sizeof (*result));
86 TEST_VERIFY (ai->ai_family == AF_INET6);
87 TEST_VERIFY (ai->ai_next == NULL);
88 memcpy (result, ai->ai_addr, sizeof (*result));
89 free (fulladdr);
90 freeaddrinfo (ai);
91 return true;
94 /* Verify that a successful call to getaddrinfo returned the expected
95 scope data. */
96 static void
97 check_ai (const char *what, const char *addr_string, const char *scope_string,
98 const struct sockaddr_in6 *sa,
99 const struct in6_addr *addr, uint32_t scope)
101 if (memcmp (addr, &sa->sin6_addr, sizeof (*addr)) != 0)
103 support_record_failure ();
104 printf ("error: getaddrinfo %s address mismatch for %s%%%s\n",
105 what, addr_string, scope_string);
107 if (sa->sin6_scope_id != scope)
109 support_record_failure ();
110 printf ("error: getaddrinfo %s scope mismatch for %s%%%s\n"
111 " expected: %" PRIu32 "\n"
112 " actual: %" PRIu32 "\n",
113 what, addr_string, scope_string, scope, sa->sin6_scope_id);
117 /* Check a single address were we expected a failure. */
118 static void
119 expect_failure (const char *address, const char *scope)
121 if (test_verbose > 0)
122 printf ("info: expecting failure for %s%%%s\n", address, scope);
123 struct in6_addr addr = from_string (address);
124 uint32_t result = 1234;
125 if (__inet6_scopeid_pton (&addr, scope, &result) == 0)
127 support_record_failure ();
128 printf ("error: unexpected success for %s%%%s\n",
129 address, scope);
131 if (result != 1234)
133 support_record_failure ();
134 printf ("error: unexpected result update for %s%%%s\n",
135 address, scope);
138 struct sockaddr_in6 sa;
139 if (call_gai (AF_UNSPEC, address, scope, &sa))
141 support_record_failure ();
142 printf ("error: unexpected getaddrinfo success for %s%%%s (AF_UNSPEC)\n",
143 address, scope);
145 if (call_gai (AF_INET6, address, scope, &sa))
147 support_record_failure ();
148 printf ("error: unexpected getaddrinfo success for %s%%%s (AF_INET6)\n",
149 address, scope);
153 /* Check a single address were we expected a success. */
154 static void
155 expect_success (const char *address, const char *scope, uint32_t expected)
157 if (test_verbose > 0)
158 printf ("info: expecting success for %s%%%s\n", address, scope);
159 struct in6_addr addr = from_string (address);
160 uint32_t actual = expected + 1;
161 if (__inet6_scopeid_pton (&addr, scope, &actual) != 0)
163 support_record_failure ();
164 printf ("error: unexpected failure for %s%%%s\n",
165 address, scope);
167 if (actual != expected)
169 support_record_failure ();
170 printf ("error: unexpected result for for %s%%%s\n",
171 address, scope);
172 printf (" expected: %" PRIu32 "\n", expected);
173 printf (" actual: %" PRIu32 "\n", actual);
176 struct sockaddr_in6 sa;
177 memset (&sa, 0xc0, sizeof (sa));
178 if (call_gai (AF_UNSPEC, address, scope, &sa))
179 check_ai ("AF_UNSPEC", address, scope, &sa, &addr, expected);
180 else
182 support_record_failure ();
183 printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_UNSPEC)\n",
184 address, scope);
186 memset (&sa, 0xc0, sizeof (sa));
187 if (call_gai (AF_INET6, address, scope, &sa))
188 check_ai ("AF_INET6", address, scope, &sa, &addr, expected);
189 else
191 support_record_failure ();
192 printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_INET6)\n",
193 address, scope);
197 static int
198 do_test (void)
200 setup_interface ();
202 static const char *test_addresses[]
203 = { "::", "::1", "2001:db8::1", NULL };
204 for (int i = 0; test_addresses[i] != NULL; ++i)
206 expect_success (test_addresses[i], "0", 0);
207 expect_success (test_addresses[i], "5555", 5555);
209 expect_failure (test_addresses[i], "");
210 expect_failure (test_addresses[i], "-1");
211 expect_failure (test_addresses[i], "-99");
212 expect_failure (test_addresses[i], "037777777777");
213 expect_failure (test_addresses[i], "0x");
214 expect_failure (test_addresses[i], "0x1");
217 if (interface_name != NULL)
219 expect_success ("fe80::1", interface_name, interface_index);
220 expect_success ("ff02::1", interface_name, interface_index);
221 expect_success ("ff01::1", interface_name, interface_index);
222 expect_failure ("::", interface_name);
223 expect_failure ("::1", interface_name);
224 expect_failure ("2001:db8::1", interface_name);
227 return 0;
230 #include <support/test-driver.c>