]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/getiface.c
28aa03053652a87ebc213a91eea034b3feaea0e2
[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
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/ioctl.h>
15 #include <netinet/in.h>
16 #include <netinet/tcp.h>
17 #include <net/if.h>
18 #include <errno.h>
19
20 #ifdef __svr4__
21 #include <sys/sockio.h>
22 #endif
23
24 #include <atalk/util.h>
25
26 /* allocation size for interface list. */
27 #define IFACE_NUM 5
28
29 /* we leave all of the ioctl's to the application */
30 static int addname(char **list, int *i, int *length, const char *name) 
31
32 {
33     /* if we've run out of room, allocate some more. just return
34      * the present list if we can't. */
35      if (*i >= *length) {
36       char **new = realloc(list, sizeof(char **)*(*length + IFACE_NUM));
37        
38       if (!new) /* just break if we can't allocate anything */
39         return -1;
40       *length += IFACE_NUM;
41     }
42      
43     if ((list[*i] = strdup(name)) == NULL)
44       return -1;
45
46     (*i)++;
47     list[*i] = NULL; /* zero out the next entry */
48     return 0;
49 }
50
51
52 static int getifaces(const int sockfd, char **list, int *length)
53 {
54 #ifdef HAVE_IFNAMEINDEX
55       struct if_nameindex *ifstart, *ifs;
56       int i = 0;
57   
58       if (!list || *length < 1) 
59         return 0;
60
61       ifs = ifstart = if_nameindex();
62       while (ifs && ifs->if_name) {
63         /* just bail if there's a problem */
64         if (addname(list, &i, length, ifs->if_name) < 0)
65           break;
66         ifs++;
67       }
68
69       if_freenameindex(ifstart);
70       return i;
71
72 #else
73     struct ifconf       ifc;
74     struct ifreq        ifrs[ 64 ], *ifr, *nextifr;
75     int                 ifrsize, i = 0;
76
77     if (!list || *length < 1)
78       return 0;
79
80     memset( &ifc, 0, sizeof( struct ifconf ));
81     ifc.ifc_len = sizeof( ifrs );
82     memset( ifrs, 0, sizeof( ifrs ));
83     ifc.ifc_buf = (caddr_t)ifrs;
84     if ( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) {
85         return 0;
86     }
87
88     for ( ifr = ifc.ifc_req; ifc.ifc_len >= sizeof( struct ifreq );
89             ifc.ifc_len -= ifrsize, ifr = nextifr ) {
90 #ifdef BSD4_4
91         ifrsize = sizeof(ifr->ifr_name) +
92           (ifr->ifr_addr.sa_len > sizeof(struct sockaddr)
93            ? ifr->ifr_addr.sa_len : sizeof(struct sockaddr));
94 #else BSD4_4
95         ifrsize = sizeof( struct ifreq );
96 #endif BSD4_4
97         nextifr = (struct ifreq *)((caddr_t)ifr + ifrsize );
98
99         /* just bail if there's a problem */
100         if (addname(list, &i, length, ifr->ifr_name) < 0)
101           break;
102     }
103     return i;
104 #endif
105 }
106
107
108 /*
109  * Get interfaces from the kernel. we keep an extra null entry to signify
110  * the end of the interface list. 
111  */
112 char **getifacelist()
113 {
114   char **list = (char **) malloc(sizeof(char **)*(IFACE_NUM + 1));
115   char **new;
116   int length = IFACE_NUM, i, fd;
117
118   if (!list)
119     return NULL;
120       
121   if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
122     return NULL;
123
124   if ((i = getifaces(fd, list, &length)) == 0) {
125     free(list);
126     close(fd);
127     return NULL;
128   }
129   close(fd);
130
131   if ((i < length) && 
132       (new = (char **) realloc(list, sizeof(char **)*(i + 1))))
133     return new;
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 }