File netcf-suse.patch of Package netcf
From:Patrick Mullaney <pmullaney@novell.com>
From: root <root@novy.(none)>
netcf: Suse backend for netcf
These changes address basic ethernet physical interface configuration.
Bridging and vlan configuration needs to be tested and addressed still.
Signed-off-by: Patrick Mullaney <pmullaney@novell.com>
---
Makefile.am | 2
data/xml/initscripts-get.xsl | 51 +++-
data/xml/initscripts-put.xsl | 7 -
src/Makefile.am | 1
src/drv_initscripts.c | 570 ++++++++++++++++++++++++++----------------
src/dutil.c | 32 ++
src/dutil.h | 3
7 files changed, 432 insertions(+), 234 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 416a9ad..f4f8cb6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,7 @@ dist_xml_DATA=data/xml/augeas.rng data/xml/interface.rng \
data/xml/util-get.xsl data/xml/util-put.xsl \
data/xml/initscripts-get.xsl data/xml/initscripts-put.xsl
dist_netcf_DATA=data/iptables-forward-bridged
-dist_lens_DATA=data/lenses/netcf.aug data/lenses/sysconfig.aug
+dist_lens_DATA=data/lenses/netcf.aug data/lenses/sysconfig.aug data/lenses/persist_net_rules.aug data/lenses/routes.aug
# This requires that trang is installed, but we don't want to require
# that, even for building, since the .rnc files are only a convenience
diff --git a/data/xml/initscripts-get.xsl b/data/xml/initscripts-get.xsl
index fab8ecb..dd5dff6 100644
--- a/data/xml/initscripts-get.xsl
+++ b/data/xml/initscripts-get.xsl
@@ -47,9 +47,10 @@
<xsl:template name="vlan-interface-common">
<xsl:variable name="iface" select="concat(vlan/interface/@name, '.', vlan/@tag)"/>
- <xsl:attribute name="path">/files/etc/sysconfig/network-scripts/ifcfg-<xsl:value-of select="$iface"/></xsl:attribute>
+ <xsl:attribute name="path">/files/etc/sysconfig/network/ifcfg-<xsl:value-of select="$iface"/></xsl:attribute>
<node label="DEVICE" value="{$iface}"/>
- <node label="VLAN" value="yes"/>
+ <node label="ETHERDEVICE" value="{vlan/interface/@name}"/>
+ <!-- <node label="VLAN" value="yes"/> -->
</xsl:template>
<xsl:template name='bare-vlan-interface'>
@@ -67,15 +68,21 @@
<xsl:call-template name="name-attr"/>
<xsl:call-template name="startmode"/>
<xsl:call-template name="mtu"/>
- <node label="TYPE" value="Bridge"/>
+ <node label="BRIDGE" value="yes"/>
<xsl:call-template name="interface-addressing"/>
<xsl:if test="bridge/@stp">
- <node label="STP" value="{bridge/@stp}"/>
+ <node label="BRIDGE_STP" value="{bridge/@stp}"/>
</xsl:if>
<xsl:if test="bridge/@delay">
- <node label="DELAY" value="{bridge/@delay}"/>
+ <node label="BRIDGE_FORWARDDELAY" value="{bridge/@delay}"/>
</xsl:if>
- </tree>
+ <xsl:variable name="bridges">
+ <xsl:for-each select="//bridge/interface">
+ <xsl:text> </xsl:text><xsl:value-of select="@name"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <node label="BRIDGE_PORTS"> <xsl:attribute name="value"> <xsl:value-of select="$bridges"/></xsl:attribute></node>
+ </tree>
<xsl:for-each select='bridge/interface'>
<tree>
<xsl:if test="@type = 'ethernet'">
@@ -87,7 +94,6 @@
<xsl:if test="@type = 'bond'">
<xsl:call-template name="bare-bond-interface"/>
</xsl:if>
- <node label="BRIDGE" value="{../../@name}"/>
</tree>
<xsl:if test="@type = 'bond'">
<xsl:call-template name="bond-slaves"/>
@@ -102,8 +108,6 @@
<xsl:for-each select='bond/interface'>
<tree>
<xsl:call-template name="bare-ethernet-interface"/>
- <node label="MASTER" value="{../../@name}"/>
- <node label="SLAVE" value="yes"/>
</tree>
</xsl:for-each>
</xsl:template>
@@ -129,6 +133,13 @@
<xsl:call-template name="startmode"/>
<xsl:call-template name="mtu"/>
<xsl:call-template name="interface-addressing"/>
+ <node label="BONDING_MASTER" value="yes"/>
+ <xsl:for-each select="//bond/interface">
+ <node>
+ <xsl:attribute name="label">BONDING_SLAVE_<xsl:copy-of select='position()-1'/></xsl:attribute>
+ <xsl:attribute name="value"><xsl:value-of select="@name"/></xsl:attribute>
+ </node>
+ </xsl:for-each>
<xsl:call-template name="bonding-opts-node"/>
</tree>
<xsl:call-template name="bond-slaves"/>
@@ -138,7 +149,7 @@
Named templates, following the Relax NG syntax
-->
<xsl:template name="name-attr">
- <xsl:attribute name="path">/files/etc/sysconfig/network-scripts/ifcfg-<xsl:value-of select="@name"/></xsl:attribute>
+ <xsl:attribute name="path">/files/etc/sysconfig/network/ifcfg-<xsl:value-of select="@name"/></xsl:attribute>
<node label="DEVICE" value="{@name}"/>
</xsl:template>
@@ -155,20 +166,23 @@
</xsl:if>
<xsl:call-template name="startmode"/>
<xsl:call-template name="mtu"/>
+ <node label="BOOTPROTO" value="none"/>
</xsl:template>
<xsl:template name="startmode">
<xsl:choose>
<xsl:when test="$g_startmode = 'onboot'">
- <node label="ONBOOT" value="yes"/>
+ <node label="STARTMODE" value="auto"/>
</xsl:when>
<xsl:when test="$g_startmode = 'none'">
- <node label="ONBOOT" value="no"/>
+ <node label="STARTMODE" value="manual"/>
</xsl:when>
<xsl:when test="$g_startmode = 'hotplug'">
- <node label="ONBOOT" value="no"/>
- <node label="HOTPLUG" value="yes"/>
+ <node label="STARTMODE" value="ifplugd"/>
</xsl:when>
+ <xsl:otherwise>
+ <node label="STARTMODE" value="manual"/>
+ </xsl:otherwise>
</xsl:choose>
</xsl:template>
@@ -185,12 +199,12 @@
<xsl:choose>
<xsl:when test="dhcp">
<node label="BOOTPROTO" value="dhcp"/>
- <xsl:if test="dhcp/@peerdns">
+ <!-- <xsl:if test="dhcp/@peerdns">
<node label="PEERDNS" value="{dhcp/@peerdns}"/>
- </xsl:if>
+ </xsl:if> -->
</xsl:when>
<xsl:when test="ip">
- <node label="BOOTPROTO" value="none"/>
+ <node label="BOOTPROTO" value="static"/>
<node label="IPADDR" value="{ip/@address}"/>
<xsl:if test="ip/@prefix">
<node label="NETMASK" value="{ipcalc:netmask(ip/@prefix)}"/>
@@ -199,6 +213,9 @@
<node label="GATEWAY" value="{route/@gateway}"/>
</xsl:if>
</xsl:when>
+ <xsl:otherwise>
+ <node label="BOOTPROTO" value="none"/>
+ </xsl:otherwise>
</xsl:choose>
</xsl:template>
diff --git a/data/xml/initscripts-put.xsl b/data/xml/initscripts-put.xsl
index 267d9cd..1b5145a 100644
--- a/data/xml/initscripts-put.xsl
+++ b/data/xml/initscripts-put.xsl
@@ -140,12 +140,15 @@
-->
<xsl:template name="startmode">
<xsl:choose>
- <xsl:when test="node[@label ='HOTPLUG']/@value = 'yes'">
+ <xsl:when test="node[@label ='STARTMODE']/@value = 'yes'">
<start mode='hotplug'/>
</xsl:when>
- <xsl:when test="node[@label = 'ONBOOT']/@value = 'yes'">
+ <xsl:when test="node[@label = 'STARTMODE']/@value = 'auto'">
<start mode='onboot'/>
</xsl:when>
+ <xsl:when test="node[@label = 'STARTMODE']/@value = 'manual'">
+ <start mode='manual'/>
+ </xsl:when>
<xsl:otherwise>
<start mode='none'/>
</xsl:otherwise>
diff --git a/src/Makefile.am b/src/Makefile.am
index 9d8a3d7..daa54d9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,7 +31,6 @@ libnetcf_la_SOURCES = netcf.h netcf.c internal.h \
libnetcf_la_LDFLAGS = -Wl,--version-script=netcf.syms \
-version-info $(LIBNETCF_VERSION_INFO)
libnetcf_la_LIBADD = $(NETCF_LIBDEPS) $(GNULIB)
-libnetcf_la_DEPENDENCIES = $(libnetcf_la_LIBADD) netcf.syms
ncftool_SOURCES = ncftool.c
ncftool_LDADD = libnetcf.la $(READLINE_LIBS) $(GNULIB)
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index d5bbd44..1878875 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -1,6 +1,7 @@
/*
- * drv_initscripts.c: the initscripts backend for netcf
+ * drv_initscripts.c: the initscripts backend for suse
*
+ * Copyright (C) 2010 Novell Inc.
* Copyright (C) 2009 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
@@ -17,7 +18,10 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Author: David Lutterkort <lutter@redhat.com>
+ * Derived from the drv_initscripts.c for the Redhat backend authored
+ * by David Lutterkort.
+ *
+ * Author: Patrick Mullaney <pmullaney@novell.com>
*/
#include <config.h>
@@ -30,6 +34,9 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
#include "safe-alloc.h"
#include "ref.h"
@@ -47,18 +54,44 @@
#include <libexslt/exslt.h>
+#define NETRULE_PATH "/etc/udev/rules.d/70-persistent-net.rules"
+
+static const char *const aug_files =
+ "/files";
+
static const char *const network_scripts_path =
- "/files/etc/sysconfig/network-scripts";
+ "/etc/sysconfig/network";
static const char *const ifcfg_path =
- "/files/etc/sysconfig/network-scripts/*";
+ "/files/etc/sysconfig/network/*";
+
+static const char *const udev_netrule_path =
+ NETRULE_PATH;
+
+static const char *const ifcfg_prefix =
+ "ifcfg-";
/* Augeas should only load the files we are interested in */
static const struct augeas_pv augeas_xfm_common_pv[] = {
+ /* Netrule files */
+ { "/augeas/load/Persist_Net_Rules/lens", "Persist_Net_Rules.lns" },
+ { "/augeas/load/Persist_Net_Rules/incl", NETRULE_PATH },
+ { "/augeas/load/Persist_Net_Rules/excl[1]", "*.augnew" },
+ { "/augeas/load/Persist_Net_Rules/excl[2]", "*.augsave" },
+ { "/augeas/load/Persist_Net_Rules/excl[3]", "*.rpmsave" },
+ { "/augeas/load/Persist_Net_Rules/excl[4]", "*.rpmnew" },
+ { "/augeas/load/Persist_Net_Rules/excl[5]", "*~" },
+ /* Routes files */
+ { "/augeas/load/Routes/lens", "Routes.lns" },
+ { "/augeas/load/Routes/incl", "/etc/sysconfig/network/routes" },
+ { "/augeas/load/Routes/excl[1]", "*.augnew" },
+ { "/augeas/load/Routes/excl[2]", "*.augsave" },
+ { "/augeas/load/Routes/excl[3]", "*.rpmsave" },
+ { "/augeas/load/Routes/excl[4]", "*.rpmnew" },
+ { "/augeas/load/Routes/excl[5]", "*~" },
/* Ifcfg files */
{ "/augeas/load/Ifcfg/lens", "Sysconfig.lns" },
- { "/augeas/load/Ifcfg/incl",
- "/etc/sysconfig/network-scripts/ifcfg-*" },
+ { "/augeas/load/Ifcfg/incl", "/etc/sysconfig/network/ifcfg-*" },
{ "/augeas/load/Ifcfg/excl[1]", "*~" },
{ "/augeas/load/Ifcfg/excl[2]", "*.bak" },
{ "/augeas/load/Ifcfg/excl[3]", "*.orig" },
@@ -108,13 +141,14 @@ static const char *const prog_rc_d_iptables = "/etc/init.d/iptables";
* is not a toplevel interface
*/
static const char *const subif_paths[] = {
- "MASTER", "BRIDGE"
+ "BONDING_MASTER", "BRIDGE"
};
static int is_slave(struct netcf *ncf, const char *intf) {
for (int s = 0; s < ARRAY_CARDINALITY(subif_paths); s++) {
int r;
- r = aug_fmt_match(ncf, NULL, "%s/%s", intf, subif_paths[s]);
+ r = aug_fmt_match(ncf, NULL, "%s%s/ifcfg-%s/%s",
+ aug_files, network_scripts_path, intf, subif_paths[s]);
if (r != 0)
return r;
}
@@ -122,14 +156,23 @@ static int is_slave(struct netcf *ncf, const char *intf) {
}
static bool has_ifcfg_file(struct netcf *ncf, const char *name) {
- int nmatches;
+ struct augeas *aug = NULL;
+ char *path = NULL;
+ int nmatches = 0, r;
- nmatches = aug_fmt_match(ncf, NULL,
- "%s[ DEVICE = '%s'"
- " or BRIDGE = '%s'"
- " or MASTER = '%s'"
- " or MASTER = ../*[BRIDGE = '%s']/DEVICE ]/DEVICE",
- ifcfg_path, name, name, name, name);
+ aug = get_augeas(ncf);
+ ERR_BAIL(ncf);
+
+ /* if ifcfg-NAME exists, true */
+ r = xasprintf(&path, "%s/%s/ifcfg-%s", aug_files, network_scripts_path, name);
+ ERR_NOMEM(r < 0, ncf);
+
+ nmatches = aug_match(aug, path, NULL);
+ ERR_COND_BAIL(nmatches < 0, ncf, EOTHER);
+
+ FREE(path);
+
+error:
return nmatches > 0;
}
@@ -139,76 +182,114 @@ static int cmpstrp(const void *p1, const void *p2) {
return strcmp(s1, s2);
}
-/* Find the path to the ifcfg file that has the configuration for the
- * interface with MAC address MAC.
- */
-static char *find_ifcfg_path_by_hwaddr(struct netcf *ncf, const char *mac) {
- static const char *const hwaddr_str = "/HWADDR";
+static int
+find_ifcfg_file_by_name(struct netcf *ncf, const char *name, char ***intf)
+{
+ DIR *dp;
+ struct dirent *ent;
+ const char *ifprefix = "ifcfg-";
+ const char *ifdir = network_scripts_path;
+ int found=-1, result=0, r=0;
+
+ dp = opendir (ifdir);
+ ERR_COND_BAIL(dp == NULL, ncf, EOTHER);
+ r = ALLOC_N(*intf, 1);
+ while ((ent = readdir (dp)))
+ if (ent->d_type == DT_REG &&
+ !strncmp(ifprefix, ent->d_name, strlen(ifprefix)) &&
+ strlen(ent->d_name + strlen(ifprefix)) == strlen(name) &&
+ !strncmp((ent->d_name + strlen(ifprefix)),name, strlen(name))) {
+ result = xasprintf( &(*intf)[0], "%s",
+ ent->d_name + strlen(ifprefix));
+ ERR_NOMEM(result < 0, ncf);
+ found = 1;
+ }
+ closedir (dp);
- int nhwaddr = 0, r;
- char **hwaddr = NULL;
- struct augeas *aug = NULL;
+ return found;
- aug = get_augeas(ncf);
- ERR_BAIL(ncf);
+error:
+ FREE((*intf)[0]);
+ FREE((*intf));
+ return -1;
+}
- // It would be nice if Augeas provided a way to do case-insensitive
- // matching. For now, we just write it out
- nhwaddr = aug_fmt_match(ncf, &hwaddr, "%s%s", ifcfg_path, hwaddr_str);
- ERR_COND_BAIL(nhwaddr < 0, ncf, EOTHER);
-
- /* Sort because need_config will return the last match in case
- * of multiple matches */
- qsort(hwaddr, nhwaddr, sizeof(*hwaddr), cmpstrp);
- int match = -1;
- for (int i=0; i < nhwaddr; i++) {
- const char *addr;
- r = aug_get(aug, hwaddr[i], &addr);
- ERR_COND_BAIL(r != 1, ncf, EOTHER);
- if (STRCASEEQ(addr, mac))
- match = i;
- }
- if (match != -1) {
- char *path = hwaddr[match];
- hwaddr[match] = NULL;
- path[strlen(path) - strlen(hwaddr_str)] = '\0';
- free_matches(nhwaddr, &hwaddr);
- return path;
+static int
+find_ifcfg_files(struct netcf *ncf, char ***intf)
+{
+ DIR *dp;
+ struct dirent *ent;
+ const char *ifprefix = "ifcfg-";
+ const char *ifdir = network_scripts_path;
+ int count = 0, result =0, r =0;;
+
+ dp = opendir (ifdir);
+ ERR_COND_BAIL(dp == NULL, ncf, EOTHER);
+ while ((ent = readdir (dp)))
+ if (ent->d_type == DT_REG &&
+ !strncmp(ifprefix, ent->d_name, strlen(ifprefix))) {
+ count++;
+ }
+ closedir (dp);
+
+ dp = opendir (ifdir);
+ ERR_COND_BAIL(dp == NULL, ncf, EOTHER);
+ r = ALLOC_N(*intf, count);
+ ERR_NOMEM(r < 0, ncf);
+ count = 0;
+ while ((ent = readdir (dp))) {
+ if (ent->d_type == DT_REG &&
+ !strncmp(ifprefix, ent->d_name, strlen(ifprefix))) {
+ result = xasprintf( &(*intf)[count], "%s",
+ ent->d_name + strlen(ifprefix));
+ ERR_NOMEM(result < 0, ncf);
+ count++;
+ }
}
- error:
- free_matches(nhwaddr, &hwaddr);
- return NULL;
+ closedir (dp);
+
+ qsort(*intf, count, sizeof(**intf), cmpstrp);
+
+ return count;
+
+error:
+ for(;count>=0;count--)
+ FREE((*intf)[count]);
+ FREE((*intf));
+ return -1;
}
-/* Find the path to the ifcfg file that has the configuration for the
- * interface by checking for an entry 'DEVICE=NAME'
+/* Find the mac address given the interface name in the udev persistent
+ * netrule file.
*/
-static char *find_ifcfg_path_by_device(struct netcf *ncf, const char *name) {
+static int find_hwaddr_by_device(struct netcf *ncf, const char *name,
+ const char **addr) {
+ int nmatches = 0, r;
+ char **matches = NULL;
struct augeas *aug = NULL;
- int ndevs = 0;
- char **devs = NULL;
+ char *path = NULL;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
- ndevs = aug_fmt_match(ncf, &devs, "%s[DEVICE = '%s']",
- ifcfg_path, name);
- ERR_COND_BAIL(ndevs < 0, ncf, EOTHER);
-
- if (ndevs == 0)
- return NULL;
+ nmatches = aug_fmt_match(ncf, &matches, "%s/%s/*[ NAME = '%s']",
+ aug_files, udev_netrule_path, name);
+ ERR_COND_BAIL(nmatches < 0 , ncf, EOTHER);
- qsort(devs, ndevs, sizeof(*devs), cmpstrp);
-
- char *path = devs[ndevs - 1];
- devs[ndevs - 1] = NULL;
-
- free_matches(ndevs, &devs);
+ if (nmatches == 1 ) {
+ r = xasprintf(&path, "%s/%s", matches[0], "ATTR{address}");
+ ERR_NOMEM(r < 0, ncf);
+ *addr = NULL; /* ensure that addr is NULL */
+ r = aug_get(aug, path, addr);
+ FREE(path);
+ } else
+ goto error;
- return path;
+ free_matches(nmatches, &matches);
+ return nmatches;
error:
- free_matches(ndevs, &devs);
- return NULL;
+ free_matches(nmatches, &matches);
+ return 0;
}
/* Find the path to the ifcfg file that has the configuration for
@@ -218,14 +299,13 @@ static char *find_ifcfg_path_by_device(struct netcf *ncf, const char *name) {
static char *find_ifcfg_path(struct netcf *ncf, const char *name) {
struct augeas *aug = NULL;
char *path = NULL;
- const char *mac = NULL;
int r, nmatches;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
/* if ifcfg-NAME exists, use that */
- r = xasprintf(&path, "%s/ifcfg-%s", network_scripts_path, name);
+ r = xasprintf(&path, "%s/%s/ifcfg-%s", aug_files, network_scripts_path, name);
ERR_NOMEM(r < 0, ncf);
nmatches = aug_match(aug, path, NULL);
@@ -234,98 +314,10 @@ static char *find_ifcfg_path(struct netcf *ncf, const char *name) {
if (nmatches == 1)
return path;
- FREE(path);
-
- /* Now find the config by MAC, matching on HWADDR */
- r = aug_get_mac(ncf, name, &mac);
- ERR_COND_BAIL(r < 0, ncf, EOTHER);
- if (r > 0) {
- path = find_ifcfg_path_by_hwaddr(ncf, mac);
- ERR_BAIL(ncf);
- if (path != NULL)
- return path;
- }
-
- path = find_ifcfg_path_by_device(ncf, name);
- ERR_BAIL(ncf);
-
- return path;
error:
FREE(path);
- return NULL;
-}
-
-/* Given NDEVS path to DEVICE entries which may contain duplicate devices,
- * produce a list of canonical paths to the interfaces in INTF and return
- * the number of entries. Return -1 on error
- */
-static int uniq_ifcfg_paths(struct netcf *ncf,
- int ndevs, char **devs,
- char ***intf) {
- struct augeas *aug;
- int r;
- int ndevnames = 0;
- const char **devnames = NULL;
- aug = get_augeas(ncf);
- ERR_BAIL(ncf);
-
- /* List unique device names */
- r = ALLOC_N(devnames, ndevs);
- ERR_NOMEM(r < 0, ncf);
-
- for (int i=0; i < ndevs; i++) {
- const char *name = NULL;
- r = aug_get(aug, devs[i], &name);
- ERR_COND_BAIL(r != 1, ncf, EOTHER);
- int exists = 0;
- for (int j = 0; j < ndevnames; j++)
- if (STREQ(name, devnames[j])) {
- exists = 1;
- break;
- }
- if (!exists)
- devnames[ndevnames++] = name;
- }
- qsort(devnames, ndevnames, sizeof(*devnames), cmpstrp);
-
- /* Find canonical config for each device name */
- r = ALLOC_N(*intf, ndevnames);
- ERR_NOMEM(r < 0, ncf);
- for (int i= 0; i < ndevnames; i++) {
- (*intf)[i] = find_ifcfg_path(ncf, devnames[i]);
- ERR_BAIL(ncf);
- }
-
- FREE(devnames);
- return ndevnames;
-
- error:
- FREE(devnames);
- free_matches(ndevnames, intf);
- return -1;
-}
-
-/* List all configured network devices; returns the number of devices or -1
- * on error. On success, the path to the config file for each interface
- * is returned in INTF
- */
-static int list_ifcfg_paths(struct netcf *ncf, char ***intf) {
- int result = 0, ndevs;
- char **devs = NULL;
-
- ndevs = aug_fmt_match(ncf, &devs, "%s/DEVICE", ifcfg_path);
- ERR_COND_BAIL(ndevs < 0, ncf, EOTHER);
-
- result = uniq_ifcfg_paths(ncf, ndevs, devs, intf);
- ERR_BAIL(ncf);
-
- free_matches(ndevs, &devs);
- return result;
-
- error:
- free_matches(ndevs, &devs);
- return -1;
+ return NULL;
}
static int list_interfaces(struct netcf *ncf, char ***intf) {
@@ -335,8 +327,8 @@ static int list_interfaces(struct netcf *ncf, char ***intf) {
aug = get_augeas(ncf);
ERR_BAIL(ncf);
- /* Look in augeas for all interfaces */
- nint = list_ifcfg_paths(ncf, intf);
+ /* Look for all interfaces */
+ nint = find_ifcfg_files(ncf, intf);
ERR_BAIL(ncf);
result = nint;
@@ -491,6 +483,7 @@ int drv_init(struct netcf *ncf) {
goto error;
// FIXME: Check for errors
+
xsltInit();
exsltStrRegister();
ncf->driver->get = parse_stylesheet(ncf, "initscripts-get.xsl");
@@ -498,8 +491,10 @@ int drv_init(struct netcf *ncf) {
ncf->driver->rng = rng_parse(ncf, "interface.rng");
ERR_BAIL(ncf);
+#ifdef NCF_CHECK_BRIDGING_RULES
bridge_physdevs(ncf);
ERR_BAIL(ncf);
+#endif
/* open a socket for interface ioctls */
ncf->driver->ioctl_fd = init_ioctl_fd(ncf);
@@ -534,11 +529,10 @@ void drv_entry(struct netcf *ncf) {
static int list_interface_ids(struct netcf *ncf,
int maxnames, char **names,
- unsigned int flags,
- const char *id_attr) {
+ unsigned int flags) {
struct augeas *aug = NULL;
- int nint = 0, nmatches = 0, nqualified = 0, result = 0, r;
- char **intf = NULL, **matches = NULL;
+ int nint = 0, nqualified = 0, result = 0;
+ char **intf = NULL;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
@@ -547,17 +541,13 @@ static int list_interface_ids(struct netcf *ncf,
if (!names) {
maxnames = nint; /* if not returning list, ignore maxnames too */
}
+
for (result = 0; (result < nint) && (nqualified < maxnames); result++) {
- nmatches = aug_fmt_match(ncf, &matches,
- "%s/%s", intf[result], id_attr);
- ERR_BAIL(ncf);
- if (nmatches > 0) {
const char *name;
int is_qualified = ((flags & (NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE))
- == (NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE));
+ == (NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE));
- r = aug_get(aug, matches[nmatches-1], &name);
- ERR_COND_BAIL(r < 0, ncf, EOTHER);
+ name = intf[result];
if (!is_qualified) {
int is_active = if_is_active(ncf, name);
@@ -575,24 +565,21 @@ static int list_interface_ids(struct netcf *ncf,
}
nqualified++;
}
- }
- free_matches(nmatches, &matches);
}
free_matches(nint, &intf);
return nqualified;
error:
- free_matches(nmatches, &matches);
free_matches(nint, &intf);
return -1;
}
int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names,
unsigned int flags) {
- return list_interface_ids(ncf, maxnames, names, flags, "DEVICE");
+ return list_interface_ids(ncf, maxnames, names, flags);
}
int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
- return list_interface_ids(ncf, 0, NULL, flags, "DEVICE");
+ return list_interface_ids(ncf, 0, NULL, flags);
}
struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name) {
@@ -607,7 +594,7 @@ struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name) {
pathx = find_ifcfg_path(ncf, name);
ERR_BAIL(ncf);
- if (pathx == NULL || is_slave(ncf, pathx))
+ if (pathx == NULL || is_slave(ncf, name))
goto done;
name_dup = strdup(name);
@@ -629,12 +616,15 @@ struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name) {
* The format is a very simple representation of the Augeas tree (see
* xml/augeas.rng)
*/
-static xmlDocPtr aug_get_xml(struct netcf *ncf, int nint, char **intf) {
+static xmlDocPtr aug_get_xml(struct netcf_if *nif, int nint, char **intf) {
struct augeas *aug;
xmlDocPtr result = NULL;
xmlNodePtr root = NULL, tree = NULL;
char **matches = NULL;
+ struct netcf *ncf = nif->ncf;
int nmatches, r;
+ int pathoffset = strlen(aug_files) + strlen(network_scripts_path)
+ + strlen(ifcfg_prefix) + 1;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
@@ -646,17 +636,33 @@ static xmlDocPtr aug_get_xml(struct netcf *ncf, int nint, char **intf) {
for (int i=0; i < nint; i++) {
tree = xmlNewChild(root, NULL, BAD_CAST "tree", NULL);
xmlNewProp(tree, BAD_CAST "path", BAD_CAST intf[i]);
- nmatches = aug_fmt_match(ncf, &matches, "%s/%s", intf[i], "*");
+ nmatches = aug_fmt_match(ncf, &matches, "%s%s/ifcfg-%s/%s",
+ aug_files, network_scripts_path, intf[i], "*");
ERR_COND_BAIL(nint < 0, ncf, EOTHER);
for (int j = 0; j < nmatches; j++) {
xmlNodePtr node = xmlNewChild(tree, NULL, BAD_CAST "node", NULL);
const char *value;
xmlNewProp(node, BAD_CAST "label",
- BAD_CAST matches[j] + strlen(intf[i]) + 1);
+ BAD_CAST matches[j] + pathoffset + strlen(intf[i]) + 1);
r = aug_get(aug, matches[j], &value);
ERR_COND_BAIL(r < 0, ncf, EOTHER);
xmlNewProp(node, BAD_CAST "value", BAD_CAST value);
}
+ {
+ xmlNodePtr node = xmlNewChild(tree, NULL, BAD_CAST "node", NULL);
+ xmlNewProp(node, BAD_CAST "label",
+ BAD_CAST "DEVICE" );
+ xmlNewProp(node, BAD_CAST "value", BAD_CAST nif->name);
+ }
+ {
+ const char *mac = NULL;
+ if( find_hwaddr_by_device(ncf, nif->name, &mac) > 0 ) {
+ xmlNodePtr node = xmlNewChild(tree, NULL, BAD_CAST "node", NULL);
+ xmlNewProp(node, BAD_CAST "label",
+ BAD_CAST "HWADDR" );
+ xmlNewProp(node, BAD_CAST "value", BAD_CAST mac);
+ }
+ }
free_matches(nmatches, &matches);
}
@@ -672,8 +678,11 @@ static xmlDocPtr aug_get_xml(struct netcf *ncf, int nint, char **intf) {
static int aug_put_xml(struct netcf *ncf, xmlDocPtr xml) {
xmlNodePtr forest;
char *path = NULL, *lpath = NULL, *label = NULL, *value = NULL;
+ char *device = NULL, *mac = NULL, *gateway = NULL;
+ char **rules = NULL;
struct augeas *aug = NULL;
- int result = -1;
+ int result = -1, nrules = 0, ethphysical = 0;
+ int toplevel = 1;
int r;
aug = get_augeas(ncf);
@@ -689,7 +698,7 @@ static int aug_put_xml(struct netcf *ncf, xmlDocPtr xml) {
EINTERNAL, "expected node labeled 'tree', not '%s'",
tree->name);
path = xml_prop(tree, "path");
- int toplevel = 1;
+ /*int toplevel = 1;*/
/* This is a little drastic, since it clears out the file entirely */
r = aug_rm(aug, path);
ERR_THROW(r < 0, ncf, EINTERNAL, "aug_rm of '%s' failed", path);
@@ -697,23 +706,154 @@ static int aug_put_xml(struct netcf *ncf, xmlDocPtr xml) {
label = xml_prop(node, "label");
value = xml_prop(node, "value");
/* We should mark the toplevel interface from the XSLT */
- if (STREQ(label, "BRIDGE") || STREQ(label, "MASTER")) {
+ if (STREQ(label, "BRIDGE") || STREQ(label, "BONDING_MASTER")) {
toplevel = 0;
}
- r = xasprintf(&lpath, "%s/%s", path, label);
- ERR_NOMEM(r < 0, ncf);
-
- r = aug_set(aug, lpath, value);
- ERR_THROW(r < 0, ncf, EOTHER,
- "aug_set of '%s' failed", lpath);
- FREE(lpath);
- xmlFree(label);
- xmlFree(value);
+ if (STREQ(label, "DEVICE")) {
+ device = value;
+ if(!strchr(value, '.') && !strncmp("eth", value, strlen("eth")))
+ ethphysical = 1;
+ xmlFree(label);
+ } else if(STREQ(label, "HWADDR")) {
+ mac = value;
+ xmlFree(label);
+ //continue;
+ } else if(STREQ(label, "GATEWAY")) {
+ gateway = value;
+ xmlFree(label);
+ //continue;
+ } else {
+ r = xasprintf(&lpath, "%s/%s", path, label);
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, value);
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+ FREE(lpath);
+ xmlFree(label);
+ xmlFree(value);
+ }
label = value = NULL;
}
xmlFree(path);
path = NULL;
}
+ if( device && !mac && ethphysical && toplevel ){
+ mac = malloc(20);
+ if( if_hwaddr(ncf, device, mac, 20) ){
+ free(mac);
+ mac = NULL;
+ }
+ }
+ if( device && gateway && ethphysical && toplevel ) {
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ network_scripts_path, "routes/default", "gateway");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, gateway);
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ network_scripts_path, "routes/default", "netmask");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "-");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ network_scripts_path, "routes/default", "device");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, device );
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+ }
+ if( device && mac && ethphysical && toplevel ) {
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "SUBSYSTEM");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "net");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "ACTION");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "add");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "DRIVERS");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "?*");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "ATTR{address}");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, mac);
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+#ifdef OS113
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "ATTR{dev_id}");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "0x0");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+#endif
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "ATTR{type}");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "1");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+
+ r = xasprintf(&lpath, "%s%s/%s/%s", aug_files,
+ udev_netrule_path, device, "KERNEL");
+ ERR_NOMEM(r < 0, ncf);
+
+ r = aug_set(aug, lpath, "eth*");
+ ERR_THROW(r < 0, ncf, EOTHER,
+ "aug_set of '%s' failed", lpath);
+
+ FREE(lpath);
+ }
+ xmlFree(device);
+ xmlFree(mac);
+ xmlFree(gateway);
result = 0;
error:
xmlFree(label);
@@ -728,24 +868,17 @@ static int aug_put_xml(struct netcf *ncf, xmlDocPtr xml) {
*/
static xmlDocPtr aug_get_xml_for_nif(struct netcf_if *nif) {
struct netcf *ncf;
- char **devs = NULL, **intf = NULL;
+ char **intf = NULL;
xmlDocPtr aug_xml = NULL;
- int ndevs = 0, nint = 0;
+ int nint = 0;
ncf = nif->ncf;
- ndevs = aug_fmt_match(ncf, &devs,
- "%s[ DEVICE = '%s' or BRIDGE = '%s' or MASTER = '%s'"
- " or MASTER = ../*[BRIDGE = '%s']/DEVICE ]/DEVICE",
- ifcfg_path, nif->name, nif->name, nif->name, nif->name);
- ERR_BAIL(ncf);
-
- nint = uniq_ifcfg_paths(ncf, ndevs, devs, &intf);
+ nint = find_ifcfg_file_by_name(ncf, nif->name, &intf);
ERR_BAIL(ncf);
- aug_xml = aug_get_xml(ncf, nint, intf);
+ aug_xml = aug_get_xml(nif, nint, intf);
error:
- free_matches(ndevs, &devs);
free_matches(nint, &intf);
return aug_xml;
}
@@ -871,7 +1004,7 @@ static bool is_bond(struct netcf *ncf, const char *name) {
int nmatches = 0;
nmatches = aug_fmt_match(ncf, NULL,
- "%s[ MASTER = '%s']", ifcfg_path, name);
+ "%s[ BONDING_MASTER = '%s']", ifcfg_path, name);
return nmatches > 0;
}
@@ -880,8 +1013,8 @@ static bool is_bridge(struct netcf *ncf, const char *name) {
int nmatches = 0;
nmatches = aug_fmt_match(ncf, NULL,
- "%s[ DEVICE = '%s' and TYPE = 'Bridge']",
- ifcfg_path, name);
+ "%s%s/ifcfg-%s[ BRIDGE = 'yes' ]",
+ aug_files, network_scripts_path, name);
return nmatches > 0;
}
@@ -917,21 +1050,32 @@ static int bridge_slaves(struct netcf *ncf, const char *name, char ***slaves) {
static void rm_interface(struct netcf *ncf, const char *name) {
int r;
char *path = NULL;
+ char **rules = NULL;
struct augeas *aug = NULL;
+ int nrules = 0;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
/* The last or clause catches slaves of a bond that are enslaved to
* a bridge NAME */
- r = xasprintf(&path,
- "%s[ DEVICE = '%s' or BRIDGE = '%s' or MASTER = '%s' "
- " or MASTER = ../*[BRIDGE = '%s']/DEVICE ]",
- ifcfg_path, name, name, name, name);
+ r = xasprintf(&path, "%s/%s/ifcfg-%s",
+ aug_files, network_scripts_path, name);
ERR_NOMEM(r < 0, ncf);
r = aug_rm(aug, path);
ERR_COND_BAIL(r < 0, ncf, EOTHER);
+
+ nrules = aug_fmt_match(ncf, &rules, "%s/%s/%s",
+ aug_files, udev_netrule_path, name);
+ ERR_COND_BAIL(nrules < 0, ncf, EINTERNAL);
+
+ while(nrules > 0) {
+ nrules--;
+ r = aug_rm(aug, rules[nrules]);
+ }
+ free_matches(nrules, &rules);
+
error:
FREE(path);
}
diff --git a/src/dutil.c b/src/dutil.c
index 2a6eaa0..05ec95a 100644
--- a/src/dutil.c
+++ b/src/dutil.c
@@ -547,6 +547,38 @@ int netlink_close(struct netcf *ncf) {
return 0;
}
+static size_t format_mac_addr(unsigned char *buf, int buflen,
+ const unsigned char *addr, int len)
+{
+ int i;
+ char *cp = (char *)buf;
+
+ for (i = 0; i < len; i++) {
+ cp += snprintf(cp, buflen - (cp - (char *)buf), "%02x", addr[i]);
+ if (i == len - 1) {
+ *cp = '\0';
+ break;
+ }
+ strncpy(cp, ":", 1);
+ cp++;
+ }
+ return cp - (char *)buf;
+}
+
+int if_hwaddr(struct netcf *ncf, const char *intf,
+ unsigned char *mac, int buflen) {
+ struct ifreq ifr;
+ int ret;
+
+ MEMZERO(&ifr, 1);
+ strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+ ret = ioctl(ncf->driver->ioctl_fd, SIOCGIFHWADDR, &ifr);
+ memcpy(mac,ifr.ifr_hwaddr.sa_data,6);
+ format_mac_addr(mac,buflen, (unsigned char *)ifr.ifr_hwaddr.sa_data,6);
+ return ret;
+}
+
int if_is_active(struct netcf *ncf, const char *intf) {
struct ifreq ifr;
diff --git a/src/dutil.h b/src/dutil.h
index 90dc59a..c1dfbb7 100644
--- a/src/dutil.h
+++ b/src/dutil.h
@@ -122,6 +122,9 @@ 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);
+/* Retrieve the hw mac address of the interface INTF */
+int if_hwaddr(struct netcf *ncf, const char *intf, unsigned char *mac, int len);
+
/* Interface types recognized by netcf. */
typedef enum {
NETCF_IFACE_TYPE_NONE = 0, /* not yet determined */