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