Standardize License information
[openafs.git] / src / rx / rx_getaddr.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #ifndef lint
11 #endif
12 /* getaddr -- get our internet address. July, 1986 */
13
14 #include <afs/param.h>
15 #ifndef KERNEL
16 #ifndef AFS_NT40_ENV
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <net/if.h>
21 #include <netinet/in.h>
22 #include <sys/ioctl.h>
23 /*
24  * By including this, we get any system dependencies. In particular,
25  * the pthreads for solaris requires the socket call to be mapped.
26  */
27 #include "rx.h"
28 #endif
29 #else   /* KERNEL */
30 #ifdef UKERNEL
31 #include "../rx/rx_kcommon.h"
32 #else /* UKERNEL */
33 /* nothing here required yet */
34 #endif /* UKERNEL */
35 #endif  /* KERNEL */
36
37 #define NIFS            512
38
39 #ifdef KERNEL
40 /* only used for generating random noise */
41
42 afs_int32 rxi_tempAddr=0;       /* default attempt */
43
44 /* set the advisory noise */
45 afs_int32 rxi_setaddr(x)
46 afs_int32 x;{
47     rxi_tempAddr = x;
48 }
49
50 /* get approx to net addr */
51 afs_int32 rxi_getaddr() {
52     return rxi_tempAddr;
53 }
54
55 #endif /* KERNEL */
56
57 #ifndef KERNEL
58
59 /* to satisfy those who call setaddr */
60 rxi_setaddr(x)
61 afs_int32 x; {
62     return 0;
63 }
64
65 #endif /* !KERNEL */
66
67
68 #if !defined(AFS_NT40_ENV)
69 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
70  * rx_Init which sets up the list of addresses for us.
71  */
72
73 #ifndef KERNEL
74
75 /* Return our internet address as a long in network byte order.  Returns zero
76  * if it can't find one.
77  */
78 afs_int32 rxi_getaddr ()
79 {
80         afs_int32       buffer[1024];
81         int     count;
82
83         count = rx_getAllAddr(buffer, 1024); 
84         if ( count > 0 )
85                 return buffer[0]; /* returns the first address */
86         else
87                 return count;
88 }
89
90 #endif /* !KERNEL */
91
92 #if !defined(KERNEL) || defined(UKERNEL)
93
94 #ifndef MAX
95 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
96 #endif
97
98 #ifdef UKERNEL
99 #undef ioctl
100 #undef socket
101 #endif /* UKERNEL */
102
103 /* this function returns the total number of interface addresses 
104 ** the buffer has to be passed in by the caller
105 */
106 int rx_getAllAddr (buffer,maxSize)
107 afs_int32       buffer[];
108 int     maxSize;        /* sizeof of buffer in afs_int32 units */
109 {
110     int     s;
111     int     i, len, count=0;
112     struct ifconf   ifc;
113     struct ifreq    ifs[NIFS], *ifr;
114     struct sockaddr_in *a;
115     char        *cp, *cplim;    /* used only for AIX 41 */
116
117     s = socket(AF_INET, SOCK_DGRAM, 0);
118     if (s < 0)
119         return 0;
120     ifc.ifc_len = sizeof(ifs);
121     ifc.ifc_buf = (caddr_t) ifs;
122     i = ioctl(s, SIOCGIFCONF, &ifc);
123     if (i < 0)
124         return 0;
125     len = ifc.ifc_len / sizeof(struct ifreq);
126     if (len > NIFS)
127         len = NIFS;
128 #if     defined(AFS_AIX41_ENV)
129     if ( ifc.ifc_len > sizeof(ifs) )    /* safety check */
130         ifc.ifc_len = sizeof(ifs); 
131     for ( cp = (char *)ifc.ifc_buf, 
132                 cplim= ifc.ifc_buf+ifc.ifc_len;
133                 cp < cplim;
134                 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))){
135         ifr = (struct ifreq *)cp;
136 #else
137     for (i = 0; i < len; ++i) {
138         ifr = &ifs[i];
139 #endif
140         a = (struct sockaddr_in *) &ifr->ifr_addr;
141         if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
142             if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
143                 perror("SIOCGIFFLAGS");
144                 continue; /* ignore this address */
145             }
146             if (ifr->ifr_flags & IFF_LOOPBACK) {
147                 continue;        /* skip aliased loopbacks as well. */
148             }
149             if ( count >= maxSize )  /* no more space */
150                 printf("Too many interfaces..ignoring 0x%x\n",
151                        a->sin_addr.s_addr);
152             else
153                 buffer[count++] = a->sin_addr.s_addr;
154         }
155     }
156     close(s);
157     return count;
158 }
159
160 /* this function returns the total number of interface addresses
161  * the buffer has to be passed in by the caller. It also returns
162  * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
163  * gets the mask which is then passed into the kernel and is used
164  * by afsi_SetServerIPRank().
165  */
166 int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize)
167    afs_int32   addrBuffer[];   /* the network addrs in net byte order */
168    afs_int32   maskBuffer[];   /* the subnet masks */
169    afs_int32   mtuBuffer[];    /* the MTU sizes */
170    int     maxSize;        /* sizeof of buffer in afs_int32 units */
171 {
172    int     s;
173    int     i, len, count=0;
174    struct ifconf   ifc;
175    struct ifreq    ifs[NIFS], *ifr, tempIfr;
176    struct sockaddr_in *a;
177    char        *cp, *cplim;    /* used only for AIX 41 */
178
179 #if !defined(AFS_USERSPACE_IP_ADDR)
180    count = rx_getAllAddr(addrBuffer, 1024);
181    for (i=0; i<count; i++) {
182       maskBuffer[i] = htonl(0xffffffff);
183       mtuBuffer[i]  = htonl(1500);
184    }
185    return count;
186 #else  /* AFS_USERSPACE_IP_ADDR */
187    s = socket(AF_INET, SOCK_DGRAM, 0);
188    if (s < 0) return 0;
189
190    ifc.ifc_len = sizeof(ifs);
191    ifc.ifc_buf = (caddr_t) ifs;
192    i = ioctl(s, SIOCGIFCONF, &ifc);
193    if (i < 0) {
194       close(s);
195       return 0;
196    }
197    len = ifc.ifc_len / sizeof(struct ifreq);
198    if (len > NIFS) len = NIFS;
199
200 #if     defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
201    if ( ifc.ifc_len > sizeof(ifs) )    /* safety check */
202      ifc.ifc_len = sizeof(ifs);
203    for ( cp = (char *)ifc.ifc_buf,
204         cplim= ifc.ifc_buf+ifc.ifc_len;
205         cp < cplim;
206         cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
207       ifr = (struct ifreq *)cp;
208 #else
209    for (i = 0; i < len; ++i) {
210       ifr = &ifs[i];
211 #endif
212       a = (struct sockaddr_in *) &ifr->ifr_addr;
213       if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
214
215          if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
216             perror("SIOCGIFFLAGS");
217             continue; /* ignore this address */
218          }
219          if (ifr->ifr_flags & IFF_LOOPBACK) {
220             continue;    /* skip aliased loopbacks as well. */
221          }
222
223          if ( count >= maxSize ) { /* no more space */
224             printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr);
225             continue;
226          }
227
228          addrBuffer[count] = a->sin_addr.s_addr;
229
230          if ( ioctl(s, SIOCGIFNETMASK, (caddr_t)ifr) < 0 ) {
231             perror("SIOCGIFNETMASK");
232             maskBuffer[count] = htonl(0xffffffff);
233          } else {
234             maskBuffer[count] = (((struct sockaddr_in *)
235                                   (&ifr->ifr_addr))->sin_addr).s_addr;
236          }
237
238          mtuBuffer[count] = htonl(1500);
239 #ifdef SIOCGIFMTU
240          if ( ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) {
241             perror("SIOCGIFMTU");
242          } else {
243             mtuBuffer[count] = ifr->ifr_metric;
244          }
245 #endif /* SIOCGIFMTU */
246 #ifdef SIOCRIPMTU
247          if ( ioctl(s, SIOCRIPMTU, (caddr_t)ifr) < 0) {
248             perror("SIOCRIPMTU");
249          } else {
250             mtuBuffer[count] = ifr->ifr_metric;
251          }
252 #endif /* SIOCRIPMTU */
253
254          count++;
255       }
256    }
257    close(s);
258    return count;
259 #endif /* AFS_USERSPACE_IP_ADDR */
260 }
261
262 #endif /* ! AFS_NT40_ENV */
263 #endif /* !KERNEL || UKERNEL */