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