xref: /netbsd-src/lib/libc/net/if_nameindex.c (revision c5e820cae412164fcbee52f470436200af5358ea)
1*c5e820caSchristos /*	$NetBSD: if_nameindex.c,v 1.7 2012/03/13 21:13:41 christos Exp $	*/
21bc25f59Sitojun /*	$KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $	*/
392db021bSitojun 
492db021bSitojun /*-
592db021bSitojun  * Copyright (c) 1997, 2000
692db021bSitojun  *	Berkeley Software Design, Inc.  All rights reserved.
792db021bSitojun  *
892db021bSitojun  * Redistribution and use in source and binary forms, with or without
992db021bSitojun  * modification, are permitted provided that the following conditions
1092db021bSitojun  * are met:
1192db021bSitojun  * 1. Redistributions of source code must retain the above copyright
1292db021bSitojun  *    notice, this list of conditions and the following disclaimer.
1392db021bSitojun  *
1492db021bSitojun  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
1592db021bSitojun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1692db021bSitojun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1792db021bSitojun  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
1892db021bSitojun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1992db021bSitojun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2092db021bSitojun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2192db021bSitojun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2292db021bSitojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2392db021bSitojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2492db021bSitojun  * SUCH DAMAGE.
2592db021bSitojun  *
2692db021bSitojun  *	BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
2792db021bSitojun  */
2892db021bSitojun 
2972eddcacSitojun #include <sys/cdefs.h>
3072eddcacSitojun #if defined(LIBC_SCCS) && !defined(lint)
31*c5e820caSchristos __RCSID("$NetBSD: if_nameindex.c,v 1.7 2012/03/13 21:13:41 christos Exp $");
3272eddcacSitojun #endif /* LIBC_SCCS and not lint */
3372eddcacSitojun 
3492db021bSitojun #include "namespace.h"
3592db021bSitojun #include <sys/types.h>
3692db021bSitojun #include <sys/socket.h>
3792db021bSitojun #include <net/if_dl.h>
3892db021bSitojun #include <net/if.h>
3992db021bSitojun #include <ifaddrs.h>
4092db021bSitojun #include <stdlib.h>
4192db021bSitojun #include <string.h>
4292db021bSitojun 
4392db021bSitojun #ifdef __weak_alias
__weak_alias(if_nameindex,_if_nameindex)4492db021bSitojun __weak_alias(if_nameindex,_if_nameindex)
4592db021bSitojun __weak_alias(if_freenameindex,_if_freenameindex)
4692db021bSitojun #endif
4792db021bSitojun /*
481bc25f59Sitojun  * From RFC 2553:
4992db021bSitojun  *
501bc25f59Sitojun  * 4.3 Return All Interface Names and Indexes
511bc25f59Sitojun  *
521bc25f59Sitojun  *    The if_nameindex structure holds the information about a single
531bc25f59Sitojun  *    interface and is defined as a result of including the <net/if.h>
541bc25f59Sitojun  *    header.
551bc25f59Sitojun  *
561bc25f59Sitojun  *       struct if_nameindex {
571bc25f59Sitojun  *         unsigned int   if_index;
581bc25f59Sitojun  *         char          *if_name;
591bc25f59Sitojun  *       };
6092db021bSitojun  *
6192db021bSitojun  *    The final function returns an array of if_nameindex structures, one
6292db021bSitojun  *    structure per interface.
6392db021bSitojun  *
6492db021bSitojun  *       struct if_nameindex  *if_nameindex(void);
6592db021bSitojun  *
6692db021bSitojun  *    The end of the array of structures is indicated by a structure with
6792db021bSitojun  *    an if_index of 0 and an if_name of NULL.  The function returns a NULL
681bc25f59Sitojun  *    pointer upon an error, and would set errno to the appropriate value.
6992db021bSitojun  *
7092db021bSitojun  *    The memory used for this array of structures along with the interface
7192db021bSitojun  *    names pointed to by the if_name members is obtained dynamically.
7292db021bSitojun  *    This memory is freed by the next function.
7392db021bSitojun  *
7492db021bSitojun  * 4.4.  Free Memory
7592db021bSitojun  *
7692db021bSitojun  *    The following function frees the dynamic memory that was allocated by
7792db021bSitojun  *    if_nameindex().
7892db021bSitojun  *
7992db021bSitojun  *        #include <net/if.h>
8092db021bSitojun  *
8192db021bSitojun  *        void  if_freenameindex(struct if_nameindex *ptr);
8292db021bSitojun  *
8392db021bSitojun  *    The argument to this function must be a pointer that was returned by
8492db021bSitojun  *    if_nameindex().
8592db021bSitojun  */
8692db021bSitojun 
8792db021bSitojun struct if_nameindex *
8892db021bSitojun if_nameindex(void)
8992db021bSitojun {
9092db021bSitojun 	struct ifaddrs *ifaddrs, *ifa;
91*c5e820caSchristos 	size_t nbytes, ni;
9292db021bSitojun 	struct if_nameindex *ifni, *ifni2;
9392db021bSitojun 	char *cp;
9492db021bSitojun 
9592db021bSitojun 	if (getifaddrs(&ifaddrs) < 0)
9692db021bSitojun 		return(NULL);
9792db021bSitojun 
9892db021bSitojun 	/*
9992db021bSitojun 	 * First, find out how many interfaces there are, and how
10092db021bSitojun 	 * much space we need for the string names.
10192db021bSitojun 	 */
10292db021bSitojun 	ni = 0;
10392db021bSitojun 	nbytes = 0;
10492db021bSitojun 	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
10592db021bSitojun 		if (ifa->ifa_addr &&
10692db021bSitojun 		    ifa->ifa_addr->sa_family == AF_LINK) {
10792db021bSitojun 			nbytes += strlen(ifa->ifa_name) + 1;
10892db021bSitojun 			ni++;
10992db021bSitojun 		}
11092db021bSitojun 	}
11192db021bSitojun 
11292db021bSitojun 	/*
11392db021bSitojun 	 * Next, allocate a chunk of memory, use the first part
11492db021bSitojun 	 * for the array of structures, and the last part for
11592db021bSitojun 	 * the strings.
11692db021bSitojun 	 */
117ff9df0b1Sitojun 	cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
11802db12ebSchristos 	ifni = (struct if_nameindex *)(void *)cp;
11992db021bSitojun 	if (ifni == NULL)
12092db021bSitojun 		goto out;
121ff9df0b1Sitojun 	cp += (ni + 1) * sizeof(struct if_nameindex);
12292db021bSitojun 
12392db021bSitojun 	/*
12492db021bSitojun 	 * Now just loop through the list of interfaces again,
12592db021bSitojun 	 * filling in the if_nameindex array and making copies
12692db021bSitojun 	 * of all the strings.
12792db021bSitojun 	 */
12892db021bSitojun 	ifni2 = ifni;
12992db021bSitojun 	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
13092db021bSitojun 		if (ifa->ifa_addr &&
13192db021bSitojun 		    ifa->ifa_addr->sa_family == AF_LINK) {
13292db021bSitojun 			ifni2->if_index =
133a0d18445Schristos 			    ((struct sockaddr_dl*)
134a0d18445Schristos 			    (void *)ifa->ifa_addr)->sdl_index;
13592db021bSitojun 			ifni2->if_name = cp;
13692db021bSitojun 			strcpy(cp, ifa->ifa_name);
13792db021bSitojun 			ifni2++;
13892db021bSitojun 			cp += strlen(cp) + 1;
13992db021bSitojun 		}
14092db021bSitojun 	}
14192db021bSitojun 	/*
14292db021bSitojun 	 * Finally, don't forget to terminate the array.
14392db021bSitojun 	 */
14492db021bSitojun 	ifni2->if_index = 0;
14592db021bSitojun 	ifni2->if_name = NULL;
14692db021bSitojun out:
14792db021bSitojun 	freeifaddrs(ifaddrs);
14892db021bSitojun 	return(ifni);
14992db021bSitojun }
15092db021bSitojun 
15192db021bSitojun void
if_freenameindex(struct if_nameindex * ptr)15292db021bSitojun if_freenameindex(struct if_nameindex *ptr)
15392db021bSitojun {
15492db021bSitojun 	free(ptr);
15592db021bSitojun }
156