ifcfg-rh: add support for Wake-on-LAN ethtool options

Based on branch danw/wip/ethtool by Dan Winship <danw@redhat.com>

(cherry picked from commit 2e0d0bc050)
This commit is contained in:
Beniamino Galvani 2015-05-12 11:55:52 +02:00
parent d449d82304
commit fc91d538f5
5 changed files with 256 additions and 1 deletions

View file

@ -3501,6 +3501,80 @@ wireless_connection_from_ifcfg (const char *file,
return connection;
}
static void
parse_ethtool_options (shvarFile *ifcfg, NMSettingWired *s_wired, char *value)
{
NMSettingWiredWakeOnLan wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
gboolean use_password = FALSE;
char **words, **iter, *flag;
if (!value || !value[0])
return;
words = g_strsplit_set (value, " ", 0);
iter = words;
while (iter[0]) {
if (g_str_equal (iter[0], "wol") && iter[1] && *iter[1]) {
for (flag = iter[1]; *flag; flag++) {
switch (*flag) {
case 'p':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_PHY;
break;
case 'u':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST;
break;
case 'm':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST;
break;
case 'b':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST;
break;
case 'a':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_ARP;
break;
case 'g':
wol_flags |= NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC;
break;
case 's':
use_password = TRUE;
break;
case 'd':
wol_flags = NM_SETTING_WIRED_WAKE_ON_LAN_NONE;
use_password = FALSE;
break;
default:
PARSE_WARNING ("unrecognized Wake-on-LAN option '%c'", *flag);
}
}
if (!NM_FLAGS_HAS (wol_flags, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
use_password = FALSE;
g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN, wol_flags, NULL);
iter += 2;
continue;
}
if (g_str_equal (iter[0], "sopass") && iter[1] && *iter[1]) {
if (use_password) {
if (nm_utils_hwaddr_valid (iter[1], ETH_ALEN))
g_object_set (s_wired, NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, iter[1], NULL);
else
PARSE_WARNING ("Wake-on-LAN password '%s' is invalid", iter[1]);
} else
PARSE_WARNING ("Wake-on-LAN password not expected");
iter += 2;
continue;
}
/* Silently skip unknown options */
iter++;
}
g_strfreev (words);
}
static NMSetting *
make_wired_setting (shvarFile *ifcfg,
const char *file,
@ -3636,6 +3710,10 @@ make_wired_setting (shvarFile *ifcfg,
g_free (value);
}
value = svGetValue (ifcfg, "ETHTOOL_OPTS", FALSE);
parse_ethtool_options (ifcfg, s_wired, value);
g_free (value);
return (NMSetting *) s_wired;
error:

View file

@ -123,7 +123,8 @@ EXTRA_DIST = \
ifcfg-test-team-master \
ifcfg-test-team-port \
ifcfg-test-team-port-empty-config \
ifcfg-test-vlan-trailing-spaces
ifcfg-test-vlan-trailing-spaces \
ifcfg-test-wired-wake-on-lan
# make target dependencies can't have colons in their names, which ends up
# meaning that we can't add the alias files to EXTRA_DIST

View file

@ -0,0 +1,22 @@
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
TYPE=Ethernet
DEVICE=eth0
HWADDR=00:11:22:33:44:ee
BOOTPROTO=none
ONBOOT=yes
USERCTL=yes
MTU=1492
NM_CONTROLLED=yes
DNS1=4.2.2.1
DNS2=4.2.2.2
IPADDR=192.168.1.5
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
IPV6INIT=yes
IPV6_AUTOCONF=no
IPV6ADDR=dead:beaf::1
IPV6ADDR_SECONDARIES="dead:beaf::2/56"
DNS3=1:2:3:4::a
DNS4=1:2:3:4::b
RES_OPTIONS=
ETHTOOL_OPTS="speed 100 duplex full wol apgs sopass 00:11:22:33:44:55 autoneg off"

View file

@ -5103,6 +5103,43 @@ test_read_wifi_wep_eap_ttls_chap (void)
g_object_unref (connection);
}
static void
test_read_wired_wake_on_lan (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
gboolean success;
GError *error = NULL;
connection = connection_from_file_test (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-wake-on-lan",
NULL, TYPE_WIRELESS, NULL, &error);
g_assert_no_error (error);
g_assert (connection);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME);
s_wired = nm_connection_get_setting_wired (connection);
g_assert (s_wired);
g_assert_cmpint (nm_setting_wired_get_wake_on_lan (s_wired),
==,
NM_SETTING_WIRED_WAKE_ON_LAN_ARP |
NM_SETTING_WIRED_WAKE_ON_LAN_PHY |
NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC);
g_assert_cmpstr (nm_setting_wired_get_wake_on_lan_password (s_wired),
==,
"00:11:22:33:44:55");
g_object_unref (connection);
}
static void
test_read_wifi_hidden (void)
{
@ -5217,6 +5254,90 @@ test_write_wifi_hidden (void)
g_object_unref (reread);
}
static void
test_write_wired_wake_on_lan (void)
{
NMConnection *connection, *reread;
NMSettingConnection *s_con;
NMSettingWired *s_wired;
NMSettingWiredWakeOnLan wol;
char *uuid, *testfile = NULL, *val;
gboolean success;
GError *error = NULL;
shvarFile *f;
connection = nm_simple_connection_new ();
/* Connection setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
nm_connection_add_setting (connection, NM_SETTING (s_con));
uuid = nm_utils_uuid_generate ();
g_object_set (s_con,
NM_SETTING_CONNECTION_ID, "Test Write Wired Wake-on-LAN",
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
NULL);
g_free (uuid);
/* Wired setting */
s_wired = (NMSettingWired *) nm_setting_wired_new ();
nm_connection_add_setting (connection, NM_SETTING (s_wired));
wol = NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST |
NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST |
NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC;
g_object_set (s_wired,
NM_SETTING_WIRED_WAKE_ON_LAN, wol,
NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, "00:00:00:11:22:33",
NULL);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
/* Save the ifcfg */
success = writer_new_connection (connection,
TEST_SCRATCH_DIR "/network-scripts/",
&testfile,
&error);
g_assert_no_error (error);
g_assert (success);
f = svOpenFile (testfile, &error);
g_assert_no_error (error);
g_assert (f);
/* re-read the file to check that the key was written. */
val = svGetValue (f, "ETHTOOL_OPTS", FALSE);
g_assert (val);
g_assert (strstr (val, "wol"));
g_assert (strstr (val, "sopass 00:00:00:11:22:33"));
g_free (val);
svCloseFile (f);
/* reread will be normalized, so we must normalize connection too. */
nm_connection_normalize (connection, NULL, NULL, NULL);
/* re-read the connection for comparison */
reread = connection_from_file_test (testfile, NULL, TYPE_ETHERNET,
NULL, &error);
unlink (testfile);
g_assert_no_error (error);
g_assert (reread);
success = nm_connection_verify (reread, &error);
g_assert_no_error (error);
g_assert (success);
g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT));
g_free (testfile);
g_object_unref (connection);
g_object_unref (reread);
}
static void
test_read_wifi_band_a (void)
{
@ -12551,6 +12672,7 @@ int main (int argc, char **argv)
test_read_vlan_only_vlan_id ();
test_read_vlan_only_device ();
g_test_add_func (TPATH "vlan/physdev", test_read_vlan_physdev);
g_test_add_func (TPATH "wired/read-wake-on-lan", test_read_wired_wake_on_lan);
test_write_wired_static ();
test_write_wired_static_ip6_only ();
@ -12565,6 +12687,7 @@ int main (int argc, char **argv)
test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE);
test_write_wired_aliases ();
g_test_add_func (TPATH "ipv4/write-static-addresses-GATEWAY", test_write_gateway);
g_test_add_func (TPATH "wired/write-wake-on-lan", test_write_wired_wake_on_lan);
test_write_wifi_open ();
test_write_wifi_open_hex_ssid ();
test_write_wifi_wep ();

