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