xref: /netbsd-src/external/mpl/bind/dist/lib/isc/netscope.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: netscope.c,v 1.7 2025/01/26 16:25:37 christos Exp $	*/
2d68c78b8Schristos 
3d68c78b8Schristos /*
4d68c78b8Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5d68c78b8Schristos  *
68596601aSchristos  * SPDX-License-Identifier: MPL-2.0
78596601aSchristos  *
8d68c78b8Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9d68c78b8Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
10fce770bdSchristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11d68c78b8Schristos  *
12d68c78b8Schristos  * See the COPYRIGHT file distributed with this work for additional
13d68c78b8Schristos  * information regarding copyright ownership.
14d68c78b8Schristos  */
15d68c78b8Schristos 
16d68c78b8Schristos /*! \file */
17d68c78b8Schristos 
18d4a20c3eSchristos #include <inttypes.h>
19d4a20c3eSchristos #include <stdlib.h>
20d4a20c3eSchristos 
21d68c78b8Schristos #include <isc/net.h>
22d68c78b8Schristos #include <isc/netscope.h>
23d68c78b8Schristos #include <isc/result.h>
245606745fSchristos #include <isc/string.h>
25fce770bdSchristos #include <isc/util.h>
26d68c78b8Schristos 
27d68c78b8Schristos isc_result_t
28d4a20c3eSchristos isc_netscope_pton(int af, char *scopename, void *addr, uint32_t *zoneid) {
29d68c78b8Schristos 	char *ep;
30d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX
31d68c78b8Schristos 	unsigned int ifid;
32d68c78b8Schristos 	struct in6_addr *in6;
335606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */
34fce770bdSchristos 	uint32_t zone = 0;
35d4a20c3eSchristos 	uint64_t llz;
36d68c78b8Schristos 
37fce770bdSchristos #ifndef HAVE_IF_NAMETOINDEX
38fce770bdSchristos 	UNUSED(addr);
39fce770bdSchristos #endif
40fce770bdSchristos 
41d68c78b8Schristos 	/* at this moment, we only support AF_INET6 */
425606745fSchristos 	if (af != AF_INET6) {
43*bcda20f6Schristos 		return ISC_R_FAILURE;
445606745fSchristos 	}
45d68c78b8Schristos 
46d68c78b8Schristos 	/*
475606745fSchristos 	 * Basically, "names" are more stable than numeric IDs in terms
485606745fSchristos 	 * of renumbering, and are more preferred.  However, since there
495606745fSchristos 	 * is no standard naming convention and APIs to deal with the
505606745fSchristos 	 * names.  Thus, we only handle the case of link-local
515606745fSchristos 	 * addresses, for which we use interface names as link names,
525606745fSchristos 	 * assuming one to one mapping between interfaces and links.
53d68c78b8Schristos 	 */
54d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX
55d68c78b8Schristos 	in6 = (struct in6_addr *)addr;
56d68c78b8Schristos 	if (IN6_IS_ADDR_LINKLOCAL(in6) &&
57d68c78b8Schristos 	    (ifid = if_nametoindex((const char *)scopename)) != 0)
585606745fSchristos 	{
59d4a20c3eSchristos 		zone = (uint32_t)ifid;
605606745fSchristos 	} else {
615606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */
62d4a20c3eSchristos 		llz = strtoull(scopename, &ep, 10);
635606745fSchristos 		if (ep == scopename) {
64*bcda20f6Schristos 			return ISC_R_FAILURE;
655606745fSchristos 		}
66d68c78b8Schristos 
67d68c78b8Schristos 		/* check overflow */
68d4a20c3eSchristos 		zone = (uint32_t)(llz & 0xffffffffUL);
695606745fSchristos 		if (zone != llz) {
70*bcda20f6Schristos 			return ISC_R_FAILURE;
715606745fSchristos 		}
72d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX
73d68c78b8Schristos 	}
745606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */
75d68c78b8Schristos 
76d68c78b8Schristos 	*zoneid = zone;
77*bcda20f6Schristos 	return ISC_R_SUCCESS;
78d68c78b8Schristos }
79