1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

* include/ifaddrs.c (struct in6addrinfo): Add prefixlen field.

* sysdeps/unix/sysv/linux/check_pf.c (make_request): Always return
	list of interfaces.  Also store prefix length.
	* sysdeps/posix/getaddrinfo.c (sort_result): Add prefixlen element.
	(rfc3484_sort): In rule 9, for IPv4 addresses count only matching
	prefix if source and destination address are in the same subnet.
	(getaddrinfo): Always call __check_pf.  Fill in prefixlen field.
	Always look for matching record in in6ai list.
	Correct source_addr_len value for IPv6->IPv4 converted records.
This commit is contained in:
Ulrich Drepper
2007-11-12 23:55:58 +00:00
parent c1600ce36d
commit 6f3914d5a3
3 changed files with 154 additions and 148 deletions

View File

@ -145,92 +145,69 @@ make_request (int fd, pid_t pid, bool *seen_ipv4, bool *seen_ipv6,
struct rtattr *rta = IFA_RTA (ifam);
size_t len = nlmh->nlmsg_len - NLMSG_LENGTH (sizeof (*ifam));
switch (ifam->ifa_family)
if (ifam->ifa_family != AF_INET
&& ifam->ifa_family != AF_INET6)
continue;
const void *local = NULL;
const void *address = NULL;
while (RTA_OK (rta, len))
{
const void *local;
const void *address;
case AF_INET:
local = NULL;
address = NULL;
while (RTA_OK (rta, len))
switch (rta->rta_type)
{
switch (rta->rta_type)
{
case IFA_LOCAL:
local = RTA_DATA (rta);
break;
case IFA_LOCAL:
local = RTA_DATA (rta);
break;
case IFA_ADDRESS:
address = RTA_DATA (rta);
goto out_v4;
}
rta = RTA_NEXT (rta, len);
case IFA_ADDRESS:
address = RTA_DATA (rta);
goto out;
}
if (local != NULL)
rta = RTA_NEXT (rta, len);
}
if (local != NULL)
{
address = local;
out:
if (ifam->ifa_family != AF_INET)
{
out_v4:
if (*(const in_addr_t *) (address ?: local)
if (*(const in_addr_t *) address
!= htonl (INADDR_LOOPBACK))
*seen_ipv4 = true;
}
break;
case AF_INET6:
local = NULL;
address = NULL;
while (RTA_OK (rta, len))
else
{
switch (rta->rta_type)
{
case IFA_LOCAL:
local = RTA_DATA (rta);
break;
case IFA_ADDRESS:
address = RTA_DATA (rta);
goto out_v6;
}
rta = RTA_NEXT (rta, len);
}
if (local != NULL)
{
out_v6:
if (!IN6_IS_ADDR_LOOPBACK (address ?: local))
if (!IN6_IS_ADDR_LOOPBACK (address))
*seen_ipv6 = true;
}
if (ifam->ifa_flags & (IFA_F_DEPRECATED
| IFA_F_TEMPORARY
| IFA_F_HOMEADDRESS
| IFA_F_OPTIMISTIC))
{
struct in6ailist *newp = alloca (sizeof (*newp));
newp->info.flags = (((ifam->ifa_flags
& (IFA_F_DEPRECATED
| IFA_F_OPTIMISTIC))
? in6ai_deprecated : 0)
| ((ifam->ifa_flags
& IFA_F_TEMPORARY)
? in6ai_temporary : 0)
| ((ifam->ifa_flags
& IFA_F_HOMEADDRESS)
? in6ai_homeaddress : 0));
memcpy (newp->info.addr, address ?: local,
sizeof (newp->info.addr));
newp->next = in6ailist;
in6ailist = newp;
++in6ailistlen;
}
break;
default:
/* Ignore. */
break;
}
struct in6ailist *newp = alloca (sizeof (*newp));
newp->info.flags = (((ifam->ifa_flags
& (IFA_F_DEPRECATED
| IFA_F_OPTIMISTIC))
? in6ai_deprecated : 0)
| ((ifam->ifa_flags
& IFA_F_TEMPORARY)
? in6ai_temporary : 0)
| ((ifam->ifa_flags
& IFA_F_HOMEADDRESS)
? in6ai_homeaddress : 0));
newp->info.prefixlen = ifam->ifa_prefixlen;
if (ifam->ifa_family == AF_INET)
{
newp->info.addr[0] = 0;
newp->info.addr[1] = 0;
newp->info.addr[2] = htonl (0xffff);
newp->info.addr[3] = *(const in_addr_t *) address;
}
else
memcpy (newp->info.addr, address, sizeof (newp->info.addr));
newp->next = in6ailist;
in6ailist = newp;
++in6ailistlen;
}
else if (nlmh->nlmsg_type == NLMSG_DONE)
/* We found the end, leave the loop. */