Home | History | Annotate | Line # | Download | only in isc
      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