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