--- /dev/null
+From c5f080923f0c52084a929b4125e8fbe19f6e7279 Mon Sep 17 00:00:00 2001
+From: Mu Qiao <qiaomuf@gentoo.org>
+Date: Tue, 6 Dec 2011 14:55:03 +0800
+Subject: [PATCH] ifnet: support reading openrc style
+
+IP configuration like 192.168.1.{2..4} is not supported anymore.
+---
+ src/settings/plugins/ifnet/connection_parser.c | 14 +-
+ src/settings/plugins/ifnet/net_parser.c | 84 ++++++++++----
+ src/settings/plugins/ifnet/net_utils.c | 144 ++++++++++--------------
+ src/settings/plugins/ifnet/tests/net | 11 ++-
+ src/settings/plugins/ifnet/tests/test_all.c | 30 ++++-
+ 5 files changed, 163 insertions(+), 120 deletions(-)
+
+diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
+index b4aaa8d..66ce318 100644
+--- a/src/settings/plugins/ifnet/connection_parser.c
++++ b/src/settings/plugins/ifnet/connection_parser.c
+@@ -567,7 +567,7 @@ make_wired_connection_setting (NMConnection *connection,
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+ }
+
+-/* add NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
++/* add NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
+ * NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID in future*/
+ static void
+ make_ip4_setting (NMConnection *connection,
+@@ -596,19 +596,19 @@ make_ip4_setting (NMConnection *connection,
+ g_object_unref (ip4_setting);
+ return;
+ }
+- if (!strcmp (method, "dhcp"))
++ if (strstr (method, "dhcp"))
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+- else if (!strcmp (method, "autoip")){
++ else if (strstr (method, "autoip")){
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+ nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+ return;
+- } else if (!strcmp (method, "shared")){
++ } else if (strstr (method, "shared")){
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_SHARED,
+@@ -663,7 +663,7 @@ make_ip4_setting (NMConnection *connection,
+ }
+
+ /* add dhcp hostname and client id */
+- if (!is_static_block && !strcmp (method, "dhcp")) {
++ if (!is_static_block && strstr (method, "dhcp")) {
+ gchar *dhcp_hostname, *client_id;
+
+ get_dhcp_hostname_and_client_id (&dhcp_hostname, &client_id);
+@@ -868,7 +868,7 @@ make_ip6_setting (NMConnection *connection,
+ nm_ip6_route_set_dest (route, iblock->ip);
+ nm_ip6_route_set_next_hop (route, iblock->next_hop);
+ nm_ip6_route_set_prefix (route, iblock->prefix);
+- /* metric is not per routes configuration right now
++ /* metric is not per routes configuration right now
+ * global metric is also supported (metric="x") */
+ if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
+ metric = strtol (metric_str, NULL, 10);
+@@ -995,7 +995,7 @@ make_wireless_connection_setting (const char *conn_name,
+ goto error;
+ }
+
+- /* mode=0: infrastructure
++ /* mode=0: infrastructure
+ * mode=1: adhoc */
+ value = wpa_get_value (conn_name, "mode");
+ if (value)
+diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c
+index a48103d..4befc37 100644
+--- a/src/settings/plugins/ifnet/net_parser.c
++++ b/src/settings/plugins/ifnet/net_parser.c
+@@ -169,12 +169,10 @@ init_block_by_line (gchar * buf)
+ conn = add_new_connection_config ("wireless", pos);
+ }
+ data = g_strdup (key_value[1]);
+- tmp = strip_string (data, '(');
+- tmp = strip_string (tmp, ')');
+- strip_string (tmp, '"');
++ tmp = strip_string (data, '"');
+ strip_string (tmp, '\'');
+ if (conn)
+- g_hash_table_insert (conn, g_strdup (key_value[0]),
++ g_hash_table_insert (conn, strip_string (g_strdup (key_value[0]), ' '),
+ g_strdup (tmp));
+ g_free (data);
+ g_strfreev (key_value);
+@@ -283,6 +281,22 @@ is_function (gchar * line)
+ return FALSE;
+ }
+
++static void
++append_line (GString *buf, gchar* line)
++{
++ gchar *pos = NULL;
++
++ if ((pos = strchr (line, '#')) != NULL)
++ *pos = '\0';
++ g_strstrip (line);
++
++ if (line[0] != '\0') {
++ g_string_append_printf (buf,
++ " %s", line);
++ }
++ g_free (line);
++}
++
+ gboolean
+ ifnet_init (gchar * config_file)
+ {
+@@ -292,6 +306,8 @@ ifnet_init (gchar * config_file)
+ /* Handle multiple lines with brackets */
+ gboolean complete = TRUE;
+
++ gboolean openrc_style = TRUE;
++
+ /* line buffer */
+ GString *buf;
+
+@@ -319,36 +335,60 @@ ifnet_init (gchar * config_file)
+ strip_function (channel, line);
+ continue;
+ }
+- if (line[0] != '#' && line[0] != '\0') {
+- gchar *pos = NULL;
+
++ // New openrc style, bash arrays are not allowed. We only care about '"'
++ if (openrc_style && line[0] != '#' && line[0] != '\0'
++ && !strchr (line, '(') && !strchr (line, ')')) {
++ gchar *tmp = line;
++
++ while ((tmp = strchr (tmp, '"')) != NULL) {
++ complete = !complete;
++ ++tmp;
++ }
++
++ append_line (buf, line);
++ // Add "(separator) for routes. It will be easier for later parsing
++ if (strstr (buf->str, "via"))
++ g_string_append_printf (buf, "\"");
++
++ if (!complete)
++ continue;
++
++ strip_string (buf->str, '"');
++
++ init_block_by_line (buf->str);
++ g_string_free (buf, TRUE);
++ buf = g_string_new (NULL);
++ }
++ // Old bash arrays for baselayout-1, to be deleted
++ else if (line[0] != '#' && line[0] != '\0') {
+ if (!complete) {
+ complete =
+ g_strrstr (line,
+ ")") == NULL ? FALSE : TRUE;
+- if ((pos = strchr (line, '#')) != NULL)
+- *pos = '\0';
+- g_strstrip (line);
+- if (line[0] != '\0') {
+- g_string_append_printf (buf,
+- " %s", line);
+- }
+- g_free (line);
+- if (!complete)
++
++ append_line (buf, line);
++ if (!complete) {
++ openrc_style = FALSE;
+ continue;
++ }
++ else {
++ openrc_style = TRUE;
++ }
+ } else {
+ complete =
+ (g_strrstr (line, "(") != NULL
+ && g_strrstr (line, ")") != NULL)
+ || g_strrstr (line, "(") == NULL;
+- if ((pos = strchr (line, '#')) != NULL)
+- *pos = '\0';
+- g_strstrip (line);
+- if (line[0] != '\0')
+- g_string_append (buf, line);
+- g_free (line);
++
++ append_line (buf, line);
+ if (!complete)
++ {
++ openrc_style = FALSE;
+ continue;
++ } else {
++ openrc_style = TRUE;
++ }
+ }
+ init_block_by_line (buf->str);
+ g_string_free (buf, TRUE);
+@@ -391,7 +431,7 @@ ifnet_set_data (const char *conn_name, const char *key, const char *value)
+ }
+ /* Remove existing key value pair */
+ if (g_hash_table_lookup_extended (conn, key, &old_key, &old_value)) {
+- if (stripped && !strcmp(old_value, stripped)){
++ if (stripped && !strcmp (old_value, stripped)){
+ g_free (stripped);
+ return;
+ }
+diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c
+index b533ae3..fc7e283 100644
+--- a/src/settings/plugins/ifnet/net_utils.c
++++ b/src/settings/plugins/ifnet/net_utils.c
+@@ -352,6 +352,49 @@ is_ip6_address (const char *in_address)
+
+ }
+
++// 'c' is only used for openrc style
++static gchar **
++split_addresses_by_char (const gchar *addresses, const gchar *c)
++{
++ gchar **ipset;
++
++ if (addresses == NULL)
++ return NULL;
++
++ if (strchr (addresses, '(') != NULL) { // old baselayout style
++ gchar *tmp = g_strdup (addresses);
++ strip_string (tmp, '(');
++ strip_string (tmp, ')');
++ strip_string (tmp, '"');
++ strip_string (tmp, '\'');
++ ipset = g_strsplit (tmp, "\" \"", 0);
++ g_free(tmp);
++ } else { // openrc style
++ if (strstr (addresses, "netmask"))
++ // There is only one ip address if "netmask" is specified.
++ // '\n' is not used in config so there will be only one split.
++ ipset = g_strsplit (addresses, "\n", 0);
++ else
++ ipset = g_strsplit (addresses, c, 0);
++ }
++
++ return ipset;
++}
++
++static gchar **
++split_addresses (const gchar* addresses)
++{
++ // " " is only used by openrc style
++ return split_addresses_by_char (addresses, " ");
++}
++
++static gchar **
++split_routes (const gchar* routes)
++{
++ // "\"" is only used by openrc style
++ return split_addresses_by_char (routes, "\"");
++}
++
+ gboolean
+ has_ip6_address (const char *conn_name)
+ {
+@@ -360,7 +403,7 @@ has_ip6_address (const char *conn_name)
+ guint i;
+
+ g_return_val_if_fail (conn_name != NULL, FALSE);
+- ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
++ ipset = split_addresses (ifnet_get_data (conn_name, "config"));
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ if (!is_ip6_address (ipset[i]))
+@@ -512,8 +555,11 @@ get_ip4_gateway (gchar * gateway)
+ tmp = g_strdup (tmp);
+ strip_string (tmp, ' ');
+ strip_string (tmp, '"');
++
++ // Only one gateway is selected
+ if ((split = strstr (tmp, "\"")) != NULL)
+ *split = '\0';
++
+ if (!inet_pton (AF_INET, tmp, &tmp_ip4_addr))
+ goto error;
+ g_free (tmp);
+@@ -567,14 +613,11 @@ convert_ip4_config_block (const char *conn_name)
+ gchar *ip;
+ guint32 def_gateway = 0;
+ const char *routes;
+- gchar *pos;
+ ip_block *start = NULL, *current = NULL, *iblock = NULL;
+- const char *pattern =
+- "((\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.)\\{(\\d{1,3})\\.\\.(\\d{1,3})\\}(/\\d{1,2}))";
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+
+- ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
++ ipset = split_addresses (ifnet_get_data (conn_name, "config"));
+ length = g_strv_length (ipset);
+
+ routes = ifnet_get_data (conn_name, "routes");
+@@ -584,73 +627,16 @@ convert_ip4_config_block (const char *conn_name)
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+ ip = strip_string (ip, '"');
+- //Handle ip like 192.168.4.{1..3}
+- if ((pos = strchr (ip, '{')) != NULL) {
+- gchar *ip_start, *ip_prefix;
+- gchar *begin_str, *end_str;
+- int begin, end, j;
+- GRegex *regex;
+- GMatchInfo *match_info;
+-
+- regex = g_regex_new (pattern, 0, 0, NULL);
+- g_regex_match (regex, ip, 0, &match_info);
+- g_regex_unref (regex);
+-
+- if (!g_match_info_matches (match_info)) {
+- g_match_info_free (match_info);
+- continue;
+- }
+- begin_str = g_match_info_fetch (match_info, 3);
+- end_str = g_match_info_fetch (match_info, 4);
+- begin = atoi (begin_str);
+- end = atoi (end_str);
+- ip_start = g_match_info_fetch (match_info, 2);
+- ip_prefix = g_match_info_fetch (match_info, 5);
+- if (end < begin || begin < 1 || end > 254) {
+- g_match_info_free (match_info);
+- continue;
+- }
+-
+- for (j = begin; j <= end; j++) {
+- char suf[4];
+- gchar *newip;
+-
+- sprintf (suf, "%d", j);
+- newip =
+- g_strconcat (ip_start, suf, ip_prefix,
+- NULL);
+- iblock = create_ip4_block (newip);
+- if (iblock == NULL) {
+- g_free (newip);
+- continue;
+- }
+- if (!iblock->gateway && def_gateway != 0)
+- iblock->gateway = def_gateway;
+- if (start == NULL)
+- start = current = iblock;
+- else {
+- current->next = iblock;
+- current = iblock;
+- }
+- g_free (newip);
+- }
+- g_free (begin_str);
+- g_free (end_str);
+- g_free (ip_start);
+- g_free (ip_prefix);
+- g_match_info_free (match_info);
+- } else {
+- iblock = create_ip4_block (ip);
+- if (iblock == NULL)
+- continue;
+- if (!iblock->gateway && def_gateway != 0)
+- iblock->gateway = def_gateway;
+- if (start == NULL)
+- start = current = iblock;
+- else {
+- current->next = iblock;
+- current = iblock;
+- }
++ iblock = create_ip4_block (ip);
++ if (iblock == NULL)
++ continue;
++ if (!iblock->gateway && def_gateway != 0)
++ iblock->gateway = def_gateway;
++ if (start == NULL)
++ start = current = iblock;
++ else {
++ current->next = iblock;
++ current = iblock;
+ }
+ }
+ g_strfreev (ipset);
+@@ -667,7 +653,7 @@ convert_ip6_config_block (const char *conn_name)
+ ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+- ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
++ ipset = split_addresses (ifnet_get_data (conn_name, "config"));
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+@@ -693,15 +679,11 @@ convert_ip4_routes_block (const char *conn_name)
+ guint length;
+ guint i;
+ gchar *ip;
+- const char *routes;
+ ip_block *start = NULL, *current = NULL, *iblock = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+
+- routes = ifnet_get_data (conn_name, "routes");
+- if (!routes)
+- return NULL;
+- ipset = g_strsplit (routes, "\" \"", 0);
++ ipset = split_routes (ifnet_get_data (conn_name, "routes"));
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+@@ -731,15 +713,11 @@ convert_ip6_routes_block (const char *conn_name)
+ guint length;
+ guint i;
+ gchar *ip, *tmp_addr;
+- const char *routes;
+ ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+ struct in6_addr *tmp_ip6_addr;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+- routes = ifnet_get_data (conn_name, "routes");
+- if (!routes)
+- return NULL;
+- ipset = g_strsplit (routes, "\" \"", 0);
++ ipset = split_routes (ifnet_get_data (conn_name, "routes"));
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+diff --git a/src/settings/plugins/ifnet/tests/net b/src/settings/plugins/ifnet/tests/net
+index 0eef399..27d39f4 100644
+--- a/src/settings/plugins/ifnet/tests/net
++++ b/src/settings/plugins/ifnet/tests/net
+@@ -27,10 +27,9 @@ config_eth2=(
+ routes_eth2=("default via 4321:0:1:2:3:4:567:89ab")
+ enable_ipv6_eth2="true"
+ config_eth3=("nufjlsjlll")
+-managed_eth4=("false")
++managed_eth4="false"
+ routes_eth4=("default via 4321:0:1:2:3:4:567:89ab")
+ config_eth5=("dhcp")
+-config_eth6=("192.168.4.{1..101}/24")
+
+ config_eth7=( "dhcp" )
+ auto_eth7="true"
+@@ -38,6 +37,14 @@ auto_eth7="true"
+ # missing config_eth8
+ auto_eth8="true"
+
++#new openrc style
++config_eth9="202.117.16.10/24 202.117.17.10/24"
++routes_eth9="default via 202.117.16.1
++10.0.0.0/8 via 192.168.0.1
++"
++config_eth10="202.117.16.2 netmask 255.255.255.0"
++routes_eth10="10.0.0.0/8 via 192.168.0.1"
++
+ config_myxjtu2=("202.117.16.121/24 brd 202.117.16.255")
+ routes_myxjtu2=("default via 202.117.16.1")
+ dns_servers_myxjtu2="202.117.0.20 202.117.0.21"
+diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c
+index 52d9ce2..9ca5f65 100644
+--- a/src/settings/plugins/ifnet/tests/test_all.c
++++ b/src/settings/plugins/ifnet/tests/test_all.c
+@@ -37,7 +37,7 @@ static void
+ test_getdata ()
+ {
+ ASSERT (ifnet_get_data ("eth1", "config")
+- && strcmp (ifnet_get_data ("eth1", "config"), "dhcp") == 0,
++ && strcmp (ifnet_get_data ("eth1", "config"), "( \"dhcp\" )") == 0,
+ "get data", "config_eth1 is not correct");
+ ASSERT (ifnet_get_data ("ppp0", "username")
+ && strcmp (ifnet_get_data ("ppp0", "username"), "user") == 0,
+@@ -84,7 +84,7 @@ test_is_static ()
+ ASSERT (is_static_ip4 ("eth0") == TRUE, "is static",
+ "a static interface is recognized as dhcp");
+ ASSERT (!is_static_ip6 ("eth0") == TRUE, "is static",
+- "a static interface is recognized as dhcp");
++ "a dhcp interface is recognized as static");
+ }
+
+ static void
+@@ -182,10 +182,6 @@ test_convert_ipv4_config_block ()
+ ASSERT (iblock == NULL, "convert config_block",
+ "convert error configuration");
+ destroy_ip_block (iblock);
+- iblock = convert_ip4_config_block ("eth6");
+- ASSERT (iblock != NULL, "convert config_block",
+- "convert error configuration");
+- destroy_ip_block (iblock);
+ }
+
+ static void
+@@ -200,6 +196,16 @@ test_convert_ipv4_routes_block ()
+ destroy_ip_block (tmp);
+ ASSERT (iblock == NULL, "convert ip4 routes",
+ "should only get one route");
++
++ iblock = convert_ip4_routes_block ("eth9");
++ tmp = iblock;
++
++ ASSERT (iblock != NULL, "convert ip4 routes", "should get one route");
++ check_ip_block (iblock, "10.0.0.0", "255.0.0.0", "192.168.0.1");
++ iblock = iblock->next;
++ destroy_ip_block (tmp);
++ ASSERT (iblock == NULL, "convert ip4 routes",
++ "should only get one route");
+ }
+
+ static void
+@@ -272,6 +278,18 @@ test_new_connection ()
+ "new connection failed: %s",
+ error ? error->message : "NONE");
+ g_object_unref (connection);
++
++ connection = ifnet_update_connection_from_config_block ("eth9", &error);
++ ASSERT (connection != NULL, "new connection",
++ "new connection(eth9) failed: %s",
++ error ? error->message : "NONE");
++ g_object_unref (connection);
++
++ connection = ifnet_update_connection_from_config_block ("eth10", &error);
++ ASSERT (connection != NULL, "new connection",
++ "new connection(eth10) failed: %s",
++ error ? error->message : "NONE");
++ g_object_unref (connection);
+ }
+
+ #define NET_GEN_NAME "net.generate"
+--
+1.7.3.4
+
+From 73a17edee3ba1f378166e0eee69f25b28902ce8d Mon Sep 17 00:00:00 2001
+From: Mu Qiao <qiaomuf@gentoo.org>
+Date: Wed, 7 Dec 2011 10:39:26 +0800
+Subject: [PATCH 2/2] ifnet: support writing for openrc style
+
+---
+ src/settings/plugins/ifnet/net_parser.c | 20 +++++++++++++-------
+ 1 files changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c
+index 4befc37..abca89c 100644
+--- a/src/settings/plugins/ifnet/net_parser.c
++++ b/src/settings/plugins/ifnet/net_parser.c
+@@ -476,22 +476,28 @@ format_ips (gchar * value, gchar ** out_line, gchar * key, gchar * name)
+ guint length, i;
+ GString *formated_string = g_string_new (NULL);
+
++ strip_string (value, '(');
++ strip_string (value, ')');
+ strip_string (value, '"');
+- ipset = g_strsplit (value, "\" \"", 0);
++ ipset = g_strsplit (value, "\"", 0);
+ length = g_strv_length (ipset);
+
+ //only one line
+ if (length < 2) {
+ *out_line =
+- g_strdup_printf ("%s_%s=( \"%s\" )\n", key, name, value);
++ g_strdup_printf ("%s_%s=\"%s\"\n", key, name, value);
+ goto done;
+ }
+ // Multiple lines
+- g_string_append_printf (formated_string, "%s_%s=(\n", key, name);
++ g_string_append_printf (formated_string, "%s_%s=\"\n", key, name);
+ for (i = 0; i < length; i++)
+- g_string_append_printf (formated_string,
+- "\t\"%s\"\n", ipset[i]);
+- g_string_append (formated_string, ")\n");
++ {
++ strip_string (ipset[i], ' ');
++ if (ipset[i][0] != '\0')
++ g_string_append_printf (formated_string,
++ "%s\n", ipset[i]);
++ }
++ g_string_append (formated_string, "\"\n");
+ *out_line = g_strdup (formated_string->str);
+ done:
+ g_string_free (formated_string, TRUE);
+@@ -506,7 +512,7 @@ ifnet_flush_to_file (const char *config_file)
+ gpointer key, value, name, network;
+ GHashTableIter iter, iter_network;
+ GList *list_iter;
+- gchar *out_line;
++ gchar *out_line = NULL;
+ gsize bytes_written;
+ gboolean result = FALSE;
+
+--
+1.7.3.4
+