[netcf-devel] [PATCH] (REVISED) Fill in interface details in ncf_if_xml_state.
Laine Stump
laine at laine.org
Wed Nov 4 05:46:43 UTC 2009
Details include slave/master interfaces of bridge (yes,
multiple physicals are now supported), vlan, and bond interfaces.
All interface types now have enough information to pass libvirt xml
parsing.
---
src/drv_initscripts.c | 13 +--
src/dutil.c | 510 +++++++++++++++++++++++++++++++++++++++----------
src/dutil.h | 19 ++-
3 files changed, 430 insertions(+), 112 deletions(-)
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index 6163035..055b624 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -769,8 +769,6 @@ char *drv_xml_state(struct netcf_if *nif) {
struct netcf *ncf;
xmlDocPtr ncf_xml = NULL;
xmlNodePtr root;
- xmlAttrPtr prop;
- const char *type;
ncf = nif->ncf;
@@ -782,17 +780,8 @@ char *drv_xml_state(struct netcf_if *nif) {
root = xmlNewNode(NULL, BAD_CAST "interface");
ERR_NOMEM(root == NULL, ncf);
xmlDocSetRootElement(ncf_xml, root);
- prop = xmlNewProp(root, BAD_CAST "name", BAD_CAST nif->name);
- ERR_NOMEM(prop == NULL, ncf);
- type = if_type(ncf, nif->name);
- ERR_BAIL(ncf);
- prop = xmlSetProp(root, BAD_CAST "type", BAD_CAST type);
- ERR_NOMEM(prop == NULL, ncf);
-
- /* get the current IP address and prefix, and add both to the
- * document.
- */
+ /* add all info we can gather from the kernel/sysfs/procfs */
add_state_to_xml_doc(nif, ncf_xml);
ERR_BAIL(ncf);
diff --git a/src/dutil.c b/src/dutil.c
index d4eea90..35a6734 100644
--- a/src/dutil.c
+++ b/src/dutil.c
@@ -50,6 +50,10 @@
#include <netlink/cache.h>
#include <netlink/route/addr.h>
#include <netlink/route/link.h>
+/* For some reason, the headers for libnl vlan functions aren't installed */
+extern int rtnl_link_vlan_get_id(struct rtnl_link *link);
+
+#include <dirent.h>
#include <libxml/parser.h>
#include <libxml/relaxng.h>
@@ -432,6 +436,46 @@ char *xml_prop(xmlNodePtr node, const char *name) {
return (char *) xmlGetProp(node, BAD_CAST name);
}
+/* Create a new node and link it into the document, even if one of the
+ * same name already exists. A NULL return means there was a memory
+ * failure, and it needs to be reported by the caller.
+ */
+static xmlNodePtr xml_new_node(xmlDocPtr doc,
+ xmlNodePtr parent, const char *name) {
+ xmlNodePtr cur, ret = NULL;
+
+ ret = xmlNewDocNode(doc, NULL, BAD_CAST name, NULL);
+ if (ret != NULL) {
+ cur = xmlAddChild(parent, ret);
+ if (cur == NULL) {
+ xmlFreeNode(ret);
+ ret = NULL;
+ }
+ }
+ return ret;
+}
+
+/* Find existing node of given name within parent, or create and link
+ * in a new one if not found.
+ */
+static xmlNodePtr xml_node(xmlDocPtr doc,
+ xmlNodePtr parent, const char *name) {
+ xmlNodePtr cur, ret = NULL;
+
+ for (cur = parent->children; cur != NULL; cur = cur->next) {
+ if ((cur->type == XML_ELEMENT_NODE)
+ && xmlStrEqual(cur->name, BAD_CAST name)) {
+ ret = cur;
+ break;
+ }
+ }
+ if (ret == NULL) {
+ /* node not found, create a new one */
+ ret = xml_new_node(doc, parent, name);
+ }
+ return ret;
+}
+
int init_ioctl_fd(struct netcf *ncf) {
int ioctl_fd;
int flags;
@@ -509,40 +553,106 @@ int if_is_active(struct netcf *ncf, const char *intf) {
return ((ifr.ifr_flags & IFF_UP) == IFF_UP);
}
-const char *if_type(struct netcf *ncf, const char *intf) {
+netcf_if_type_t if_type(struct netcf *ncf, const char *intf) {
char *path;
struct stat stats;
- const char *ret = NULL;
+ netcf_if_type_t ret = NETCF_IFACE_TYPE_NONE;
xasprintf(&path, "/proc/net/vlan/%s", intf);
ERR_NOMEM(path == NULL, ncf);
if ((stat (path, &stats) == 0) && S_ISREG (stats.st_mode)) {
- ret = "vlan";
+ ret = NETCF_IFACE_TYPE_VLAN;
}
FREE(path);
- if (ret == NULL) {
+ if (ret == NETCF_IFACE_TYPE_NONE) {
xasprintf(&path, "/sys/class/net/%s/bridge", intf);
ERR_NOMEM(path == NULL, ncf);
if (stat (path, &stats) == 0 && S_ISDIR (stats.st_mode))
- ret = "bridge";
+ ret = NETCF_IFACE_TYPE_BRIDGE;
FREE(path);
}
- if (ret == NULL) {
+ if (ret == NETCF_IFACE_TYPE_NONE) {
xasprintf(&path, "/sys/class/net/%s/bonding", intf);
ERR_NOMEM(path == NULL, ncf);
if (stat (path, &stats) == 0 && S_ISDIR (stats.st_mode))
- ret = "bond";
+ ret = NETCF_IFACE_TYPE_BOND;
FREE(path);
}
- if (ret == NULL)
- ret = "ethernet";
+ if (ret == NETCF_IFACE_TYPE_NONE)
+ ret = NETCF_IFACE_TYPE_ETHERNET;
error:
FREE(path);
return ret;
}
+/* Given a netcf_if_type_t, return a const char * representation */
+const char *if_type_str(netcf_if_type_t type) {
+ switch (type) {
+ case NETCF_IFACE_TYPE_ETHERNET:
+ return "ethernet";
+ case NETCF_IFACE_TYPE_BOND:
+ return "bond";
+ case NETCF_IFACE_TYPE_BRIDGE:
+ return "bridge";
+ case NETCF_IFACE_TYPE_VLAN:
+ return "vlan";
+ default:
+ return NULL;
+ }
+}
+
+static int if_bridge_phys_name(struct netcf *ncf,
+ const char *intf, char ***phys_names) {
+ /* We can learn the name of the physical interface associated with
+ * this bridge by looking for the names of the links in
+ * /sys/class/net/$ifname/brif.
+ *
+ * The caller of this function must free the array of strings that is
+ * returned.
+ *
+ */
+ int r, ii, ret = 0;
+ char *dirpath = NULL;
+ DIR *dir = NULL;
+
+ *phys_names = NULL;
+
+ xasprintf(&dirpath, "/sys/class/net/%s/brif", intf);
+ ERR_NOMEM(dirpath == NULL, ncf);
+
+ dir = opendir(dirpath);
+ if (dir != NULL) {
+ struct dirent *d;
+
+ while ((d = readdir (dir)) != NULL) {
+ if (STRNEQ(d->d_name, ".") && STRNEQ(d->d_name, "..")) {
+ r = REALLOC_N(*phys_names, ret + 1);
+ ERR_NOMEM(r < 0, ncf);
+ ret++;
+ xasprintf(&((*phys_names)[ret - 1]), "%s", d->d_name);
+ ERR_NOMEM((*phys_names)[ret - 1] == NULL, ncf);
+ }
+ }
+ }
+ goto done;
+
+error:
+ for (ii = 0; ii < ret; ii++)
+ FREE((*phys_names)[ii]);
+ FREE(*phys_names);
+ *phys_names = NULL;
+ ret = -1;
+
+done:
+ if (dir)
+ closedir (dir);
+ FREE(dirpath);
+ return ret;
+
+}
+
/* Create a new netcf if instance for interface NAME */
struct netcf_if *make_netcf_if(struct netcf *ncf, char *name) {
int r;
@@ -602,24 +712,28 @@ int dutil_put_aug(struct netcf *ncf, const char *aug_xml, char **ncf_xml) {
return result;
}
+
+static void add_type_specific_info(struct netcf *ncf,
+ const char *ifname, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root);
+
/* Data that needs to be preserved between calls to the libnl iterator
* callback.
*/
-struct nl_callback_data {
+struct nl_ip_callback_data {
xmlDocPtr doc;
xmlNodePtr root;
xmlNodePtr protov4;
xmlNodePtr protov6;
- xmlNodePtr mac;
- struct netcf_if *nif;
+ struct netcf *ncf;
};
/* add all ip addresses for the given interface to the xml document
*/
-static void add_ips_cb(struct nl_object *obj, void *arg) {
- struct nl_callback_data *cb_data = arg;
+static void add_ip_info_cb(struct nl_object *obj, void *arg) {
+ struct nl_ip_callback_data *cb_data = arg;
struct rtnl_addr *addr = (struct rtnl_addr *)obj;
- struct netcf *ncf = cb_data->nif->ncf;
+ struct netcf *ncf = cb_data->ncf;
struct nl_addr *local_addr;
int family, prefix;
@@ -673,16 +787,8 @@ static void add_ips_cb(struct nl_object *obj, void *arg) {
if (*proto == NULL) {
/* No node exists for this protocol family. Create one.
*/
- *proto = xmlNewDocNode(cb_data->doc, NULL, BAD_CAST "protocol", NULL);
+ *proto = xml_new_node(cb_data->doc, cb_data->root, "protocol");
ERR_NOMEM(*proto == NULL, ncf);
-
- cur = xmlAddChild(cb_data->root, *proto);
- if (cur == NULL) {
- xmlFreeNode(*proto);
- *proto = NULL;
- report_error(ncf, NETCF_ENOMEM, NULL);
- goto error;
- }
prop = xmlSetProp(*proto, BAD_CAST "family", BAD_CAST family_str);
ERR_NOMEM(prop == NULL, ncf);
@@ -691,84 +797,316 @@ static void add_ips_cb(struct nl_object *obj, void *arg) {
/* Create a new ip node for this address/prefix, and set the
* properties
*/
- ip_node = xmlNewDocNode(cb_data->doc, NULL, BAD_CAST "ip", NULL);
- ERR_NOMEM((ip_node == NULL), ncf);
- cur = xmlAddChild(*proto, ip_node);
- if (cur == NULL) {
- xmlFreeNode(ip_node);
- report_error(ncf, NETCF_ENOMEM, NULL);
- goto error;
- }
+ ip_node = xml_new_node(cb_data->doc, *proto, "ip");
+ ERR_NOMEM(ip_node == NULL, ncf);
prop = xmlSetProp(ip_node, BAD_CAST "address", BAD_CAST ip_str);
- ERR_NOMEM((prop == NULL), ncf);
+ ERR_NOMEM(prop == NULL, ncf);
snprintf(prefix_str, sizeof(prefix_str), "%d", prefix);
prop = xmlSetProp(ip_node, BAD_CAST "prefix", BAD_CAST prefix_str);
- ERR_NOMEM((prop == NULL), ncf);
+ ERR_NOMEM(prop == NULL, ncf);
+
+error:
+ return;
+}
+static void add_ip_info(struct netcf *ncf,
+ const char *ifname ATTRIBUTE_UNUSED, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root) {
+ struct nl_ip_callback_data cb_data
+ = { doc, root, NULL, NULL, ncf };
+ struct rtnl_addr *filter_addr = NULL;
+
+ filter_addr = rtnl_addr_alloc();
+ ERR_NOMEM(filter_addr == NULL, ncf);
+
+ rtnl_addr_set_ifindex(filter_addr, ifindex);
+ nl_cache_foreach_filter(ncf->driver->addr_cache,
+ OBJ_CAST(filter_addr), add_ip_info_cb,
+ &cb_data);
error:
+ if (filter_addr)
+ rtnl_addr_put(filter_addr);
return;
}
-static void add_mac_cb(struct nl_object *obj, void *arg) {
- struct nl_callback_data *cb_data = arg;
+
+struct nl_ethernet_callback_data {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr mac;
+ struct netcf *ncf;
+};
+
+static void add_ethernet_info_cb(struct nl_object *obj, void *arg) {
+ struct nl_ethernet_callback_data *cb_data = arg;
struct rtnl_link *iflink = (struct rtnl_link *)obj;
- struct netcf *ncf = cb_data->nif->ncf;
+ struct netcf *ncf = cb_data->ncf;
struct nl_addr *addr;
- char mac_str[64];
- xmlNodePtr cur;
xmlAttrPtr prop = NULL;
- if (cb_data->mac != NULL)
+ if ((cb_data->mac == NULL)
+ && ((addr = rtnl_link_get_addr(iflink)) != NULL)
+ && !nl_addr_iszero(addr)) {
+
+ char mac_str[64];
+
+ nl_addr2str(addr, mac_str, sizeof(mac_str));
+ cb_data->mac = xml_node(cb_data->doc, cb_data->root, "mac");
+ ERR_NOMEM(cb_data->mac == NULL, ncf);
+ prop = xmlSetProp(cb_data->mac, BAD_CAST "address", BAD_CAST mac_str);
+ ERR_NOMEM(prop == NULL, ncf);
+ }
+error:
+ return;
+}
+
+static void add_ethernet_info(struct netcf *ncf,
+ const char *ifname ATTRIBUTE_UNUSED, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root) {
+ struct nl_ethernet_callback_data cb_data
+ = { doc, root, NULL, ncf };
+ struct rtnl_link *filter_link = NULL;
+
+ filter_link = rtnl_link_alloc();
+ ERR_NOMEM(filter_link == NULL, ncf);
+
+ rtnl_link_set_ifindex(filter_link, ifindex);
+ nl_cache_foreach_filter(ncf->driver->link_cache,
+ OBJ_CAST(filter_link), add_ethernet_info_cb,
+ &cb_data);
+error:
+ if (filter_link)
+ rtnl_link_put(filter_link);
+ return;
+}
+
+struct nl_vlan_callback_data {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr vlan;
+ struct netcf *ncf;
+};
+
+static void add_vlan_info_cb(struct nl_object *obj, void *arg) {
+ struct nl_vlan_callback_data *cb_data = arg;
+ struct rtnl_link *iflink = (struct rtnl_link *)obj;
+ struct netcf *ncf = cb_data->ncf;
+
+ struct rtnl_link *master_link;
+ char *master_name = NULL;
+ int l_link, vlan_id, master_ifindex;
+ char vlan_id_str[16];
+ char *link_type;
+ xmlNodePtr interface_node;
+ xmlAttrPtr prop = NULL;
+
+ /* If this really is a vlan link, get the master interface and vlan id.
+ */
+ if (cb_data->vlan != NULL)
return;
- addr = rtnl_link_get_addr(iflink);
- if ((addr == NULL) || nl_addr_iszero(addr))
+ link_type = rtnl_link_get_info_type(iflink);
+ if ((link_type == NULL) || STRNEQ(link_type, "vlan"))
return;
- nl_addr2str(addr, mac_str, sizeof(mac_str));
+ l_link = rtnl_link_get_link(iflink);
+ if (l_link == RTNL_LINK_NOT_FOUND)
+ return;
- for (cur = cb_data->root->children; cur != NULL; cur = cur->next) {
- if ((cur->type == XML_ELEMENT_NODE) &&
- xmlStrEqual(cur->name, BAD_CAST "mac")) {
- cb_data->mac = cur;
- break;
- }
- }
+ master_link = rtnl_link_get(nl_object_get_cache(obj), l_link);
+ if (master_link == NULL)
+ return;
- if (cb_data->mac == NULL) {
- /* No mac node exists in the document, create a new one.
- */
- cb_data->mac = xmlNewDocNode(cb_data->doc, NULL, BAD_CAST "mac", NULL);
- ERR_NOMEM(cb_data->mac == NULL, ncf);
+ master_name = rtnl_link_get_name(master_link);
+ if (master_name == NULL)
+ return;
- cur = xmlAddChild(cb_data->root, cb_data->mac);
- if (cur == NULL) {
- xmlFreeNode(cb_data->mac);
- cb_data->mac = NULL;
- report_error(ncf, NETCF_ENOMEM, NULL);
- goto error;
- }
+
+ cb_data->vlan = xml_node(cb_data->doc, cb_data->root, "vlan");
+ ERR_NOMEM(cb_data->vlan == NULL, ncf);
+
+ vlan_id = rtnl_link_vlan_get_id(iflink);
+ snprintf(vlan_id_str, sizeof(vlan_id_str), "%d", vlan_id);
+ prop = xmlSetProp(cb_data->vlan, BAD_CAST "tag", BAD_CAST vlan_id_str);
+ ERR_NOMEM(prop == NULL, ncf);
+
+ interface_node = xml_new_node(cb_data->doc, cb_data->vlan, "interface");
+ ERR_NOMEM(interface_node == NULL, ncf);
+
+ /* Add in type-specific info of master interface */
+ master_ifindex = rtnl_link_name2i(ncf->driver->link_cache, master_name);
+ ERR_THROW((master_ifindex == RTNL_LINK_NOT_FOUND), ncf, ENETLINK,
+ "couldn't find ifindex for vlan master interface `%s`",
+ master_name);
+ add_type_specific_info(ncf, master_name, master_ifindex,
+ cb_data->doc, interface_node);
+
+error:
+ return;
+}
+
+static void add_vlan_info(struct netcf *ncf,
+ const char *ifname ATTRIBUTE_UNUSED, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root) {
+ struct nl_vlan_callback_data cb_data
+ = { doc, root, NULL, ncf };
+ struct rtnl_link *filter_link = NULL;
+
+ filter_link = rtnl_link_alloc();
+ ERR_NOMEM(filter_link == NULL, ncf);
+
+ rtnl_link_set_ifindex(filter_link, ifindex);
+ nl_cache_foreach_filter(ncf->driver->link_cache,
+ OBJ_CAST(filter_link), add_vlan_info_cb,
+ &cb_data);
+ ERR_BAIL(ncf);
+error:
+ if (filter_link)
+ rtnl_link_put(filter_link);
+ return;
+}
+
+static void add_bridge_info(struct netcf *ncf,
+ const char *ifname, int ifindex ATTRIBUTE_UNUSED,
+ xmlDocPtr doc, xmlNodePtr root) {
+ char **phys_names;
+ int nphys, ii;
+ xmlNodePtr bridge_node = NULL, interface_node = NULL;
+
+ nphys = if_bridge_phys_name(ncf, ifname, &phys_names);
+ if (nphys <= 0)
+ return;
+
+ bridge_node = xml_node(doc, root, "bridge");
+ ERR_NOMEM(bridge_node == NULL, ncf);
+
+ for (ii = 0; ii < nphys; ii++) {
+ int phys_ifindex;
+
+ interface_node = xml_new_node(doc, bridge_node, "interface");
+ ERR_NOMEM(interface_node == NULL, ncf);
+
+ /* Add in type-specific info of physical interface */
+ phys_ifindex = rtnl_link_name2i(ncf->driver->link_cache, phys_names[ii]);
+ ERR_THROW((phys_ifindex == RTNL_LINK_NOT_FOUND), ncf, ENETLINK,
+ "couldn't find ifindex for physical interface `%s` of bridge %s",
+ phys_names[ii], ifname);
+
+ add_type_specific_info(ncf, phys_names[ii], phys_ifindex, doc, interface_node);
}
- prop = xmlSetProp(cb_data->mac, BAD_CAST "address", BAD_CAST mac_str);
+error:
+ for (ii = 0; ii < nphys; ii++)
+ FREE(phys_names[ii]);
+ FREE(phys_names);
+}
+
+
+struct nl_bond_callback_data {
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ xmlNodePtr bond;
+ int master_ifindex;
+ struct netcf *ncf;
+};
+
+static void add_bond_info_cb(struct nl_object *obj, void *arg ATTRIBUTE_UNUSED) {
+ struct nl_bond_callback_data *cb_data = arg;
+ struct rtnl_link *iflink = (struct rtnl_link *)obj;
+ struct netcf *ncf = cb_data->ncf;
+
+ xmlNodePtr interface_node;
+
+ /* If this is a slave link, and the master is master_ifindex, add the interface
+ * info to the bond.
+ */
+
+ if (!(rtnl_link_get_flags(iflink) & IFF_SLAVE)
+ || rtnl_link_get_master(iflink) != cb_data->master_ifindex)
+ return;
+
+ cb_data->bond = xml_node(cb_data->doc, cb_data->root, "bond");
+ ERR_NOMEM(cb_data->bond == NULL, ncf);
+
+ /* XXX - if we learn where to get bridge "mode" property, set it here */
+
+ /* XXX - need to add node like one of these:
+ *
+ * <miimon freq="100" updelay="10" carrier="ioctl"/>
+ * or
+ * <arpmode interval='something' target='something'>
+ */
+
+ /* add a new interface node */
+ interface_node = xml_new_node(cb_data->doc, cb_data->bond, "interface");
+ ERR_NOMEM(interface_node == NULL, ncf);
+
+ /* Add in type-specific info of this slave interface */
+ add_type_specific_info(ncf, rtnl_link_get_name(iflink),
+ rtnl_link_get_ifindex(iflink),
+ cb_data->doc, interface_node);
+error:
+ return;
+}
+
+static void add_bond_info(struct netcf *ncf,
+ const char *ifname ATTRIBUTE_UNUSED, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root) {
+ struct nl_bond_callback_data cb_data
+ = { doc, root, NULL, ifindex, ncf };
+
+ nl_cache_foreach(ncf->driver->link_cache, add_bond_info_cb, &cb_data);
+}
+
+
+static void add_type_specific_info(struct netcf *ncf,
+ const char *ifname, int ifindex,
+ xmlDocPtr doc, xmlNodePtr root) {
+ xmlAttrPtr prop;
+ netcf_if_type_t iftype;
+ const char *iftype_str;
+
+ prop = xmlNewProp(root, BAD_CAST "name", BAD_CAST ifname);
ERR_NOMEM(prop == NULL, ncf);
+ iftype = if_type(ncf, ifname);
+ ERR_BAIL(ncf);
+ iftype_str = if_type_str(iftype);
+
+ if (iftype_str) {
+ prop = xmlSetProp(root, BAD_CAST "type", BAD_CAST if_type_str(iftype));
+ ERR_NOMEM(prop == NULL, ncf);
+ }
+
+ switch (iftype) {
+ case NETCF_IFACE_TYPE_ETHERNET:
+ add_ethernet_info(ncf, ifname, ifindex, doc, root);
+ break;
+ case NETCF_IFACE_TYPE_BRIDGE:
+ add_bridge_info(ncf, ifname, ifindex, doc, root);
+ break;
+ case NETCF_IFACE_TYPE_VLAN:
+ add_vlan_info(ncf, ifname, ifindex, doc, root);
+ break;
+ case NETCF_IFACE_TYPE_BOND:
+ add_bond_info(ncf, ifname, ifindex, doc, root);
+ break;
+ default:
+ break;
+ }
error:
return;
}
void add_state_to_xml_doc(struct netcf_if *nif, xmlDocPtr doc) {
-
- struct nl_callback_data cb_data = { doc, NULL, NULL, NULL, NULL, nif };
- struct rtnl_addr *filter_addr = NULL;
- struct rtnl_link *filter_link = NULL;
+ xmlNodePtr root;
int ifindex, code;
- cb_data.root = xmlDocGetRootElement(doc);
- ERR_THROW((cb_data.root == NULL), nif->ncf, EINTERNAL,
+ root = xmlDocGetRootElement(doc);
+ ERR_THROW((root == NULL), nif->ncf, EINTERNAL,
"failed to get document root element");
- ERR_THROW(!xmlStrEqual(cb_data.root->name, BAD_CAST "interface"),
+ ERR_THROW(!xmlStrEqual(root->name, BAD_CAST "interface"),
nif->ncf, EINTERNAL, "root document is not an interface");
/* Update the caches with any recent changes */
@@ -781,39 +1119,17 @@ void add_state_to_xml_doc(struct netcf_if *nif, xmlDocPtr doc) {
ERR_THROW((code < 0), nif->ncf, ENETLINK,
"failed to refill interface address cache");
- /* The addr cache only knows about ifindex, not name */
ifindex = rtnl_link_name2i(nif->ncf->driver->link_cache, nif->name);
ERR_THROW((ifindex == RTNL_LINK_NOT_FOUND), nif->ncf, ENETLINK,
- "Could find ifindex for interface `%s`", nif->name);
+ "couldn't find ifindex for interface `%s`", nif->name);
- /* Build an rtnl_link with the interface index set, and use it to
- * find the entry for this interface and extract the mac
- * address.
- */
- filter_link = rtnl_link_alloc();
- ERR_NOMEM((filter_link == NULL), nif->ncf);
+ add_type_specific_info(nif->ncf, nif->name, ifindex, doc, root);
+ ERR_BAIL(nif->ncf);
- rtnl_link_set_ifindex(filter_link, ifindex);
- nl_cache_foreach_filter(nif->ncf->driver->link_cache,
- OBJ_CAST(filter_link), add_mac_cb,
- &cb_data);
-
- /* Build an rtnl_addr with the interface name set. This is used by
- * the iterator to filter the contents of the address cache.
- */
- filter_addr = rtnl_addr_alloc();
- ERR_NOMEM((filter_addr == NULL), nif->ncf);
-
- rtnl_addr_set_ifindex(filter_addr, ifindex);
+ add_ip_info(nif->ncf, nif->name, ifindex, doc, root);
+ ERR_BAIL(nif->ncf);
- nl_cache_foreach_filter(nif->ncf->driver->addr_cache,
- OBJ_CAST(filter_addr), add_ips_cb,
- &cb_data);
error:
- if (filter_addr)
- rtnl_addr_put(filter_addr);
- if (filter_link)
- rtnl_link_put(filter_link);
return;
}
diff --git a/src/dutil.h b/src/dutil.h
index 93dae1a..90dc59a 100644
--- a/src/dutil.h
+++ b/src/dutil.h
@@ -122,10 +122,23 @@ int netlink_close(struct netcf *ncf);
/* Check if the interface INTF is up using an ioctl call */
int if_is_active(struct netcf *ncf, const char *intf);
-/* return the type of the interface - "ethernet" (physical device),
- * "bridge", "bond", or "vlan"
+/* Interface types recognized by netcf. */
+typedef enum {
+ NETCF_IFACE_TYPE_NONE = 0, /* not yet determined */
+ NETCF_IFACE_TYPE_ETHERNET, /* any physical device is "ethernet" */
+ NETCF_IFACE_TYPE_BOND,
+ NETCF_IFACE_TYPE_BRIDGE,
+ NETCF_IFACE_TYPE_VLAN,
+} netcf_if_type_t;
+
+/* Return the type of the interface.
*/
-const char *if_type(struct netcf *ncf, const char *intf);
+netcf_if_type_t if_type(struct netcf *ncf, const char *intf);
+
+/* Given a netcf_if_type_t enum value, return a const char *representation
+ * This pointer has an indefinite life, and shouldn't be / can't be free'd.
+ */
+const char *if_type_str(netcf_if_type_t type);
/* Create a new netcf if instance for interface NAME */
struct netcf_if *make_netcf_if(struct netcf *ncf, char *name);
--
1.6.5.15.gc274d
More information about the netcf-devel
mailing list