PageRenderTime 22ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/libisc/interfaceiter.c

https://bitbucket.org/freebsd/freebsd-head/
C | 220 lines | 140 code | 28 blank | 52 comment | 28 complexity | b2711ff2be231b929598dbdfc8569faa MD5 | raw file
  1/*
  2 * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
  3 * Copyright (C) 1999-2003  Internet Software Consortium.
  4 *
  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.
  8 *
  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.
 16 */
 17
 18/* $Id: interfaceiter.c,v 1.22.2.1.10.14 2004/08/28 06:25:22 marka Exp $ */
 19
 20#include <config.h>
 21
 22#define ISC_ONLY_IPV6
 23
 24#include <sys/types.h>
 25#include <sys/ioctl.h>
 26#ifdef HAVE_SYS_SOCKIO_H
 27#include <sys/sockio.h>		/* Required for ifiter_ioctl.c. */
 28#endif
 29
 30#include <stdio.h>
 31#include <stdlib.h>
 32#include <unistd.h>
 33#include <errno.h>
 34
 35#include <isc/interfaceiter.h>
 36#include <isc/magic.h>
 37#include <isc/mem.h>
 38#include <isc/msgs.h>
 39#include <isc/net.h>
 40#include <isc/print.h>
 41#include <isc/result.h>
 42#include <isc/strerror.h>
 43#include <isc/string.h>
 44#include <isc/types.h>
 45#include <isc/util.h>
 46
 47/* Must follow <isc/net.h>. */
 48#ifdef HAVE_NET_IF6_H
 49#include <net/if6.h>
 50#endif
 51
 52/* Common utility functions */
 53
 54/*
 55 * Extract the network address part from a "struct sockaddr".
 56 *
 57 * The address family is given explicitly
 58 * instead of using src->sa_family, because the latter does not work
 59 * for copying a network mask obtained by SIOCGIFNETMASK (it does
 60 * not have a valid address family).
 61 */
 62
 63static void
 64get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src,
 65	 char *ifname)
 66{
 67	struct sockaddr_in6 *sa6;
 68
 69#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \
 70    !defined(ISC_PLATFORM_HAVESCOPEID)
 71	UNUSED(ifname);
 72#endif
 73
 74	/* clear any remaining value for safety */
 75	memset(dst, 0, sizeof(*dst));
 76
 77	dst->family = family;
 78	switch (family) {
 79	case AF_INET:
 80		memcpy(&dst->type.in,
 81		       &((struct sockaddr_in *) src)->sin_addr,
 82		       sizeof(struct in_addr));
 83		break;
 84	case AF_INET6:
 85		sa6 = (struct sockaddr_in6 *)src;
 86		memcpy(&dst->type.in6, &sa6->sin6_addr,
 87		       sizeof(struct in6_addr));
 88#ifdef ISC_PLATFORM_HAVESCOPEID
 89		if (sa6->sin6_scope_id != 0)
 90			isc_netaddr_setzone(dst, sa6->sin6_scope_id);
 91		else {
 92			/*
 93			 * BSD variants embed scope zone IDs in the 128bit
 94			 * address as a kernel internal form.  Unfortunately,
 95			 * the embedded IDs are not hidden from applications
 96			 * when getting access to them by sysctl or ioctl.
 97			 * We convert the internal format to the pure address
 98			 * part and the zone ID part.
 99			 * Since multicast addresses should not appear here
100			 * and they cannot be distinguished from netmasks,
101			 * we only consider unicast link-local addresses.
102			 */
103			if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
104				isc_uint16_t zone16;
105
106				memcpy(&zone16, &sa6->sin6_addr.s6_addr[2],
107				       sizeof(zone16));
108				zone16 = ntohs(zone16);
109				if (zone16 != 0) {
110					/* the zone ID is embedded */
111					isc_netaddr_setzone(dst,
112							    (isc_uint32_t)zone16);
113					dst->type.in6.s6_addr[2] = 0;
114					dst->type.in6.s6_addr[3] = 0;
115#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
116				} else if (ifname != NULL) {
117					unsigned int zone;
118
119					/*
120					 * sin6_scope_id is still not provided,
121					 * but the corresponding interface name
122					 * is know.  Use the interface ID as
123					 * the link ID.
124					 */
125					zone = if_nametoindex(ifname);
126					if (zone != 0) {
127						isc_netaddr_setzone(dst,
128								    (isc_uint32_t)zone);
129					}
130#endif
131				}
132			}
133		}
134#endif
135		break;
136	default:
137		INSIST(0);
138		break;
139	}
140}
141
142/*
143 * Include system-dependent code.
144 */
145
146#if HAVE_GETIFADDRS
147#include "ifiter_getifaddrs.c"
148#elif HAVE_IFLIST_SYSCTL
149#include "ifiter_sysctl.c"
150#else
151#include "ifiter_ioctl.c"
152#endif
153
154/*
155 * The remaining code is common to the sysctl and ioctl case.
156 */
157
158isc_result_t
159isc_interfaceiter_current(isc_interfaceiter_t *iter,
160			  isc_interface_t *ifdata)
161{
162	REQUIRE(iter->result == ISC_R_SUCCESS);
163	memcpy(ifdata, &iter->current, sizeof(*ifdata));
164	return (ISC_R_SUCCESS);
165}
166
167isc_result_t
168isc_interfaceiter_first(isc_interfaceiter_t *iter) {
169	isc_result_t result;
170
171	REQUIRE(VALID_IFITER(iter));
172
173	internal_first(iter);
174	for (;;) {
175		result = internal_current(iter);
176		if (result != ISC_R_IGNORE)
177			break;
178		result = internal_next(iter);
179		if (result != ISC_R_SUCCESS)
180			break;
181	}
182	iter->result = result;
183	return (result);
184}
185
186isc_result_t
187isc_interfaceiter_next(isc_interfaceiter_t *iter) {
188	isc_result_t result;
189
190	REQUIRE(VALID_IFITER(iter));
191	REQUIRE(iter->result == ISC_R_SUCCESS);
192
193	for (;;) {
194		result = internal_next(iter);
195		if (result != ISC_R_SUCCESS)
196			break;
197		result = internal_current(iter);
198		if (result != ISC_R_IGNORE)
199			break;
200	}
201	iter->result = result;
202	return (result);
203}
204
205void
206isc_interfaceiter_destroy(isc_interfaceiter_t **iterp)
207{
208	isc_interfaceiter_t *iter;
209	REQUIRE(iterp != NULL);
210	iter = *iterp;
211	REQUIRE(VALID_IFITER(iter));
212
213	internal_destroy(iter);
214	if (iter->buf != NULL)
215		isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
216
217	iter->magic = 0;
218	isc_mem_put(iter->mctx, iter, sizeof(*iter));
219	*iterp = NULL;
220}