rx_identity: Add a super user value
[openafs.git] / src / rx / rx_getaddr.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #ifndef KERNEL
14
15 # include <roken.h>
16 # ifndef AFS_NT40_ENV
17 # include <net/if.h>
18 #  if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
19 #   include <sys/sysctl.h>
20 #   ifndef AFS_ARM_DARWIN_ENV
21 #    include <net/route.h>
22 #   endif
23 #   include <net/if_dl.h>
24 #  endif
25
26 /*
27  * By including this, we get any system dependencies. In particular,
28  * the pthreads for solaris requires the socket call to be mapped.
29  */
30 #  include "rx.h"
31 #  include "rx_globals.h"
32 # endif /* AFS_NT40_ENV */
33 #else /* KERNEL */
34 # ifdef UKERNEL
35 #  include "rx/rx_kcommon.h"
36 # else /* UKERNEL */
37 #  include "rx/rx.h"
38 # endif /* UKERNEL */
39 #endif /* KERNEL */
40
41 #define NIFS            512
42
43 #if defined(AFS_USR_DFBSD_ENV)
44 # include <net/if.h>
45 # include <sys/sockio.h>
46 #endif
47
48 #ifdef KERNEL
49 /* only used for generating random noise */
50
51 afs_uint32 rxi_tempAddr = 0;    /* default attempt */
52
53 /* set the advisory noise */
54 void
55 rxi_setaddr(afs_uint32 x)
56 {
57     rxi_tempAddr = x;
58 }
59
60 /* get approx to net addr */
61 afs_uint32
62 rxi_getaddr(void)
63 {
64     return rxi_tempAddr;
65 }
66
67 #endif /* KERNEL */
68
69 #ifndef KERNEL
70
71 /* to satisfy those who call setaddr */
72 void
73 rxi_setaddr(afs_uint32 x)
74 {
75 }
76
77 #endif /* !KERNEL */
78
79
80 #if !defined(AFS_NT40_ENV)
81 /* For NT, rxi_getaddr has moved to rx_user.c. rxi_GetIfInfo is called by
82  * rx_Init which sets up the list of addresses for us.
83  */
84
85 #ifndef KERNEL
86
87 /* Return our internet address as a long in network byte order.  Returns zero
88  * if it can't find one.
89  */
90 afs_uint32
91 rxi_getaddr(void)
92 {
93     afs_uint32 buffer[1024];
94     int count;
95
96     count = rx_getAllAddr(buffer, 1024);
97     if (count > 0)
98         return buffer[0];       /* returns the first address */
99     else
100         return count;
101 }
102
103 #endif /* !KERNEL */
104
105 #if !defined(KERNEL) || defined(UKERNEL)
106
107 #ifndef MAX
108 #define MAX(A,B) (((A)<(B)) ? (B) : (A))
109 #endif
110
111 #ifdef UKERNEL
112 #undef ioctl
113 #undef socket
114 #endif /* UKERNEL */
115
116 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
117 #define ROUNDUP(a) \
118         ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
119 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
120
121 static void
122 rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo)
123 {
124     struct sockaddr *sa;
125     int i;
126
127     memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info));
128     for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
129         if ((rtinfo->rti_addrs & (1 << i)) == 0)
130             continue;
131         rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
132         ADVANCE(cp, sa);
133     }
134 }
135 #endif
136
137 static_inline int
138 rxi_IsLoopbackIface(struct sockaddr_in *a, unsigned long flags)
139 {
140     afs_uint32 addr = ntohl(a->sin_addr.s_addr);
141     if (rx_IsLoopbackAddr(addr)) {
142         return 1;
143     }
144     if ((flags & IFF_LOOPBACK) && ((addr & 0xff000000) == 0x7f000000)) {
145         return 1;
146     }
147     return 0;
148 }
149
150 /* this function returns the total number of interface addresses
151 ** the buffer has to be passed in by the caller
152 */
153 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
154 #if defined(AFS_OBSD42_ENV)
155 void
156 ifm_fixversion(char *buffer, size_t *size) {
157     struct if_msghdr *ifm;
158     char *b = buffer;
159     char *s, *t;
160
161     if ((t = malloc(*size)) != NULL) {
162         memcpy(t, buffer, *size);
163
164         for (s = t; s < t + *size; s += ifm->ifm_msglen) {
165             ifm = (struct if_msghdr *)s;
166
167             if (ifm->ifm_version == RTM_VERSION) {
168                 memcpy(b, ifm, ifm->ifm_msglen);
169                 b += ifm->ifm_msglen;
170             }
171         }
172
173         free(t);
174
175         *size = b - buffer;
176     }
177 }
178 #endif
179
180 int
181 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
182 {
183     size_t needed;
184     int mib[6];
185     struct if_msghdr *ifm, *nextifm;
186     struct ifa_msghdr *ifam;
187     struct sockaddr_dl *sdl;
188     struct rt_addrinfo info;
189     char *buf, *lim, *next;
190     int count = 0, addrcount = 0;
191
192     mib[0] = CTL_NET;
193     mib[1] = PF_ROUTE;
194     mib[2] = 0;
195     mib[3] = AF_INET;           /* address family */
196     mib[4] = NET_RT_IFLIST;
197     mib[5] = 0;
198     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
199         return 0;
200     if ((buf = malloc(needed)) == NULL)
201         return 0;
202     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
203         free(buf);
204         return 0;
205     }
206 #if defined(AFS_OBSD42_ENV)
207     ifm_fixversion(buf, &needed);
208 #endif
209     lim = buf + needed;
210     next = buf;
211     while (next < lim) {
212         ifm = (struct if_msghdr *)next;
213         if (ifm->ifm_type != RTM_IFINFO) {
214             dpf(("out of sync parsing NET_RT_IFLIST\n"));
215             free(buf);
216             return 0;
217         }
218         sdl = (struct sockaddr_dl *)(ifm + 1);
219         next += ifm->ifm_msglen;
220         ifam = NULL;
221         addrcount = 0;
222         while (next < lim) {
223             nextifm = (struct if_msghdr *)next;
224             if (nextifm->ifm_type != RTM_NEWADDR)
225                 break;
226             if (ifam == NULL)
227                 ifam = (struct ifa_msghdr *)nextifm;
228             addrcount++;
229             next += nextifm->ifm_msglen;
230         }
231         if ((ifm->ifm_flags & IFF_UP) == 0)
232             continue;           /* not up */
233         while (addrcount > 0) {
234             struct sockaddr_in *a;
235
236             info.rti_addrs = ifam->ifam_addrs;
237
238             /* Expand the compacted addresses */
239             rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
240                       &info);
241             if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
242                 addrcount--;
243                 continue;
244             }
245             a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
246
247             if (count >= maxSize)       /* no more space */
248                 dpf(("Too many interfaces..ignoring 0x%x\n",
249                        a->sin_addr.s_addr));
250             else if (!loopbacks && rxi_IsLoopbackIface(a, ifm->ifm_flags)) {
251                 addrcount--;
252                 continue;       /* skip loopback address as well. */
253             } else if (loopbacks && ifm->ifm_flags & IFF_LOOPBACK) {
254                 addrcount--;
255                 continue;       /* skip aliased loopbacks as well. */
256             } else
257                 buffer[count++] = a->sin_addr.s_addr;
258             addrcount--;
259             ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
260         }
261     }
262     free(buf);
263     return count;
264 }
265
266 int
267 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
268                      afs_uint32 mtuBuffer[], int maxSize)
269 {
270     int s;
271
272     size_t needed;
273     int mib[6];
274     struct if_msghdr *ifm, *nextifm;
275     struct ifa_msghdr *ifam;
276     struct sockaddr_dl *sdl;
277     struct rt_addrinfo info;
278     char *buf, *lim, *next;
279     int count = 0, addrcount = 0;
280
281     mib[0] = CTL_NET;
282     mib[1] = PF_ROUTE;
283     mib[2] = 0;
284     mib[3] = AF_INET;           /* address family */
285     mib[4] = NET_RT_IFLIST;
286     mib[5] = 0;
287     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
288         return 0;
289     if ((buf = malloc(needed)) == NULL)
290         return 0;
291     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
292         free(buf);
293         return 0;
294     }
295 #if defined(AFS_OBSD42_ENV)
296     ifm_fixversion(buf, &needed);
297 #endif
298     s = socket(PF_INET, SOCK_DGRAM, 0);
299     if (s < 0)
300         return 0;
301     lim = buf + needed;
302     next = buf;
303     while (next < lim) {
304         ifm = (struct if_msghdr *)next;
305         if (ifm->ifm_type != RTM_IFINFO) {
306             dpf(("out of sync parsing NET_RT_IFLIST\n"));
307             free(buf);
308             return 0;
309         }
310         sdl = (struct sockaddr_dl *)(ifm + 1);
311         next += ifm->ifm_msglen;
312         ifam = NULL;
313         addrcount = 0;
314         while (next < lim) {
315             nextifm = (struct if_msghdr *)next;
316             if (nextifm->ifm_type != RTM_NEWADDR)
317                 break;
318             if (ifam == NULL)
319                 ifam = (struct ifa_msghdr *)nextifm;
320             addrcount++;
321             next += nextifm->ifm_msglen;
322         }
323         if ((ifm->ifm_flags & IFF_UP) == 0)
324             continue;           /* not up */
325         while (addrcount > 0) {
326             struct sockaddr_in *a;
327
328             info.rti_addrs = ifam->ifam_addrs;
329
330             /* Expand the compacted addresses */
331             rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam,
332                       &info);
333             if (info.rti_info[RTAX_IFA]->sa_family != AF_INET) {
334                 addrcount--;
335                 continue;
336             }
337             a = (struct sockaddr_in *) info.rti_info[RTAX_IFA];
338
339             if (!rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr))) {
340                 if (count >= maxSize) { /* no more space */
341                     dpf(("Too many interfaces..ignoring 0x%x\n",
342                            a->sin_addr.s_addr));
343                 } else {
344                     struct ifreq ifr;
345
346                     addrBuffer[count] = a->sin_addr.s_addr;
347                     a = (struct sockaddr_in *) info.rti_info[RTAX_NETMASK];
348                     if (a)
349                         maskBuffer[count] = a->sin_addr.s_addr;
350                     else
351                         maskBuffer[count] = htonl(0xffffffff);
352                     memset(&ifr, 0, sizeof(ifr));
353                     ifr.ifr_addr.sa_family = AF_INET;
354                     strncpy(ifr.ifr_name, sdl->sdl_data, sdl->sdl_nlen);
355                     if (ioctl(s, SIOCGIFMTU, (caddr_t) & ifr) < 0)
356                         mtuBuffer[count] = htonl(1500);
357                     else
358                         mtuBuffer[count] = htonl(ifr.ifr_mtu);
359                     count++;
360                 }
361             }
362             addrcount--;
363             ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
364         }
365     }
366     free(buf);
367     return count;
368 }
369
370
371 int
372 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
373 {
374     return rx_getAllAddr_internal(buffer, maxSize, 0);
375 }
376 /* this function returns the total number of interface addresses
377 ** the buffer has to be passed in by the caller
378 */
379 #else /* UKERNEL indirectly, on DARWIN or XBSD */
380 static int
381 rx_getAllAddr_internal(afs_uint32 buffer[], int maxSize, int loopbacks)
382 {
383     int s;
384     int i, len, count = 0;
385     struct ifconf ifc;
386     struct ifreq ifs[NIFS], *ifr;
387     struct sockaddr_in *a;
388     /* can't ever be AFS_DARWIN_ENV or AFS_XBSD_ENV, no? */
389 #if    defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
390     char *cp, *cplim, *cpnext;  /* used only for AIX 41 */
391 #endif
392
393     s = socket(AF_INET, SOCK_DGRAM, 0);
394     if (s < 0)
395         return 0;
396     ifc.ifc_len = sizeof(ifs);
397     ifc.ifc_buf = (caddr_t) ifs;
398     i = ioctl(s, SIOCGIFCONF, &ifc);
399     if (i < 0)
400         return 0;
401     len = ifc.ifc_len / sizeof(struct ifreq);
402     if (len > NIFS)
403         len = NIFS;
404 #if    defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
405     if (ifc.ifc_len > sizeof(ifs))      /* safety check */
406         ifc.ifc_len = sizeof(ifs);
407     for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
408          cp < cplim;
409 #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
410          cp += _SIZEOF_ADDR_IFREQ(*ifr)
411 #else
412 #ifdef AFS_AIX51_ENV
413          cp = cpnext
414 #else
415          cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))
416 #endif
417 #endif
418         )
419 #else
420     for (i = 0; i < len; ++i)
421 #endif
422     {
423 #if    defined(AFS_AIX41_ENV) || defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
424         ifr = (struct ifreq *)cp;
425 #else
426         ifr = &ifs[i];
427 #endif
428         a = (struct sockaddr_in *)&ifr->ifr_addr;
429 #ifdef AFS_AIX51_ENV
430         cpnext = cp + sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a));
431 #endif
432         if (a->sin_family != AF_INET)
433             continue;
434         if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
435             perror("SIOCGIFFLAGS");
436             continue;           /* ignore this address */
437         }
438         if (a->sin_addr.s_addr != 0) {
439             if (!loopbacks) {
440                 if (rxi_IsLoopbackIface(a, ifr->ifr_flags))
441                     continue;   /* skip loopback address as well. */
442             } else {
443                 if (ifr->ifr_flags & IFF_LOOPBACK)
444                     continue;   /* skip aliased loopbacks as well. */
445             }
446             if (count >= maxSize)       /* no more space */
447                 dpf(("Too many interfaces..ignoring 0x%x\n",
448                        a->sin_addr.s_addr));
449             else
450                 buffer[count++] = a->sin_addr.s_addr;
451         }
452     }
453     close(s);
454     return count;
455 }
456
457 int
458 rx_getAllAddr(afs_uint32 buffer[], int maxSize)
459 {
460     return rx_getAllAddr_internal(buffer, maxSize, 0);
461 }
462
463 /* this function returns the total number of interface addresses
464  * the buffer has to be passed in by the caller. It also returns
465  * the interface mask. If AFS_USERSPACE_IP_ADDR is defined, it
466  * gets the mask which is then passed into the kernel and is used
467  * by afsi_SetServerIPRank().
468  */
469 int
470 rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[], afs_uint32 maskBuffer[],
471                      afs_uint32 mtuBuffer[], int maxSize)
472 {
473     int i, count = 0;
474 #if defined(AFS_USERSPACE_IP_ADDR)
475     int s, len;
476     struct ifconf ifc;
477     struct ifreq ifs[NIFS], *ifr;
478     struct sockaddr_in *a;
479 #endif
480
481 #if     defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
482     char *cp, *cplim;           /* used only for AIX 41 */
483 #endif
484
485 #if !defined(AFS_USERSPACE_IP_ADDR)
486     count = rx_getAllAddr_internal(addrBuffer, 1024, 0);
487     for (i = 0; i < count; i++) {
488         maskBuffer[i] = htonl(0xffffffff);
489         mtuBuffer[i] = htonl(1500);
490     }
491     return count;
492 #else /* AFS_USERSPACE_IP_ADDR */
493     s = socket(AF_INET, SOCK_DGRAM, 0);
494     if (s < 0)
495         return 0;
496
497     ifc.ifc_len = sizeof(ifs);
498     ifc.ifc_buf = (caddr_t) ifs;
499     i = ioctl(s, SIOCGIFCONF, &ifc);
500     if (i < 0) {
501         close(s);
502         return 0;
503     }
504     len = ifc.ifc_len / sizeof(struct ifreq);
505     if (len > NIFS)
506         len = NIFS;
507
508 #if     defined(AFS_AIX41_ENV) || defined(AFS_USR_AIX_ENV)
509     if (ifc.ifc_len > sizeof(ifs))      /* safety check */
510         ifc.ifc_len = sizeof(ifs);
511     for (cp = (char *)ifc.ifc_buf, cplim = ifc.ifc_buf + ifc.ifc_len;
512          cp < cplim;
513          cp += sizeof(ifr->ifr_name) + MAX(a->sin_len, sizeof(*a))) {
514         ifr = (struct ifreq *)cp;
515 #else
516     for (i = 0; i < len; ++i) {
517         ifr = &ifs[i];
518 #endif
519         a = (struct sockaddr_in *)&ifr->ifr_addr;
520         if (a->sin_addr.s_addr != 0 && a->sin_family == AF_INET) {
521
522             if (ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
523                 perror("SIOCGIFFLAGS");
524                 continue;       /* ignore this address */
525             }
526
527             if (rx_IsLoopbackAddr(ntohl(a->sin_addr.s_addr)))
528                 continue;   /* skip loopback address as well. */
529
530             if (count >= maxSize) {     /* no more space */
531                 dpf(("Too many interfaces..ignoring 0x%x\n",
532                        a->sin_addr.s_addr));
533                 continue;
534             }
535
536             addrBuffer[count] = a->sin_addr.s_addr;
537
538             if (ioctl(s, SIOCGIFNETMASK, (caddr_t) ifr) < 0) {
539                 perror("SIOCGIFNETMASK");
540                 maskBuffer[count] = htonl(0xffffffff);
541             } else {
542                 maskBuffer[count] = (((struct sockaddr_in *)
543                                       (&ifr->ifr_addr))->sin_addr).s_addr;
544             }
545
546             mtuBuffer[count] = htonl(1500);
547 #ifdef SIOCGIFMTU
548             if (ioctl(s, SIOCGIFMTU, (caddr_t) ifr) < 0) {
549                 perror("SIOCGIFMTU");
550             } else {
551                 mtuBuffer[count] = htonl(ifr->ifr_metric);
552             }
553 #endif /* SIOCGIFMTU */
554 #ifdef SIOCRIPMTU
555             if (ioctl(s, SIOCRIPMTU, (caddr_t) ifr) < 0) {
556                 perror("SIOCRIPMTU");
557             } else {
558                 mtuBuffer[count] = htonl(ifr->ifr_metric);
559             }
560 #endif /* SIOCRIPMTU */
561
562             count++;
563         }
564     }
565     close(s);
566     return count;
567 #endif /* AFS_USERSPACE_IP_ADDR */
568 }
569 #endif
570
571 #endif /* ! AFS_NT40_ENV */
572 #endif /* !KERNEL || UKERNEL */