[netcf-devel] [PATCH] Add active/inactive flag to ncf_num_of_interfaces() & ncf_list_interfaces().
Laine Stump
laine at laine.org
Mon Jun 29 22:13:49 UTC 2009
This patch modifies ncf_num_of_interfaces() and ncf_list_interfaces to take
a flag argument that specifies whether to count/list interfaces that are
up, down, or both. It uses the SIOCGIFFLAGS ioctl to retrieve this
information.
---
src/drv_initscripts.c | 101 ++++++++++++++++++++++++++++++++++++++--------
src/internal.h | 4 +-
src/ncftool.c | 16 ++++++-
src/netcf.c | 8 ++--
src/netcf.h | 21 +++++++---
tests/test-initscripts.c | 4 +-
6 files changed, 121 insertions(+), 33 deletions(-)
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index fe57a52..fe74df9 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -30,6 +30,11 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
#include "safe-alloc.h"
#include "ref.h"
#include "list.h"
@@ -86,6 +91,7 @@ struct driver {
xsltStylesheetPtr put;
xsltStylesheetPtr get;
xmlRelaxNGPtr rng;
+ int ioctl_fd;
};
/* Entries in a ifcfg file that tell us that the interface
@@ -214,6 +220,18 @@ static int is_slave(struct netcf *ncf, const char *intf) {
return 0;
}
+static int is_active(struct netcf *ncf, const char *intf) {
+ struct ifreq ifr;
+
+ MEMZERO(&ifr, 1);
+ strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name)] = '\0';
+ if (ioctl(ncf->driver->ioctl_fd, SIOCGIFFLAGS, &ifr)) {
+ return 0;
+ }
+ return ((ifr.ifr_flags & IFF_UP) == IFF_UP);
+}
+
static int list_interfaces(struct netcf *ncf, char ***intf) {
int nint = 0, result = 0;
struct augeas *aug = NULL;
@@ -422,11 +440,35 @@ static char *xml_prop(xmlNodePtr node, const char *name) {
return (char *) xmlGetProp(node, BAD_CAST name);
}
+static int init_ioctl_fd(struct netcf *ncf) {
+
+ int ioctl_fd;
+ int flags;
+
+ ioctl_fd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_THROW(ioctl_fd < 0, ncf, EINTERNAL, "failed to open socket for interface ioctl");
+
+ flags = fcntl(ioctl_fd, F_GETFD);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to get flags for ioctl socket");
+
+ flags = fcntl(ioctl_fd, F_SETFD, flags | FD_CLOEXEC);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to set FD_CLOEXEC flag on ioctl socket");
+ return ioctl_fd;
+
+error:
+ if (ioctl_fd >= 0)
+ close(ioctl_fd);
+ return -1;
+}
+
int drv_init(struct netcf *ncf) {
int r;
if (ALLOC(ncf->driver) < 0)
return -1;
+
+ ncf->driver->ioctl_fd = -1;
+
// FIXME: Check for errors
xsltInit();
r = xslt_ext_register();
@@ -436,7 +478,13 @@ int drv_init(struct netcf *ncf) {
ncf->driver->rng = rng_parse(ncf, "interface.rng");
/* We undconditionally bridge physdevs; could be more discriminating */
bridge_physdevs(ncf);
+
+ /* open a socket for interface ioctls */
+ ncf->driver->ioctl_fd = init_ioctl_fd(ncf);
+ if (ncf->driver->ioctl_fd < 0)
+ goto error;
return 0;
+
error:
FREE(ncf->driver);
return -1;
@@ -447,49 +495,68 @@ void drv_close(struct netcf *ncf) {
xsltFreeStylesheet(ncf->driver->put);
xslt_ext_unregister();
xsltCleanupGlobals();
+ if (ncf->driver->ioctl_fd >= 0)
+ close(ncf->driver->ioctl_fd);
FREE(ncf->driver);
}
-int drv_num_of_interfaces(struct netcf *ncf) {
- int nint = 0;
- char **intf = NULL;
-
- nint = list_interfaces(ncf, &intf);
- free_matches(nint, &intf);
- return nint;
-}
-
static int list_interface_ids(struct netcf *ncf,
int maxnames, char **names,
+ unsigned int flags,
const char *id_attr) {
struct augeas *aug = NULL;
- int nint = 0, nmatches = 0, result = 0, r;
+ int nint = 0, nmatches = 0, nqualified = 0, result = 0, r;
char **intf = NULL, **matches = NULL;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
nint = list_interfaces(ncf, &intf);
- for (result = 0; result < nint && result < maxnames; result++) {
+ if (!names) {
+ maxnames = nint; /* if not returning list, ignore maxnames too */
+ }
+ for (result = 0; (result < nint) && (nqualified < maxnames); result++) {
nmatches = aug_submatch(ncf, intf[result], id_attr, &matches);
if (nmatches > 0) {
const char *name;
+ int is_qualified = ((flags & (NETCF_ACTIVE|NETCF_INACTIVE))
+ == (NETCF_ACTIVE|NETCF_INACTIVE));
+
r = aug_get(aug, matches[nmatches-1], &name);
ERR_COND_BAIL(r < 0, ncf, EOTHER);
- names[result] = strdup(name);
- ERR_COND_BAIL(names[result] == NULL, ncf, ENOMEM);
+
+ if (!is_qualified) {
+ int if_is_active = is_active(ncf, name);
+ if ((if_is_active && (flags & NETCF_ACTIVE))
+ || ((!if_is_active) && (flags & NETCF_INACTIVE))) {
+
+ is_qualified = 1;
+ }
+ }
+
+ if (is_qualified) {
+ if (names) {
+ names[nqualified] = strdup(name);
+ ERR_COND_BAIL(names[nqualified] == NULL, ncf, ENOMEM);
+ }
+ nqualified++;
+ }
}
free_matches(nmatches, &matches);
}
free_matches(nint, &intf);
- return result;
+ return nqualified;
error:
free_matches(nmatches, &matches);
free_matches(nint, &intf);
return -1;
}
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
- return list_interface_ids(ncf, maxnames, names, "DEVICE");
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
+ return list_interface_ids(ncf, maxnames, names, flags, "DEVICE");
+}
+
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
+ return list_interface_ids(ncf, 0, NULL, flags, "DEVICE");
}
static struct netcf_if *make_netcf_if(struct netcf *ncf, char *name) {
@@ -912,7 +979,7 @@ int drv_lookup_by_mac_string(struct netcf *ncf, const char *mac,
struct augeas *aug = NULL;
char *path = NULL, *ifcfg = NULL;
const char **names = NULL;
- int nmatches;
+ int nmatches = 0;
char **matches = NULL;
int r;
int result = -1;
diff --git a/src/internal.h b/src/internal.h
index 60c5855..f0ab030 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -152,8 +152,8 @@ void vreport_error(struct netcf *ncf, netcf_errcode_t errcode,
*/
int drv_init(struct netcf *netcf);
void drv_close(struct netcf *netcf);
-int drv_num_of_interfaces(struct netcf *ncf);
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names);
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags);
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags);
struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name);
int drv_lookup_by_mac_string(struct netcf *, const char *mac,
int maxifaces, struct netcf_if **ifaces);
diff --git a/src/ncftool.c b/src/ncftool.c
index cee1fce..bb4c431 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -137,13 +137,21 @@ static const char *arg_value(const struct command *cmd, const char *name) {
static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
int nint;
char **intf;
+ unsigned int flags = NETCF_ACTIVE;
- nint = ncf_num_of_interfaces(ncf);
+ if (opt_present(cmd, "inactive")) {
+ flags = NETCF_INACTIVE;
+ }
+ if (opt_present(cmd, "all")) {
+ flags = NETCF_ACTIVE | NETCF_INACTIVE;
+ }
+
+ nint = ncf_num_of_interfaces(ncf, flags);
if (nint < 0)
return CMD_RES_ERR;
if (ALLOC_N(intf, nint) < 0)
return CMD_RES_ENOMEM;
- nint = ncf_list_interfaces(ncf, nint, intf);
+ nint = ncf_list_interfaces(ncf, nint, intf, flags);
if (nint < 0)
return CMD_RES_ERR;
for (int i=0; i < nint; i++) {
@@ -175,6 +183,10 @@ static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
static const struct command_opt_def cmd_list_opts[] = {
{ .tag = CMD_OPT_BOOL, .name = "macs",
.help = "show MAC addresses" },
+ { .tag = CMD_OPT_BOOL, .name = "all",
+ .help = "show all (up & down) interfaces" },
+ { .tag = CMD_OPT_BOOL, .name = "inactive",
+ .help = "show only inactive (down) interfaces" },
CMD_OPT_DEF_LAST
};
diff --git a/src/netcf.c b/src/netcf.c
index 4d9943c..906db7d 100644
--- a/src/netcf.c
+++ b/src/netcf.c
@@ -102,17 +102,17 @@ void ncf_close(struct netcf *ncf) {
*
* Maybe we should just list them as STRUCT NETCF_IF *
*/
-int ncf_num_of_interfaces(struct netcf *ncf) {
+int ncf_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
ERR_RESET(ncf);
- return drv_num_of_interfaces(ncf);
+ return drv_num_of_interfaces(ncf, flags);
}
-int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
+int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
int result;
ERR_RESET(ncf);
MEMZERO(names, maxnames);
- result = drv_list_interfaces(ncf, maxnames, names);
+ result = drv_list_interfaces(ncf, maxnames, names, flags);
if (result < 0)
for (int i=0; i < maxnames; i++)
FREE(names[i]);
diff --git a/src/netcf.h b/src/netcf.h
index e209fc1..273ffdd 100644
--- a/src/netcf.h
+++ b/src/netcf.h
@@ -24,10 +24,6 @@
#define NETCF_H_
/*
- * FIXME: We need a way to distinguish between 'active' interfaces (i.e.,
- * ones that are up) and ones that are merely defined; maybe punt that to
- * clients ?
- *
* FIXME: NM needs a way to be notified of changes to the underlying
* network files, either we provide a way to register callbacks for an
* interface, or we hand out a list of files that contain the configs for
@@ -53,6 +49,18 @@ typedef enum {
NETCF_EEXEC /* external program execution failed or returned non-0 */
} netcf_errcode_t;
+
+/*
+ * flags accepted by ncf_num_of_interfaces and ncf_list_interfaces.
+ * IMPORTANT NOTE: These are bits, so you should assign only powers of two
+ * (Default behavior is to match NO interfaces)
+ */
+typedef enum {
+ NETCF_INACTIVE = 1, /* match down interfaces */
+ NETCF_ACTIVE = 2, /* match up interfaces */
+} netcf_if_flag_t;
+
+
/*
* Initialize netcf. This function must be called before any other netcf
* function can be called.
@@ -70,9 +78,10 @@ void ncf_close(struct netcf *);
* identified by their name.
*/
int
-ncf_num_of_interfaces(struct netcf *);
+ncf_num_of_interfaces(struct netcf *, unsigned int flags);
int
-ncf_list_interfaces(struct netcf *, int maxnames, char **names);
+ncf_list_interfaces(struct netcf *, int maxnames, char **names, unsigned int flags);
+
/* Look up interfaces by UUID, name and hwaddr (MAC-48) */
struct netcf_if *
diff --git a/tests/test-initscripts.c b/tests/test-initscripts.c
index 46c5920..5cca298 100644
--- a/tests/test-initscripts.c
+++ b/tests/test-initscripts.c
@@ -169,11 +169,11 @@ static void testListInterfaces(CuTest *tc) {
static const char *const exp_names[] = { "br0", "bond0", "lo" };
static const int exp_nint = ARRAY_CARDINALITY(exp_names);
- nint = ncf_num_of_interfaces(ncf);
+ nint = ncf_num_of_interfaces(ncf, NETCF_FLAG_ACTIVE|NETCF_FLAG_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
if (ALLOC_N(names, nint) < 0)
die("allocation failed");
- nint = ncf_list_interfaces(ncf, nint, names);
+ nint = ncf_list_interfaces(ncf, nint, names, NETCF_FLAG_ACTIVE|NETCF_FLAG_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
for (int i=0; i < exp_nint; i++) {
int found = 0;
--
1.6.0.6
More information about the netcf-devel
mailing list