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.
38 #include "../rx/rx_kcommon.h"
47 /* only used for generating random noise */
49 afs_int32 rxi_tempAddr=0; /* default attempt */
51 /* set the advisory noise */
52 void rxi_setaddr(afs_int32 x)
57 /* get approx to net addr */
58 afs_int32 rxi_getaddr(void)
67 /* to satisfy those who call setaddr */
68 void rxi_setaddr(afs_int32 x)
75 #if !defined(AFS_NT40_ENV)
76 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
77 * rx_Init which sets up the list of addresses for us.
82 /* Return our internet address as a long in network byte order. Returns zero
83 * if it can't find one.
85 afs_int32 rxi_getaddr(void)
87 afs_int32 buffer[1024];
90 count = rx_getAllAddr(buffer, 1024);
92 return buffer[0]; /* returns the first address */
99 #if !defined(KERNEL) || defined(UKERNEL)
102 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
110 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
112 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
113 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
116 rt_xaddrs(cp, cplim, rtinfo)
118 struct rt_addrinfo *rtinfo;
123 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
124 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
125 if ((rtinfo->rti_addrs & (1 << i)) == 0)
127 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
134 /* this function returns the total number of interface addresses
135 ** the buffer has to be passed in by the caller
137 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
138 int rx_getAllAddr (buffer,maxSize)
140 int maxSize; /* sizeof of buffer in afs_int32 units */
144 struct if_msghdr *ifm, *nextifm;
145 struct ifa_msghdr *ifam;
146 struct sockaddr_dl *sdl;
147 struct rt_addrinfo info;
148 char *buf, *lim, *next;
149 int count=0,addrcount=0;
154 mib[3] = AF_INET; /* address family */
155 mib[4] = NET_RT_IFLIST;
157 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
159 if ((buf = malloc(needed)) == NULL)
161 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
168 ifm = (struct if_msghdr *)next;
169 if (ifm->ifm_type != RTM_IFINFO) {
170 printf("out of sync parsing NET_RT_IFLIST\n");
174 sdl = (struct sockaddr_dl *)(ifm + 1);
175 next += ifm->ifm_msglen;
179 nextifm = (struct if_msghdr *)next;
180 if (nextifm->ifm_type != RTM_NEWADDR)
183 ifam = (struct ifa_msghdr *)nextifm;
185 next += nextifm->ifm_msglen;
187 if ((ifm->ifm_flags & IFF_UP) == 0)
188 continue; /* not up */
189 if (ifm->ifm_flags & IFF_LOOPBACK) {
190 continue; /* skip aliased loopbacks as well. */
192 while (addrcount > 0) {
193 struct sockaddr_in *a;
195 info.rti_addrs = ifam->ifam_addrs;
197 /* Expand the compacted addresses */
198 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
200 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
202 a=info.rti_info[RTAX_IFA];
204 if ( count >= maxSize ) /* no more space */
205 printf("Too many interfaces..ignoring 0x%x\n",
208 buffer[count++] = a->sin_addr.s_addr;
210 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
216 int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize)
217 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
218 afs_int32 maskBuffer[]; /* the subnet masks */
219 afs_int32 mtuBuffer[]; /* the MTU sizes */
220 int maxSize; /* sizeof of buffer in afs_int32 units */
226 struct if_msghdr *ifm, *nextifm;
227 struct ifa_msghdr *ifam;
228 struct sockaddr_dl *sdl;
229 struct rt_addrinfo info;
230 char *buf, *lim, *next;
231 int count=0,addrcount=0;
236 mib[3] = AF_INET; /* address family */
237 mib[4] = NET_RT_IFLIST;
239 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
241 if ((buf = malloc(needed)) == NULL)
243 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
247 s=socket(PF_INET, SOCK_DGRAM, 0);
253 ifm = (struct if_msghdr *)next;
254 if (ifm->ifm_type != RTM_IFINFO) {
255 printf("out of sync parsing NET_RT_IFLIST\n");
259 sdl = (struct sockaddr_dl *)(ifm + 1);
260 next += ifm->ifm_msglen;
264 nextifm = (struct if_msghdr *)next;
265 if (nextifm->ifm_type != RTM_NEWADDR)
268 ifam = (struct ifa_msghdr *)nextifm;
270 next += nextifm->ifm_msglen;
272 if ((ifm->ifm_flags & IFF_UP) == 0)
273 continue; /* not up */
274 if (ifm->ifm_flags & IFF_LOOPBACK) {
275 continue; /* skip aliased loopbacks as well. */
277 while (addrcount > 0) {
278 struct sockaddr_in *a;
280 info.rti_addrs = ifam->ifam_addrs;
282 /* Expand the compacted addresses */
283 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
285 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
287 a=info.rti_info[RTAX_IFA];
289 if ( count >= maxSize ) { /* no more space */
290 printf("Too many interfaces..ignoring 0x%x\n",
295 addrBuffer[count] = a->sin_addr.s_addr;
296 a=info.rti_info[RTAX_NETMASK];
298 maskBuffer[count]=a->sin_addr.s_addr;
300 maskBuffer[count] = htonl(0xffffffff);
301 memset(&ifr, sizeof(ifr), 0);
302 ifr.ifr_addr.sa_family=AF_INET;
303 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
304 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
305 mtuBuffer[count]=htonl(1500);
307 mtuBuffer[count]=htonl(ifr.ifr_mtu);
311 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
320 int rx_getAllAddr (buffer,maxSize)
322 int maxSize; /* sizeof of buffer in afs_int32 units */
327 struct ifreq ifs[NIFS], *ifr;
328 struct sockaddr_in *a;
329 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
330 char *cp, *cplim; /* used only for AIX 41 */
333 s = socket(AF_INET, SOCK_DGRAM, 0);
336 ifc.ifc_len = sizeof(ifs);
337 ifc.ifc_buf = (caddr_t) ifs;
338 i = ioctl(s, SIOCGIFCONF, &ifc);
341 len = ifc.ifc_len / sizeof(struct ifreq);
344 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
345 if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */
346 ifc.ifc_len = sizeof(ifs);
347 for ( cp = (char *)ifc.ifc_buf,
348 cplim= ifc.ifc_buf+ifc.ifc_len;
350 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
351 cp += _SIZEOF_ADDR_IFREQ(*ifr))
353 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)))
356 ifr = (struct ifreq *)cp;
358 for (i = 0; i < len; ++i) {
361 a = (struct sockaddr_in *) &ifr->ifr_addr;
362 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
363 if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
364 perror("SIOCGIFFLAGS");
365 continue; /* ignore this address */
367 if (ifr->ifr_flags & IFF_LOOPBACK) {
368 continue; /* skip aliased loopbacks as well. */
370 if ( count >= maxSize ) /* no more space */
371 printf("Too many interfaces..ignoring 0x%x\n",
374 buffer[count++] = a->sin_addr.s_addr;
381 /* this function returns the total number of interface addresses
382 * the buffer has to be passed in by the caller. It also returns
383 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
384 * gets the mask which is then passed into the kernel and is used
385 * by afsi_SetServerIPRank().
387 int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize)
388 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
389 afs_int32 maskBuffer[]; /* the subnet masks */
390 afs_int32 mtuBuffer[]; /* the MTU sizes */
391 int maxSize; /* sizeof of buffer in afs_int32 units */
396 struct ifreq ifs[NIFS], *ifr;
397 struct sockaddr_in *a;
398 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
399 char *cp, *cplim; /* used only for AIX 41 */
402 #if !defined(AFS_USERSPACE_IP_ADDR)
403 count = rx_getAllAddr(addrBuffer, 1024);
404 for (i=0; i<count; i++) {
405 maskBuffer[i] = htonl(0xffffffff);
406 mtuBuffer[i] = htonl(1500);
409 #else /* AFS_USERSPACE_IP_ADDR */
410 s = socket(AF_INET, SOCK_DGRAM, 0);
413 ifc.ifc_len = sizeof(ifs);
414 ifc.ifc_buf = (caddr_t) ifs;
415 i = ioctl(s, SIOCGIFCONF, &ifc);
420 len = ifc.ifc_len / sizeof(struct ifreq);
421 if (len > NIFS) len = NIFS;
423 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
424 if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */
425 ifc.ifc_len = sizeof(ifs);
426 for ( cp = (char *)ifc.ifc_buf,
427 cplim= ifc.ifc_buf+ifc.ifc_len;
429 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
430 ifr = (struct ifreq *)cp;
432 for (i = 0; i < len; ++i) {
435 a = (struct sockaddr_in *) &ifr->ifr_addr;
436 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
438 if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
439 perror("SIOCGIFFLAGS");
440 continue; /* ignore this address */
442 if (ifr->ifr_flags & IFF_LOOPBACK) {
443 continue; /* skip aliased loopbacks as well. */
446 if ( count >= maxSize ) { /* no more space */
447 printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr);
451 addrBuffer[count] = a->sin_addr.s_addr;
453 if ( ioctl(s, SIOCGIFNETMASK, (caddr_t)ifr) < 0 ) {
454 perror("SIOCGIFNETMASK");
455 maskBuffer[count] = htonl(0xffffffff);
457 maskBuffer[count] = (((struct sockaddr_in *)
458 (&ifr->ifr_addr))->sin_addr).s_addr;
461 mtuBuffer[count] = htonl(1500);
463 if ( ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) {
464 perror("SIOCGIFMTU");
466 mtuBuffer[count] = htonl(ifr->ifr_metric);
468 #endif /* SIOCGIFMTU */
470 if ( ioctl(s, SIOCRIPMTU, (caddr_t)ifr) < 0) {
471 perror("SIOCRIPMTU");
473 mtuBuffer[count] = htonl(ifr->ifr_metric);
475 #endif /* SIOCRIPMTU */
482 #endif /* AFS_USERSPACE_IP_ADDR */
486 #endif /* ! AFS_NT40_ENV */
487 #endif /* !KERNEL || UKERNEL */
489 #endif /* !AFS_DJGPP_ENV */