From 64e183481d9991d83999b09a051e294643b30786 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Sat, 31 Mar 2001 06:33:48 +0000 Subject: [PATCH] * t_gifconf.c: New file git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13127 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/os/ChangeLog | 4 ++ src/lib/krb5/os/t_gifconf.c | 127 ++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/lib/krb5/os/t_gifconf.c diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog index 8647ce0b8..ceff3a62c 100644 --- a/src/lib/krb5/os/ChangeLog +++ b/src/lib/krb5/os/ChangeLog @@ -1,3 +1,7 @@ +2001-03-31 Ken Raeburn + + * t_gifconf.c: New file. + 2001-03-10 Ezra Peisach * def_realm.c: Move prototype for krb5_try_realm_txt_rr() to diff --git a/src/lib/krb5/os/t_gifconf.c b/src/lib/krb5/os/t_gifconf.c new file mode 100644 index 000000000..1fd0d05e6 --- /dev/null +++ b/src/lib/krb5/os/t_gifconf.c @@ -0,0 +1,127 @@ +/* SIOCGIFCONF: + + The behavior of this ioctl varies across systems. + + The "largest gap" values are the largest number of bytes I've seen + left unused at the end of the supplied buffer when there were more + entries to return. These values may of coures be dependent on the + configurations of the particular systems I was testing with. + + NetBSD 1.5-alpha: The returned ifc_len is the desired amount of + space, always. The returned list may be truncated if there isn't + enough room; no overrun. Largest gap: 43. (NetBSD now has + getifaddrs.) + + Solaris 2.7: Return EINVAL if the buffer space is too small for all + the data to be returned, including ifc_len==0. Solaris is the only + system I've found so far that actually returns an error. No gap. + + Linux 2.2.12 (RH 6.1 dist, x86): The buffer is filled in with as + many entries as will fit, and the size used is returned in ifc_len. + The list is truncated if needed, with no indication. Largest gap: 31. + + IRIX 6.5: The buffer is filled in with as many entries as will fit + in N-1 bytes, and the size used is returned in ifc_len. Providing + exactly the desired number of bytes is inadequate; the buffer must + be *bigger* than needed. (E.g., 32->0, 33->32.) The returned + ifc_len is always less than the supplied one. Largest gap: 32. + + AIX 4.3.3: Sometimes the returned ifc_len is bigger than the + supplied one, but it may not be big enough for *all* the + interfaces. Sometimes it's smaller than the supplied value, even + if the returned list is truncated. The list is filled in with as + many entries as will fit; no overrun. Largest gap: 143. + + Older AIX: We're told by W. David Shambroom in + PR krb5-kdc/919 that older versions of AIX have a bug in the + SIOCGIFCONF ioctl which can cause them to overrun the supplied + buffer. However, we don't yet have details as to which version, + whether the overrun amount was bounded (e.g., one ifreq's worth) or + not, whether it's a real buffer overrun or someone assuming it was + because ifc_len was increased, etc. Once we've got details, we can + try to work around the problem. + + Digital UNIX 4.0F: If input ifc_len is zero, return an ifc_len + that's big enough to include all entries. (Actually, on our + system, it appears to be larger than that by 32.) If input ifc_len + is nonzero, fill in as many entries as will fit, and set ifc_len + accordingly. (Tested only with INIT of zero.) + + So... if the returned ifc_len is bigger than the supplied one, + we'll need at least that much space -- but possibly more -- to hold + all the results. If the returned value is smaller or the same, we + may still need more space. + + Using this ioctl is going to be messy. Let's just hope that + getifaddrs() catches on quickly.... */ + +#include +#include +#include +#include +#include +#include + +#if (defined(sun) || defined(__sun__)) && !defined(SIOCGIFCONF) +/* Sun puts socket ioctls in another file. */ +#include +#endif + +#define INIT 0xc3 + +int main () { + char buffer[2048]; + int i, sock, t, olen = -9, omod = -9; + struct ifconf ifc; + int gap = -1, lastgap = -1; + + sock = socket (AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror ("socket"); + exit (1); + } + printf ("sizeof(struct if_req)=%d\n", sizeof (struct ifreq)); + for (t = 0; t < sizeof (buffer); t++) { + ifc.ifc_len = t; + ifc.ifc_buf = buffer; + memset (buffer, INIT, sizeof (buffer)); + i = ioctl (sock, SIOCGIFCONF, (char *) &ifc); + if (i < 0) { + /* Solaris returns "Invalid argument" if the buffer is too + small. AIX and Linux return no error indication. */ + int e = errno; + sprintf (buffer, "SIOCGIFCONF(%d)", t); + errno = e; + perror (buffer); + if (e == EINVAL) + continue; + fprintf (stderr, "exiting on unexpected error\n"); + exit (1); + } + i = sizeof (buffer) - 1; + while (buffer[i] == ((char)INIT) && i >= 0) + i--; + if (omod != i) { + /* Okay... the gap computed on the *last* iteration is the + largest for that particular size of returned data. + Save it, and then start computing gaps for the next + bigger size of returned data. If we never get anything + bigger back, we discard the newer value and only keep + LASTGAP because all we care about is how much slop we + need to "prove" that there really weren't any more + entries to be returned. */ + if (gap > lastgap) + lastgap = gap; + } + gap = t - i - 1; + if (olen != ifc.ifc_len || omod != i) { + printf ("ifc_len in = %4d, ifc_len out = %4d, last mod = %4d\n", + t, ifc.ifc_len, i); + olen = ifc.ifc_len; + omod = i; + } + } + printf ("finished at ifc_len %d\n", t); + printf ("largest gap = %d\n", lastgap); + exit (0); +} -- 2.26.2