summaryrefslogtreecommitdiff
path: root/lib/libc/net/getifaddrs.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2008-11-24 20:08:50 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2008-11-24 20:08:50 +0000
commitedbb8187351a6912bc70146c3075c0a13caf4ba1 (patch)
tree839bada16275712c38dccf852375ee80915cc849 /lib/libc/net/getifaddrs.c
parentf07d9b721c398e4e750910b8a5fa59530c322179 (diff)
Correctly jump over routing headers and calculate the size of the if_data
struct in the if_msghdr instead of using sizeof() blindly. This allows us to grow if_data without causing issues for the getifaddrs() users. OK deraadt@ (who needs this for some cool upcomming stuff)
Diffstat (limited to 'lib/libc/net/getifaddrs.c')
-rw-r--r--lib/libc/net/getifaddrs.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/lib/libc/net/getifaddrs.c b/lib/libc/net/getifaddrs.c
index 0db89f6c190..6f7ea157215 100644
--- a/lib/libc/net/getifaddrs.c
+++ b/lib/libc/net/getifaddrs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: getifaddrs.c,v 1.9 2002/08/09 06:12:25 itojun Exp $ */
+/* $OpenBSD: getifaddrs.c,v 1.10 2008/11/24 20:08:49 claudio Exp $ */
/*
* Copyright (c) 1995, 1999
@@ -36,6 +36,7 @@
#include <errno.h>
#include <ifaddrs.h>
+#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -61,7 +62,7 @@ getifaddrs(struct ifaddrs **pif)
struct sockaddr_dl *dl;
struct sockaddr *sa;
u_short index = 0;
- size_t len, alen;
+ size_t len, alen, dlen;
struct ifaddrs *ifa, *ift;
int i;
char *data;
@@ -92,7 +93,8 @@ getifaddrs(struct ifaddrs **pif)
if (ifm->ifm_addrs & RTA_IFP) {
index = ifm->ifm_index;
++icnt;
- dl = (struct sockaddr_dl *)(ifm + 1);
+ dl = (struct sockaddr_dl *)(next +
+ rtm->rtm_hdrlen);
dcnt += SA_RLEN((struct sockaddr *)dl) +
ALIGNBYTES;
dcnt += sizeof(ifm->ifm_data);
@@ -109,7 +111,7 @@ getifaddrs(struct ifaddrs **pif)
#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
if (index == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
break;
- p = (char *)(ifam + 1);
+ p = next + rtm->rtm_hdrlen;
++icnt;
/* Scan to look for length of address */
alen = 0;
@@ -169,7 +171,8 @@ getifaddrs(struct ifaddrs **pif)
ifm = (struct if_msghdr *)rtm;
if (ifm->ifm_addrs & RTA_IFP) {
index = ifm->ifm_index;
- dl = (struct sockaddr_dl *)(ifm + 1);
+ dl = (struct sockaddr_dl *)(next +
+ rtm->rtm_hdrlen);
cif = ift;
ift->ifa_name = names;
@@ -185,7 +188,11 @@ getifaddrs(struct ifaddrs **pif)
/* ifm_data needs to be aligned */
ift->ifa_data = data = (void *)ALIGN(data);
- memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
+ dlen = rtm->rtm_hdrlen -
+ offsetof(struct if_msghdr, ifm_data);
+ if (dlen > sizeof(ifm->ifm_data))
+ dlen = sizeof(ifm->ifm_data);
+ memcpy(data, &ifm->ifm_data, dlen);
data += sizeof(ifm->ifm_data);
ift = (ift->ifa_next = ift + 1);
@@ -203,7 +210,7 @@ getifaddrs(struct ifaddrs **pif)
ift->ifa_name = cif->ifa_name;
ift->ifa_flags = cif->ifa_flags;
ift->ifa_data = NULL;
- p = (char *)(ifam + 1);
+ p = next + rtm->rtm_hdrlen;
/* Scan to look for length of address */
alen = 0;
for (p0 = p, i = 0; i < RTAX_MAX; i++) {