4 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: ifiter_getifaddrs.c,v 1.2.68.3 2004/03/06 08:14:59 marka Exp */
23 * Obtain the list of network interfaces using the getifaddrs(3) library.
28 #define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G')
29 #define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
31 struct isc_interfaceiter
{
32 unsigned int magic
; /* Magic number. */
34 void *buf
; /* (unused) */
35 unsigned int bufsize
; /* (always 0) */
36 struct ifaddrs
*ifaddrs
; /* List of ifaddrs */
37 struct ifaddrs
*pos
; /* Ptr to current ifaddr */
38 isc_interface_t current
; /* Current interface data. */
39 isc_result_t result
; /* Last result code. */
43 isc_interfaceiter_create(isc_mem_t
*mctx
, isc_interfaceiter_t
**iterp
) {
44 isc_interfaceiter_t
*iter
;
46 char strbuf
[ISC_STRERRORSIZE
];
48 REQUIRE(iterp
!= NULL
);
49 REQUIRE(*iterp
== NULL
);
51 iter
= isc_mem_get(mctx
, sizeof(*iter
));
53 return (ISC_R_NOMEMORY
);
60 if (getifaddrs(&iter
->ifaddrs
) < 0) {
61 isc__strerror(errno
, strbuf
, sizeof(strbuf
));
62 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
63 isc_msgcat_get(isc_msgcat
,
64 ISC_MSGSET_IFITERGETIFADDRS
,
67 "addresses: getifaddrs: %s"),
69 result
= ISC_R_UNEXPECTED
;
74 * A newly created iterator has an undefined position
75 * until isc_interfaceiter_first() is called.
78 iter
->result
= ISC_R_FAILURE
;
80 iter
->magic
= IFITER_MAGIC
;
82 return (ISC_R_SUCCESS
);
85 if (iter
->ifaddrs
!= NULL
) /* just in case */
86 freeifaddrs(iter
->ifaddrs
);
87 isc_mem_put(mctx
, iter
, sizeof(*iter
));
92 * Get information about the current interface to iter->current.
93 * If successful, return ISC_R_SUCCESS.
94 * If the interface has an unsupported address family,
95 * return ISC_R_IGNORE.
99 internal_current(isc_interfaceiter_t
*iter
) {
102 unsigned int namelen
;
104 REQUIRE(VALID_IFITER(iter
));
109 INSIST(ifa
->ifa_name
!= NULL
);
110 INSIST(ifa
->ifa_addr
!= NULL
);
112 family
= ifa
->ifa_addr
->sa_family
;
113 if (family
!= AF_INET
&& family
!= AF_INET6
)
114 return (ISC_R_IGNORE
);
116 memset(&iter
->current
, 0, sizeof(iter
->current
));
118 namelen
= strlen(ifa
->ifa_name
);
119 if (namelen
> sizeof(iter
->current
.name
) - 1)
120 namelen
= sizeof(iter
->current
.name
) - 1;
122 memset(iter
->current
.name
, 0, sizeof(iter
->current
.name
));
123 memcpy(iter
->current
.name
, ifa
->ifa_name
, namelen
);
125 iter
->current
.flags
= 0;
127 if ((ifa
->ifa_flags
& IFF_UP
) != 0)
128 iter
->current
.flags
|= INTERFACE_F_UP
;
130 if ((ifa
->ifa_flags
& IFF_POINTOPOINT
) != 0)
131 iter
->current
.flags
|= INTERFACE_F_POINTTOPOINT
;
133 if ((ifa
->ifa_flags
& IFF_LOOPBACK
) != 0)
134 iter
->current
.flags
|= INTERFACE_F_LOOPBACK
;
136 if ((ifa
->ifa_flags
& IFF_BROADCAST
) != 0) {
137 iter
->current
.flags
|= INTERFACE_F_BROADCAST
;
141 if ((ifa
->ifa_flags
& IFF_MULTICAST
) != 0) {
142 iter
->current
.flags
|= INTERFACE_F_MULTICAST
;
145 iter
->current
.af
= family
;
147 get_addr(family
, &iter
->current
.address
, ifa
->ifa_addr
, ifa
->ifa_name
);
149 if (ifa
->ifa_netmask
!= NULL
)
150 get_addr(family
, &iter
->current
.netmask
, ifa
->ifa_netmask
,
153 if (ifa
->ifa_dstaddr
!= NULL
&&
154 (iter
->current
.flags
& INTERFACE_F_POINTTOPOINT
) != 0)
155 get_addr(family
, &iter
->current
.dstaddress
, ifa
->ifa_dstaddr
,
158 if (ifa
->ifa_broadaddr
!= NULL
&&
159 (iter
->current
.flags
& INTERFACE_F_BROADCAST
) != 0)
160 get_addr(family
, &iter
->current
.broadcast
, ifa
->ifa_broadaddr
,
163 return (ISC_R_SUCCESS
);
167 * Step the iterator to the next interface. Unlike
168 * isc_interfaceiter_next(), this may leave the iterator
169 * positioned on an interface that will ultimately
170 * be ignored. Return ISC_R_NOMORE if there are no more
171 * interfaces, otherwise ISC_R_SUCCESS.
174 internal_next(isc_interfaceiter_t
*iter
) {
175 iter
->pos
= iter
->pos
->ifa_next
;
177 if (iter
->pos
== NULL
)
178 return (ISC_R_NOMORE
);
180 return (ISC_R_SUCCESS
);
184 internal_destroy(isc_interfaceiter_t
*iter
) {
186 freeifaddrs(iter
->ifaddrs
);
187 iter
->ifaddrs
= NULL
;
191 void internal_first(isc_interfaceiter_t
*iter
) {
192 iter
->pos
= iter
->ifaddrs
;