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 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 * 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 * 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 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