Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:lafenghu
netcf
netcf-suse.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File netcf-suse.patch of Package netcf
From:Patrick Mullaney <pmullaney@novell.com> 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> --- src/Makefile.am | 1 src/drv_initscripts.c | 537 ++++++++++++++++++++++++++++++------------------- src/dutil.c | 44 +++- src/dutil.h | 3 4 files changed, 361 insertions(+), 224 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..b117d02 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> @@ -159,7 +162,7 @@ </xsl:template> <xsl:template name="mtu"> - <xsl:if test="node[@label='MTU']"> + <xsl:if test="node[@label='MTU'][@value != '']"> <mtu size="{node[@label='MTU']/@value}"/> </xsl:if> </xsl:template> 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..2759f9f 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,10 @@ #include <stdbool.h> #include <string.h> #include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include <dirent.h> + #include "safe-alloc.h" #include "ref.h" @@ -47,18 +55,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 +142,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 +157,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 +183,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; - - qsort(devs, ndevs, sizeof(*devs), cmpstrp); + nmatches = aug_fmt_match(ncf, &matches, "%s/%s/*[ NAME = '%s']", + aug_files, udev_netrule_path, name); + ERR_COND_BAIL(nmatches < 0 , ncf, EOTHER); - 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 +300,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 +315,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 +328,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; @@ -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; + const char *val = NULL; struct augeas *aug = NULL; - int result = -1; + int result = -1, 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,137 @@ 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); + 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); + } else if(STREQ(label, "GATEWAY")) { + gateway = value; + xmlFree(label); + } 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, (unsigned char *)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 ) { + char *pmac=NULL; + + r = xasprintf(&lpath, "%s%s/%s/%s", aug_files, + udev_netrule_path, device, "ATTR{address}"); + ERR_NOMEM(r < 0, ncf); + + r = aug_get(aug, lpath, &val); + + FREE(lpath); + + for(pmac = mac;*pmac!= '\0';++pmac) + *pmac = tolower(*pmac); + + if ( strncmp(val, mac, strlen(mac)) ) { + + val = NULL; /* don't free val returned from aug_get */ + + 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, value); + r = aug_set(aug, lpath, mac); 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; } + xmlFree(device); + xmlFree(mac); + xmlFree(gateway); result = 0; error: xmlFree(label); @@ -728,24 +851,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); + nint = find_ifcfg_file_by_name(ncf, nif->name, &intf); ERR_BAIL(ncf); - nint = uniq_ifcfg_paths(ncf, ndevs, devs, &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 +987,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 +996,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; } @@ -924,14 +1040,13 @@ static void rm_interface(struct netcf *ncf, const char *name) { /* 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); + error: FREE(path); } diff --git a/src/dutil.c b/src/dutil.c index 2a6eaa0..e52ca3a 100644 --- a/src/dutil.c +++ b/src/dutil.c @@ -175,18 +175,6 @@ struct augeas *get_augeas(struct netcf *ncf) { r = aug_load(aug); ERR_THROW(r < 0, ncf, EOTHER, "failed to load config files"); - /* FIXME: we need to produce _much_ better diagnostics here - need - * to analyze what came back in /augeas//error; ultimately, we need - * to understand whether this is harmless or a real error. For real - * errors, we need to return an error. - */ - r = aug_match(aug, "/augeas//error", NULL); - if (r > 0 && NCF_DEBUG(ncf)) { - fprintf(stderr, "warning: augeas initialization had errors\n"); - fprintf(stderr, "please file a bug with the following lines in the bug report:\n"); - aug_print(aug, stderr, "/augeas//error"); - } - ERR_THROW(r > 0, ncf, EOTHER, "errors in loading some config files"); ncf->driver->load_augeas = 0; } return ncf->driver->augeas; @@ -547,6 +535,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 */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor