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