1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2002, 2003 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 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
;
86 /* Now copy the information we already have from SIOCGIFCONF. */
87 storage
[i
].ia
.ifa_name
= strncpy (storage
[i
].name
, ifr
->ifr_name
,
88 sizeof storage
[i
].name
);
89 storage
[i
].addr
= ifr
->ifr_addr
;
91 /* The SIOCGIFCONF call filled in only the name and address.
92 Now we must also ask for the other information we need. */
94 if (__ioctl (fd
, SIOCGIFFLAGS
, ifr
) < 0)
96 storage
[i
].ia
.ifa_flags
= ifr
->ifr_flags
;
98 ifr
->ifr_addr
= storage
[i
].addr
;
100 if (__ioctl (fd
, SIOCGIFNETMASK
, ifr
) < 0)
101 storage
[i
].ia
.ifa_netmask
= NULL
;
104 storage
[i
].ia
.ifa_netmask
= &storage
[i
].netmask
;
105 storage
[i
].netmask
= ifr
->ifr_netmask
;
108 if (ifr
->ifr_flags
& IFF_BROADCAST
)
110 ifr
->ifr_addr
= storage
[i
].addr
;
111 if (__ioctl (fd
, SIOCGIFBRDADDR
, ifr
) < 0)
112 storage
[i
].ia
.ifa_broadaddr
= NULL
;
114 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
;
115 storage
[i
].broadaddr
= ifr
->ifr_broadaddr
;
118 else if (ifr
->ifr_flags
& IFF_POINTOPOINT
)
120 ifr
->ifr_addr
= storage
[i
].addr
;
121 if (__ioctl (fd
, SIOCGIFDSTADDR
, ifr
) < 0)
122 storage
[i
].ia
.ifa_broadaddr
= NULL
;
125 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
;
126 storage
[i
].broadaddr
= ifr
->ifr_dstaddr
;
130 storage
[i
].ia
.ifa_broadaddr
= NULL
;
132 storage
[i
].ia
.ifa_data
= NULL
; /* Nothing here for now. */
134 ifr
= __if_nextreq (ifr
);
135 } while (++i
< nifs
);
136 if (i
< nifs
) /* Broke out early on error. */
140 __if_freereq (ifreqs
, nifs
);
144 storage
[i
- 1].ia
.ifa_next
= NULL
;
146 *ifap
= &storage
[0].ia
;
149 __if_freereq (ifreqs
, nifs
);
155 libc_hidden_def (getifaddrs
)
159 freeifaddrs (struct ifaddrs
*ifa
)
163 libc_hidden_def (freeifaddrs
)