mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-22 10:50:07 +00:00
Update.
* sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs): Check lengths before copying. This might leave holes in the list. Adjust pointers if necessary. (netlink_receive): Allocate only one block. (free_netlink_handle): Adjust appropriately. (getifaddrs): Lots of cleanups.
This commit is contained in:
parent
5bdd77cb60
commit
31dfab9e17
@ -1,5 +1,12 @@
|
||||
2003-04-16 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/ifaddrs.c (getifaddrs): Check lengths
|
||||
before copying. This might leave holes in the list. Adjust
|
||||
pointers if necessary.
|
||||
(netlink_receive): Allocate only one block.
|
||||
(free_netlink_handle): Adjust appropriately.
|
||||
(getifaddrs): Lots of cleanups.
|
||||
|
||||
* string/test-strncpy.c (do_one_test): Mark start and stop as
|
||||
possibly unused.
|
||||
|
||||
|
@ -252,7 +252,8 @@ netlink_open (struct netlink_handle *h)
|
||||
Since we get at first all RTM_NEWLINK entries, it can never happen
|
||||
that a RTM_NEWADDR index is not known to this map. */
|
||||
static int
|
||||
map_newlink (int index, int *map, int max)
|
||||
internal_function
|
||||
map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -261,6 +262,8 @@ map_newlink (int index, int *map, int max)
|
||||
if (map[i] == -1)
|
||||
{
|
||||
map[i] = index;
|
||||
if (i > 0)
|
||||
ifas[i - 1].ifa.ifa_next = &ifas[i].ifa;
|
||||
return i;
|
||||
}
|
||||
else if (map[i] == index)
|
||||
@ -389,9 +392,6 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
if ((newlink + newaddr) == 0)
|
||||
goto exit_free;
|
||||
|
||||
/* Table for mapping kernel index to entry in our list. */
|
||||
map_newlink_data = alloca (newlink * sizeof (int));
|
||||
|
||||
/* Allocate memory for all entries we have and initialize next
|
||||
pointer. */
|
||||
ifas = (struct ifaddrs_storage *) calloc (1,
|
||||
@ -404,11 +404,10 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < newlink + newaddr - 1; i++)
|
||||
{
|
||||
ifas[i].ifa.ifa_next = &ifas[i + 1].ifa;
|
||||
map_newlink_data[i] = -1;
|
||||
}
|
||||
/* Table for mapping kernel index to entry in our list. */
|
||||
map_newlink_data = alloca (newlink * sizeof (int));
|
||||
memset (map_newlink_data, '\xff', newlink * sizeof (int));
|
||||
|
||||
ifa_data_ptr = (char *) &ifas[newlink + newaddr];
|
||||
newaddr_idx = 0; /* Counter for newaddr index. */
|
||||
|
||||
@ -447,7 +446,7 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
/* Interfaces are stored in the first "newlink" entries
|
||||
of our list, starting in the order as we got from the
|
||||
kernel. */
|
||||
ifa_index = map_newlink (ifim->ifi_index - 1,
|
||||
ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
|
||||
map_newlink_data, newlink);
|
||||
ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
|
||||
|
||||
@ -459,36 +458,44 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
switch (rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
if (rta_payload <= sizeof (ifas[ifa_index].addr))
|
||||
{
|
||||
ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
|
||||
memcpy (ifas[ifa_index].addr.sl.sll_addr,
|
||||
(char *) rta_data, rta_payload);
|
||||
ifas[ifa_index].addr.sl.sll_halen = rta_payload;
|
||||
ifas[ifa_index].addr.sl.sll_ifindex = ifim->ifi_index;
|
||||
ifas[ifa_index].addr.sl.sll_ifindex
|
||||
= ifim->ifi_index;
|
||||
ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;
|
||||
|
||||
ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
|
||||
ifas[ifa_index].ifa.ifa_addr
|
||||
= &ifas[ifa_index].addr.sa;
|
||||
}
|
||||
break;
|
||||
|
||||
case IFLA_BROADCAST:
|
||||
if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
|
||||
{
|
||||
ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
|
||||
memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
|
||||
(char *) rta_data, rta_payload);
|
||||
ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
|
||||
ifas[ifa_index].broadaddr.sl.sll_ifindex
|
||||
= ifim->ifi_index;
|
||||
ifas[ifa_index].broadaddr.sl.sll_hatype = ifim->ifi_type;
|
||||
ifas[ifa_index].broadaddr.sl.sll_hatype
|
||||
= ifim->ifi_type;
|
||||
|
||||
ifas[ifa_index].ifa.ifa_broadaddr
|
||||
= &ifas[ifa_index].broadaddr.sa;
|
||||
}
|
||||
break;
|
||||
|
||||
case IFLA_IFNAME: /* Name of Interface */
|
||||
if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
|
||||
{
|
||||
ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
|
||||
strncpy (ifas[ifa_index].name, rta_data,
|
||||
rta_payload);
|
||||
ifas[ifa_index].name[rta_payload] = '\0';
|
||||
*(char *) __mempcpy (ifas[ifa_index].name, rta_data,
|
||||
rta_payload) = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
@ -521,13 +528,15 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
size_t rtasize = IFA_PAYLOAD (nlh);
|
||||
|
||||
/* New Addresses are stored in the order we got them from
|
||||
the kernel after interfaces. Theoretically it is possible
|
||||
the kernel after the interfaces. Theoretically it is possible
|
||||
that we have holes in the interface part of the list,
|
||||
but we always have already the interface for this address. */
|
||||
ifa_index = newlink + newaddr_idx;
|
||||
ifas[ifa_index].ifa.ifa_flags
|
||||
= ifas[map_newlink (ifam->ifa_index - 1,
|
||||
= ifas[map_newlink (ifam->ifa_index - 1, ifas,
|
||||
map_newlink_data, newlink)].ifa.ifa_flags;
|
||||
if (ifa_index > 0)
|
||||
ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
|
||||
++newaddr_idx;
|
||||
|
||||
while (RTA_OK (rta, rtasize))
|
||||
@ -565,20 +574,27 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
switch (ifam->ifa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
/* Size must match that of an address for IPv4. */
|
||||
if (rta_payload == 4)
|
||||
memcpy (&((struct sockaddr_in *) sa)->sin_addr,
|
||||
rta_data, rta_payload);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* Size must match that of an address for IPv6. */
|
||||
if (rta_payload == 16)
|
||||
{
|
||||
memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
|
||||
rta_data, rta_payload);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (rta_data) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
|
||||
((struct sockaddr_in6 *) sa)->sin6_scope_id =
|
||||
ifam->ifa_scope;
|
||||
if (IN6_IS_ADDR_LINKLOCAL (rta_data)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
|
||||
((struct sockaddr_in6 *) sa)->sin6_scope_id
|
||||
= ifam->ifa_scope;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (rta_payload <= sizeof (ifas[ifa_index].addr))
|
||||
memcpy (sa->sa_data, rta_data, rta_payload);
|
||||
break;
|
||||
}
|
||||
@ -605,20 +621,27 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
switch (ifam->ifa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
/* Size must match that of an address for IPv4. */
|
||||
if (rta_payload == 4)
|
||||
memcpy (&ifas[ifa_index].addr.s4.sin_addr,
|
||||
rta_data, rta_payload);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* Size must match that of an address for IPv6. */
|
||||
if (rta_payload == 16)
|
||||
{
|
||||
memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
|
||||
rta_data, rta_payload);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (rta_data) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
|
||||
ifas[ifa_index].addr.s6.sin6_scope_id =
|
||||
ifam->ifa_scope;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (rta_payload <= sizeof (ifas[ifa_index].addr))
|
||||
memcpy (ifas[ifa_index].addr.sa.sa_data,
|
||||
rta_data, rta_payload);
|
||||
break;
|
||||
@ -639,20 +662,27 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
switch (ifam->ifa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
/* Size must match that of an address for IPv4. */
|
||||
if (rta_payload == 4)
|
||||
memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
|
||||
rta_data, rta_payload);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* Size must match that of an address for IPv6. */
|
||||
if (rta_payload == 16)
|
||||
{
|
||||
memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
|
||||
rta_data, rta_payload);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (rta_data)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
|
||||
ifas[ifa_index].broadaddr.s6.sin6_scope_id
|
||||
= ifam->ifa_scope;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (rta_payload <= sizeof (ifas[ifa_index].addr))
|
||||
memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
|
||||
rta_data, rta_payload);
|
||||
break;
|
||||
@ -663,9 +693,8 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
|
||||
{
|
||||
ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
|
||||
strncpy (ifas[ifa_index].name, rta_data,
|
||||
rta_payload);
|
||||
ifas[ifa_index].name[rta_payload] = '\0';
|
||||
*(char *) __mempcpy (ifas[ifa_index].name, rta_data,
|
||||
rta_payload) = '\0';
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
@ -686,7 +715,7 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
address, use the name from the interface entry. */
|
||||
if (ifas[ifa_index].ifa.ifa_name == NULL)
|
||||
ifas[ifa_index].ifa.ifa_name
|
||||
= ifas[map_newlink (ifam->ifa_index - 1,
|
||||
= ifas[map_newlink (ifam->ifa_index - 1, ifas,
|
||||
map_newlink_data, newlink)].ifa.ifa_name;
|
||||
|
||||
/* Calculate the netmask. */
|
||||
@ -738,6 +767,24 @@ getifaddrs (struct ifaddrs **ifap)
|
||||
}
|
||||
}
|
||||
|
||||
assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);
|
||||
|
||||
if (newaddr_idx > 0)
|
||||
{
|
||||
for (i = 0; i < newlink; ++i)
|
||||
if (map_newlink_data[i] == -1)
|
||||
{
|
||||
/* We have fewer links then we anticipated. Adjust the
|
||||
forward pointer to the first address entry. */
|
||||
ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
|
||||
}
|
||||
|
||||
if (i == 0 && newlink > 0)
|
||||
/* No valid link, but we allocated memory. We have to
|
||||
populate the first entry. */
|
||||
memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
|
||||
}
|
||||
|
||||
if (ifap != NULL)
|
||||
*ifap = &ifas[0].ifa;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user