1100138Sume/* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */ 2100138Sume 3100138Sume/*- 4100138Sume * Copyright (c) 1997, 2000 5100138Sume * Berkeley Software Design, Inc. All rights reserved. 6100138Sume * 7100138Sume * Redistribution and use in source and binary forms, with or without 8100138Sume * modification, are permitted provided that the following conditions 9100138Sume * are met: 10100138Sume * 1. Redistributions of source code must retain the above copyright 11100138Sume * notice, this list of conditions and the following disclaimer. 12100138Sume * 13100138Sume * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND 14100138Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15100138Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16100138Sume * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE 17100138Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18100138Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19100138Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20100138Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21100138Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22100138Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23100138Sume * SUCH DAMAGE. 24100138Sume * 25100138Sume * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp 26100138Sume */ 27100138Sume 28100138Sume#include <sys/cdefs.h> 29100138Sume__FBSDID("$FreeBSD$"); 30100138Sume 31100138Sume#include <sys/types.h> 32100138Sume#include <sys/socket.h> 33100138Sume#include <net/if_dl.h> 34100138Sume#include <net/if.h> 35100138Sume#include <ifaddrs.h> 36100138Sume#include <stdlib.h> 37100138Sume#include <string.h> 38100138Sume 39100138Sume/* 40100138Sume * From RFC 2553: 41100138Sume * 42100138Sume * 4.3 Return All Interface Names and Indexes 43100138Sume * 44100138Sume * The if_nameindex structure holds the information about a single 45100138Sume * interface and is defined as a result of including the <net/if.h> 46100138Sume * header. 47100138Sume * 48100138Sume * struct if_nameindex { 49100138Sume * unsigned int if_index; 50100138Sume * char *if_name; 51100138Sume * }; 52100138Sume * 53100138Sume * The final function returns an array of if_nameindex structures, one 54100138Sume * structure per interface. 55100138Sume * 56100138Sume * struct if_nameindex *if_nameindex(void); 57100138Sume * 58100138Sume * The end of the array of structures is indicated by a structure with 59100138Sume * an if_index of 0 and an if_name of NULL. The function returns a NULL 60100138Sume * pointer upon an error, and would set errno to the appropriate value. 61100138Sume * 62100138Sume * The memory used for this array of structures along with the interface 63100138Sume * names pointed to by the if_name members is obtained dynamically. 64100138Sume * This memory is freed by the next function. 65100138Sume * 66100138Sume * 4.4. Free Memory 67100138Sume * 68100138Sume * The following function frees the dynamic memory that was allocated by 69100138Sume * if_nameindex(). 70100138Sume * 71100138Sume * #include <net/if.h> 72100138Sume * 73100138Sume * void if_freenameindex(struct if_nameindex *ptr); 74100138Sume * 75100138Sume * The argument to this function must be a pointer that was returned by 76100138Sume * if_nameindex(). 77100138Sume */ 78100138Sume 79100138Sumestruct if_nameindex * 80100138Sumeif_nameindex(void) 81100138Sume{ 82100138Sume struct ifaddrs *ifaddrs, *ifa; 83100138Sume unsigned int ni; 84100138Sume int nbytes; 85100138Sume struct if_nameindex *ifni, *ifni2; 86100138Sume char *cp; 87100138Sume 88100138Sume if (getifaddrs(&ifaddrs) < 0) 89100138Sume return(NULL); 90100138Sume 91100138Sume /* 92100138Sume * First, find out how many interfaces there are, and how 93100138Sume * much space we need for the string names. 94100138Sume */ 95100138Sume ni = 0; 96100138Sume nbytes = 0; 97100138Sume for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 98100138Sume if (ifa->ifa_addr && 99100138Sume ifa->ifa_addr->sa_family == AF_LINK) { 100100138Sume nbytes += strlen(ifa->ifa_name) + 1; 101100138Sume ni++; 102100138Sume } 103100138Sume } 104100138Sume 105100138Sume /* 106100138Sume * Next, allocate a chunk of memory, use the first part 107100138Sume * for the array of structures, and the last part for 108100138Sume * the strings. 109100138Sume */ 110100138Sume cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes); 111100138Sume ifni = (struct if_nameindex *)cp; 112100138Sume if (ifni == NULL) 113100138Sume goto out; 114100138Sume cp += (ni + 1) * sizeof(struct if_nameindex); 115100138Sume 116100138Sume /* 117100138Sume * Now just loop through the list of interfaces again, 118100138Sume * filling in the if_nameindex array and making copies 119100138Sume * of all the strings. 120100138Sume */ 121100138Sume ifni2 = ifni; 122100138Sume for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { 123100138Sume if (ifa->ifa_addr && 124100138Sume ifa->ifa_addr->sa_family == AF_LINK) { 125100138Sume ifni2->if_index = 126235640Smarcel LLINDEX((struct sockaddr_dl*)ifa->ifa_addr); 127100138Sume ifni2->if_name = cp; 128100138Sume strcpy(cp, ifa->ifa_name); 129100138Sume ifni2++; 130100138Sume cp += strlen(cp) + 1; 131100138Sume } 132100138Sume } 133100138Sume /* 134100138Sume * Finally, don't forget to terminate the array. 135100138Sume */ 136100138Sume ifni2->if_index = 0; 137100138Sume ifni2->if_name = NULL; 138100138Sumeout: 139100138Sume freeifaddrs(ifaddrs); 140100138Sume return(ifni); 141100138Sume} 142100138Sume 143100138Sumevoid 144100138Sumeif_freenameindex(struct if_nameindex *ptr) 145100138Sume{ 146100138Sume free(ptr); 147100138Sume} 148