From 1e7fe9f955a3d9d24a8f7545a033f8b90126e3bf Mon Sep 17 00:00:00 2001 From: fenner Date: Wed, 17 Oct 2001 04:12:29 +0000 Subject: [PATCH] The interface index space may be sparsely populated (e.g. when an interface in the middle is if_detach()'d). Return (and handle) ENOENT when the ifmib(4) is accessed for a nonexistent interface. MFC after: 14 days --- libexec/rpc.rstatd/rstat_proc.c | 4 ++++ share/man/man4/ifmib.4 | 6 +++++- sys/net/if_mib.c | 3 ++- tools/tools/ifinfo/ifinfo.c | 7 ++++++- usr.sbin/slstat/slstat.c | 6 +++++- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/libexec/rpc.rstatd/rstat_proc.c b/libexec/rpc.rstatd/rstat_proc.c index 10143267f66b..2b63394ddb9b 100644 --- a/libexec/rpc.rstatd/rstat_proc.c +++ b/libexec/rpc.rstatd/rstat_proc.c @@ -51,6 +51,7 @@ static const char rcsid[] = #include #include +#include #include #include #include @@ -294,6 +295,9 @@ updatestat() mib[4] = i; mib[5] = IFDATA_GENERAL; if (sysctl(mib, 6, &ifmd, &len, 0, 0) < 0) { + if (errno == ENOENT) + continue; + syslog(LOG_ERR, "sysctl(net.link.ifdata.%d.general)" ": %m", i); exit(1); diff --git a/share/man/man4/ifmib.4 b/share/man/man4/ifmib.4 index 9fd6bc891a8c..dc9b28d28c2f 100644 --- a/share/man/man4/ifmib.4 +++ b/share/man/man4/ifmib.4 @@ -76,7 +76,7 @@ MIB. The manifest constants for each level in the .Ar name are defined in .Aq Pa net/if_mib.h . -A count of interfaces (and thus rows in the table) is given by +The index of the last row in the table is given by .Dq Li net.link.generic.system.ifcount (or, using the manifest constants, .Dv CTL_NET , @@ -87,6 +87,10 @@ A count of interfaces (and thus rows in the table) is given by A management application searching for a particular interface should start with row 1 and continue through the table row-by-row until the desired interface is found, or the interface count is reached. +Note that the table may be sparse, i.e. a given row may not exist, +indicated by an errno of +.Er ENOENT . +Such an error should be ignored, and the next row should be checked. .Pp The generic interface information, common to all interfaces, can be accessed via the following procedure: diff --git a/sys/net/if_mib.c b/sys/net/if_mib.c index 5b04cbb2ba32..b8e7ed6f6766 100644 --- a/sys/net/if_mib.c +++ b/sys/net/if_mib.c @@ -80,7 +80,8 @@ sysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XXX bad syntax! */ if (namelen != 2) return EINVAL; - if (name[0] <= 0 || name[0] > if_index) + if (name[0] <= 0 || name[0] > if_index || + ifaddr_byindex(name[0]) == NULL) return ENOENT; ifp = ifaddr_byindex(name[0])->ifa_ifp; diff --git a/tools/tools/ifinfo/ifinfo.c b/tools/tools/ifinfo/ifinfo.c index 8e462ddb1665..54ca16426430 100644 --- a/tools/tools/ifinfo/ifinfo.c +++ b/tools/tools/ifinfo/ifinfo.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -99,9 +100,13 @@ main(int argc, char **argv) name[3] = IFMIB_IFDATA; name[4] = i; name[5] = IFDATA_GENERAL; - if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) + if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) { + if (errno == ENOENT) + continue; + err(EX_OSERR, "sysctl(net.link.ifdata.%d.general)", i); + } if (!isit(argc - optind, argv + optind, ifmd.ifmd_name)) continue; diff --git a/usr.sbin/slstat/slstat.c b/usr.sbin/slstat/slstat.c index 27c27ed0a6d4..ac1fa83e7107 100644 --- a/usr.sbin/slstat/slstat.c +++ b/usr.sbin/slstat/slstat.c @@ -120,8 +120,12 @@ main(argc, argv) for (i = 1; ; i++) { name[4] = i; - if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) + if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) { + if (errno == ENOENT) + continue; + err(1, "sysctl"); + } if (strncmp(interface, ifmd.ifmd_name, IFNAMSIZ) == 0 && ifmd.ifmd_data.ifi_type == IFT_SLIP) { indx = i;