View file

@ -42,6 +42,8 @@
#include <nm-setting-team-port.h>
#include "nm-core-internal.h"
#include <nm-utils.h>
#include "nm-core-internal.h"
#include "nm-macros-internal.h"
#include "nm-logging.h"
#include "gsystem-local-alloc.h"
@ -1048,6 +1050,8 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
const char *const *s390_subchannels;
GString *str;
const char * const *macaddr_blacklist;
NMSettingWiredWakeOnLan wol;
const char *wol_password;
s_wired = nm_connection_get_setting_wired (connection);
if (!s_wired) {
@ -1131,6 +1135,33 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
g_string_free (str, TRUE);
}
svSetValue (ifcfg, "ETHTOOL_OPTS", NULL, FALSE);
wol = nm_setting_wired_get_wake_on_lan (s_wired);
wol_password = nm_setting_wired_get_wake_on_lan_password (s_wired);
if (wol) {
str = g_string_sized_new (30);
g_string_append (str, "wol ");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY))
g_string_append (str, "p");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST))
g_string_append (str, "u");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST))
g_string_append (str, "m");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST))
g_string_append (str, "b");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP))
g_string_append (str, "a");
if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
g_string_append (str, "g");
if (wol_password && NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
g_string_append_printf (str, "s sopass %s", wol_password);
svSetValue (ifcfg, "ETHTOOL_OPTS", str->str, FALSE);
g_string_free (str, TRUE);
}
svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE);
return TRUE;