Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131878347
D25029.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D25029.diff
View Options
Index: head/sbin/ifconfig/ifconfig.8
===================================================================
--- head/sbin/ifconfig/ifconfig.8
+++ head/sbin/ifconfig/ifconfig.8
@@ -56,6 +56,7 @@
.Fl a
.Op Fl L
.Op Fl d
+.Op Fl [gG] Ar groupname
.Op Fl m
.Op Fl u
.Op Fl v
@@ -2910,9 +2911,26 @@
to display information about all interfaces in the system.
The
.Fl d
-flag limits this to interfaces that are down, and
+flag limits this to interfaces that are down,
.Fl u
-limits this to interfaces that are up.
+limits this to interfaces that are up,
+limits this to interfaces that are up,
+.Fl g
+limits this to members of the specified group of interfaces, and
+.Fl G
+excludes members of the specified group from the list.
+Both
+.Fl g
+and
+.Fl G
+flags may be specified to apply both conditions.
+Only one option
+.Fl g
+should be specified as later override previous ones
+(same for
+.Fl G ) .
+.Sy groupname
+may contain shell patterns in which case it should be quoted.
When no arguments are given,
.Fl a
is implied.
@@ -3036,6 +3054,9 @@
.Pp
Display inet and inet6 address subnet masks in CIDR notation
.Dl # ifconfig -f inet:cidr,inet6:cidr
+.Pp
+Display interfaces that are up with the exception of loopback
+.Dl # ifconfig -a -u -G lo
.Sh DIAGNOSTICS
Messages indicating the specified interface does not exist, the
requested address is unknown, or the user is not privileged and
Index: head/sbin/ifconfig/ifconfig.c
===================================================================
--- head/sbin/ifconfig/ifconfig.c
+++ head/sbin/ifconfig/ifconfig.c
@@ -63,6 +63,7 @@
#include <arpa/inet.h>
#include <netdb.h>
+#include <fnmatch.h>
#include <ifaddrs.h>
#include <ctype.h>
#include <err.h>
@@ -105,6 +106,8 @@
/* Formatter Strings */
char *f_inet, *f_inet6, *f_ether, *f_addr;
+static bool group_member(const char *ifname, const char *match,
+ const char *nomatch);
static int ifconfig(int argc, char *const *argv, int iscreate,
const struct afswtch *afp);
static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
@@ -402,13 +405,14 @@
char options[1024], *cp, *envformat, *namecp = NULL;
struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
struct ifa_order_elt *cur, *tmp;
- const char *ifname;
+ const char *ifname, *matchgroup, *nogroup;
struct option *p;
size_t iflen;
int flags;
all = downonly = uponly = namesonly = noload = verbose = 0;
f_inet = f_inet6 = f_ether = f_addr = NULL;
+ matchgroup = nogroup = NULL;
envformat = getenv("IFCONFIG_FORMAT");
if (envformat != NULL)
@@ -421,7 +425,7 @@
atexit(printifnamemaybe);
/* Parse leading line options */
- strlcpy(options, "f:adklmnuv", sizeof(options));
+ strlcpy(options, "G:adf:klmnuv", sizeof(options));
for (p = opts; p != NULL; p = p->next)
strlcat(options, p->opt, sizeof(options));
while ((c = getopt(argc, argv, options)) != -1) {
@@ -437,6 +441,11 @@
usage();
setformat(optarg);
break;
+ case 'G':
+ if (optarg == NULL || all == 0)
+ usage();
+ nogroup = optarg;
+ break;
case 'k':
printkeys++;
break;
@@ -455,6 +464,14 @@
case 'v':
verbose++;
break;
+ case 'g':
+ if (all) {
+ if (optarg == NULL)
+ usage();
+ matchgroup = optarg;
+ break;
+ }
+ /* FALLTHROUGH */
default:
for (p = opts; p != NULL; p = p->next)
if (p->opt[0] == c) {
@@ -626,6 +643,8 @@
continue;
if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
continue;
+ if (!group_member(ifa->ifa_name, matchgroup, nogroup))
+ continue;
/*
* Are we just listing the interfaces?
*/
@@ -668,6 +687,73 @@
done:
freeformat();
exit(exit_code);
+}
+
+/*
+ * Returns true if an interface should be listed because any its groups
+ * matches shell pattern "match" and none of groups matches pattern "nomatch".
+ * If any pattern is NULL, corresponding condition is skipped.
+ */
+static bool
+group_member(const char *ifname, const char *match, const char *nomatch)
+{
+ static int sock = -1;
+
+ struct ifgroupreq ifgr;
+ struct ifg_req *ifg;
+ int len;
+ bool matched, nomatched;
+
+ /* Sanity checks. */
+ if (match == NULL && nomatch == NULL)
+ return (true);
+ if (ifname == NULL)
+ return (false);
+
+ memset(&ifgr, 0, sizeof(ifgr));
+ strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ);
+
+ /* The socket is opened once. Let _exit() close it. */
+ if (sock == -1) {
+ sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (sock == -1)
+ errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__);
+ }
+
+ /* Determine amount of memory for the list of groups. */
+ if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
+ if (errno == EINVAL || errno == ENOTTY)
+ return (false);
+ else
+ errx(1, "%s: SIOCGIFGROUP", __func__);
+ }
+
+ /* Obtain the list of groups. */
+ len = ifgr.ifgr_len;
+ ifgr.ifgr_groups =
+ (struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg));
+
+ if (ifgr.ifgr_groups == NULL)
+ errx(1, "%s: no memory", __func__);
+ if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
+ errx(1, "%s: SIOCGIFGROUP", __func__);
+
+ /* Perform matching. */
+ matched = false;
+ nomatched = true;
+ for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) {
+ len -= sizeof(struct ifg_req);
+ if (match)
+ matched |= !fnmatch(match, ifg->ifgrq_group, 0);
+ if (nomatch)
+ nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0);
+ }
+
+ if (match && !nomatch)
+ return (matched);
+ if (!match && nomatch)
+ return (nomatched);
+ return (matched && nomatched);
}
static struct afswtch *afs = NULL;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 12, 10:07 PM (20 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23643186
Default Alt Text
D25029.diff (5 KB)
Attached To
Mode
D25029: Introduce ifconfig -a -[gG] groupname
Attached
Detach File
Event Timeline
Log In to Comment