1 /* $NetBSD: netscope.c,v 1.7 2025/01/26 16:25:37 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 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