2 * Copyright 2000, International Business Machines Corporation and others.
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
12 /* getaddr -- get our internet address. July, 1986 */
14 #include <afs/param.h>
17 #include <sys/types.h>
18 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <sys/ioctl.h>
24 * By including this, we get any system dependencies. In particular,
25 * the pthreads for solaris requires the socket call to be mapped.
31 #include "../rx/rx_kcommon.h"
33 /* nothing here required yet */
40 /* only used for generating random noise */
42 afs_int32 rxi_tempAddr=0; /* default attempt */
44 /* set the advisory noise */
45 afs_int32 rxi_setaddr(x)
50 /* get approx to net addr */
51 afs_int32 rxi_getaddr() {
59 /* to satisfy those who call setaddr */
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.
75 /* Return our internet address as a long in network byte order. Returns zero
76 * if it can't find one.
78 afs_int32 rxi_getaddr ()
80 afs_int32 buffer[1024];
83 count = rx_getAllAddr(buffer, 1024);
85 return buffer[0]; /* returns the first address */
92 #if !defined(KERNEL) || defined(UKERNEL)
95 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
103 /* this function returns the total number of interface addresses
104 ** the buffer has to be passed in by the caller
106 int rx_getAllAddr (buffer,maxSize)
108 int maxSize; /* sizeof of buffer in afs_int32 units */
113 struct ifreq ifs[NIFS], *ifr;
114 struct sockaddr_in *a;
115 char *cp, *cplim; /* used only for AIX 41 */
117 s = socket(AF_INET, SOCK_DGRAM, 0);
120 ifc.ifc_len = sizeof(ifs);
121 ifc.ifc_buf = (caddr_t) ifs;
122 i = ioctl(s, SIOCGIFCONF, &ifc);
125 len = ifc.ifc_len / sizeof(struct ifreq);
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;
134 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))){
135 ifr = (struct ifreq *)cp;
137 for (i = 0; i < len; ++i) {
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 */
146 if (ifr->ifr_flags & IFF_LOOPBACK) {
147 continue; /* skip aliased loopbacks as well. */
149 if ( count >= maxSize ) /* no more space */
150 printf("Too many interfaces..ignoring 0x%x\n",
153 buffer[count++] = a->sin_addr.s_addr;
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().
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 */
175 struct ifreq ifs[NIFS], *ifr, tempIfr;
176 struct sockaddr_in *a;
177 char *cp, *cplim; /* used only for AIX 41 */
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);
186 #else /* AFS_USERSPACE_IP_ADDR */
187 s = socket(AF_INET, SOCK_DGRAM, 0);
190 ifc.ifc_len = sizeof(ifs);
191 ifc.ifc_buf = (caddr_t) ifs;
192 i = ioctl(s, SIOCGIFCONF, &ifc);
197 len = ifc.ifc_len / sizeof(struct ifreq);
198 if (len > NIFS) len = NIFS;
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;
206 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
207 ifr = (struct ifreq *)cp;
209 for (i = 0; i < len; ++i) {
212 a = (struct sockaddr_in *) &ifr->ifr_addr;
213 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
215 if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
216 perror("SIOCGIFFLAGS");
217 continue; /* ignore this address */
219 if (ifr->ifr_flags & IFF_LOOPBACK) {
220 continue; /* skip aliased loopbacks as well. */
223 if ( count >= maxSize ) { /* no more space */
224 printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr);
228 addrBuffer[count] = a->sin_addr.s_addr;
230 if ( ioctl(s, SIOCGIFNETMASK, (caddr_t)ifr) < 0 ) {
231 perror("SIOCGIFNETMASK");
232 maskBuffer[count] = htonl(0xffffffff);
234 maskBuffer[count] = (((struct sockaddr_in *)
235 (&ifr->ifr_addr))->sin_addr).s_addr;
238 mtuBuffer[count] = htonl(1500);
240 if ( ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) {
241 perror("SIOCGIFMTU");
243 mtuBuffer[count] = ifr->ifr_metric;
245 #endif /* SIOCGIFMTU */
247 if ( ioctl(s, SIOCRIPMTU, (caddr_t)ifr) < 0) {
248 perror("SIOCRIPMTU");
250 mtuBuffer[count] = ifr->ifr_metric;
252 #endif /* SIOCRIPMTU */
259 #endif /* AFS_USERSPACE_IP_ADDR */
262 #endif /* ! AFS_NT40_ENV */
263 #endif /* !KERNEL || UKERNEL */