/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #ifndef lint #endif /* getaddr -- get our internet address. July, 1986 */ #include #ifndef KERNEL #ifndef AFS_NT40_ENV #include #include #include #include #include #include /* * By including this, we get any system dependencies. In particular, * the pthreads for solaris requires the socket call to be mapped. */ #include "rx.h" #endif #else /* KERNEL */ #ifdef UKERNEL #include "../rx/rx_kcommon.h" #else /* UKERNEL */ /* nothing here required yet */ #endif /* UKERNEL */ #endif /* KERNEL */ #define NIFS 512 #ifdef KERNEL /* only used for generating random noise */ afs_int32 rxi_tempAddr=0; /* default attempt */ /* set the advisory noise */ afs_int32 rxi_setaddr(x) afs_int32 x;{ rxi_tempAddr = x; } /* get approx to net addr */ afs_int32 rxi_getaddr() { return rxi_tempAddr; } #endif /* KERNEL */ #ifndef KERNEL /* to satisfy those who call setaddr */ rxi_setaddr(x) afs_int32 x; { return 0; } #endif /* !KERNEL */ #if !defined(AFS_NT40_ENV) /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by * rx_Init which sets up the list of addresses for us. */ #ifndef KERNEL /* Return our internet address as a long in network byte order. Returns zero * if it can't find one. */ afs_int32 rxi_getaddr () { afs_int32 buffer[1024]; int count; count = rx_getAllAddr(buffer, 1024); if ( count > 0 ) return buffer[0]; /* returns the first address */ else return count; } #endif /* !KERNEL */ #if !defined(KERNEL) || defined(UKERNEL) #ifndef MAX #define MAX(A,B) (((A)<(B)) ? (B) : (A)) #endif #ifdef UKERNEL #undef ioctl #undef socket #endif /* UKERNEL */ /* this function returns the total number of interface addresses ** the buffer has to be passed in by the caller */ int rx_getAllAddr (buffer,maxSize) afs_int32 buffer[]; int maxSize; /* sizeof of buffer in afs_int32 units */ { int s; int i, len, count=0; struct ifconf ifc; struct ifreq ifs[NIFS], *ifr; struct sockaddr_in *a; char *cp, *cplim; /* used only for AIX 41 */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; ifc.ifc_len = sizeof(ifs); ifc.ifc_buf = (caddr_t) ifs; i = ioctl(s, SIOCGIFCONF, &ifc); if (i < 0) return 0; len = ifc.ifc_len / sizeof(struct ifreq); if (len > NIFS) len = NIFS; #if defined(AFS_AIX41_ENV) if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */ ifc.ifc_len = sizeof(ifs); for ( cp = (char *)ifc.ifc_buf, cplim= ifc.ifc_buf+ifc.ifc_len; cp < cplim; cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))){ ifr = (struct ifreq *)cp; #else for (i = 0; i < len; ++i) { ifr = &ifs[i]; #endif a = (struct sockaddr_in *) &ifr->ifr_addr; if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) { if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) { perror("SIOCGIFFLAGS"); continue; /* ignore this address */ } if (ifr->ifr_flags & IFF_LOOPBACK) { continue; /* skip aliased loopbacks as well. */ } if ( count >= maxSize ) /* no more space */ printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr); else buffer[count++] = a->sin_addr.s_addr; } } close(s); return count; } /* this function returns the total number of interface addresses * the buffer has to be passed in by the caller. It also returns * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it * gets the mask which is then passed into the kernel and is used * by afsi_SetServerIPRank(). */ int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize) afs_int32 addrBuffer[]; /* the network addrs in net byte order */ afs_int32 maskBuffer[]; /* the subnet masks */ afs_int32 mtuBuffer[]; /* the MTU sizes */ int maxSize; /* sizeof of buffer in afs_int32 units */ { int s; int i, len, count=0; struct ifconf ifc; struct ifreq ifs[NIFS], *ifr, tempIfr; struct sockaddr_in *a; char *cp, *cplim; /* used only for AIX 41 */ #if !defined(AFS_USERSPACE_IP_ADDR) count = rx_getAllAddr(addrBuffer, 1024); for (i=0; i NIFS) len = NIFS; #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV) if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */ ifc.ifc_len = sizeof(ifs); for ( cp = (char *)ifc.ifc_buf, cplim= ifc.ifc_buf+ifc.ifc_len; cp < cplim; cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) { ifr = (struct ifreq *)cp; #else for (i = 0; i < len; ++i) { ifr = &ifs[i]; #endif a = (struct sockaddr_in *) &ifr->ifr_addr; if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) { if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) { perror("SIOCGIFFLAGS"); continue; /* ignore this address */ } if (ifr->ifr_flags & IFF_LOOPBACK) { continue; /* skip aliased loopbacks as well. */ } if ( count >= maxSize ) { /* no more space */ printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr); continue; } addrBuffer[count] = a->sin_addr.s_addr; if ( ioctl(s, SIOCGIFNETMASK, (caddr_t)ifr) < 0 ) { perror("SIOCGIFNETMASK"); maskBuffer[count] = htonl(0xffffffff); } else { maskBuffer[count] = (((struct sockaddr_in *) (&ifr->ifr_addr))->sin_addr).s_addr; } mtuBuffer[count] = htonl(1500); #ifdef SIOCGIFMTU if ( ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) { perror("SIOCGIFMTU"); } else { mtuBuffer[count] = ifr->ifr_metric; } #endif /* SIOCGIFMTU */ #ifdef SIOCRIPMTU if ( ioctl(s, SIOCRIPMTU, (caddr_t)ifr) < 0) { perror("SIOCRIPMTU"); } else { mtuBuffer[count] = ifr->ifr_metric; } #endif /* SIOCRIPMTU */ count++; } } close(s); return count; #endif /* AFS_USERSPACE_IP_ADDR */ } #endif /* ! AFS_NT40_ENV */ #endif /* !KERNEL || UKERNEL */