first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[bbaumbach/samba-autobuild/.git] / source3 / lib / netmask.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    code to query kernel netmask
5    Copyright (C) Andrew Tridgell 1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23 /* working out the netmask for an interface is an incredibly non-portable
24    thing. We have several possible implementations below, and autoconf
25    tries each of them to see what works 
26
27    Note that this file does _not_ include includes.h. That is so this code
28    can be called directly from the autoconf tests. That also means
29    this code cannot use any of the normal Samba debug stuff or defines.
30    This is standalone code.
31
32 */
33
34 #ifndef AUTOCONF
35 #include "config.h"
36 #endif
37
38 #ifdef HAVE_NETMASK_IFCONF
39
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <netdb.h>
47 #include <sys/ioctl.h>
48 #include <net/if.h>
49
50 #ifndef SIOCGIFCONF
51 #include <sys/sockio.h>
52 #endif
53
54 /*
55  * Prototype for gcc in fussy mode.
56  */
57
58 int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask);
59
60 /****************************************************************************
61   get the netmask address for a local interface
62 ****************************************************************************/
63 int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask)
64 {  
65         struct ifconf ifc;
66         char buff[2048];
67         int fd, i, n;
68         struct ifreq *ifr=NULL;
69
70         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
71 #ifdef DEBUG
72                 fprintf(stderr,"socket failed\n");
73 #endif
74                 return -1;
75         }
76   
77         ifc.ifc_len = sizeof(buff);
78         ifc.ifc_buf = buff;
79         if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
80 #ifdef DEBUG
81                 fprintf(stderr,"SIOCGIFCONF failed\n");
82 #endif
83                 close(fd);
84                 return -1;
85         } 
86
87         ifr = ifc.ifc_req;
88   
89         n = ifc.ifc_len / sizeof(struct ifreq);
90         
91 #ifdef DEBUG
92         fprintf(stderr,"%d interfaces - looking for %s\n", 
93                 n, inet_ntoa(*ipaddr));
94 #endif
95
96         /* Loop through interfaces, looking for given IP address */
97         for (i=n-1;i>=0;i--) {
98                 if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != 0) {
99 #ifdef DEBUG
100                         fprintf(stderr,"SIOCGIFADDR failed\n");
101 #endif
102                         continue;
103                 }
104
105 #ifdef DEBUG
106                 fprintf(stderr,"interface %s\n", 
107                         inet_ntoa((*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr));
108 #endif
109                 if (ipaddr->s_addr !=
110                     (*(struct sockaddr_in *)&ifr[i].ifr_addr).sin_addr.s_addr) {
111                         continue;
112                 }
113
114                 if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != 0) {
115 #ifdef DEBUG
116                         fprintf(stderr,"SIOCGIFNETMASK failed\n");
117 #endif
118                         close(fd);
119                         return -1;
120                 }  
121                 close(fd);
122                 (*nmask) = ((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr;
123 #ifdef DEBUG
124                 fprintf(stderr,"netmask %s\n", inet_ntoa(*nmask));
125 #endif
126                 return 0;
127         }
128
129 #ifdef DEBUG
130         fprintf(stderr,"interface not found\n");
131 #endif
132
133         close(fd);
134         return -1;
135 }  
136
137 #elif defined(HAVE_NETMASK_IFREQ)
138
139 #include <stdio.h>
140 #include <sys/types.h>
141 #include <sys/socket.h>
142 #include <netinet/in.h>
143 #include <arpa/inet.h>
144 #include <netdb.h>
145 #include <sys/ioctl.h>
146 #include <net/if.h>
147
148 #ifndef SIOCGIFCONF
149 #include <sys/sockio.h>
150 #endif
151
152 #ifndef I_STR
153 #include <sys/stropts.h>
154 #endif
155
156
157 /****************************************************************************
158 this should cover most of the rest of systems
159 ****************************************************************************/
160  int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask)
161 {
162         struct ifreq ifreq;
163         struct strioctl strioctl;
164         struct ifconf *ifc;
165         char buff[2048];
166         int fd, i, n;
167         struct ifreq *ifr=NULL;
168
169         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
170 #ifdef DEBUG
171                 fprintf(stderr,"socket failed\n");
172 #endif
173                 return -1;
174         }
175   
176         ifc = (struct ifconf *)buff;
177         ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
178         strioctl.ic_cmd = SIOCGIFCONF;
179         strioctl.ic_dp  = (char *)ifc;
180         strioctl.ic_len = sizeof(buff);
181         if (ioctl(fd, I_STR, &strioctl) < 0) {
182 #ifdef DEBUG
183                 fprintf(stderr,"SIOCGIFCONF failed\n");
184 #endif
185                 close(fd);
186                 return -1;
187         } 
188         
189         ifr = (struct ifreq *)ifc->ifc_req;  
190
191         /* Loop through interfaces, looking for given IP address */
192         n = ifc->ifc_len / sizeof(struct ifreq);
193
194         for (i = 0; i<n; i++, ifr++) {
195 #ifdef DEBUG
196                 fprintf(stderr,"interface %s\n", 
197                         inet_ntoa((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr.s_addr));
198 #endif
199                 if (ipaddr->s_addr ==
200                     (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
201                         break;
202                 }
203         }
204
205 #ifdef DEBUG
206         if (i == n) {
207                 fprintf(stderr,"interface not found\n");
208                 close(fd);
209                 return -1;
210         }
211 #endif
212
213         ifreq = *ifr;
214   
215         strioctl.ic_cmd = SIOCGIFNETMASK;
216         strioctl.ic_dp  = (char *)&ifreq;
217         strioctl.ic_len = sizeof(struct ifreq);
218         if (ioctl(fd, I_STR, &strioctl) != 0) {
219 #ifdef DEBUG
220                 fprintf(stderr,"Failed SIOCGIFNETMASK\n");
221 #endif
222                 close(fd);
223                 return -1;
224         }
225
226         close(fd);
227         *nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
228 #ifdef DEBUG
229         fprintf(stderr,"netmask %s\n", inet_ntoa(*nmask));
230 #endif
231         return 0;
232 }
233
234 #elif defined(HAVE_NETMASK_AIX)
235
236 #include <stdio.h>
237 #include <sys/types.h>
238 #include <sys/socket.h>
239 #include <netinet/in.h>
240 #include <arpa/inet.h>
241 #include <netdb.h>
242 #include <sys/ioctl.h>
243 #include <net/if.h>
244
245 #ifndef SIOCGIFCONF
246 #include <sys/sockio.h>
247 #endif
248
249 /****************************************************************************
250 this one is for AIX
251 ****************************************************************************/
252  int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask)
253 {
254         char buff[2048];
255         int fd, i, n;
256         struct ifconf ifc;
257         struct ifreq *ifr=NULL;
258
259         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
260 #ifdef DEBUG
261                 fprintf(stderr,"socket failed\n");
262 #endif
263                 return -1;
264         }
265
266
267         ifc.ifc_len = sizeof(buff);
268         ifc.ifc_buf = buff;
269
270         if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
271 #ifdef DEBUG
272                 fprintf(stderr,"SIOCGIFCONF failed\n");
273 #endif
274                 close(fd);
275                 return -1;
276         }
277
278         ifr = ifc.ifc_req;
279         /* Loop through interfaces, looking for given IP address */
280         i = ifc.ifc_len;
281         while (i > 0) {
282 #ifdef DEBUG
283                 fprintf(stderr,"interface %s\n", 
284                         inet_ntoa((*(struct sockaddr_in *)&ifr->ifr_addr).sin_addr));
285 #endif
286                 if (ipaddr->s_addr ==
287                     (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
288                         break;
289                 }
290                 i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
291                 ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + 
292                                        IFNAMSIZ);
293         }
294   
295
296 #ifdef DEBUG
297         if (i <= 0) {
298                 fprintf(stderr,"interface not found\n");
299                 close(fd);
300                 return -1;
301         }
302 #endif
303
304         if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
305 #ifdef DEBUG
306                 fprintf(stderr,"SIOCGIFNETMASK failed\n");
307 #endif
308                 close(fd);
309                 return -1;
310         }  
311
312         close(fd);
313
314         (*nmask) = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
315 #ifdef DEBUG
316         fprintf(stderr,"netmask %s\n", inet_ntoa(*nmask));
317 #endif
318         return 0;
319 }
320
321 #else /* a dummy version */
322 struct in_addr; /* it may not have been declared before */
323  int get_netmask(struct in_addr *ipaddr, struct in_addr *nmask)
324 {
325         return -1;
326 }
327 #endif
328
329
330 #ifdef AUTOCONF
331 /* this is the autoconf driver to test get_netmask() */
332
333  main()
334 {
335         char buf[1024];
336         struct hostent *hp;
337         struct in_addr ip, nmask;
338
339         if (gethostname(buf, sizeof(buf)-1) != 0) {
340                 fprintf(stderr,"gethostname failed\n");
341                 exit(1);
342         }
343
344         hp = gethostbyname(buf);
345
346         if (!hp) {
347                 fprintf(stderr,"gethostbyname failed\n");
348                 exit(1);
349         }
350
351         memcpy((char *)&ip, (char *)hp->h_addr, hp->h_length);
352
353         if (get_netmask(&ip, &nmask) == 0) exit(0);
354
355         fprintf(stderr,"get_netmask failed\n");
356         exit(1);
357 }
358 #endif