]> arthur.barton.de Git - netatalk.git/blob - libatalk/util/getiface.c
implemented config.h
[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 #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 #include <net/if.h>
21 #include <errno.h>
22
23 #ifdef __svr4__
24 #include <sys/sockio.h>
25 #endif
26
27 #include <atalk/util.h>
28
29 /* allocation size for interface list. */
30 #define IFACE_NUM 5
31
32 /* we leave all of the ioctl's to the application */
33 static int addname(char **list, int *i, int *length, const char *name) 
34
35 {
36     /* if we've run out of room, allocate some more. just return
37      * the present list if we can't. */
38      if (*i >= *length) {
39       char **new = realloc(list, sizeof(char **)*(*length + IFACE_NUM));
40        
41       if (!new) /* just break if we can't allocate anything */
42         return -1;
43       *length += IFACE_NUM;
44     }
45      
46     if ((list[*i] = strdup(name)) == NULL)
47       return -1;
48
49     (*i)++;
50     list[*i] = NULL; /* zero out the next entry */
51     return 0;
52 }
53
54
55 static int getifaces(const int sockfd, char **list, int *length)
56 {
57 #ifdef HAVE_IFNAMEINDEX
58       struct if_nameindex *ifstart, *ifs;
59       int i = 0;
60   
61       if (!list || *length < 1) 
62         return 0;
63
64       ifs = ifstart = if_nameindex();
65       while (ifs && ifs->if_name) {
66         /* just bail if there's a problem */
67         if (addname(list, &i, length, ifs->if_name) < 0)
68           break;
69         ifs++;
70       }
71
72       if_freenameindex(ifstart);
73       return i;
74
75 #else
76     struct ifconf       ifc;
77     struct ifreq        ifrs[ 64 ], *ifr, *nextifr;
78     int                 ifrsize, i = 0;
79
80     if (!list || *length < 1)
81       return 0;
82
83     memset( &ifc, 0, sizeof( struct ifconf ));
84     ifc.ifc_len = sizeof( ifrs );
85     memset( ifrs, 0, sizeof( ifrs ));
86     ifc.ifc_buf = (caddr_t)ifrs;
87     if ( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) {
88         return 0;
89     }
90
91     for ( ifr = ifc.ifc_req; ifc.ifc_len >= 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(list, &i, length, ifr->ifr_name) < 0)
104           break;
105     }
106     return i;
107 #endif
108 }
109
110
111 /*
112  * Get interfaces from the kernel. we keep an extra null entry to signify
113  * the end of the interface list. 
114  */
115 char **getifacelist()
116 {
117   char **list = (char **) malloc(sizeof(char **)*(IFACE_NUM + 1));
118   char **new;
119   int length = IFACE_NUM, i, fd;
120
121   if (!list)
122     return NULL;
123       
124   if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
125     return NULL;
126
127   if ((i = getifaces(fd, list, &length)) == 0) {
128     free(list);
129     close(fd);
130     return NULL;
131   }
132   close(fd);
133
134   if ((i < length) && 
135       (new = (char **) realloc(list, sizeof(char **)*(i + 1))))
136     return new;
137
138   return list;
139 }
140
141
142 /* go through and free the interface list */
143 void freeifacelist(char **ifacelist)
144 {
145   char *value, **list = ifacelist;
146
147   if (!ifacelist)
148     return;
149
150   while (value = *list++) {
151     free(value);
152   }
153
154   free(ifacelist);
155 }