source: rtems/cpukit/libnetworking/libc/getifaddrs.c @ cb68253

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

  • Property mode set to 100644
File size: 10.2 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $      */
4
5/*
6 * Copyright (c) 1995, 1999
7 *      Berkeley Software Design, Inc.  All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *      BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
28 */
29/*
30 * NOTE: SIOCGIFCONF case is not LP64 friendly.  it also does not perform
31 * try-and-error for region size.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include <sys/cdefs.h>
39
40#include <sys/types.h>
41#include <sys/ioctl.h>
42#include <sys/socket.h>
43#include <net/if.h>
44#ifdef  NET_RT_IFLIST
45#include <sys/param.h>
46#include <net/route.h>
47#include <sys/sysctl.h>
48#include <net/if_dl.h>
49#endif
50
51#include <errno.h>
52#include <ifaddrs.h>
53#include <stdlib.h>
54#include <string.h>
55
56#if !defined(AF_LINK)
57#define SA_LEN(sa)      sizeof(struct sockaddr)
58#endif
59
60#if !defined(SA_LEN)
61#define SA_LEN(sa)      (sa)->sa_len
62#endif
63
64#define SALIGN  (sizeof(long) - 1)
65#define SA_RLEN(sa)     ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
66
67#ifndef ALIGNBYTES
68/*
69 * On systems with a routing socket, ALIGNBYTES should match the value
70 * that the kernel uses when building the messages.
71 */
72#define ALIGNBYTES      XXX
73#endif
74#ifndef ALIGN
75#define ALIGN(p)        (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
76#endif
77
78#if     _BSDI_VERSION >= 199701
79#define HAVE_IFM_DATA
80#endif
81
82#if     _BSDI_VERSION >= 199802
83/* ifam_data is very specific to recent versions of bsdi */
84#define HAVE_IFAM_DATA
85#endif
86
87#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
88#define HAVE_IFM_DATA
89#endif
90
91#define MAX_SYSCTL_TRY 5
92
93int
94getifaddrs(struct ifaddrs **pif)
95{
96        int icnt = 1;
97        int dcnt = 0;
98        int ncnt = 0;
99#ifdef  NET_RT_IFLIST
100        int ntry = 0;
101        int mib[6];
102        size_t needed;
103        char *buf;
104        char *next;
105        struct ifaddrs *cif = 0;
106        char *p, *p0;
107        struct rt_msghdr *rtm;
108        struct if_msghdr *ifm;
109        struct ifa_msghdr *ifam;
110        struct sockaddr_dl *dl;
111        struct sockaddr *sa;
112        struct ifaddrs *ifa, *ift;
113        u_short idx = 0;
114#else   /* NET_RT_IFLIST */
115        char buf[1024];
116        int m, sock;
117        struct ifconf ifc;
118        struct ifreq *ifr;
119        struct ifreq *lifr;
120#endif  /* NET_RT_IFLIST */
121        int i;
122        size_t len, alen;
123        char *data;
124        char *names;
125
126#ifdef  NET_RT_IFLIST
127        mib[0] = CTL_NET;
128        mib[1] = PF_ROUTE;
129        mib[2] = 0;             /* protocol */
130        mib[3] = 0;             /* wildcard address family */
131        mib[4] = NET_RT_IFLIST;
132        mib[5] = 0;             /* no flags */
133        do {
134                /*
135                 * We'll try to get addresses several times in case that
136                 * the number of addresses is unexpectedly increased during
137                 * the two sysctl calls.  This should rarely happen, but we'll
138                 * try to do our best for applications that assume success of
139                 * this library (which should usually be the case).
140                 * Portability note: since FreeBSD does not add margin of
141                 * memory at the first sysctl, the possibility of failure on
142                 * the second sysctl call is a bit higher.
143                 */
144
145                if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
146                        return (-1);
147                if ((buf = malloc(needed)) == NULL)
148                        return (-1);
149                if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
150                        if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
151                                free(buf);
152                                return (-1);
153                        }
154                        free(buf);
155                        buf = NULL;
156                }
157        } while (buf == NULL);
158
159        for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
160                rtm = (struct rt_msghdr *)(void *)next;
161                if (rtm->rtm_version != RTM_VERSION)
162                        continue;
163                switch (rtm->rtm_type) {
164                case RTM_IFINFO:
165                        ifm = (struct if_msghdr *)(void *)rtm;
166                        if (ifm->ifm_addrs & RTA_IFP) {
167                                idx = ifm->ifm_index;
168                                ++icnt;
169                                dl = (struct sockaddr_dl *)(void *)(ifm + 1);
170                                dcnt += SA_RLEN((struct sockaddr *)(void*)dl) +
171                                    ALIGNBYTES;
172#ifdef  HAVE_IFM_DATA
173                                dcnt += sizeof(ifm->ifm_data);
174#endif  /* HAVE_IFM_DATA */
175                                ncnt += dl->sdl_nlen + 1;
176                        } else
177                                idx = 0;
178                        break;
179
180                case RTM_NEWADDR:
181                        ifam = (struct ifa_msghdr *)(void *)rtm;
182                        if (idx && ifam->ifam_index != idx)
183                                abort();        /* this cannot happen */
184
185#define RTA_MASKS       (RTA_NETMASK | RTA_IFA | RTA_BRD)
186                        if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
187                                break;
188                        p = (char *)(void *)(ifam + 1);
189                        ++icnt;
190#ifdef  HAVE_IFAM_DATA
191                        dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES;
192#endif  /* HAVE_IFAM_DATA */
193                        /* Scan to look for length of address */
194                        alen = 0;
195                        for (p0 = p, i = 0; i < RTAX_MAX; i++) {
196                                if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
197                                    == 0)
198                                        continue;
199                                sa = (struct sockaddr *)(void *)p;
200                                len = SA_RLEN(sa);
201                                if (i == RTAX_IFA) {
202                                        alen = len;
203                                        break;
204                                }
205                                p += len;
206                        }
207                        for (p = p0, i = 0; i < RTAX_MAX; i++) {
208                                if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
209                                    == 0)
210                                        continue;
211                                sa = (struct sockaddr *)(void *)p;
212                                len = SA_RLEN(sa);
213                                if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
214                                        dcnt += alen;
215                                else
216                                        dcnt += len;
217                                p += len;
218                        }
219                        break;
220                }
221        }
222#else   /* NET_RT_IFLIST */
223        ifc.ifc_buf = buf;
224        ifc.ifc_len = sizeof(buf);
225
226        if ((sock = _socket(AF_INET, SOCK_STREAM, 0)) < 0)
227                return (-1);
228        i =  _ioctl(sock, SIOCGIFCONF, (char *)&ifc);
229        _close(sock);
230        if (i < 0)
231                return (-1);
232
233        ifr = ifc.ifc_req;
234        lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
235
236        while (ifr < lifr) {
237                struct sockaddr *sa;
238
239                sa = &ifr->ifr_addr;
240                ++icnt;
241                dcnt += SA_RLEN(sa);
242                ncnt += sizeof(ifr->ifr_name) + 1;
243               
244                if (SA_LEN(sa) < sizeof(*sa))
245                        ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
246                else
247                        ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
248        }
249#endif  /* NET_RT_IFLIST */
250
251        if (icnt + dcnt + ncnt == 1) {
252                *pif = NULL;
253                free(buf);
254                return (0);
255        }
256        data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
257        if (data == NULL) {
258                free(buf);
259                return(-1);
260        }
261
262        ifa = (struct ifaddrs *)(void *)data;
263        data += sizeof(struct ifaddrs) * icnt;
264        names = data + dcnt;
265
266        memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
267        ift = ifa;
268
269#ifdef  NET_RT_IFLIST
270        idx = 0;
271        for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
272                rtm = (struct rt_msghdr *)(void *)next;
273                if (rtm->rtm_version != RTM_VERSION)
274                        continue;
275                switch (rtm->rtm_type) {
276                case RTM_IFINFO:
277                        ifm = (struct if_msghdr *)(void *)rtm;
278                        if (ifm->ifm_addrs & RTA_IFP) {
279                                idx = ifm->ifm_index;
280                                dl = (struct sockaddr_dl *)(void *)(ifm + 1);
281
282                                cif = ift;
283                                ift->ifa_name = names;
284                                ift->ifa_flags = (int)ifm->ifm_flags;
285                                memcpy(names, dl->sdl_data,
286                                    (size_t)dl->sdl_nlen);
287                                names[dl->sdl_nlen] = 0;
288                                names += dl->sdl_nlen + 1;
289
290                                ift->ifa_addr = (struct sockaddr *)(void *)data;
291                                memcpy(data, dl,
292                                    (size_t)SA_LEN((struct sockaddr *)
293                                    (void *)dl));
294                                data += SA_RLEN((struct sockaddr *)(void *)dl);
295
296#ifdef  HAVE_IFM_DATA
297                                /* ifm_data needs to be aligned */
298                                ift->ifa_data = data = (void *)ALIGN(data);
299                                memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
300                                data += sizeof(ifm->ifm_data);
301#else   /* HAVE_IFM_DATA */
302                                ift->ifa_data = NULL;
303#endif  /* HAVE_IFM_DATA */
304
305                                ift = (ift->ifa_next = ift + 1);
306                        } else
307                                idx = 0;
308                        break;
309
310                case RTM_NEWADDR:
311                        ifam = (struct ifa_msghdr *)(void *)rtm;
312                        if (idx && ifam->ifam_index != idx)
313                                abort();        /* this cannot happen */
314
315                        if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
316                                break;
317                        ift->ifa_name = cif->ifa_name;
318                        ift->ifa_flags = cif->ifa_flags;
319                        ift->ifa_data = NULL;
320                        p = (char *)(void *)(ifam + 1);
321                        /* Scan to look for length of address */
322                        alen = 0;
323                        for (p0 = p, i = 0; i < RTAX_MAX; i++) {
324                                if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
325                                    == 0)
326                                        continue;
327                                sa = (struct sockaddr *)(void *)p;
328                                len = SA_RLEN(sa);
329                                if (i == RTAX_IFA) {
330                                        alen = len;
331                                        break;
332                                }
333                                p += len;
334                        }
335                        for (p = p0, i = 0; i < RTAX_MAX; i++) {
336                                if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
337                                    == 0)
338                                        continue;
339                                sa = (struct sockaddr *)(void *)p;
340                                len = SA_RLEN(sa);
341                                switch (i) {
342                                case RTAX_IFA:
343                                        ift->ifa_addr =
344                                            (struct sockaddr *)(void *)data;
345                                        memcpy(data, p, len);
346                                        data += len;
347                                        break;
348
349                                case RTAX_NETMASK:
350                                        ift->ifa_netmask =
351                                            (struct sockaddr *)(void *)data;
352                                        if (SA_LEN(sa) == 0) {
353                                                memset(data, 0, alen);
354                                                data += alen;
355                                                break;
356                                        }
357                                        memcpy(data, p, len);
358                                        data += len;
359                                        break;
360
361                                case RTAX_BRD:
362                                        ift->ifa_broadaddr =
363                                            (struct sockaddr *)(void *)data;
364                                        memcpy(data, p, len);
365                                        data += len;
366                                        break;
367                                }
368                                p += len;
369                        }
370
371#ifdef  HAVE_IFAM_DATA
372                        /* ifam_data needs to be aligned */
373                        ift->ifa_data = data = (void *)ALIGN(data);
374                        memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data));
375                        data += sizeof(ifam->ifam_data);
376#endif  /* HAVE_IFAM_DATA */
377
378                        ift = (ift->ifa_next = ift + 1);
379                        break;
380                }
381        }
382
383        free(buf);
384#else   /* NET_RT_IFLIST */
385        ifr = ifc.ifc_req;
386        lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
387
388        while (ifr < lifr) {
389                struct sockaddr *sa;
390
391                ift->ifa_name = names;
392                names[sizeof(ifr->ifr_name)] = 0;
393                strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
394                while (*names++)
395                        ;
396
397                ift->ifa_addr = (struct sockaddr *)data;
398                sa = &ifr->ifr_addr;
399                memcpy(data, sa, SA_LEN(sa));
400                data += SA_RLEN(sa);
401               
402                ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
403                ift = (ift->ifa_next = ift + 1);
404        }
405#endif  /* NET_RT_IFLIST */
406        if (--ift >= ifa) {
407                ift->ifa_next = NULL;
408                *pif = ifa;
409        } else {
410                *pif = NULL;
411                free(ifa);
412        }
413        return (0);
414}
415
416void
417freeifaddrs(struct ifaddrs *ifp)
418{
419
420        free(ifp);
421}
Note: See TracBrowser for help on using the repository browser.