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>
21 #include <net-internal.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. */
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
)
52 if (inet_pton (AF_INET6
, address
, &addr
) != 1)
53 FAIL_EXIT1 ("inet_pton (\"%s\")", address
);
57 /* Invoke getaddrinfo to parse ADDRESS%SCOPE. Return true if
58 getaddrinfo was successful. */
60 call_gai (int family
, const char *address
, const char *scope
,
61 struct sockaddr_in6
*result
)
63 struct addrinfo hints
=
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
)
76 printf ("info: getaddrinfo (\"%s\"): %s (%d)\n",
77 fulladdr
, gai_strerror (ret
), ret
);
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
));
94 /* Verify that a successful call to getaddrinfo returned the expected
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. */
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",
133 support_record_failure ();
134 printf ("error: unexpected result update for %s%%%s\n",
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",
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",
153 /* Check a single address were we expected a success. */
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",
167 if (actual
!= expected
)
169 support_record_failure ();
170 printf ("error: unexpected result for for %s%%%s\n",
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
);
182 support_record_failure ();
183 printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_UNSPEC)\n",
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
);
191 support_record_failure ();
192 printf ("error: unexpected getaddrinfo failure for %s%%%s (AF_INET6)\n",
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
);
230 #include <support/test-driver.c>