1*bcda20f6Schristos /* $NetBSD: netscope.c,v 1.7 2025/01/26 16:25:37 christos Exp $ */ 2d68c78b8Schristos 3d68c78b8Schristos /* 4d68c78b8Schristos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5d68c78b8Schristos * 68596601aSchristos * SPDX-License-Identifier: MPL-2.0 78596601aSchristos * 8d68c78b8Schristos * This Source Code Form is subject to the terms of the Mozilla Public 9d68c78b8Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this 10fce770bdSchristos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11d68c78b8Schristos * 12d68c78b8Schristos * See the COPYRIGHT file distributed with this work for additional 13d68c78b8Schristos * information regarding copyright ownership. 14d68c78b8Schristos */ 15d68c78b8Schristos 16d68c78b8Schristos /*! \file */ 17d68c78b8Schristos 18d4a20c3eSchristos #include <inttypes.h> 19d4a20c3eSchristos #include <stdlib.h> 20d4a20c3eSchristos 21d68c78b8Schristos #include <isc/net.h> 22d68c78b8Schristos #include <isc/netscope.h> 23d68c78b8Schristos #include <isc/result.h> 245606745fSchristos #include <isc/string.h> 25fce770bdSchristos #include <isc/util.h> 26d68c78b8Schristos 27d68c78b8Schristos isc_result_t 28d4a20c3eSchristos isc_netscope_pton(int af, char *scopename, void *addr, uint32_t *zoneid) { 29d68c78b8Schristos char *ep; 30d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX 31d68c78b8Schristos unsigned int ifid; 32d68c78b8Schristos struct in6_addr *in6; 335606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */ 34fce770bdSchristos uint32_t zone = 0; 35d4a20c3eSchristos uint64_t llz; 36d68c78b8Schristos 37fce770bdSchristos #ifndef HAVE_IF_NAMETOINDEX 38fce770bdSchristos UNUSED(addr); 39fce770bdSchristos #endif 40fce770bdSchristos 41d68c78b8Schristos /* at this moment, we only support AF_INET6 */ 425606745fSchristos if (af != AF_INET6) { 43*bcda20f6Schristos return ISC_R_FAILURE; 445606745fSchristos } 45d68c78b8Schristos 46d68c78b8Schristos /* 475606745fSchristos * Basically, "names" are more stable than numeric IDs in terms 485606745fSchristos * of renumbering, and are more preferred. However, since there 495606745fSchristos * is no standard naming convention and APIs to deal with the 505606745fSchristos * names. Thus, we only handle the case of link-local 515606745fSchristos * addresses, for which we use interface names as link names, 525606745fSchristos * assuming one to one mapping between interfaces and links. 53d68c78b8Schristos */ 54d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX 55d68c78b8Schristos in6 = (struct in6_addr *)addr; 56d68c78b8Schristos if (IN6_IS_ADDR_LINKLOCAL(in6) && 57d68c78b8Schristos (ifid = if_nametoindex((const char *)scopename)) != 0) 585606745fSchristos { 59d4a20c3eSchristos zone = (uint32_t)ifid; 605606745fSchristos } else { 615606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */ 62d4a20c3eSchristos llz = strtoull(scopename, &ep, 10); 635606745fSchristos if (ep == scopename) { 64*bcda20f6Schristos return ISC_R_FAILURE; 655606745fSchristos } 66d68c78b8Schristos 67d68c78b8Schristos /* check overflow */ 68d4a20c3eSchristos zone = (uint32_t)(llz & 0xffffffffUL); 695606745fSchristos if (zone != llz) { 70*bcda20f6Schristos return ISC_R_FAILURE; 715606745fSchristos } 72d4a20c3eSchristos #ifdef HAVE_IF_NAMETOINDEX 73d68c78b8Schristos } 745606745fSchristos #endif /* ifdef HAVE_IF_NAMETOINDEX */ 75d68c78b8Schristos 76d68c78b8Schristos *zoneid = zone; 77*bcda20f6Schristos return ISC_R_SUCCESS; 78d68c78b8Schristos } 79