1 /* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-1-Clause 5 * 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/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/types.h> 34 #include <sys/socket.h> 35 #include <net/if_dl.h> 36 #include <net/if.h> 37 #include <ifaddrs.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 /* 42 * From RFC 2553: 43 * 44 * 4.3 Return All Interface Names and Indexes 45 * 46 * The if_nameindex structure holds the information about a single 47 * interface and is defined as a result of including the <net/if.h> 48 * header. 49 * 50 * struct if_nameindex { 51 * unsigned int if_index; 52 * char *if_name; 53 * }; 54 * 55 * The final function returns an array of if_nameindex structures, one 56 * structure per interface. 57 * 58 * struct if_nameindex *if_nameindex(void); 59 * 60 * The end of the array of structures is indicated by a structure with 61 * an if_index of 0 and an if_name of NULL. The function returns a NULL 62 * pointer upon an error, and would set errno to the appropriate value. 63 * 64 * The memory used for this array of structures along with the interface 65 * names pointed to by the if_name members is obtained dynamically. 66 * This memory is freed by the next function. 67 * 68 * 4.4. Free Memory 69 * 70 * The following function frees the dynamic memory that was allocated by 71 * if_nameindex(). 72 * 73 * #include <net/if.h> 74 * 75 * void if_freenameindex(struct if_nameindex *ptr); 76 * 77 * The argument to this function must be a pointer that was returned by 78 * if_nameindex(). 79 */ 80 81 struct if_nameindex * 82 if_nameindex(void) 83 { 84 struct ifaddrs *ifaddrs, *ifa; 85 unsigned int ni; 86 int nbytes; 87 struct if_nameindex *ifni, *ifni2; 88 char *cp; 89 90 if (getifaddrs(&ifaddrs) < 0) 91 return(NULL); 92 93 /* 94 * First, find out how many interfaces there are, and how 95 * much space we need for the string names. 96 */ 97 ni = 0; 98 nbytes = 0; 99 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 100 if (ifa->ifa_addr && 101 ifa->ifa_addr->sa_family == AF_LINK) { 102 nbytes += strlen(ifa->ifa_name) + 1; 103 ni++; 104 } 105 } 106 107 /* 108 * Next, allocate a chunk of memory, use the first part 109 * for the array of structures, and the last part for 110 * the strings. 111 */ 112 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes); 113 ifni = (struct if_nameindex *)cp; 114 if (ifni == NULL) 115 goto out; 116 cp += (ni + 1) * sizeof(struct if_nameindex); 117 118 /* 119 * Now just loop through the list of interfaces again, 120 * filling in the if_nameindex array and making copies 121 * of all the strings. 122 */ 123 ifni2 = ifni; 124 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 125 if (ifa->ifa_addr && 126 ifa->ifa_addr->sa_family == AF_LINK) { 127 ifni2->if_index = 128 LLINDEX((struct sockaddr_dl*)ifa->ifa_addr); 129 ifni2->if_name = cp; 130 strcpy(cp, ifa->ifa_name); 131 ifni2++; 132 cp += strlen(cp) + 1; 133 } 134 } 135 /* 136 * Finally, don't forget to terminate the array. 137 */ 138 ifni2->if_index = 0; 139 ifni2->if_name = NULL; 140 out: 141 freeifaddrs(ifaddrs); 142 return(ifni); 143 } 144 145 void 146 if_freenameindex(struct if_nameindex *ptr) 147 { 148 free(ptr); 149 } 150