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 #include <sys/types.h>
19 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <sys/ioctl.h>
25 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
26 #include <sys/sysctl.h>
27 #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.
35 #include "rx_internal.h"
37 #include "rx_globals.h"
38 #endif /* AFS_NT40_ENV */
41 #include "rx/rx_kcommon.h"
43 #include "rx/rx_internal.h"
50 #if defined(AFS_USR_DFBSD_ENV)
52 #include <sys/sockio.h>
56 /* only used for generating random noise */
58 afs_uint32 rxi_tempAddr = 0; /* default attempt */
60 /* set the advisory noise */
62 rxi_setaddr(afs_uint32 x)
67 /* get approx to net addr */
78 /* to satisfy those who call setaddr */
80 rxi_setaddr(afs_uint32 x)
87 #if !defined(AFS_NT40_ENV)
88 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
89 * rx_Init which sets up the list of addresses for us.
94 /* Return our internet address as a long in network byte order. Returns zero
95 * if it can't find one.
100 afs_uint32 buffer[1024];
103 count = rx_getAllAddr(buffer, 1024);
105 return buffer[0]; /* returns the first address */
112 #if !defined(KERNEL) || defined(UKERNEL)
115 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
123 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
125 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
126 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
129 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
134 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
135 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
136 if ((rtinfo->rti_addrs & (1 << i)) == 0)
138 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
145 /* this function returns the total number of interface addresses
146 ** the buffer has to be passed in by the caller
148 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
150 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
154 struct if_msghdr *ifm, *nextifm;
155 struct ifa_msghdr *ifam;
156 struct sockaddr_dl *sdl;
157 struct rt_addrinfo info;
158 char *buf, *lim, *next;
159 int count = 0, addrcount = 0;
164 mib[3] = AF_INET; /* address family */
165 mib[4] = NET_RT_IFLIST;
167 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
169 if ((buf = malloc(needed)) == NULL)
171 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
178 ifm = (struct if_msghdr *)next;
179 if (ifm->ifm_type != RTM_IFINFO) {
180 dpf(("out of sync parsing NET_RT_IFLIST\n"));
184 sdl = (struct sockaddr_dl *)(ifm + 1);
185 next += ifm->ifm_msglen;
189 nextifm = (struct if_msghdr *)next;
190 if (nextifm->ifm_type != RTM_NEWADDR)
193 ifam = (struct ifa_msghdr *)nextifm;
195 next += nextifm->ifm_msglen;
197 if ((ifm->ifm_flags & IFF_UP) == 0)
198 continue; /* not up */
199 while (addrcount > 0) {
200 struct sockaddr_in *a;
202 info.rti_addrs = ifam->ifam_addrs;
204 /* Expand the compacted addresses */
205 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
207 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
211 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
213 if (count >= maxSize) /* no more space */
214 dpf(("Too many interfaces..ignoring 0x%x\n",
215 a->sin_addr.s_addr));
216 else if (!loopbacks && a->sin_addr.s_addr == htonl(0x7f000001)) {
218 continue; /* skip loopback address as well. */
219 } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) {
221 continue; /* skip aliased loopbacks as well. */
223 buffer[count++] = a->sin_addr.s_addr;
225 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
233 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
234 afs_uint32 mtuBuffer[], int maxSize)
240 struct if_msghdr *ifm, *nextifm;
241 struct ifa_msghdr *ifam;
242 struct sockaddr_dl *sdl;
243 struct rt_addrinfo info;
244 char *buf, *lim, *next;
245 int count = 0, addrcount = 0;
250 mib[3] = AF_INET; /* address family */
251 mib[4] = NET_RT_IFLIST;
253 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
255 if ((buf = malloc(needed)) == NULL)
257 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
261 s = socket(PF_INET, SOCK_DGRAM, 0);
267 ifm = (struct if_msghdr *)next;
268 if (ifm->ifm_type != RTM_IFINFO) {
269 dpf(("out of sync parsing NET_RT_IFLIST\n"));
273 sdl = (struct sockaddr_dl *)(ifm + 1);
274 next += ifm->ifm_msglen;
278 nextifm = (struct if_msghdr *)next;
279 if (nextifm->ifm_type != RTM_NEWADDR)
282 ifam = (struct ifa_msghdr *)nextifm;
284 next += nextifm->ifm_msglen;
286 if ((ifm->ifm_flags & IFF_UP) == 0)
287 continue; /* not up */
288 while (addrcount > 0) {
289 struct sockaddr_in *a;
291 info.rti_addrs = ifam->ifam_addrs;
293 /* Expand the compacted addresses */
294 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
296 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
300 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
302 if (a->sin_addr.s_addr != htonl(0x7f000001) ) {
303 if (count >= maxSize) { /* no more space */
304 dpf(("Too many interfaces..ignoring 0x%x\n",
305 a->sin_addr.s_addr));
309 addrBuffer[count] = a->sin_addr.s_addr;
310 a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK];
312 maskBuffer[count] = a->sin_addr.s_addr;
314 maskBuffer[count] = htonl(0xffffffff);
315 memset(&ifr, 0, sizeof(ifr));
316 ifr.ifr_addr.sa_family = AF_INET;
317 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
318 if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
319 mtuBuffer[count] = htonl(1500);
321 mtuBuffer[count] = htonl(ifr.ifr_mtu);
326 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
335 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
337 return rx_getAllAddr_internal(buffer, maxSize, 0);
339 /* this function returns the total number of interface addresses
340 ** the buffer has to be passed in by the caller
342 #else /* UKERNEL indirectly, on DARWIN or XBSD */
344 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
347 int i, len, count = 0;
349 struct ifreq ifs[NIFS], *ifr;
350 struct sockaddr_in *a;
351 /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */
352 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
353 char *cp, *cplim, *cpnext; /* used only for AIX 41 */
356 s = socket(AF_INET, SOCK_DGRAM, 0);
359 ifc.ifc_len = sizeof(ifs);
360 ifc.ifc_buf = (caddr_t) ifs;
361 i = ioctl(s, SIOCGIFCONF, &ifc);
364 len = ifc.ifc_len / sizeof(struct ifreq);
367 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
368 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
369 ifc.ifc_len = sizeof(ifs);
370 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
372 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
373 cp += _SIZEOF_ADDR_IFREQ(*ifr)
378 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))
383 for (i = 0; i < len; ++i)
386 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
387 ifr = (struct ifreq *)cp;
391 a = (struct sockaddr_in *)&ifr->ifr_addr;
393 cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
395 if (a->sin_family != AF_INET)
397 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
398 perror("SIOCGIFFLAGS");
399 continue; /* ignore this address */
401 if (a->sin_addr.s_addr != 0) {
403 if (a->sin_addr.s_addr == htonl(0x7f000001))
404 continue; /* skip loopback address as well. */
406 if (ifr->ifr_flags & IFF_LOOPBACK)
407 continue; /* skip aliased loopbacks as well. */
409 if (count >= maxSize) /* no more space */
410 dpf(("Too many interfaces..ignoring 0x%x\n",
411 a->sin_addr.s_addr));
413 buffer[count++] = a->sin_addr.s_addr;
421 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
423 return rx_getAllAddr_internal(buffer, maxSize, 0);
426 /* this function returns the total number of interface addresses
427 * the buffer has to be passed in by the caller. It also returns
428 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
429 * gets the mask which is then passed into the kernel and is used
430 * by afsi_SetServerIPRank().
433 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
434 afs_uint32 mtuBuffer[], int maxSize)
437 int i, len, count = 0;
439 struct ifreq ifs[NIFS], *ifr;
440 struct sockaddr_in *a;
441 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
442 char *cp, *cplim; /* used only for AIX 41 */
445 #if !defined(AFS_USERSPACE_IP_ADDR)
446 count = rx_getAllAddr_internal(addrBuffer, 1024, 0);
447 for (i = 0; i < count; i++) {
448 maskBuffer[i] = htonl(0xffffffff);
449 mtuBuffer[i] = htonl(1500);
452 #else /* AFS_USERSPACE_IP_ADDR */
453 s = socket(AF_INET, SOCK_DGRAM, 0);
457 ifc.ifc_len = sizeof(ifs);
458 ifc.ifc_buf = (caddr_t) ifs;
459 i = ioctl(s, SIOCGIFCONF, &ifc);
464 len = ifc.ifc_len / sizeof(struct ifreq);
468 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
469 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
470 ifc.ifc_len = sizeof(ifs);
471 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
473 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
474 ifr = (struct ifreq *)cp;
476 for (i = 0; i < len; ++i) {
479 a = (struct sockaddr_in *)&ifr->ifr_addr;
480 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
482 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
483 perror("SIOCGIFFLAGS");
484 continue; /* ignore this address */
487 if (a->sin_addr.s_addr == htonl(0x7f000001) )
488 continue; /* skip loopback address as well. */
490 if (count >= maxSize) { /* no more space */
491 dpf(("Too many interfaces..ignoring 0x%x\n",
492 a->sin_addr.s_addr));
496 addrBuffer[count] = a->sin_addr.s_addr;
498 if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
499 perror("SIOCGIFNETMASK");
500 maskBuffer[count] = htonl(0xffffffff);
502 maskBuffer[count] = (((struct sockaddr_in *)
503 (&ifr->ifr_addr))->sin_addr).s_addr;
506 mtuBuffer[count] = htonl(1500);
508 if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
509 perror("SIOCGIFMTU");
511 mtuBuffer[count] = htonl(ifr->ifr_metric);
513 #endif /* SIOCGIFMTU */
515 if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
516 perror("SIOCRIPMTU");
518 mtuBuffer[count] = htonl(ifr->ifr_metric);
520 #endif /* SIOCRIPMTU */
527 #endif /* AFS_USERSPACE_IP_ADDR */
531 #endif /* ! AFS_NT40_ENV */
532 #endif /* !KERNEL || UKERNEL */