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