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