]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/getiface.c
Fixed a bug that could lead to segfaults.
[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, int *length, 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      if (*i >= *length) {
47       char **new = realloc(list, sizeof(char **)*(*length + IFACE_NUM));
48        
49       if (!new) /* just break if we can't allocate anything */
50         return -1;
51
52       /* copy the old list */
53       memcpy(new, list, *length);
54       list = new;
55       
56       *length += IFACE_NUM;
57     }
58      
59     if ((list[*i] = strdup(name)) == NULL)
60       return -1;
61
62     (*i)++;
63     list[*i] = NULL; /* zero out the next entry */
64     return 0;
65 }
66
67
68 static int getifaces(const int sockfd, char **list, int *length)
69 {
70 #ifdef HAVE_IFNAMEINDEX
71       struct if_nameindex *ifstart, *ifs;
72       int i = 0;
73   
74       if (!list || *length < 1) 
75         return 0;
76
77       ifs = ifstart = if_nameindex();
78       while (ifs && ifs->if_name) {
79         /* just bail if there's a problem */
80         if (addname(list, &i, length, ifs->if_name) < 0)
81           break;
82         ifs++;
83       }
84
85       if_freenameindex(ifstart);
86       return i;
87
88 #else
89     struct ifconf       ifc;
90     struct ifreq        ifrs[ 64 ], *ifr, *nextifr;
91     int                 ifrsize, i = 0;
92
93     if (!list || *length < 1)
94       return 0;
95
96     memset( &ifc, 0, sizeof( struct ifconf ));
97     ifc.ifc_len = sizeof( ifrs );
98     memset( ifrs, 0, sizeof( ifrs ));
99     ifc.ifc_buf = (caddr_t)ifrs;
100     if ( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) {
101         return 0;
102     }
103
104     for ( ifr = ifc.ifc_req; ifc.ifc_len >= sizeof( struct ifreq );
105             ifc.ifc_len -= ifrsize, ifr = nextifr ) {
106 #ifdef BSD4_4
107         ifrsize = sizeof(ifr->ifr_name) +
108           (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
109            ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr));
110 #else /* !BSD4_4 */
111         ifrsize = sizeof( struct ifreq );
112 #endif /* BSD4_4 */
113         nextifr = (struct ifreq *)((caddr_t)ifr + ifrsize );
114
115         /* just bail if there's a problem */
116         if (addname(list, &i, length, ifr->ifr_name) < 0)
117           break;
118     }
119     return i;
120 #endif
121 }
122
123
124 /*
125  * Get interfaces from the kernel. we keep an extra null entry to signify
126  * the end of the interface list. 
127  */
128 char **getifacelist()
129 {
130   char **list = (char **) malloc(sizeof(char **)*(IFACE_NUM + 1));
131   char **new;
132   int length = IFACE_NUM, i, fd;
133
134   if (!list)
135     return NULL;
136       
137   if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
138     return NULL;
139
140   if ((i = getifaces(fd, list, &length)) == 0) {
141     free(list);
142     close(fd);
143     return NULL;
144   }
145   close(fd);
146
147   if ((i < length) && 
148       (new = (char **) realloc(list, sizeof(char **)*(i + 1))))
149     return new;
150
151   return list;
152 }
153
154
155 /* go through and free the interface list */
156 void freeifacelist(char **ifacelist)
157 {
158   char *value, **list = ifacelist;
159
160   if (!ifacelist)
161     return;
162
163   while ((value = *list++)) {
164     free(value);
165   }
166
167   free(ifacelist);
168 }