1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #include <sys/socket.h>
23 #include <sys/ioctl.h>
28 #include <netinet/in.h>
32 /* Create a linked list of `struct ifaddrs' structures, one for each
33 network interface on the host machine. If successful, store the
34 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
36 getifaddrs (struct ifaddrs
**ifap
)
38 /* This implementation handles only IPv4 interfaces.
39 The various ioctls below will only work on an AF_INET socket.
40 Some different mechanism entirely must be used for IPv6. */
41 int fd
= __socket (AF_INET
, SOCK_DGRAM
, 0);
48 __ifreq (&ifreqs
, &nifs
, fd
);
49 if (ifreqs
== NULL
) /* XXX doesn't distinguish error vs none */
55 /* Now we have the list of interfaces and each one's address.
56 Put it into the expected format and fill in the remaining details. */
64 struct sockaddr addr
, netmask
, broadaddr
;
65 char name
[IF_NAMESIZE
];
70 storage
= malloc (nifs
* sizeof storage
[0]);
74 __if_freereq (ifreqs
, nifs
);
82 /* Fill in all pointers to the storage we've already allocated. */
83 storage
[i
].ia
.ifa_next
= &storage
[i
+ 1].ia
;
84 storage
[i
].ia
.ifa_addr
= &storage
[i
].addr
;
85 storage
[i
].ia
.ifa_netmask
= &storage
[i
].netmask
;
86 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
; /* & dstaddr */
88 /* Now copy the information we already have from SIOCGIFCONF. */
89 storage
[i
].ia
.ifa_name
= strncpy (storage
[i
].name
, ifr
->ifr_name
,
90 sizeof storage
[i
].name
);
91 storage
[i
].addr
= ifr
->ifr_addr
;
93 /* The SIOCGIFCONF call filled in only the name and address.
94 Now we must also ask for the other information we need. */
96 if (__ioctl (fd
, SIOCGIFFLAGS
, ifr
) < 0)
98 storage
[i
].ia
.ifa_flags
= ifr
->ifr_flags
;
100 ifr
->ifr_addr
= storage
[i
].addr
;
102 if (__ioctl (fd
, SIOCGIFNETMASK
, ifr
) < 0)
104 storage
[i
].netmask
= ifr
->ifr_netmask
;
106 if (ifr
->ifr_flags
& IFF_BROADCAST
)
108 ifr
->ifr_addr
= storage
[i
].addr
;
109 if (__ioctl (fd
, SIOCGIFBRDADDR
, ifr
) < 0)
111 storage
[i
].broadaddr
= ifr
->ifr_broadaddr
;
113 else if (ifr
->ifr_flags
& IFF_POINTOPOINT
)
115 ifr
->ifr_addr
= storage
[i
].addr
;
116 if (__ioctl (fd
, SIOCGIFDSTADDR
, ifr
) < 0)
118 storage
[i
].broadaddr
= ifr
->ifr_dstaddr
;
122 memset (&storage
[i
].broadaddr
, 0, sizeof storage
[i
].broadaddr
);
124 storage
[i
].ia
.ifa_data
= NULL
; /* Nothing here for now. */
126 ifr
= __if_nextreq (ifr
);
127 } while (++i
< nifs
);
128 if (i
< nifs
) /* Broke out early on error. */
132 __if_freereq (ifreqs
, nifs
);
136 storage
[i
- 1].ia
.ifa_next
= NULL
;
138 *ifap
= &storage
[0].ia
;
141 __if_freereq (ifreqs
, nifs
);
148 freeifaddrs (struct ifaddrs
*ifa
)