1 /* $OpenBSD: if_nameindex.c,v 1.13 2016/12/16 17:44:59 krw Exp $ */ 2 /* $KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $ */ 3 4 /*- 5 * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 1997, 2000 7 * Berkeley Software Design, Inc. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp 28 */ 29 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <sys/sysctl.h> 33 #include <net/if.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <errno.h> 37 38 /* 39 * From RFC 2553: 40 * 41 * 4.3 Return All Interface Names and Indexes 42 * 43 * The if_nameindex structure holds the information about a single 44 * interface and is defined as a result of including the <net/if.h> 45 * header. 46 * 47 * struct if_nameindex { 48 * unsigned int if_index; 49 * char *if_name; 50 * }; 51 * 52 * The final function returns an array of if_nameindex structures, one 53 * structure per interface. 54 * 55 * struct if_nameindex *if_nameindex(void); 56 * 57 * The end of the array of structures is indicated by a structure with 58 * an if_index of 0 and an if_name of NULL. The function returns a NULL 59 * pointer upon an error, and would set errno to the appropriate value. 60 * 61 * The memory used for this array of structures along with the interface 62 * names pointed to by the if_name members is obtained dynamically. 63 * This memory is freed by the next function. 64 * 65 * 4.4. Free Memory 66 * 67 * The following function frees the dynamic memory that was allocated by 68 * if_nameindex(). 69 * 70 * #include <net/if.h> 71 * 72 * void if_freenameindex(struct if_nameindex *ptr); 73 * 74 * The argument to this function must be a pointer that was returned by 75 * if_nameindex(). 76 */ 77 78 struct if_nameindex * 79 if_nameindex(void) 80 { 81 struct if_nameindex_msg *ifnm = NULL; 82 struct if_nameindex *ifni = NULL, *ifni2; 83 char *cp; 84 size_t needed; 85 unsigned int ni, i; 86 int mib[6]; 87 88 mib[0] = CTL_NET; 89 mib[1] = PF_ROUTE; 90 mib[2] = 0; /* protocol */ 91 mib[3] = 0; /* not used */ 92 mib[4] = NET_RT_IFNAMES; 93 mib[5] = 0; /* no flags */ 94 while (1) { 95 struct if_nameindex_msg *buf = NULL; 96 97 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 98 goto out; 99 if (needed == 0) 100 break; 101 if ((buf = realloc(ifnm, needed)) == NULL) 102 goto out; 103 ifnm = buf; 104 if (sysctl(mib, 6, ifnm, &needed, NULL, 0) == -1) { 105 if (errno == ENOMEM) 106 continue; 107 goto out; 108 } 109 break; 110 } 111 112 /* 113 * Allocate a chunk of memory, use the first part for the array of 114 * structures, and the last part for the strings. 115 */ 116 ni = needed / sizeof(*ifnm); 117 ifni = calloc(ni + 1, sizeof(struct if_nameindex) + IF_NAMESIZE); 118 if (ifni == NULL) 119 goto out; 120 cp = (char *)(ifni + (ni + 1)); 121 122 ifni2 = ifni; 123 for (i = 0; i < ni; i++) { 124 ifni2->if_index = ifnm[i].if_index; 125 /* don't care about truncation */ 126 strlcpy(cp, ifnm[i].if_name, IF_NAMESIZE); 127 ifni2->if_name = cp; 128 ifni2++; 129 cp += IF_NAMESIZE; 130 } 131 /* Finally, terminate the array. */ 132 ifni2->if_index = 0; 133 ifni2->if_name = NULL; 134 out: 135 free(ifnm); 136 return ifni; 137 } 138 139 void 140 if_freenameindex(struct if_nameindex *ptr) 141 { 142 free(ptr); 143 } 144 DEF_WEAK(if_nameindex); 145 DEF_WEAK(if_freenameindex); 146