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
13 /* getaddr -- get our internet address. July, 1986 */
15 #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_FBSD_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"
41 /* nothing here required yet */
48 /* only used for generating random noise */
50 afs_int32 rxi_tempAddr=0; /* default attempt */
52 /* set the advisory noise */
53 afs_int32 rxi_setaddr(x)
58 /* get approx to net addr */
59 afs_int32 rxi_getaddr() {
67 /* to satisfy those who call setaddr */
76 #if !defined(AFS_NT40_ENV)
77 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
78 * rx_Init which sets up the list of addresses for us.
83 /* Return our internet address as a long in network byte order. Returns zero
84 * if it can't find one.
86 afs_int32 rxi_getaddr ()
88 afs_int32 buffer[1024];
91 count = rx_getAllAddr(buffer, 1024);
93 return buffer[0]; /* returns the first address */
100 #if !defined(KERNEL) || defined(UKERNEL)
103 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
111 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
113 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
114 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
117 rt_xaddrs(cp, cplim, rtinfo)
119 struct rt_addrinfo *rtinfo;
124 memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
125 for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
126 if ((rtinfo->rti_addrs & (1 << i)) == 0)
128 rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
135 /* this function returns the total number of interface addresses
136 ** the buffer has to be passed in by the caller
138 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
139 int rx_getAllAddr (buffer,maxSize)
141 int maxSize; /* sizeof of buffer in afs_int32 units */
145 struct if_msghdr *ifm, *nextifm;
146 struct ifa_msghdr *ifam;
147 struct sockaddr_dl *sdl;
148 struct rt_addrinfo info;
149 char *buf, *lim, *next;
150 int count=0,addrcount=0;
155 mib[3] = AF_INET; /* address family */
156 mib[4] = NET_RT_IFLIST;
158 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
160 if ((buf = malloc(needed)) == NULL)
162 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
169 ifm = (struct if_msghdr *)next;
170 if (ifm->ifm_type != RTM_IFINFO) {
171 printf("out of sync parsing NET_RT_IFLIST\n");
175 sdl = (struct sockaddr_dl *)(ifm + 1);
176 next += ifm->ifm_msglen;
180 nextifm = (struct if_msghdr *)next;
181 if (nextifm->ifm_type != RTM_NEWADDR)
184 ifam = (struct ifa_msghdr *)nextifm;
186 next += nextifm->ifm_msglen;
188 if ((ifm->ifm_flags & IFF_UP) == 0)
189 continue; /* not up */
190 if (ifm->ifm_flags & IFF_LOOPBACK) {
191 continue; /* skip aliased loopbacks as well. */
193 while (addrcount > 0) {
194 struct sockaddr_in *a;
196 info.rti_addrs = ifam->ifam_addrs;
198 /* Expand the compacted addresses */
199 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
201 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
203 a=info.rti_info[RTAX_IFA];
205 if ( count >= maxSize ) /* no more space */
206 printf("Too many interfaces..ignoring 0x%x\n",
209 buffer[count++] = a->sin_addr.s_addr;
211 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
217 int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize)
218 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
219 afs_int32 maskBuffer[]; /* the subnet masks */
220 afs_int32 mtuBuffer[]; /* the MTU sizes */
221 int maxSize; /* sizeof of buffer in afs_int32 units */
227 struct if_msghdr *ifm, *nextifm;
228 struct ifa_msghdr *ifam;
229 struct sockaddr_dl *sdl;
230 struct rt_addrinfo info;
231 char *buf, *lim, *next;
232 int count=0,addrcount=0;
237 mib[3] = AF_INET; /* address family */
238 mib[4] = NET_RT_IFLIST;
240 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
242 if ((buf = malloc(needed)) == NULL)
244 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
248 s=socket(PF_INET, SOCK_DGRAM, 0);
254 ifm = (struct if_msghdr *)next;
255 if (ifm->ifm_type != RTM_IFINFO) {
256 printf("out of sync parsing NET_RT_IFLIST\n");
260 sdl = (struct sockaddr_dl *)(ifm + 1);
261 next += ifm->ifm_msglen;
265 nextifm = (struct if_msghdr *)next;
266 if (nextifm->ifm_type != RTM_NEWADDR)
269 ifam = (struct ifa_msghdr *)nextifm;
271 next += nextifm->ifm_msglen;
273 if ((ifm->ifm_flags & IFF_UP) == 0)
274 continue; /* not up */
275 if (ifm->ifm_flags & IFF_LOOPBACK) {
276 continue; /* skip aliased loopbacks as well. */
278 while (addrcount > 0) {
279 struct sockaddr_in *a;
281 info.rti_addrs = ifam->ifam_addrs;
283 /* Expand the compacted addresses */
284 rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
286 if (info.rti_info[RTAX_IFA]->sa_family != AF_INET)
288 a=info.rti_info[RTAX_IFA];
290 if ( count >= maxSize ) { /* no more space */
291 printf("Too many interfaces..ignoring 0x%x\n",
296 addrBuffer[count] = a->sin_addr.s_addr;
297 a=info.rti_info[RTAX_NETMASK];
299 maskBuffer[count]=a->sin_addr.s_addr;
301 maskBuffer[count] = htonl(0xffffffff);
302 memset(&ifr, sizeof(ifr), 0);
303 ifr.ifr_addr.sa_family=AF_INET;
304 strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
305 if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0)
306 mtuBuffer[count]=1500;
308 mtuBuffer[count]=ifr.ifr_mtu;
312 ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
321 int rx_getAllAddr (buffer,maxSize)
323 int maxSize; /* sizeof of buffer in afs_int32 units */
328 struct ifreq ifs[NIFS], *ifr;
329 struct sockaddr_in *a;
330 char *cp, *cplim; /* used only for AIX 41 */
332 s = socket(AF_INET, SOCK_DGRAM, 0);
335 ifc.ifc_len = sizeof(ifs);
336 ifc.ifc_buf = (caddr_t) ifs;
337 i = ioctl(s, SIOCGIFCONF, &ifc);
340 len = ifc.ifc_len / sizeof(struct ifreq);
343 #if defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
344 if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */
345 ifc.ifc_len = sizeof(ifs);
346 for ( cp = (char *)ifc.ifc_buf,
347 cplim= ifc.ifc_buf+ifc.ifc_len;
349 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
350 cp += _SIZEOF_ADDR_IFREQ(*ifr))
352 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a)))
355 ifr = (struct ifreq *)cp;
357 for (i = 0; i < len; ++i) {
360 a = (struct sockaddr_in *) &ifr->ifr_addr;
361 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
362 if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
363 perror("SIOCGIFFLAGS");
364 continue; /* ignore this address */
366 if (ifr->ifr_flags & IFF_LOOPBACK) {
367 continue; /* skip aliased loopbacks as well. */
369 if ( count >= maxSize ) /* no more space */
370 printf("Too many interfaces..ignoring 0x%x\n",
373 buffer[count++] = a->sin_addr.s_addr;
380 /* this function returns the total number of interface addresses
381 * the buffer has to be passed in by the caller. It also returns
382 * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
383 * gets the mask which is then passed into the kernel and is used
384 * by afsi_SetServerIPRank().
386 int rxi_getAllAddrMaskMtu (addrBuffer, maskBuffer, mtuBuffer, maxSize)
387 afs_int32 addrBuffer[]; /* the network addrs in net byte order */
388 afs_int32 maskBuffer[]; /* the subnet masks */
389 afs_int32 mtuBuffer[]; /* the MTU sizes */
390 int maxSize; /* sizeof of buffer in afs_int32 units */
395 struct ifreq ifs[NIFS], *ifr, tempIfr;
396 struct sockaddr_in *a;
397 char *cp, *cplim; /* used only for AIX 41 */
399 #if !defined(AFS_USERSPACE_IP_ADDR)
400 count = rx_getAllAddr(addrBuffer, 1024);
401 for (i=0; i<count; i++) {
402 maskBuffer[i] = htonl(0xffffffff);
403 mtuBuffer[i] = htonl(1500);
406 #else /* AFS_USERSPACE_IP_ADDR */
407 s = socket(AF_INET, SOCK_DGRAM, 0);
410 ifc.ifc_len = sizeof(ifs);
411 ifc.ifc_buf = (caddr_t) ifs;
412 i = ioctl(s, SIOCGIFCONF, &ifc);
417 len = ifc.ifc_len / sizeof(struct ifreq);
418 if (len > NIFS) len = NIFS;
420 #if defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
421 if ( ifc.ifc_len > sizeof(ifs) ) /* safety check */
422 ifc.ifc_len = sizeof(ifs);
423 for ( cp = (char *)ifc.ifc_buf,
424 cplim= ifc.ifc_buf+ifc.ifc_len;
426 cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
427 ifr = (struct ifreq *)cp;
429 for (i = 0; i < len; ++i) {
432 a = (struct sockaddr_in *) &ifr->ifr_addr;
433 if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
435 if ( ioctl(s, SIOCGIFFLAGS, ifr) < 0 ) {
436 perror("SIOCGIFFLAGS");
437 continue; /* ignore this address */
439 if (ifr->ifr_flags & IFF_LOOPBACK) {
440 continue; /* skip aliased loopbacks as well. */
443 if ( count >= maxSize ) { /* no more space */
444 printf("Too many interfaces..ignoring 0x%x\n", a->sin_addr.s_addr);
448 addrBuffer[count] = a->sin_addr.s_addr;
450 if ( ioctl(s, SIOCGIFNETMASK, (caddr_t)ifr) < 0 ) {
451 perror("SIOCGIFNETMASK");
452 maskBuffer[count] = htonl(0xffffffff);
454 maskBuffer[count] = (((struct sockaddr_in *)
455 (&ifr->ifr_addr))->sin_addr).s_addr;
458 mtuBuffer[count] = htonl(1500);
460 if ( ioctl(s, SIOCGIFMTU, (caddr_t)ifr) < 0) {
461 perror("SIOCGIFMTU");
463 mtuBuffer[count] = ifr->ifr_metric;
465 #endif /* SIOCGIFMTU */
467 if ( ioctl(s, SIOCRIPMTU, (caddr_t)ifr) < 0) {
468 perror("SIOCRIPMTU");
470 mtuBuffer[count] = ifr->ifr_metric;
472 #endif /* SIOCRIPMTU */
479 #endif /* AFS_USERSPACE_IP_ADDR */
483 #endif /* ! AFS_NT40_ENV */
484 #endif /* !KERNEL || UKERNEL */
486 #endif /* !AFS_DJGPP_ENV */