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 27isc_result_t 28isc_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