xref: /openbsd-src/lib/libc/net/if_nameindex.c (revision 1c6ffb17912b016ef46a3b11060d1356aca4d58f)
1*1c6ffb17Skrw /*	$OpenBSD: if_nameindex.c,v 1.13 2016/12/16 17:44:59 krw Exp $	*/
22fc8ca5aSmillert /*	$KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $	*/
32fc8ca5aSmillert 
42fc8ca5aSmillert /*-
5864f048cSclaudio  * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org>
62fc8ca5aSmillert  * Copyright (c) 1997, 2000
72fc8ca5aSmillert  *	Berkeley Software Design, Inc.  All rights reserved.
8bc4c5135Scmetz  *
9bc4c5135Scmetz  * Redistribution and use in source and binary forms, with or without
10bc4c5135Scmetz  * modification, are permitted provided that the following conditions
11bc4c5135Scmetz  * are met:
12bc4c5135Scmetz  * 1. Redistributions of source code must retain the above copyright
13bc4c5135Scmetz  *    notice, this list of conditions and the following disclaimer.
14bc4c5135Scmetz  *
152fc8ca5aSmillert  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
16bc4c5135Scmetz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17bc4c5135Scmetz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182fc8ca5aSmillert  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
19bc4c5135Scmetz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20bc4c5135Scmetz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21bc4c5135Scmetz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22bc4c5135Scmetz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23bc4c5135Scmetz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24bc4c5135Scmetz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25bc4c5135Scmetz  * SUCH DAMAGE.
262fc8ca5aSmillert  *
272fc8ca5aSmillert  *	BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
28bc4c5135Scmetz  */
29bc4c5135Scmetz 
30bc4c5135Scmetz #include <sys/types.h>
31bc4c5135Scmetz #include <sys/socket.h>
32864f048cSclaudio #include <sys/sysctl.h>
332fc8ca5aSmillert #include <net/if.h>
342fc8ca5aSmillert #include <stdlib.h>
35b2c288efSderaadt #include <string.h>
36864f048cSclaudio #include <errno.h>
37bc4c5135Scmetz 
382fc8ca5aSmillert /*
392fc8ca5aSmillert  * From RFC 2553:
402fc8ca5aSmillert  *
412fc8ca5aSmillert  * 4.3 Return All Interface Names and Indexes
422fc8ca5aSmillert  *
432fc8ca5aSmillert  *    The if_nameindex structure holds the information about a single
442fc8ca5aSmillert  *    interface and is defined as a result of including the <net/if.h>
452fc8ca5aSmillert  *    header.
462fc8ca5aSmillert  *
472fc8ca5aSmillert  *       struct if_nameindex {
482fc8ca5aSmillert  *         unsigned int   if_index;
492fc8ca5aSmillert  *         char          *if_name;
502fc8ca5aSmillert  *       };
512fc8ca5aSmillert  *
522fc8ca5aSmillert  *    The final function returns an array of if_nameindex structures, one
532fc8ca5aSmillert  *    structure per interface.
542fc8ca5aSmillert  *
552fc8ca5aSmillert  *       struct if_nameindex  *if_nameindex(void);
562fc8ca5aSmillert  *
572fc8ca5aSmillert  *    The end of the array of structures is indicated by a structure with
582fc8ca5aSmillert  *    an if_index of 0 and an if_name of NULL.  The function returns a NULL
592fc8ca5aSmillert  *    pointer upon an error, and would set errno to the appropriate value.
602fc8ca5aSmillert  *
612fc8ca5aSmillert  *    The memory used for this array of structures along with the interface
622fc8ca5aSmillert  *    names pointed to by the if_name members is obtained dynamically.
632fc8ca5aSmillert  *    This memory is freed by the next function.
642fc8ca5aSmillert  *
652fc8ca5aSmillert  * 4.4.  Free Memory
662fc8ca5aSmillert  *
672fc8ca5aSmillert  *    The following function frees the dynamic memory that was allocated by
682fc8ca5aSmillert  *    if_nameindex().
692fc8ca5aSmillert  *
702fc8ca5aSmillert  *        #include <net/if.h>
712fc8ca5aSmillert  *
722fc8ca5aSmillert  *        void  if_freenameindex(struct if_nameindex *ptr);
732fc8ca5aSmillert  *
742fc8ca5aSmillert  *    The argument to this function must be a pointer that was returned by
752fc8ca5aSmillert  *    if_nameindex().
762fc8ca5aSmillert  */
772fc8ca5aSmillert 
78b2c288efSderaadt struct if_nameindex *
if_nameindex(void)79b2c288efSderaadt if_nameindex(void)
80bc4c5135Scmetz {
81864f048cSclaudio 	struct if_nameindex_msg *ifnm = NULL;
82864f048cSclaudio 	struct if_nameindex *ifni = NULL, *ifni2;
832fc8ca5aSmillert 	char *cp;
84*1c6ffb17Skrw 	size_t needed;
85864f048cSclaudio 	unsigned int ni, i;
86864f048cSclaudio 	int mib[6];
87bc4c5135Scmetz 
88864f048cSclaudio 	mib[0] = CTL_NET;
89864f048cSclaudio 	mib[1] = PF_ROUTE;
90864f048cSclaudio 	mib[2] = 0;		/* protocol */
91864f048cSclaudio 	mib[3] = 0;		/* not used */
92864f048cSclaudio 	mib[4] = NET_RT_IFNAMES;
93864f048cSclaudio 	mib[5] = 0;		/* no flags */
94864f048cSclaudio 	while (1) {
95864f048cSclaudio 		struct if_nameindex_msg *buf = NULL;
9671794f70Sderaadt 
97864f048cSclaudio 		if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
98864f048cSclaudio 			goto out;
99864f048cSclaudio 		if (needed == 0)
100864f048cSclaudio 			break;
101864f048cSclaudio 		if ((buf = realloc(ifnm, needed)) == NULL)
102864f048cSclaudio 			goto out;
103864f048cSclaudio 		ifnm = buf;
104864f048cSclaudio 		if (sysctl(mib, 6, ifnm, &needed, NULL, 0) == -1) {
105864f048cSclaudio 			if (errno == ENOMEM)
106864f048cSclaudio 				continue;
107864f048cSclaudio 			goto out;
10871794f70Sderaadt 		}
109864f048cSclaudio 		break;
11071794f70Sderaadt 	}
111bc4c5135Scmetz 
1122fc8ca5aSmillert 	/*
113864f048cSclaudio 	 * Allocate a chunk of memory, use the first part for the array of
114864f048cSclaudio 	 * structures, and the last part for the strings.
1152fc8ca5aSmillert 	 */
116864f048cSclaudio 	ni = needed / sizeof(*ifnm);
117864f048cSclaudio 	ifni = calloc(ni + 1, sizeof(struct if_nameindex) + IF_NAMESIZE);
1182fc8ca5aSmillert 	if (ifni == NULL)
1192fc8ca5aSmillert 		goto out;
120864f048cSclaudio 	cp = (char *)(ifni + (ni + 1));
121bc4c5135Scmetz 
1222fc8ca5aSmillert 	ifni2 = ifni;
123864f048cSclaudio 	for (i = 0; i < ni; i++) {
124864f048cSclaudio 		ifni2->if_index = ifnm[i].if_index;
125864f048cSclaudio 		/* don't care about truncation */
126864f048cSclaudio 		strlcpy(cp, ifnm[i].if_name, IF_NAMESIZE);
1272fc8ca5aSmillert 		ifni2->if_name = cp;
1282fc8ca5aSmillert 		ifni2++;
129864f048cSclaudio 		cp += IF_NAMESIZE;
130b2c288efSderaadt 	}
131864f048cSclaudio 	/* Finally, terminate the array. */
1322fc8ca5aSmillert 	ifni2->if_index = 0;
1332fc8ca5aSmillert 	ifni2->if_name = NULL;
1342fc8ca5aSmillert out:
135864f048cSclaudio 	free(ifnm);
136864f048cSclaudio 	return ifni;
137b2c288efSderaadt }
138c6e14be5Sclaudio 
139c6e14be5Sclaudio void
if_freenameindex(struct if_nameindex * ptr)140c6e14be5Sclaudio if_freenameindex(struct if_nameindex *ptr)
141c6e14be5Sclaudio {
142c6e14be5Sclaudio 	free(ptr);
143c6e14be5Sclaudio }
144864f048cSclaudio DEF_WEAK(if_nameindex);
145864f048cSclaudio DEF_WEAK(if_freenameindex);
146