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>
24 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
25 #include <sys/sysctl.h>
26 #include <net/route.h>
27 #include <net/if_dl.h>
31 * By including this, we get any system dependencies. In particular,
32 * the pthreads for solaris requires the socket call to be mapped.
35 #include "rx_globals.h"
36 #endif /* AFS_NT40_ENV */
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(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
126 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
127 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
128 if ((rtinfo->rti_addrs & (1 << i)) == 0)
130 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
137 /* this function returns the total number of interface addresses
138 ** the buffer has to be passed in by the caller
140 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
142 rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
146 struct if_msghdr *ifm, *nextifm;
147 struct ifa_msghdr *ifam;
148 struct sockaddr_dl *sdl;
149 struct rt_addrinfo info;
150 char *buf, *lim, *next;
151 int count = 0, addrcount = 0;
156 mib[3] = AF_INET; /* address family */
157 mib[4] = NET_RT_IFLIST;
159 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
161 if ((buf = malloc(needed)) == NULL)
163 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
170 ifm = (struct if_msghdr *)next;
171 if (ifm->ifm_type != RTM_IFINFO) {
172 dpf(("out of sync parsing NET_RT_IFLIST\n"));
176 sdl = (struct sockaddr_dl *)(ifm + 1);
177 next += ifm->ifm_msglen;
181 nextifm = (struct if_msghdr *)next;
182 if (nextifm->ifm_type != RTM_NEWADDR)
185 ifam = (struct ifa_msghdr *)nextifm;
187 next += nextifm->ifm_msglen;
189 if ((ifm->ifm_flags & IFF_UP) == 0)
190 continue; /* not up */
191 while (addrcount > 0) {
192 struct sockaddr_in *a;
194 info.rti_addrs = ifam->ifam_addrs;
196 /* Expand the compacted addresses */
197 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
199 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
203 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
205 if (count >= maxSize) /* no more space */
206 dpf(("Too many interfaces..ignoring 0x%x\n",
207 a->sin_addr.s_addr));
208 else if (!loopbacks && a->sin_addr.s_addr == htonl(0x7f000001)) {
210 continue; /* skip loopback address as well. */
211 } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) {
213 continue; /* skip aliased loopbacks as well. */
215 buffer[count++] = a->sin_addr.s_addr;
217 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
225 rxi_getAllAddrMaskMtu(afs_int32 addrBuffer[], afs_int32 maskBuffer[],
226 afs_int32 mtuBuffer[], int maxSize)
232 struct if_msghdr *ifm, *nextifm;
233 struct ifa_msghdr *ifam;
234 struct sockaddr_dl *sdl;
235 struct rt_addrinfo info;
236 char *buf, *lim, *next;
237 int count = 0, addrcount = 0, i;
242 mib[3] = AF_INET; /* address family */
243 mib[4] = NET_RT_IFLIST;
245 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
247 if ((buf = malloc(needed)) == NULL)
249 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
253 s = socket(PF_INET, SOCK_DGRAM, 0);
259 ifm = (struct if_msghdr *)next;
260 if (ifm->ifm_type != RTM_IFINFO) {
261 dpf(("out of sync parsing NET_RT_IFLIST\n"));
265 sdl = (struct sockaddr_dl *)(ifm + 1);
266 next += ifm->ifm_msglen;
270 nextifm = (struct if_msghdr *)next;
271 if (nextifm->ifm_type != RTM_NEWADDR)
274 ifam = (struct ifa_msghdr *)nextifm;
276 next += nextifm->ifm_msglen;
278 if ((ifm->ifm_flags & IFF_UP) == 0)
279 continue; /* not up */
280 while (addrcount > 0) {
281 struct sockaddr_in *a;
283 info.rti_addrs = ifam->ifam_addrs;
285 /* Expand the compacted addresses */
286 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
288 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
292 a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
294 if (a->sin_addr.s_addr != htonl(0x7f000001) ) {
295 if (count >= maxSize) { /* no more space */
296 dpf(("Too many interfaces..ignoring 0x%x\n",
297 a->sin_addr.s_addr));
301 addrBuffer[count] = a->sin_addr.s_addr;
302 a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK];
304 maskBuffer[count] = a->sin_addr.s_addr;
306 maskBuffer[count] = htonl(0xffffffff);
307 memset(&ifr, 0, sizeof(ifr));
308 ifr.ifr_addr.sa_family = AF_INET;
309 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
310 if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
311 mtuBuffer[count] = htonl(1500);
313 mtuBuffer[count] = htonl(ifr.ifr_mtu);
318 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
327 rx_getAllAddr(afs_int32 buffer[], int maxSize)
329 return rx_getAllAddr_internal(buffer, maxSize, 0);
331 /* this function returns the total number of interface addresses
332 ** the buffer has to be passed in by the caller
336 rx_getAllAddr_internal(afs_int32 buffer[], int maxSize, int loopbacks)
339 int i, len, count = 0;
341 struct ifreq ifs[NIFS], *ifr;
342 struct sockaddr_in *a;
343 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
344 char *cp, *cplim, *cpnext; /* used only for AIX 41 */
347 s = socket(AF_INET, SOCK_DGRAM, 0);
350 ifc.ifc_len = sizeof(ifs);
351 ifc.ifc_buf = (caddr_t) ifs;
352 i = ioctl(s, SIOCGIFCONF, &ifc);
355 len = ifc.ifc_len / sizeof(struct ifreq);
358 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
359 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
360 ifc.ifc_len = sizeof(ifs);
361 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
363 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
364 cp += _SIZEOF_ADDR_IFREQ(*ifr)
369 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))
374 for (i = 0; i < len; ++i)
377 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
378 ifr = (struct ifreq *)cp;
382 a = (struct sockaddr_in *)&ifr->ifr_addr;
384 cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
386 if (a->sin_family != AF_INET)
388 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
389 perror("SIOCGIFFLAGS");
390 continue; /* ignore this address */
392 if (a->sin_addr.s_addr != 0) {
394 if (a->sin_addr.s_addr == htonl(0x7f000001))
395 continue; /* skip loopback address as well. */
397 if (ifr->ifr_flags & IFF_LOOPBACK)
398 continue; /* skip aliased loopbacks as well. */
400 if (count >= maxSize) /* no more space */
401 dpf(("Too many interfaces..ignoring 0x%x\n",
402 a->sin_addr.s_addr));
404 buffer[count++] = a->sin_addr.s_addr;
412 rx_getAllAddr(afs_int32 buffer[], int maxSize)
414 return rx_getAllAddr_internal(buffer, maxSize, 0);
417 /* this function returns the total number of interface addresses
418 * the buffer has to be passed in by the caller. It also returns
419 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
420 * gets the mask which is then passed into the kernel and is used
421 * by afsi_SetServerIPRank().
424 rxi_getAllAddrMaskMtu(afs_int32 addrBuffer[], afs_int32 maskBuffer[],
425 afs_int32 mtuBuffer[], int maxSize)
428 int i, len, count = 0;
430 struct ifreq ifs[NIFS], *ifr;
431 struct sockaddr_in *a;
432 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
433 char *cp, *cplim; /* used only for AIX 41 */
436 #if !defined(AFS_USERSPACE_IP_ADDR)
437 count = rx_getAllAddr_internal(addrBuffer, 1024, 0);
438 for (i = 0; i < count; i++) {
439 maskBuffer[i] = htonl(0xffffffff);
440 mtuBuffer[i] = htonl(1500);
443 #else /* AFS_USERSPACE_IP_ADDR */
444 s = socket(AF_INET, SOCK_DGRAM, 0);
448 ifc.ifc_len = sizeof(ifs);
449 ifc.ifc_buf = (caddr_t) ifs;
450 i = ioctl(s, SIOCGIFCONF, &ifc);
455 len = ifc.ifc_len / sizeof(struct ifreq);
459 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
460 if (ifc.ifc_len > sizeof(ifs)) /* safety check */
461 ifc.ifc_len = sizeof(ifs);
462 for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
464 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
465 ifr = (struct ifreq *)cp;
467 for (i = 0; i < len; ++i) {
470 a = (struct sockaddr_in *)&ifr->ifr_addr;
471 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
473 if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
474 perror("SIOCGIFFLAGS");
475 continue; /* ignore this address */
478 if (a->sin_addr.s_addr == htonl(0x7f000001) )
479 continue; /* skip loopback address as well. */
481 if (count >= maxSize) { /* no more space */
482 dpf(("Too many interfaces..ignoring 0x%x\n",
483 a->sin_addr.s_addr));
487 addrBuffer[count] = a->sin_addr.s_addr;
489 if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
490 perror("SIOCGIFNETMASK");
491 maskBuffer[count] = htonl(0xffffffff);
493 maskBuffer[count] = (((struct sockaddr_in *)
494 (&ifr->ifr_addr))->sin_addr).s_addr;
497 mtuBuffer[count] = htonl(1500);
499 if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
500 perror("SIOCGIFMTU");
502 mtuBuffer[count] = htonl(ifr->ifr_metric);
504 #endif /* SIOCGIFMTU */
506 if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
507 perror("SIOCRIPMTU");
509 mtuBuffer[count] = htonl(ifr->ifr_metric);
511 #endif /* SIOCRIPMTU */
518 #endif /* AFS_USERSPACE_IP_ADDR */
522 #endif /* ! AFS_NT40_ENV */
523 #endif /* !KERNEL || UKERNEL */