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
10 #include <afsconfig.h>
11 #include <afs/param.h>
18 # if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
19 # include <sys/sysctl.h>
20 # ifndef AFS_ARM_DARWIN_ENV
21 # include <net/route.h>
23 # include <net/if_dl.h>
27 * By including this, we get any system dependencies. In particular,
28 * the pthreads for solaris requires the socket call to be mapped.
31 # include "rx_globals.h"
32 # endif /* AFS_NT40_ENV */
35 # include "rx/rx_kcommon.h"
43 #if defined(AFS_USR_DFBSD_ENV)
45 # include <sys/sockio.h>
49 /* only used for generating random noise */
51 afs_uint32 rxi_tempAddr = 0; /* default attempt */
53 /* set the advisory noise */
55 rxi_setaddr(afs_uint32 x)
60 /* get approx to net addr */
71 /* to satisfy those who call setaddr */
73 rxi_setaddr(afs_uint32 x)
80 #if !defined(AFS_NT40_ENV)
81 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
82 * rx_Init which sets up the list of addresses for us.
87 /* Return our internet address as a long in network byte order. Returns zero
88 * if it can't find one.
93 afs_uint32 buffer[1024];
96 count = rx_getAllAddr(buffer, 1024);
98 return buffer[0]; /* returns the first address */
105 #if !defined(KERNEL) || defined(UKERNEL)
108 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
116 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
118 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
119 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
122 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
127 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
128 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
129 if ((rtinfo->rti_addrs & (1 << i)) == 0)
131 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
138 rxi_IsLoopbackIface(struct sockaddr_in *a, unsigned long flags)
140 afs_uint32 addr = ntohl(a->sin_addr.s_addr);
141 if (rx_IsLoopbackAddr(addr)) {
144 if ((flags & IFF_LOOPBACK) && ((addr & 0xff000000) == 0x7f000000)) {
150 /* this function returns the total number of interface addresses
151 ** the buffer has to be passed in by the caller
153 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
154 #if defined(AFS_OBSD42_ENV)
156 ifm_fixversion(char *buffer, size_t *size) {
157 struct if_msghdr *ifm;
161 if ((t = malloc(*size)) != NULL) {
162 memcpy(t, buffer, *size);
164 for (s = t; s < t + *size; s += ifm->ifm_msglen) {
165 ifm = (struct if_msghdr *)s;
167 if (ifm->ifm_version == RTM_VERSION) {
168 memcpy(b, ifm, ifm->ifm_msglen);
169 b += ifm->ifm_msglen;
181 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
185 struct if_msghdr *ifm, *nextifm;
186 struct ifa_msghdr *ifam;
187 struct sockaddr_dl *sdl;
188 struct rt_addrinfo info;
189 char *buf, *lim, *next;
190 int count = 0, addrcount = 0;
195 mib[3] = AF_INET; /* address family */
196 mib[4] = NET_RT_IFLIST;
198 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
200 if ((buf = malloc(needed)) == NULL)
202 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
206 #if defined(AFS_OBSD42_ENV)
207 ifm_fixversion(buf, &needed);
212 ifm = (struct if_msghdr *)next;
213 if (ifm->ifm_type != RTM_IFINFO) {
214 dpf(("out of sync parsing NET_RT_IFLIST\n"));
218 sdl = (struct sockaddr_dl *)(ifm + 1);
219 next += ifm->ifm_msglen;
223 nextifm = (struct if_msghdr *)next;
224 if (nextifm->ifm_type != RTM_NEWADDR)
227 ifam = (struct ifa_msghdr *)nextifm;
229 next += nextifm->ifm_msglen;
231 if ((ifm->ifm_flags & IFF_UP) == 0)
232 continue; /* not up */
233 while (addrcount > 0) {
234 struct sockaddr_in *a;
236 info.rti_addrs = ifam->ifam_addrs;
238 /* Expand the compacted addresses */
239 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
241 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
245 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
247 if (count >= maxSize) /* no more space */
248 dpf(("Too many interfaces..ignoring 0x%x\n",
249 a->sin_addr.s_addr));
250 else if (!loopbacks && rxi_IsLoopbackIface(a, ifm->ifm_flags)) {
252 continue; /* skip loopback address as well. */
253 } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) {
255 continue; /* skip aliased loopbacks as well. */
257 buffer[count++] = a->sin_addr.s_addr;
259 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
267 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
268 afs_uint32 mtuBuffer[], int maxSize)
274 struct if_msghdr *ifm, *nextifm;
275 struct ifa_msghdr *ifam;
276 struct sockaddr_dl *sdl;
277 struct rt_addrinfo info;
278 char *buf, *lim, *next;
279 int count = 0, addrcount = 0;
284 mib[3] = AF_INET; /* address family */
285 mib[4] = NET_RT_IFLIST;
287 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
289 if ((buf = malloc(needed)) == NULL)
291 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
295 #if defined(AFS_OBSD42_ENV)
296 ifm_fixversion(buf, &needed);
298 s = socket(PF_INET, SOCK_DGRAM, 0);
304 ifm = (struct if_msghdr *)next;
305 if (ifm->ifm_type != RTM_IFINFO) {
306 dpf(("out of sync parsing NET_RT_IFLIST\n"));
310 sdl = (struct sockaddr_dl *)(ifm + 1);
311 next += ifm->ifm_msglen;
315 nextifm = (struct if_msghdr *)next;
316 if (nextifm->ifm_type != RTM_NEWADDR)
319 ifam = (struct ifa_msghdr *)nextifm;
321 next += nextifm->ifm_msglen;
323 if ((ifm->ifm_flags & IFF_UP) == 0)
324 continue; /* not up */
325 while (addrcount > 0) {
326 struct sockaddr_in *a;
328 info.rti_addrs = ifam->ifam_addrs;
330 /* Expand the compacted addresses */
331 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
333 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
337 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
339 if (!rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr))) {
340 if (count >= maxSize) { /* no more space */
341 dpf(("Too many interfaces..ignoring 0x%x\n",
342 a->sin_addr.s_addr));
346 addrBuffer[count] = a->sin_addr.s_addr;
347 a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK];
349 maskBuffer[count] = a->sin_addr.s_addr;
351 maskBuffer[count] = htonl(0xffffffff);
352 memset(&ifr, 0, sizeof(ifr));
353 ifr.ifr_addr.sa_family = AF_INET;
354 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
355 if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
356 mtuBuffer[count] = htonl(1500);
358 mtuBuffer[count] = htonl(ifr.ifr_mtu);
363 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
372 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
374 return rx_getAllAddr_internal(buffer, maxSize, 0);
376 /* this function returns the total number of interface addresses
377 ** the buffer has to be passed in by the caller
379 #else /* UKERNEL indirectly, on DARWIN or XBSD */
381 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
384 int i, len, count = 0;
386 struct ifreq ifs[NIFS], *ifr;
387 struct sockaddr_in *a;
388 /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */
389 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
390 char *cp, *cplim, *cpnext; /* used only for AIX 41 */
393 s = socket(AF_INET, SOCK_DGRAM, 0);
396 ifc.ifc_len = sizeof(ifs);
397 ifc.ifc_buf = (caddr_t) ifs;
398 i = ioctl(s, SIOCGIFCONF, &ifc);
401 len = ifc.ifc_len / sizeof(struct ifreq);
404 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
405 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
406 ifc.ifc_len = sizeof(ifs);
407 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
409 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
410 cp += _SIZEOF_ADDR_IFREQ(*ifr)
415 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))
420 for (i = 0; i < len; ++i)
423 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
424 ifr = (struct ifreq *)cp;
428 a = (struct sockaddr_in *)&ifr->ifr_addr;
430 cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
432 if (a->sin_family != AF_INET)
434 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
435 perror("SIOCGIFFLAGS");
436 continue; /* ignore this address */
438 if (a->sin_addr.s_addr != 0) {
440 if (rxi_IsLoopbackIface(a, ifr->ifr_flags))
441 continue; /* skip loopback address as well. */
443 if (ifr->ifr_flags & IFF_LOOPBACK)
444 continue; /* skip aliased loopbacks as well. */
446 if (count >= maxSize) /* no more space */
447 dpf(("Too many interfaces..ignoring 0x%x\n",
448 a->sin_addr.s_addr));
450 buffer[count++] = a->sin_addr.s_addr;
458 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
460 return rx_getAllAddr_internal(buffer, maxSize, 0);
463 /* this function returns the total number of interface addresses
464 * the buffer has to be passed in by the caller. It also returns
465 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
466 * gets the mask which is then passed into the kernel and is used
467 * by afsi_SetServerIPRank().
470 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
471 afs_uint32 mtuBuffer[], int maxSize)
474 #if defined(AFS_USERSPACE_IP_ADDR)
477 struct ifreq ifs[NIFS], *ifr;
478 struct sockaddr_in *a;
481 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
482 char *cp, *cplim; /* used only for AIX 41 */
485 #if !defined(AFS_USERSPACE_IP_ADDR)
486 count = rx_getAllAddr_internal(addrBuffer, 1024, 0);
487 for (i = 0; i < count; i++) {
488 maskBuffer[i] = htonl(0xffffffff);
489 mtuBuffer[i] = htonl(1500);
492 #else /* AFS_USERSPACE_IP_ADDR */
493 s = socket(AF_INET, SOCK_DGRAM, 0);
497 ifc.ifc_len = sizeof(ifs);
498 ifc.ifc_buf = (caddr_t) ifs;
499 i = ioctl(s, SIOCGIFCONF, &ifc);
504 len = ifc.ifc_len / sizeof(struct ifreq);
508 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
509 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
510 ifc.ifc_len = sizeof(ifs);
511 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
513 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
514 ifr = (struct ifreq *)cp;
516 for (i = 0; i < len; ++i) {
519 a = (struct sockaddr_in *)&ifr->ifr_addr;
520 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
522 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
523 perror("SIOCGIFFLAGS");
524 continue; /* ignore this address */
527 if (rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr)))
528 continue; /* skip loopback address as well. */
530 if (count >= maxSize) { /* no more space */
531 dpf(("Too many interfaces..ignoring 0x%x\n",
532 a->sin_addr.s_addr));
536 addrBuffer[count] = a->sin_addr.s_addr;
538 if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
539 perror("SIOCGIFNETMASK");
540 maskBuffer[count] = htonl(0xffffffff);
542 maskBuffer[count] = (((struct sockaddr_in *)
543 (&ifr->ifr_addr))->sin_addr).s_addr;
546 mtuBuffer[count] = htonl(1500);
548 if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
549 perror("SIOCGIFMTU");
551 mtuBuffer[count] = htonl(ifr->ifr_metric);
553 #endif /* SIOCGIFMTU */
555 if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
556 perror("SIOCRIPMTU");
558 mtuBuffer[count] = htonl(ifr->ifr_metric);
560 #endif /* SIOCRIPMTU */
567 #endif /* AFS_USERSPACE_IP_ADDR */
571 #endif /* ! AFS_NT40_ENV */
572 #endif /* !KERNEL || UKERNEL */