summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/net/getifaddrs.c87
1 files changed, 57 insertions, 30 deletions
diff --git a/src/lib/libc/net/getifaddrs.c b/src/lib/libc/net/getifaddrs.c
index 069ee9afab..448e76097f 100644
--- a/src/lib/libc/net/getifaddrs.c
+++ b/src/lib/libc/net/getifaddrs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: getifaddrs.c,v 1.14 2021/11/29 03:20:37 deraadt Exp $ */ 1/* $OpenBSD: getifaddrs.c,v 1.15 2025/11/13 10:34:32 deraadt Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1995, 1999 4 * Copyright (c) 1995, 1999
@@ -25,10 +25,10 @@
25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp 25 * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
26 */ 26 */
27 27
28#include <sys/param.h> /* ALIGN ALIGNBYTES */
29#include <sys/types.h> 28#include <sys/types.h>
30#include <sys/ioctl.h> 29#include <sys/ioctl.h>
31#include <sys/socket.h> 30#include <sys/socket.h>
31#include <sys/syslog.h>
32#include <net/if.h> 32#include <net/if.h>
33#include <net/route.h> 33#include <net/route.h>
34#include <sys/sysctl.h> 34#include <sys/sysctl.h>
@@ -38,35 +38,32 @@
38#include <ifaddrs.h> 38#include <ifaddrs.h>
39#include <stddef.h> 39#include <stddef.h>
40#include <stdlib.h> 40#include <stdlib.h>
41#include <stdint.h>
41#include <string.h> 42#include <string.h>
42#include <unistd.h> 43#include <unistd.h>
44#include <stdio.h>
43 45
44#define SALIGN (sizeof(long) - 1) 46#define roundup(x, y) ((((uintptr_t)(x)+((y)-1))/(y))*(y))
45#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1)) 47#define proundup(x, y) (void *)roundup(x,y)
48
49#define SA_RLEN(sa) ((sa)->sa_len ? \
50 roundup((sa)->sa_len, sizeof(long)) : \
51 roundup(1, sizeof(long)))
46 52
47int 53int
48getifaddrs(struct ifaddrs **pif) 54getifaddrs(struct ifaddrs **pif)
49{ 55{
50 int icnt = 1; 56 int icnt = 1, dcnt = 0, ncnt = 0, mib[6], i;
51 int dcnt = 0;
52 int ncnt = 0;
53 int mib[6];
54 size_t needed; 57 size_t needed;
55 char *buf = NULL, *bufp; 58 char *buf = NULL, *bufp, *data, *names, *next, *p, *p0;
56 char *next; 59 struct ifaddrs *cif = 0, *ifa, *ift;
57 struct ifaddrs *cif = 0;
58 char *p, *p0;
59 struct rt_msghdr *rtm; 60 struct rt_msghdr *rtm;
60 struct if_msghdr *ifm; 61 struct if_msghdr *ifm;
61 struct ifa_msghdr *ifam; 62 struct ifa_msghdr *ifam;
62 struct sockaddr_dl *dl; 63 struct sockaddr_dl *dl;
63 struct sockaddr *sa; 64 struct sockaddr *sa;
64 u_short index = 0; 65 u_short index = 0;
65 size_t len, alen, dlen; 66 size_t len, alen, dlen, dsize;
66 struct ifaddrs *ifa, *ift;
67 int i;
68 char *data;
69 char *names;
70 67
71 mib[0] = CTL_NET; 68 mib[0] = CTL_NET;
72 mib[1] = PF_ROUTE; 69 mib[1] = PF_ROUTE;
@@ -95,6 +92,7 @@ getifaddrs(struct ifaddrs **pif)
95 break; 92 break;
96 } 93 }
97 94
95 /* Calculate data buffer size */
98 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 96 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
99 rtm = (struct rt_msghdr *)next; 97 rtm = (struct rt_msghdr *)next;
100 if (rtm->rtm_version != RTM_VERSION) 98 if (rtm->rtm_version != RTM_VERSION)
@@ -107,10 +105,15 @@ getifaddrs(struct ifaddrs **pif)
107 ++icnt; 105 ++icnt;
108 dl = (struct sockaddr_dl *)(next + 106 dl = (struct sockaddr_dl *)(next +
109 rtm->rtm_hdrlen); 107 rtm->rtm_hdrlen);
110 dcnt += SA_RLEN((struct sockaddr *)dl) +
111 ALIGNBYTES;
112 dcnt += sizeof(ifm->ifm_data);
113 ncnt += dl->sdl_nlen + 1; 108 ncnt += dl->sdl_nlen + 1;
109
110 /* sockaddr's need long alignment */
111 dcnt = roundup(dcnt, sizeof(long));
112 dcnt += SA_RLEN((struct sockaddr *)dl);
113
114 /* ifm_data[] needs long long alignment */
115 dcnt = roundup(dcnt, sizeof(long long));
116 dcnt += sizeof(ifm->ifm_data);
114 } else 117 } else
115 index = 0; 118 index = 0;
116 break; 119 break;
@@ -145,6 +148,8 @@ getifaddrs(struct ifaddrs **pif)
145 continue; 148 continue;
146 sa = (struct sockaddr *)p; 149 sa = (struct sockaddr *)p;
147 len = SA_RLEN(sa); 150 len = SA_RLEN(sa);
151 /* sockaddr's need long alignment */
152 dcnt = roundup(dcnt, sizeof(long));
148 if (i == RTAX_NETMASK && sa->sa_len == 0) 153 if (i == RTAX_NETMASK && sa->sa_len == 0)
149 dcnt += alen; 154 dcnt += alen;
150 else 155 else
@@ -155,23 +160,29 @@ getifaddrs(struct ifaddrs **pif)
155 } 160 }
156 } 161 }
157 162
158 if (icnt + dcnt + ncnt == 1) { 163 if (icnt + ncnt + dcnt == 1) {
159 *pif = NULL; 164 *pif = NULL;
160 free(buf); 165 free(buf);
161 return (0); 166 return (0);
162 } 167 }
163 data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt); 168
169 dsize = sizeof(struct ifaddrs) * icnt;
170 dsize += ncnt;
171 dsize = roundup(dsize, sizeof(long long));
172 dsize += dcnt;
173
174 data = calloc(dsize, 1);
164 if (data == NULL) { 175 if (data == NULL) {
165 free(buf); 176 free(buf);
166 return(-1); 177 return(-1);
167 } 178 }
168 179
169 ifa = (struct ifaddrs *)data; 180 /* ifaddrs[], names, then if_data[] */
181 ift = ifa = (struct ifaddrs *)data;
170 data += sizeof(struct ifaddrs) * icnt; 182 data += sizeof(struct ifaddrs) * icnt;
171 names = data + dcnt; 183 names = data;
172 184 data += ncnt;
173 memset(ifa, 0, sizeof(struct ifaddrs) * icnt); 185 data = proundup(data, sizeof(long long));
174 ift = ifa;
175 186
176 index = 0; 187 index = 0;
177 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 188 for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
@@ -193,19 +204,21 @@ getifaddrs(struct ifaddrs **pif)
193 names[dl->sdl_nlen] = 0; 204 names[dl->sdl_nlen] = 0;
194 names += dl->sdl_nlen + 1; 205 names += dl->sdl_nlen + 1;
195 206
207 data = proundup(data, sizeof(long));
196 ift->ifa_addr = (struct sockaddr *)data; 208 ift->ifa_addr = (struct sockaddr *)data;
197 memcpy(data, dl, 209 memcpy(data, dl,
198 ((struct sockaddr *)dl)->sa_len); 210 ((struct sockaddr *)dl)->sa_len);
199 data += SA_RLEN((struct sockaddr *)dl); 211 data += SA_RLEN((struct sockaddr *)dl);
200 212
201 /* ifm_data needs to be aligned */ 213 /* if_data needs long long alignment */
202 ift->ifa_data = data = (void *)ALIGN(data); 214 data = proundup(data, sizeof(long long));
215 ift->ifa_data = data;
203 dlen = rtm->rtm_hdrlen - 216 dlen = rtm->rtm_hdrlen -
204 offsetof(struct if_msghdr, ifm_data); 217 offsetof(struct if_msghdr, ifm_data);
205 if (dlen > sizeof(ifm->ifm_data)) 218 if (dlen > sizeof(ifm->ifm_data))
206 dlen = sizeof(ifm->ifm_data); 219 dlen = sizeof(ifm->ifm_data);
207 memcpy(data, &ifm->ifm_data, dlen); 220 memcpy(data, &ifm->ifm_data, dlen);
208 data += sizeof(ifm->ifm_data); 221 data += dlen;
209 222
210 ift = (ift->ifa_next = ift + 1); 223 ift = (ift->ifa_next = ift + 1);
211 } else 224 } else
@@ -245,12 +258,14 @@ getifaddrs(struct ifaddrs **pif)
245 len = SA_RLEN(sa); 258 len = SA_RLEN(sa);
246 switch (i) { 259 switch (i) {
247 case RTAX_IFA: 260 case RTAX_IFA:
261 data = proundup(data, sizeof(long));
248 ift->ifa_addr = (struct sockaddr *)data; 262 ift->ifa_addr = (struct sockaddr *)data;
249 memcpy(data, p, len); 263 memcpy(data, p, len);
250 data += len; 264 data += len;
251 break; 265 break;
252 266
253 case RTAX_NETMASK: 267 case RTAX_NETMASK:
268 data = proundup(data, sizeof(long));
254 ift->ifa_netmask = 269 ift->ifa_netmask =
255 (struct sockaddr *)data; 270 (struct sockaddr *)data;
256 if (sa->sa_len == 0) { 271 if (sa->sa_len == 0) {
@@ -263,6 +278,7 @@ getifaddrs(struct ifaddrs **pif)
263 break; 278 break;
264 279
265 case RTAX_BRD: 280 case RTAX_BRD:
281 data = proundup(data, sizeof(long));
266 ift->ifa_broadaddr = 282 ift->ifa_broadaddr =
267 (struct sockaddr *)data; 283 (struct sockaddr *)data;
268 memcpy(data, p, len); 284 memcpy(data, p, len);
@@ -278,6 +294,17 @@ getifaddrs(struct ifaddrs **pif)
278 } 294 }
279 } 295 }
280 296
297 /* XXX temporary paranoia until we are sure it is bug free */
298 if (dsize != (char *)data - (char *)ifa) {
299 char buf[1024];
300
301 /* <10> is LOG_CRIT */
302 snprintf(buf, sizeof buf,
303 "<10>%s: getifaddrs: allocated %lu used %lu\n",
304 __progname, dsize, (char *)data - (char *)ifa);
305 sendsyslog(buf, strlen(buf), LOG_CONS);
306 }
307
281 free(buf); 308 free(buf);
282 if (--ift >= ifa) { 309 if (--ift >= ifa) {
283 ift->ifa_next = NULL; 310 ift->ifa_next = NULL;