2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: ifiter_getifaddrs.c,v 1.2.68.3 2004/03/06 08:14:59 marka Exp $ */
21 * Obtain the list of network interfaces using the getifaddrs(3) library.
26 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G')
27 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
29 struct isc_interfaceiter
{
30 unsigned int magic
; /* Magic number. */
32 void *buf
; /* (unused) */
33 unsigned int bufsize
; /* (always 0) */
34 struct ifaddrs
*ifaddrs
; /* List of ifaddrs */
35 struct ifaddrs
*pos
; /* Ptr to current ifaddr */
36 isc_interface_t current
; /* Current interface data. */
37 isc_result_t result
; /* Last result code. */
41 isc_interfaceiter_create(isc_mem_t
*mctx
, isc_interfaceiter_t
**iterp
) {
42 isc_interfaceiter_t
*iter
;
44 char strbuf
[ISC_STRERRORSIZE
];
46 REQUIRE(iterp
!= NULL
);
47 REQUIRE(*iterp
== NULL
);
49 iter
= isc_mem_get(mctx
, sizeof(*iter
));
51 return (ISC_R_NOMEMORY
);
58 if (getifaddrs(&iter
->ifaddrs
) < 0) {
59 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
60 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
61 isc_msgcat_get(isc_msgcat
,
62 ISC_MSGSET_IFITERGETIFADDRS
,
65 "addresses: getifaddrs: %s"),
67 result
= ISC_R_UNEXPECTED
;
72 * A newly created iterator has an undefined position
73 * until isc_interfaceiter_first() is called.
76 iter
->result
= ISC_R_FAILURE
;
78 iter
->magic
= IFITER_MAGIC
;
80 return (ISC_R_SUCCESS
);
83 if (iter
->ifaddrs
!= NULL
) /* just in case */
84 freeifaddrs(iter
->ifaddrs
);
85 isc_mem_put(mctx
, iter
, sizeof(*iter
));
90 * Get information about the current interface to iter->current.
91 * If successful, return ISC_R_SUCCESS.
92 * If the interface has an unsupported address family,
93 * return ISC_R_IGNORE.
97 internal_current(isc_interfaceiter_t
*iter
) {
100 unsigned int namelen
;
102 REQUIRE(VALID_IFITER(iter
));
107 INSIST(ifa
->ifa_name
!= NULL
);
108 INSIST(ifa
->ifa_addr
!= NULL
);
110 family
= ifa
->ifa_addr
->sa_family
;
111 if (family
!= AF_INET
&& family
!= AF_INET6
)
112 return (ISC_R_IGNORE
);
114 memset(&iter
->current
, 0, sizeof(iter
->current
));
116 namelen
= strlen(ifa
->ifa_name
);
117 if (namelen
> sizeof(iter
->current
.name
) - 1)
118 namelen
= sizeof(iter
->current
.name
) - 1;
120 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
121 memcpy(iter
->current
.name
, ifa
->ifa_name
, namelen
);
123 iter
->current
.flags
= 0;
125 if ((ifa
->ifa_flags
& IFF_UP
) != 0)
126 iter
->current
.flags
|= INTERFACE_F_UP
;
128 if ((ifa
->ifa_flags
& IFF_POINTOPOINT
) != 0)
129 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
131 if ((ifa
->ifa_flags
& IFF_LOOPBACK
) != 0)
132 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
134 if ((ifa
->ifa_flags
& IFF_BROADCAST
) != 0) {
135 iter
->current
.flags
|= INTERFACE_F_BROADCAST
;
139 if ((ifa
->ifa_flags
& IFF_MULTICAST
) != 0) {
140 iter
->current
.flags
|= INTERFACE_F_MULTICAST
;
143 iter
->current
.af
= family
;
145 get_addr(family
, &iter
->current
.address
, ifa
->ifa_addr
, ifa
->ifa_name
);
147 if (ifa
->ifa_netmask
!= NULL
)
148 get_addr(family
, &iter
->current
.netmask
, ifa
->ifa_netmask
,
151 if (ifa
->ifa_dstaddr
!= NULL
&&
152 (iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0)
153 get_addr(family
, &iter
->current
.dstaddress
, ifa
->ifa_dstaddr
,
156 if (ifa
->ifa_broadaddr
!= NULL
&&
157 (iter
->current
.flags
& INTERFACE_F_BROADCAST
) != 0)
158 get_addr(family
, &iter
->current
.broadcast
, ifa
->ifa_broadaddr
,
161 return (ISC_R_SUCCESS
);
165 * Step the iterator to the next interface. Unlike
166 * isc_interfaceiter_next(), this may leave the iterator
167 * positioned on an interface that will ultimately
168 * be ignored. Return ISC_R_NOMORE if there are no more
169 * interfaces, otherwise ISC_R_SUCCESS.
172 internal_next(isc_interfaceiter_t
*iter
) {
173 iter
->pos
= iter
->pos
->ifa_next
;
175 if (iter
->pos
== NULL
)
176 return (ISC_R_NOMORE
);
178 return (ISC_R_SUCCESS
);
182 internal_destroy(isc_interfaceiter_t
*iter
) {
184 freeifaddrs(iter
->ifaddrs
);
185 iter
->ifaddrs
= NULL
;
189 void internal_first(isc_interfaceiter_t
*iter
) {
190 iter
->pos
= iter
->ifaddrs
;