17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5e11c3f44Smeem * Common Development and Distribution License (the "License").
6e11c3f44Smeem * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21*7f0c041dSRenee Danson Sommerfeld
227c478bd9Sstevel@tonic-gate /*
23*7f0c041dSRenee Danson Sommerfeld * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <ctype.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/socket.h>
337c478bd9Sstevel@tonic-gate #include <inet/common.h>
347c478bd9Sstevel@tonic-gate #include <net/if.h>
357c478bd9Sstevel@tonic-gate #include <netinet/in.h>
367c478bd9Sstevel@tonic-gate #include <sys/sockio.h>
377c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
387c478bd9Sstevel@tonic-gate #include <unistd.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #define IPIF_SEPARATOR_CHAR ":"
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate * Given an interface name, this function retrives the associated
457c478bd9Sstevel@tonic-gate * index value. Returns index value if successful, zero otherwise.
467c478bd9Sstevel@tonic-gate * The length of the supplied interface name must be at most
477c478bd9Sstevel@tonic-gate * IF_NAMESIZE-1 bytes
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate uint32_t
if_nametoindex(const char * ifname)507c478bd9Sstevel@tonic-gate if_nametoindex(const char *ifname)
517c478bd9Sstevel@tonic-gate {
527c478bd9Sstevel@tonic-gate int s;
537c478bd9Sstevel@tonic-gate struct lifreq lifr;
547c478bd9Sstevel@tonic-gate int save_err;
557c478bd9Sstevel@tonic-gate size_t size;
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /* Make sure the given name is not NULL */
597c478bd9Sstevel@tonic-gate if ((ifname == NULL)||(*ifname == '\0')) {
607c478bd9Sstevel@tonic-gate errno = ENXIO;
617c478bd9Sstevel@tonic-gate return (0);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate * Fill up the interface name in the ioctl
667c478bd9Sstevel@tonic-gate * request message. Make sure that the length of
677c478bd9Sstevel@tonic-gate * the given interface name <= (IF_NAMESIZE-1)
687c478bd9Sstevel@tonic-gate */
697c478bd9Sstevel@tonic-gate size = strlen(ifname);
707c478bd9Sstevel@tonic-gate if (size > (IF_NAMESIZE - 1)) {
717c478bd9Sstevel@tonic-gate errno = EINVAL;
727c478bd9Sstevel@tonic-gate return (0);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate strncpy(lifr.lifr_name, ifname, size +1);
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate /* Check the v4 interfaces first */
787c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0);
797c478bd9Sstevel@tonic-gate if (s >= 0) {
807c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) >= 0) {
817c478bd9Sstevel@tonic-gate (void) close(s);
827c478bd9Sstevel@tonic-gate return (lifr.lifr_index);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate (void) close(s);
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate /* Check the v6 interface list */
887c478bd9Sstevel@tonic-gate s = socket(AF_INET6, SOCK_DGRAM, 0);
897c478bd9Sstevel@tonic-gate if (s < 0)
907c478bd9Sstevel@tonic-gate return (0);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFINDEX, (caddr_t)&lifr) < 0)
937c478bd9Sstevel@tonic-gate lifr.lifr_index = 0;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate save_err = errno;
967c478bd9Sstevel@tonic-gate (void) close(s);
977c478bd9Sstevel@tonic-gate errno = save_err;
987c478bd9Sstevel@tonic-gate return (lifr.lifr_index);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate * Given an index, this function returns the associated interface
1037c478bd9Sstevel@tonic-gate * name in the supplied buffer ifname.
1047c478bd9Sstevel@tonic-gate * Returns physical interface name if successful, NULL otherwise.
1057c478bd9Sstevel@tonic-gate * The interface name returned will be at most IF_NAMESIZE-1 bytes.
1067c478bd9Sstevel@tonic-gate */
1077c478bd9Sstevel@tonic-gate char *
if_indextoname(uint32_t ifindex,char * ifname)1087c478bd9Sstevel@tonic-gate if_indextoname(uint32_t ifindex, char *ifname)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate int n;
1117c478bd9Sstevel@tonic-gate int s;
1127c478bd9Sstevel@tonic-gate char *buf;
1137c478bd9Sstevel@tonic-gate uint32_t index;
1147c478bd9Sstevel@tonic-gate struct lifnum lifn;
1157c478bd9Sstevel@tonic-gate struct lifconf lifc;
1167c478bd9Sstevel@tonic-gate struct lifreq *lifrp;
1177c478bd9Sstevel@tonic-gate int numifs;
1187c478bd9Sstevel@tonic-gate size_t bufsize;
1197c478bd9Sstevel@tonic-gate boolean_t found;
120e11c3f44Smeem uint_t flags;
121e11c3f44Smeem
122e11c3f44Smeem flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES | LIFC_UNDER_IPMP;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate /* A interface index of 0 is invalid */
1257c478bd9Sstevel@tonic-gate if (ifindex == 0) {
1267c478bd9Sstevel@tonic-gate errno = ENXIO;
1277c478bd9Sstevel@tonic-gate return (NULL);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate s = socket(AF_INET6, SOCK_DGRAM, 0);
1317c478bd9Sstevel@tonic-gate if (s < 0) {
1327c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0);
1337c478bd9Sstevel@tonic-gate if (s < 0) {
1347c478bd9Sstevel@tonic-gate return (NULL);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /* Prepare to send a SIOCGLIFNUM request message */
1397c478bd9Sstevel@tonic-gate lifn.lifn_family = AF_UNSPEC;
140e11c3f44Smeem lifn.lifn_flags = flags;
1417c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) {
1427c478bd9Sstevel@tonic-gate int save_err = errno;
1437c478bd9Sstevel@tonic-gate (void) close(s);
1447c478bd9Sstevel@tonic-gate errno = save_err;
1457c478bd9Sstevel@tonic-gate return (NULL);
1467c478bd9Sstevel@tonic-gate }
147e11c3f44Smeem
148e11c3f44Smeem /*
149e11c3f44Smeem * NOTE: "+ 10" sleaze mitigates new IP interfaces showing up between
150e11c3f44Smeem * the SIOCGLIFNUM and the SIOCGLIFCONF.
151e11c3f44Smeem */
152e11c3f44Smeem numifs = lifn.lifn_count + 10;
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate * Provide enough buffer to obtain the interface
1567c478bd9Sstevel@tonic-gate * list from the kernel as response to a SIOCGLIFCONF
1577c478bd9Sstevel@tonic-gate * request
1587c478bd9Sstevel@tonic-gate */
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate bufsize = numifs * sizeof (struct lifreq);
1617c478bd9Sstevel@tonic-gate buf = malloc(bufsize);
1627c478bd9Sstevel@tonic-gate if (buf == NULL) {
1637c478bd9Sstevel@tonic-gate int save_err = errno;
1647c478bd9Sstevel@tonic-gate (void) close(s);
1657c478bd9Sstevel@tonic-gate errno = save_err;
1667c478bd9Sstevel@tonic-gate return (NULL);
1677c478bd9Sstevel@tonic-gate }
1687c478bd9Sstevel@tonic-gate lifc.lifc_family = AF_UNSPEC;
169e11c3f44Smeem lifc.lifc_flags = flags;
1707c478bd9Sstevel@tonic-gate lifc.lifc_len = bufsize;
1717c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf;
1727c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
1737c478bd9Sstevel@tonic-gate int save_err = errno;
1747c478bd9Sstevel@tonic-gate (void) close(s);
1757c478bd9Sstevel@tonic-gate errno = save_err;
1767c478bd9Sstevel@tonic-gate free(buf);
1777c478bd9Sstevel@tonic-gate return (NULL);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate lifrp = lifc.lifc_req;
1817c478bd9Sstevel@tonic-gate found = B_FALSE;
1827c478bd9Sstevel@tonic-gate for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) {
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * Obtain the index value of each interface, and
1857c478bd9Sstevel@tonic-gate * match to see if the retrived index value matches
186ffdae209SAnders Persson * the given one. If so we return the corresponding
1877c478bd9Sstevel@tonic-gate * device name of that interface.
1887c478bd9Sstevel@tonic-gate */
1897c478bd9Sstevel@tonic-gate size_t size;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate index = if_nametoindex(lifrp->lifr_name);
1927c478bd9Sstevel@tonic-gate if (index == 0)
1937c478bd9Sstevel@tonic-gate /* Oops the interface just disappeared */
1947c478bd9Sstevel@tonic-gate continue;
1957c478bd9Sstevel@tonic-gate if (index == ifindex) {
1967c478bd9Sstevel@tonic-gate size = strcspn(lifrp->lifr_name,
1977c478bd9Sstevel@tonic-gate (char *)IPIF_SEPARATOR_CHAR);
1987c478bd9Sstevel@tonic-gate lifrp->lifr_name[size] = '\0';
1997c478bd9Sstevel@tonic-gate found = B_TRUE;
200ffdae209SAnders Persson (void) strncpy(ifname, lifrp->lifr_name, size + 1);
2017c478bd9Sstevel@tonic-gate break;
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate (void) close(s);
2057c478bd9Sstevel@tonic-gate free(buf);
2067c478bd9Sstevel@tonic-gate if (!found) {
2077c478bd9Sstevel@tonic-gate errno = ENXIO;
2087c478bd9Sstevel@tonic-gate return (NULL);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate return (ifname);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate * This function returns all the interface names and indexes
2157c478bd9Sstevel@tonic-gate */
2167c478bd9Sstevel@tonic-gate struct if_nameindex *
if_nameindex(void)2177c478bd9Sstevel@tonic-gate if_nameindex(void)
2187c478bd9Sstevel@tonic-gate {
2197c478bd9Sstevel@tonic-gate int n;
2207c478bd9Sstevel@tonic-gate int s;
2217c478bd9Sstevel@tonic-gate boolean_t found;
2227c478bd9Sstevel@tonic-gate char *buf;
2237c478bd9Sstevel@tonic-gate struct lifnum lifn;
2247c478bd9Sstevel@tonic-gate struct lifconf lifc;
2257c478bd9Sstevel@tonic-gate struct lifreq *lifrp;
2267c478bd9Sstevel@tonic-gate int numifs;
2277c478bd9Sstevel@tonic-gate int index;
2287c478bd9Sstevel@tonic-gate int i;
2297c478bd9Sstevel@tonic-gate int physinterf_num;
2307c478bd9Sstevel@tonic-gate size_t bufsize;
2317c478bd9Sstevel@tonic-gate struct if_nameindex *interface_list;
2327c478bd9Sstevel@tonic-gate struct if_nameindex *interface_entry;
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate s = socket(AF_INET6, SOCK_DGRAM, 0);
2357c478bd9Sstevel@tonic-gate if (s < 0) {
2367c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0);
2377c478bd9Sstevel@tonic-gate if (s < 0)
2387c478bd9Sstevel@tonic-gate return (NULL);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate lifn.lifn_family = AF_UNSPEC;
2427c478bd9Sstevel@tonic-gate lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
2437c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0)
2447c478bd9Sstevel@tonic-gate return (NULL);
2457c478bd9Sstevel@tonic-gate numifs = lifn.lifn_count;
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate bufsize = numifs * sizeof (struct lifreq);
2487c478bd9Sstevel@tonic-gate buf = malloc(bufsize);
2497c478bd9Sstevel@tonic-gate if (buf == NULL) {
2507c478bd9Sstevel@tonic-gate int save_err = errno;
2517c478bd9Sstevel@tonic-gate (void) close(s);
2527c478bd9Sstevel@tonic-gate errno = save_err;
2537c478bd9Sstevel@tonic-gate return (NULL);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate lifc.lifc_family = AF_UNSPEC;
2567c478bd9Sstevel@tonic-gate lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
2577c478bd9Sstevel@tonic-gate lifc.lifc_len = bufsize;
2587c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf;
2597c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) {
2607c478bd9Sstevel@tonic-gate int save_err = errno;
2617c478bd9Sstevel@tonic-gate (void) close(s);
2627c478bd9Sstevel@tonic-gate errno = save_err;
2637c478bd9Sstevel@tonic-gate free(buf);
2647c478bd9Sstevel@tonic-gate return (NULL);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate lifrp = lifc.lifc_req;
2687c478bd9Sstevel@tonic-gate (void) close(s);
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate /* Allocate the array of if_nameindex structure */
2717c478bd9Sstevel@tonic-gate interface_list = malloc((numifs + 1) * sizeof (struct if_nameindex));
2727c478bd9Sstevel@tonic-gate if (!interface_list) {
2737c478bd9Sstevel@tonic-gate int save_err = errno;
2747c478bd9Sstevel@tonic-gate free(buf);
2757c478bd9Sstevel@tonic-gate errno = save_err;
2767c478bd9Sstevel@tonic-gate return (NULL);
2777c478bd9Sstevel@tonic-gate }
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate * Make sure that terminator structure automatically
2807c478bd9Sstevel@tonic-gate * happens to be all zeroes.
2817c478bd9Sstevel@tonic-gate */
2827c478bd9Sstevel@tonic-gate bzero(interface_list, ((numifs + 1) * sizeof (struct if_nameindex)));
2837c478bd9Sstevel@tonic-gate interface_entry = interface_list;
2847c478bd9Sstevel@tonic-gate physinterf_num = 0;
2857c478bd9Sstevel@tonic-gate for (n = numifs; n > 0; n--, lifrp++) {
2867c478bd9Sstevel@tonic-gate size_t size;
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate size = strcspn(lifrp->lifr_name, (char *)IPIF_SEPARATOR_CHAR);
2897c478bd9Sstevel@tonic-gate found = B_FALSE;
2907c478bd9Sstevel@tonic-gate /*
2917c478bd9Sstevel@tonic-gate * Search the current array to see if this interface
292ffdae209SAnders Persson * already exists. Only compare the physical name.
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate for (i = 0; i < physinterf_num; i++) {
295ffdae209SAnders Persson if (strncmp(interface_entry[i].if_name,
296ffdae209SAnders Persson lifrp->lifr_name, size) == 0) {
2977c478bd9Sstevel@tonic-gate found = B_TRUE;
2987c478bd9Sstevel@tonic-gate break;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /* New one. Allocate an array element and fill it */
3037c478bd9Sstevel@tonic-gate if (!found) {
304ffdae209SAnders Persson /*
305ffdae209SAnders Persson * Obtain the index value for the interface
306ffdae209SAnders Persson */
307ffdae209SAnders Persson interface_entry[physinterf_num].if_index =
308ffdae209SAnders Persson if_nametoindex(lifrp->lifr_name);
309ffdae209SAnders Persson
310ffdae209SAnders Persson if (interface_entry[physinterf_num].if_index == 0) {
311ffdae209SAnders Persson /* The interface went away. Skip this entry. */
312ffdae209SAnders Persson continue;
313ffdae209SAnders Persson }
314ffdae209SAnders Persson
315ffdae209SAnders Persson /*
316ffdae209SAnders Persson * Truncate the name to ensure that it represents
317ffdae209SAnders Persson * a physical interface.
318ffdae209SAnders Persson */
319ffdae209SAnders Persson lifrp->lifr_name[size] = '\0';
3207c478bd9Sstevel@tonic-gate if ((interface_entry[physinterf_num].if_name =
3217c478bd9Sstevel@tonic-gate strdup(lifrp->lifr_name)) == NULL) {
3227c478bd9Sstevel@tonic-gate int save_err;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate if_freenameindex(interface_list);
3257c478bd9Sstevel@tonic-gate save_err = errno;
3267c478bd9Sstevel@tonic-gate free(buf);
3277c478bd9Sstevel@tonic-gate errno = save_err;
3287c478bd9Sstevel@tonic-gate return (NULL);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate physinterf_num++;
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate /* Create the last one of the array */
3367c478bd9Sstevel@tonic-gate interface_entry[physinterf_num].if_name = NULL;
3377c478bd9Sstevel@tonic-gate interface_entry[physinterf_num].if_index = 0;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* Free up the excess array space */
3407c478bd9Sstevel@tonic-gate free(buf);
3417c478bd9Sstevel@tonic-gate interface_list = realloc(interface_list, ((physinterf_num + 1) *
3427c478bd9Sstevel@tonic-gate sizeof (struct if_nameindex)));
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate return (interface_list);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate * This function frees the the array that is created while
3497c478bd9Sstevel@tonic-gate * the if_nameindex function.
3507c478bd9Sstevel@tonic-gate */
3517c478bd9Sstevel@tonic-gate void
if_freenameindex(struct if_nameindex * ptr)3527c478bd9Sstevel@tonic-gate if_freenameindex(struct if_nameindex *ptr)
3537c478bd9Sstevel@tonic-gate {
354*7f0c041dSRenee Danson Sommerfeld struct if_nameindex *p;
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate if (ptr == NULL)
3577c478bd9Sstevel@tonic-gate return;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /* First free the if_name member in each array element */
360*7f0c041dSRenee Danson Sommerfeld for (p = ptr; p->if_name != NULL; p++)
361*7f0c041dSRenee Danson Sommerfeld free(p->if_name);
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate /* Now free up the array space */
3647c478bd9Sstevel@tonic-gate free(ptr);
3657c478bd9Sstevel@tonic-gate }
366