]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/getiface.c
Remove bdb env on exit
[netatalk.git] / libatalk / util / getiface.c
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 */
41 static 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
56 static 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  */
120 char **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 */
140 void 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 }