2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
8 * The Regents of the University of California. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the Computer Systems
21 * Engineering Group at Lawrence Berkeley Laboratory.
22 * 4. Neither the name of the University nor of the Laboratory may be used
23 * to endorse or promote products derived from this software without
24 * specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * @(#) $Header: ifaddrlist.c,v 1.2 97/04/22 13:31:05 leres Exp $ (LBL)
42 #include <libinetutil.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
51 * See <libinetutil.h> for a description of the programming interface.
54 ifaddrlist(struct ifaddrlist
**ipaddrp
, int family
, uint_t flags
, char *errbuf
)
56 struct ifaddrlist
*ifaddrlist
= NULL
, *al
= NULL
;
57 struct sockaddr_in
*sin
;
58 struct sockaddr_in6
*sin6
;
66 (void) memset(&lifc
, 0, sizeof (lifc
));
67 if (family
!= AF_INET
&& family
!= AF_INET6
) {
68 (void) strlcpy(errbuf
, "invalid address family", ERRBUFSIZE
);
72 if ((fd
= socket(family
, SOCK_DGRAM
, 0)) == -1) {
78 * Get the number of network interfaces of type `family'.
80 lifn
.lifn_family
= family
;
81 lifn
.lifn_flags
= flags
;
83 if (ioctl(fd
, SIOCGLIFNUM
, &lifn
) == -1) {
84 opstr
= "SIOCGLIFNUM";
89 * Pad the interface count to detect when additional interfaces have
90 * been configured between SIOCGLIFNUM and SIOCGLIFCONF.
94 lifc
.lifc_flags
= flags
;
95 lifc
.lifc_family
= family
;
96 lifc
.lifc_len
= lifn
.lifn_count
* sizeof (struct lifreq
);
97 if ((lifc
.lifc_buf
= realloc(lifc
.lifc_buf
, lifc
.lifc_len
)) == NULL
) {
102 if (ioctl(fd
, SIOCGLIFCONF
, &lifc
) == -1) {
103 opstr
= "SIOCGLIFCONF";
108 * If every lifr_req slot is taken, then additional interfaces must
109 * have been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
110 * Recalculate to make sure we didn't miss any interfaces.
112 nlifr
= lifc
.lifc_len
/ sizeof (struct lifreq
);
113 if (nlifr
>= lifn
.lifn_count
)
117 * Allocate the address list to return.
119 if ((ifaddrlist
= calloc(nlifr
, sizeof (struct ifaddrlist
))) == NULL
) {
125 * Populate the address list by querying each underlying interface.
126 * If a query ioctl returns ENXIO, then the interface must have been
127 * removed after the SIOCGLIFCONF completed -- so we just ignore it.
131 for (lifrp
= lifc
.lifc_req
, i
= 0; i
< nlifr
; i
++, lifrp
++) {
132 (void) strlcpy(al
->device
, lifrp
->lifr_name
, LIFNAMSIZ
);
134 if (ioctl(fd
, SIOCGLIFFLAGS
, lifrp
) == -1) {
137 opstr
= "SIOCGLIFFLAGS";
140 al
->flags
= lifrp
->lifr_flags
;
142 if (ioctl(fd
, SIOCGLIFINDEX
, lifrp
) == -1) {
145 opstr
= "SIOCGLIFINDEX";
148 al
->index
= lifrp
->lifr_index
;
150 if (ioctl(fd
, SIOCGLIFADDR
, lifrp
) == -1) {
153 opstr
= "SIOCGLIFADDR";
157 if (family
== AF_INET
) {
158 sin
= (struct sockaddr_in
*)&lifrp
->lifr_addr
;
159 al
->addr
.addr
= sin
->sin_addr
;
161 sin6
= (struct sockaddr_in6
*)&lifrp
->lifr_addr
;
162 al
->addr
.addr6
= sin6
->sin6_addr
;
176 *ipaddrp
= ifaddrlist
;
180 (void) snprintf(errbuf
, ERRBUFSIZE
, "%s: %s", opstr
,
183 (void) snprintf(errbuf
, ERRBUFSIZE
, "%s: %s: %s", opstr
,
184 al
->device
, strerror(errno
));