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>
16 #include <sys/types.h>
17 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <sys/ioctl.h>
23 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
24 #include <sys/sysctl.h>
25 #ifndef AFS_ARM_DARWIN_ENV
26 #include <net/route.h>
28 #include <net/if_dl.h>
32 * By including this, we get any system dependencies. In particular,
33 * the pthreads for solaris requires the socket call to be mapped.
36 #include "rx_globals.h"
37 #endif /* AFS_NT40_ENV */
40 #include "rx/rx_kcommon.h"
48 #if defined(AFS_USR_DFBSD_ENV)
50 #include <sys/sockio.h>
54 /* only used for generating random noise */
56 afs_uint32 rxi_tempAddr = 0; /* default attempt */
58 /* set the advisory noise */
60 rxi_setaddr(afs_uint32 x)
65 /* get approx to net addr */
76 /* to satisfy those who call setaddr */
78 rxi_setaddr(afs_uint32 x)
85 #if !defined(AFS_NT40_ENV)
86 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
87 * rx_Init which sets up the list of addresses for us.
92 /* Return our internet address as a long in network byte order. Returns zero
93 * if it can't find one.
98 afs_uint32 buffer[1024];
101 count = rx_getAllAddr(buffer, 1024);
103 return buffer[0]; /* returns the first address */
110 #if !defined(KERNEL) || defined(UKERNEL)
113 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
121 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
123 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
124 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
127 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
132 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
133 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
134 if ((rtinfo->rti_addrs & (1 << i)) == 0)
136 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
143 rxi_IsLoopbackIface(struct sockaddr_in *a, unsigned long flags)
145 afs_uint32 addr = ntohl(a->sin_addr.s_addr);
146 if (rx_IsLoopbackAddr(addr)) {
149 if ((flags & IFF_LOOPBACK) && ((addr & 0xff000000) == 0x7f000000)) {
155 /* this function returns the total number of interface addresses
156 ** the buffer has to be passed in by the caller
158 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
159 #if defined(AFS_OBSD42_ENV)
161 ifm_fixversion(char *buffer, size_t *size) {
162 struct if_msghdr *ifm;
166 if ((t = malloc(*size)) != NULL) {
167 memcpy(t, buffer, *size);
169 for (s = t; s < t + *size; s += ifm->ifm_msglen) {
170 ifm = (struct if_msghdr *)s;
172 if (ifm->ifm_version == RTM_VERSION) {
173 memcpy(b, ifm, ifm->ifm_msglen);
174 b += ifm->ifm_msglen;
186 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
190 struct if_msghdr *ifm, *nextifm;
191 struct ifa_msghdr *ifam;
192 struct sockaddr_dl *sdl;
193 struct rt_addrinfo info;
194 char *buf, *lim, *next;
195 int count = 0, addrcount = 0;
200 mib[3] = AF_INET; /* address family */
201 mib[4] = NET_RT_IFLIST;
203 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
205 if ((buf = malloc(needed)) == NULL)
207 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
211 #if defined(AFS_OBSD42_ENV)
212 ifm_fixversion(buf, &needed);
217 ifm = (struct if_msghdr *)next;
218 if (ifm->ifm_type != RTM_IFINFO) {
219 dpf(("out of sync parsing NET_RT_IFLIST\n"));
223 sdl = (struct sockaddr_dl *)(ifm + 1);
224 next += ifm->ifm_msglen;
228 nextifm = (struct if_msghdr *)next;
229 if (nextifm->ifm_type != RTM_NEWADDR)
232 ifam = (struct ifa_msghdr *)nextifm;
234 next += nextifm->ifm_msglen;
236 if ((ifm->ifm_flags & IFF_UP) == 0)
237 continue; /* not up */
238 while (addrcount > 0) {
239 struct sockaddr_in *a;
241 info.rti_addrs = ifam->ifam_addrs;
243 /* Expand the compacted addresses */
244 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
246 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
250 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
252 if (count >= maxSize) /* no more space */
253 dpf(("Too many interfaces..ignoring 0x%x\n",
254 a->sin_addr.s_addr));
255 else if (!loopbacks && rxi_IsLoopbackIface(a, ifm->ifm_flags)) {
257 continue; /* skip loopback address as well. */
258 } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) {
260 continue; /* skip aliased loopbacks as well. */
262 buffer[count++] = a->sin_addr.s_addr;
264 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
272 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
273 afs_uint32 mtuBuffer[], int maxSize)
279 struct if_msghdr *ifm, *nextifm;
280 struct ifa_msghdr *ifam;
281 struct sockaddr_dl *sdl;
282 struct rt_addrinfo info;
283 char *buf, *lim, *next;
284 int count = 0, addrcount = 0;
289 mib[3] = AF_INET; /* address family */
290 mib[4] = NET_RT_IFLIST;
292 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
294 if ((buf = malloc(needed)) == NULL)
296 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
300 #if defined(AFS_OBSD42_ENV)
301 ifm_fixversion(buf, &needed);
303 s = socket(PF_INET, SOCK_DGRAM, 0);
309 ifm = (struct if_msghdr *)next;
310 if (ifm->ifm_type != RTM_IFINFO) {
311 dpf(("out of sync parsing NET_RT_IFLIST\n"));
315 sdl = (struct sockaddr_dl *)(ifm + 1);
316 next += ifm->ifm_msglen;
320 nextifm = (struct if_msghdr *)next;
321 if (nextifm->ifm_type != RTM_NEWADDR)
324 ifam = (struct ifa_msghdr *)nextifm;
326 next += nextifm->ifm_msglen;
328 if ((ifm->ifm_flags & IFF_UP) == 0)
329 continue; /* not up */
330 while (addrcount > 0) {
331 struct sockaddr_in *a;
333 info.rti_addrs = ifam->ifam_addrs;
335 /* Expand the compacted addresses */
336 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
338 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
342 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
344 if (!rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr))) {
345 if (count >= maxSize) { /* no more space */
346 dpf(("Too many interfaces..ignoring 0x%x\n",
347 a->sin_addr.s_addr));
351 addrBuffer[count] = a->sin_addr.s_addr;
352 a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK];
354 maskBuffer[count] = a->sin_addr.s_addr;
356 maskBuffer[count] = htonl(0xffffffff);
357 memset(&ifr, 0, sizeof(ifr));
358 ifr.ifr_addr.sa_family = AF_INET;
359 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
360 if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
361 mtuBuffer[count] = htonl(1500);
363 mtuBuffer[count] = htonl(ifr.ifr_mtu);
368 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
377 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
379 return rx_getAllAddr_internal(buffer, maxSize, 0);
381 /* this function returns the total number of interface addresses
382 ** the buffer has to be passed in by the caller
384 #else /* UKERNEL indirectly, on DARWIN or XBSD */
386 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
389 int i, len, count = 0;
391 struct ifreq ifs[NIFS], *ifr;
392 struct sockaddr_in *a;
393 /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */
394 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
395 char *cp, *cplim, *cpnext; /* used only for AIX 41 */
398 s = socket(AF_INET, SOCK_DGRAM, 0);
401 ifc.ifc_len = sizeof(ifs);
402 ifc.ifc_buf = (caddr_t) ifs;
403 i = ioctl(s, SIOCGIFCONF, &ifc);
406 len = ifc.ifc_len / sizeof(struct ifreq);
409 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
410 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
411 ifc.ifc_len = sizeof(ifs);
412 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
414 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
415 cp += _SIZEOF_ADDR_IFREQ(*ifr)
420 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))
425 for (i = 0; i < len; ++i)
428 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
429 ifr = (struct ifreq *)cp;
433 a = (struct sockaddr_in *)&ifr->ifr_addr;
435 cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
437 if (a->sin_family != AF_INET)
439 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
440 perror("SIOCGIFFLAGS");
441 continue; /* ignore this address */
443 if (a->sin_addr.s_addr != 0) {
445 if (rxi_IsLoopbackIface(a, ifr->ifr_flags))
446 continue; /* skip loopback address as well. */
448 if (ifr->ifr_flags & IFF_LOOPBACK)
449 continue; /* skip aliased loopbacks as well. */
451 if (count >= maxSize) /* no more space */
452 dpf(("Too many interfaces..ignoring 0x%x\n",
453 a->sin_addr.s_addr));
455 buffer[count++] = a->sin_addr.s_addr;
463 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
465 return rx_getAllAddr_internal(buffer, maxSize, 0);
468 /* this function returns the total number of interface addresses
469 * the buffer has to be passed in by the caller. It also returns
470 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
471 * gets the mask which is then passed into the kernel and is used
472 * by afsi_SetServerIPRank().
475 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
476 afs_uint32 mtuBuffer[], int maxSize)
479 #if defined(AFS_USERSPACE_IP_ADDR)
482 struct ifreq ifs[NIFS], *ifr;
483 struct sockaddr_in *a;
486 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
487 char *cp, *cplim; /* used only for AIX 41 */
490 #if !defined(AFS_USERSPACE_IP_ADDR)
491 count = rx_getAllAddr_internal(addrBuffer, 1024, 0);
492 for (i = 0; i < count; i++) {
493 maskBuffer[i] = htonl(0xffffffff);
494 mtuBuffer[i] = htonl(1500);
497 #else /* AFS_USERSPACE_IP_ADDR */
498 s = socket(AF_INET, SOCK_DGRAM, 0);
502 ifc.ifc_len = sizeof(ifs);
503 ifc.ifc_buf = (caddr_t) ifs;
504 i = ioctl(s, SIOCGIFCONF, &ifc);
509 len = ifc.ifc_len / sizeof(struct ifreq);
513 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
514 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
515 ifc.ifc_len = sizeof(ifs);
516 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
518 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
519 ifr = (struct ifreq *)cp;
521 for (i = 0; i < len; ++i) {
524 a = (struct sockaddr_in *)&ifr->ifr_addr;
525 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
527 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
528 perror("SIOCGIFFLAGS");
529 continue; /* ignore this address */
532 if (rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr)))
533 continue; /* skip loopback address as well. */
535 if (count >= maxSize) { /* no more space */
536 dpf(("Too many interfaces..ignoring 0x%x\n",
537 a->sin_addr.s_addr));
541 addrBuffer[count] = a->sin_addr.s_addr;
543 if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
544 perror("SIOCGIFNETMASK");
545 maskBuffer[count] = htonl(0xffffffff);
547 maskBuffer[count] = (((struct sockaddr_in *)
548 (&ifr->ifr_addr))->sin_addr).s_addr;
551 mtuBuffer[count] = htonl(1500);
553 if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
554 perror("SIOCGIFMTU");
556 mtuBuffer[count] = htonl(ifr->ifr_metric);
558 #endif /* SIOCGIFMTU */
560 if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
561 perror("SIOCRIPMTU");
563 mtuBuffer[count] = htonl(ifr->ifr_metric);
565 #endif /* SIOCRIPMTU */
572 #endif /* AFS_USERSPACE_IP_ADDR */
576 #endif /* ! AFS_NT40_ENV */
577 #endif /* !KERNEL || UKERNEL */