1/* 2 * Copyright (c) 1990,1993 Regents of The University of Michigan. 3 * Copyright (c) 1999-2000 Adrian Sun. 4 * All Rights Reserved. See COPYRIGHT. 5 */ 6 7#ifdef HAVE_CONFIG_H 8#include "config.h" 9#endif 10 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14 15#ifdef HAVE_STDINT_H 16#include <stdint.h> 17#endif 18 19#include <sys/types.h> 20#include <sys/socket.h> 21#include <sys/ioctl.h> 22#include <netinet/in.h> 23#include <netinet/tcp.h> 24#ifdef TRU64 25#include <sys/mbuf.h> 26#include <net/route.h> 27#endif /* TRU64 */ 28#include <net/if.h> 29#include <errno.h> 30 31#ifdef __svr4__ 32#include <sys/sockio.h> 33#endif 34 35#include <atalk/util.h> 36 37/* allocation size for interface list. */ 38#define IFACE_NUM 5 39 40/* we leave all of the ioctl's to the application */ 41static int addname(char **list, int *i, const char *name) 42 43{ 44 /* if we've run out of room, allocate some more. just return 45 * the present list if we can't. */ 46 47 if ((list[*i] = strdup(name)) == NULL) 48 return -1; 49 50 (*i)++; 51 list[*i] = NULL; /* zero out the next entry */ 52 return 0; 53} 54 55 56static int getifaces(const int sockfd, char ***list) 57{ 58#ifdef HAVE_IFNAMEINDEX 59 struct if_nameindex *ifstart, *ifs; 60 int i = 0; 61 char **new; 62 63 ifs = ifstart = if_nameindex(); 64 65 new = (char **) malloc((sizeof(ifs)/sizeof(struct if_nameindex) + 1) * sizeof(char *)); 66 while (ifs && ifs->if_name) { 67 /* just bail if there's a problem */ 68 if (addname(new, &i, ifs->if_name) < 0) 69 break; 70 ifs++; 71 } 72 73 if_freenameindex(ifstart); 74 *list = new; 75 return i; 76 77#else 78 struct ifconf ifc; 79 struct ifreq ifrs[ 64 ], *ifr, *nextifr; 80 int ifrsize, i = 0; 81 char **new; 82 83 if (!list) 84 return 0; 85 86 memset( &ifc, 0, sizeof( struct ifconf )); 87 ifc.ifc_len = sizeof( ifrs ); 88 memset( ifrs, 0, sizeof( ifrs )); 89 ifc.ifc_buf = (caddr_t)ifrs; 90 if ( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) { 91 return 0; 92 } 93 94 new = (char **) malloc((ifc.ifc_len/sizeof(struct ifreq) + 1) * sizeof(char *)); 95 for ( ifr = ifc.ifc_req; ifc.ifc_len >= (int) sizeof( struct ifreq ); 96 ifc.ifc_len -= ifrsize, ifr = nextifr ) { 97#ifdef BSD4_4 98 ifrsize = sizeof(ifr->ifr_name) + 99 (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) 100 ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr)); 101#else /* !BSD4_4 */ 102 ifrsize = sizeof( struct ifreq ); 103#endif /* BSD4_4 */ 104 nextifr = (struct ifreq *)((caddr_t)ifr + ifrsize ); 105 106 /* just bail if there's a problem */ 107 if (addname(new, &i, ifr->ifr_name) < 0) 108 break; 109 } 110 *list = new; 111 return i; 112#endif 113} 114 115 116/* 117 * Get interfaces from the kernel. we keep an extra null entry to signify 118 * the end of the interface list. 119 */ 120char **getifacelist(void) 121{ 122 char **list = NULL; /* FIXME */ 123 int i, fd; 124 125 if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 126 return NULL; 127 128 if ((i = getifaces(fd, &list)) == 0) { 129 free(list); 130 close(fd); 131 return NULL; 132 } 133 close(fd); 134 135 return list; 136} 137 138 139/* go through and free the interface list */ 140void freeifacelist(char **ifacelist) 141{ 142 char *value, **list = ifacelist; 143 144 if (!ifacelist) 145 return; 146 147 while ((value = *list++)) { 148 free(value); 149 } 150 151 free(ifacelist); 152} 153