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>
19 #include <sys/types.h>
20 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #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.
39 #include "rx/rx_kcommon.h"
48 /* only used for generating random noise */
50 afs_int32 rxi_tempAddr = 0; /* default attempt */
52 /* set the advisory noise */
54 rxi_setaddr(afs_int32 x)
59 /* get approx to net addr */
70 /* to satisfy those who call setaddr */
72 rxi_setaddr(afs_int32 x)
79 #if !defined(AFS_NT40_ENV)
80 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
81 * rx_Init which sets up the list of addresses for us.
86 /* Return our internet address as a long in network byte order. Returns zero
87 * if it can't find one.
92 afs_int32 buffer[1024];
95 count = rx_getAllAddr(buffer, 1024);
97 return buffer[0]; /* returns the first address */
104 #if !defined(KERNEL) || defined(UKERNEL)
107 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
115 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
117 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
118 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
121 rt_xaddrs(cp, cplim, rtinfo)
123 struct rt_addrinfo *rtinfo;
128 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
129 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
130 if ((rtinfo->rti_addrs & (1 << i)) == 0)
132 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
139 /* this function returns the total number of interface addresses
140 ** the buffer has to be passed in by the caller
142 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
144 rx_getAllAddr(buffer, maxSize)
146 int maxSize; /* sizeof of buffer in afs_int32 units */
150 struct if_msghdr *ifm, *nextifm;
151 struct ifa_msghdr *ifam;
152 struct sockaddr_dl *sdl;
153 struct rt_addrinfo info;
154 char *buf, *lim, *next;
155 int count = 0, addrcount = 0;
160 mib[3] = AF_INET; /* address family */
161 mib[4] = NET_RT_IFLIST;
163 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
165 if ((buf = malloc(needed)) == NULL)
167 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
174 ifm = (struct if_msghdr *)next;
175 if (ifm->ifm_type != RTM_IFINFO) {
176 printf("out of sync parsing NET_RT_IFLIST\n");
180 sdl = (struct sockaddr_dl *)(ifm + 1);
181 next += ifm->ifm_msglen;
185 nextifm = (struct if_msghdr *)next;
186 if (nextifm->ifm_type != RTM_NEWADDR)
189 ifam = (struct ifa_msghdr *)nextifm;
191 next += nextifm->ifm_msglen;
193 if ((ifm->ifm_flags & IFF_UP) == 0)
194 continue; /* not up */
195 if (ifm->ifm_flags & IFF_LOOPBACK) {
196 continue; /* skip aliased loopbacks as well. */
198 while (addrcount > 0) {
199 struct sockaddr_in *a;
201 info.rti_addrs = ifam->ifam_addrs;
203 /* Expand the compacted addresses */
204 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
206 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
208 a = info.rti_info[RTAX_IFA];
210 if (count >= maxSize) /* no more space */
211 printf("Too many interfaces..ignoring 0x%x\n",
214 buffer[count++] = a->sin_addr.s_addr;
216 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
224 rxi_getAllAddrMaskMtu(addrBuffer, maskBuffer, mtuBuffer, maxSize)
225 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
226 afs_int32 maskBuffer[]; /* the subnet masks */
227 afs_int32 mtuBuffer[]; /* the MTU sizes */
228 int maxSize; /* sizeof of buffer in afs_int32 units */
234 struct if_msghdr *ifm, *nextifm;
235 struct ifa_msghdr *ifam;
236 struct sockaddr_dl *sdl;
237 struct rt_addrinfo info;
238 char *buf, *lim, *next;
239 int count = 0, addrcount = 0;
244 mib[3] = AF_INET; /* address family */
245 mib[4] = NET_RT_IFLIST;
247 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
249 if ((buf = malloc(needed)) == NULL)
251 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
255 s = socket(PF_INET, SOCK_DGRAM, 0);
261 ifm = (struct if_msghdr *)next;
262 if (ifm->ifm_type != RTM_IFINFO) {
263 printf("out of sync parsing NET_RT_IFLIST\n");
267 sdl = (struct sockaddr_dl *)(ifm + 1);
268 next += ifm->ifm_msglen;
272 nextifm = (struct if_msghdr *)next;
273 if (nextifm->ifm_type != RTM_NEWADDR)
276 ifam = (struct ifa_msghdr *)nextifm;
278 next += nextifm->ifm_msglen;
280 if ((ifm->ifm_flags & IFF_UP) == 0)
281 continue; /* not up */
282 if (ifm->ifm_flags & IFF_LOOPBACK) {
283 continue; /* skip aliased loopbacks as well. */
285 while (addrcount > 0) {
286 struct sockaddr_in *a;
288 info.rti_addrs = ifam->ifam_addrs;
290 /* Expand the compacted addresses */
291 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
293 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
295 a = info.rti_info[RTAX_IFA];
297 if (count >= maxSize) { /* no more space */
298 printf("Too many interfaces..ignoring 0x%x\n",
303 addrBuffer[count] = a->sin_addr.s_addr;
304 a = info.rti_info[RTAX_NETMASK];
306 maskBuffer[count] = a->sin_addr.s_addr;
308 maskBuffer[count] = htonl(0xffffffff);
309 memset(&ifr, sizeof(ifr), 0);
310 ifr.ifr_addr.sa_family = AF_INET;
311 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
312 if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
313 mtuBuffer[count] = htonl(1500);
315 mtuBuffer[count] = htonl(ifr.ifr_mtu);
319 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
329 rx_getAllAddr(buffer, maxSize)
331 int maxSize; /* sizeof of buffer in afs_int32 units */
334 int i, len, count = 0;
336 struct ifreq ifs[NIFS], *ifr;
337 struct sockaddr_in *a;
338 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
339 char *cp, *cplim, *cpnext; /* used only for AIX 41 */
342 s = socket(AF_INET, SOCK_DGRAM, 0);
345 ifc.ifc_len = sizeof(ifs);
346 ifc.ifc_buf = (caddr_t) ifs;
347 i = ioctl(s, SIOCGIFCONF, &ifc);
350 len = ifc.ifc_len / sizeof(struct ifreq);
353 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
354 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
355 ifc.ifc_len = sizeof(ifs);
356 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
358 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
359 cp += _SIZEOF_ADDR_IFREQ(*ifr))
364 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)))
368 ifr = (struct ifreq *)cp;
370 for (i = 0; i < len; ++i) {
373 a = (struct sockaddr_in *)&ifr->ifr_addr;
375 cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
377 if (a->sin_family != AF_INET)
379 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
380 perror("SIOCGIFFLAGS");
381 continue; /* ignore this address */
383 if (a->sin_addr.s_addr != 0) {
384 if (ifr->ifr_flags & IFF_LOOPBACK) {
385 continue; /* skip aliased loopbacks as well. */
387 if (count >= maxSize) /* no more space */
388 printf("Too many interfaces..ignoring 0x%x\n",
391 buffer[count++] = a->sin_addr.s_addr;
398 /* this function returns the total number of interface addresses
399 * the buffer has to be passed in by the caller. It also returns
400 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
401 * gets the mask which is then passed into the kernel and is used
402 * by afsi_SetServerIPRank().
405 rxi_getAllAddrMaskMtu(addrBuffer, maskBuffer, mtuBuffer, maxSize)
406 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
407 afs_int32 maskBuffer[]; /* the subnet masks */
408 afs_int32 mtuBuffer[]; /* the MTU sizes */
409 int maxSize; /* sizeof of buffer in afs_int32 units */
412 int i, len, count = 0;
414 struct ifreq ifs[NIFS], *ifr;
415 struct sockaddr_in *a;
416 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
417 char *cp, *cplim; /* used only for AIX 41 */
420 #if !defined(AFS_USERSPACE_IP_ADDR)
421 count = rx_getAllAddr(addrBuffer, 1024);
422 for (i = 0; i < count; i++) {
423 maskBuffer[i] = htonl(0xffffffff);
424 mtuBuffer[i] = htonl(1500);
427 #else /* AFS_USERSPACE_IP_ADDR */
428 s = socket(AF_INET, SOCK_DGRAM, 0);
432 ifc.ifc_len = sizeof(ifs);
433 ifc.ifc_buf = (caddr_t) ifs;
434 i = ioctl(s, SIOCGIFCONF, &ifc);
439 len = ifc.ifc_len / sizeof(struct ifreq);
443 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
444 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
445 ifc.ifc_len = sizeof(ifs);
446 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
448 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
449 ifr = (struct ifreq *)cp;
451 for (i = 0; i < len; ++i) {
454 a = (struct sockaddr_in *)&ifr->ifr_addr;
455 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
457 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
458 perror("SIOCGIFFLAGS");
459 continue; /* ignore this address */
461 if (ifr->ifr_flags & IFF_LOOPBACK) {
462 continue; /* skip aliased loopbacks as well. */
465 if (count >= maxSize) { /* no more space */
466 printf("Too many interfaces..ignoring 0x%x\n",
471 addrBuffer[count] = a->sin_addr.s_addr;
473 if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
474 perror("SIOCGIFNETMASK");
475 maskBuffer[count] = htonl(0xffffffff);
477 maskBuffer[count] = (((struct sockaddr_in *)
478 (&ifr->ifr_addr))->sin_addr).s_addr;
481 mtuBuffer[count] = htonl(1500);
483 if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
484 perror("SIOCGIFMTU");
486 mtuBuffer[count] = htonl(ifr->ifr_metric);
488 #endif /* SIOCGIFMTU */
490 if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
491 perror("SIOCRIPMTU");
493 mtuBuffer[count] = htonl(ifr->ifr_metric);
495 #endif /* SIOCRIPMTU */
502 #endif /* AFS_USERSPACE_IP_ADDR */
506 #endif /* ! AFS_NT40_ENV */
507 #endif /* !KERNEL || UKERNEL */
509 #endif /* !AFS_DJGPP_ENV */