1 /* $NetBSD: if_nameindex.c,v 1.6 2000/12/20 18:47:11 christos Exp $ */ 2 /* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */ 3 4 /*- 5 * Copyright (c) 1997, 2000 6 * Berkeley Software Design, Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp 27 */ 28 29 #include <sys/cdefs.h> 30 #if defined(LIBC_SCCS) && !defined(lint) 31 __RCSID("$NetBSD: if_nameindex.c,v 1.6 2000/12/20 18:47:11 christos Exp $"); 32 #endif /* LIBC_SCCS and not lint */ 33 34 #include "namespace.h" 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <net/if_dl.h> 38 #include <net/if.h> 39 #include <ifaddrs.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #ifdef __weak_alias 44 __weak_alias(if_nameindex,_if_nameindex) 45 __weak_alias(if_freenameindex,_if_freenameindex) 46 #endif 47 /* 48 * From RFC 2553: 49 * 50 * 4.3 Return All Interface Names and Indexes 51 * 52 * The if_nameindex structure holds the information about a single 53 * interface and is defined as a result of including the <net/if.h> 54 * header. 55 * 56 * struct if_nameindex { 57 * unsigned int if_index; 58 * char *if_name; 59 * }; 60 * 61 * The final function returns an array of if_nameindex structures, one 62 * structure per interface. 63 * 64 * struct if_nameindex *if_nameindex(void); 65 * 66 * The end of the array of structures is indicated by a structure with 67 * an if_index of 0 and an if_name of NULL. The function returns a NULL 68 * pointer upon an error, and would set errno to the appropriate value. 69 * 70 * The memory used for this array of structures along with the interface 71 * names pointed to by the if_name members is obtained dynamically. 72 * This memory is freed by the next function. 73 * 74 * 4.4. Free Memory 75 * 76 * The following function frees the dynamic memory that was allocated by 77 * if_nameindex(). 78 * 79 * #include <net/if.h> 80 * 81 * void if_freenameindex(struct if_nameindex *ptr); 82 * 83 * The argument to this function must be a pointer that was returned by 84 * if_nameindex(). 85 */ 86 87 struct if_nameindex * 88 if_nameindex(void) 89 { 90 struct ifaddrs *ifaddrs, *ifa; 91 unsigned int ni; 92 int nbytes; 93 struct if_nameindex *ifni, *ifni2; 94 char *cp; 95 96 if (getifaddrs(&ifaddrs) < 0) 97 return(NULL); 98 99 /* 100 * First, find out how many interfaces there are, and how 101 * much space we need for the string names. 102 */ 103 ni = 0; 104 nbytes = 0; 105 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 106 if (ifa->ifa_addr && 107 ifa->ifa_addr->sa_family == AF_LINK) { 108 nbytes += strlen(ifa->ifa_name) + 1; 109 ni++; 110 } 111 } 112 113 /* 114 * Next, allocate a chunk of memory, use the first part 115 * for the array of structures, and the last part for 116 * the strings. 117 */ 118 cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes); 119 ifni = (struct if_nameindex *)(void *)cp; 120 if (ifni == NULL) 121 goto out; 122 cp += (ni + 1) * sizeof(struct if_nameindex); 123 124 /* 125 * Now just loop through the list of interfaces again, 126 * filling in the if_nameindex array and making copies 127 * of all the strings. 128 */ 129 ifni2 = ifni; 130 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 131 if (ifa->ifa_addr && 132 ifa->ifa_addr->sa_family == AF_LINK) { 133 ifni2->if_index = 134 ((struct sockaddr_dl*) 135 (void *)ifa->ifa_addr)->sdl_index; 136 ifni2->if_name = cp; 137 strcpy(cp, ifa->ifa_name); 138 ifni2++; 139 cp += strlen(cp) + 1; 140 } 141 } 142 /* 143 * Finally, don't forget to terminate the array. 144 */ 145 ifni2->if_index = 0; 146 ifni2->if_name = NULL; 147 out: 148 freeifaddrs(ifaddrs); 149 return(ifni); 150 } 151 152 void 153 if_freenameindex(struct if_nameindex *ptr) 154 { 155 free(ptr); 156 } 157