]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/gnu/ifaddrs.c
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
];
68 storage
= malloc (nifs
* sizeof storage
[0]);
72 __if_freereq (ifreqs
, nifs
);
79 struct ifreq
*const ifr
= &ifreqs
[i
];
81 /* Fill in all pointers to the storage we've already allocated. */
82 storage
[i
].ia
.ifa_next
= &storage
[i
+ 1].ia
;
83 storage
[i
].ia
.ifa_addr
= &storage
[i
].addr
;
84 storage
[i
].ia
.ifa_netmask
= &storage
[i
].netmask
;
85 storage
[i
].ia
.ifa_broadaddr
= &storage
[i
].broadaddr
; /* & dstaddr */
87 /* Now copy the information we already have from SIOCGIFCONF. */
88 storage
[i
].ia
.ifa_name
= strncpy (storage
[i
].name
, ifr
->ifr_name
,
89 sizeof storage
[i
].name
);
90 storage
[i
].addr
= ifr
->ifr_addr
;
92 /* The SIOCGIFCONF call filled in only the name and address.
93 Now we must also ask for the other information we need. */
95 if (__ioctl (fd
, SIOCGIFFLAGS
, ifr
) < 0)
97 storage
[i
].ia
.ifa_flags
= ifr
->ifr_flags
;
99 ifr
->ifr_addr
= storage
[i
].addr
;
100 if (__ioctl (fd
, SIOCGIFNETMASK
, ifr
) < 0)
102 storage
[i
].netmask
= ifr
->ifr_netmask
;
104 if (ifr
->ifr_flags
& IFF_BROADCAST
)
106 ifr
->ifr_addr
= storage
[i
].addr
;
107 if (__ioctl (fd
, SIOCGIFBRDADDR
, ifr
) < 0)
109 storage
[i
].broadaddr
= ifr
->ifr_broadaddr
;
111 else if (ifr
->ifr_flags
& IFF_POINTOPOINT
)
113 ifr
->ifr_addr
= storage
[i
].addr
;
114 if (__ioctl (fd
, SIOCGIFDSTADDR
, ifr
) < 0)
116 storage
[i
].broadaddr
= ifr
->ifr_dstaddr
;
120 memset (&storage
[i
].broadaddr
, 0, sizeof storage
[i
].broadaddr
);
122 storage
[i
].ia
.ifa_data
= NULL
; /* Nothing here for now. */
124 } while (++i
< nifs
);
125 if (i
< nifs
) /* Broke out early on error. */
129 __if_freereq (ifreqs
, nifs
);
132 storage
[i
- 1].ia
.ifa_next
= NULL
;
134 *ifap
= &storage
[0].ia
;
137 __if_freereq (ifreqs
, nifs
);
144 freeifaddrs (struct ifaddrs
*ifa
)