ifupdown: add support for source stanza
Since Debian 7 (Wheezy) / Ubuntu 11.04 (Natty Narwhal) ifupdown supports the source stanza to source in other configuration files from /etc/network/interfaces. Add support to the ifupdown plugin to include configuration files via source. Patch did not apply cleanly and was slightly modified by Thomas Haller. https://bugzilla.gnome.org/show_bug.cgi?id=707276 Signed-off-by: Thomas Haller <thaller@redhat.com> Reviewed-by: Sebastian Harl <tokkee@debian.org>
This commit is contained in:

committed by
Thomas Haller

parent
fc7468131c
commit
48ed1abca7
@@ -25,6 +25,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <wordexp.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include "nm-utils.h"
|
#include "nm-utils.h"
|
||||||
|
|
||||||
if_block* first;
|
if_block* first;
|
||||||
@@ -96,21 +98,33 @@ static char *join_values_with_spaces(char *dst, char **src)
|
|||||||
return(dst);
|
return(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifparser_init (const char *eni_file, int quiet)
|
void _ifparser_source (const char *path, const char *en_dir, int quiet);
|
||||||
|
void _recursive_ifparser (const char *eni_file, int quiet);
|
||||||
|
|
||||||
|
void _recursive_ifparser (const char *eni_file, int quiet)
|
||||||
{
|
{
|
||||||
FILE *inp = fopen (eni_file, "r");
|
FILE *inp;
|
||||||
char line[255];
|
char line[255];
|
||||||
int skip_to_block = 1;
|
int skip_to_block = 1;
|
||||||
int skip_long_line = 0;
|
int skip_long_line = 0;
|
||||||
int offs = 0;
|
int offs = 0;
|
||||||
|
|
||||||
|
// Check if interfaces file exists and open it
|
||||||
|
if (!g_file_test (eni_file, G_FILE_TEST_EXISTS)) {
|
||||||
|
if (!quiet)
|
||||||
|
g_warning ("Warning: interfaces file %s doesn't exist\n", eni_file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inp = fopen (eni_file, "r");
|
||||||
if (inp == NULL) {
|
if (inp == NULL) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
g_warning ("Error: Can't open %s\n", eni_file);
|
g_warning ("Error: Can't open %s\n", eni_file);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!quiet)
|
||||||
|
g_message (" interface-parser: parsing file %s\n", eni_file);
|
||||||
|
|
||||||
|
|
||||||
first = last = NULL;
|
|
||||||
while (!feof(inp))
|
while (!feof(inp))
|
||||||
{
|
{
|
||||||
char *token[128]; // 255 chars can only be split into 127 tokens
|
char *token[128]; // 255 chars can only be split into 127 tokens
|
||||||
@@ -175,8 +189,9 @@ void ifparser_init (const char *eni_file, int quiet)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are four different stanzas:
|
// There are five different stanzas:
|
||||||
// iface, mapping, auto and allow-*. Create a block for each of them.
|
// iface, mapping, auto, allow-* and source.
|
||||||
|
// Create a block for each of them except source.
|
||||||
|
|
||||||
// iface stanza takes at least 3 parameters
|
// iface stanza takes at least 3 parameters
|
||||||
if (strcmp(token[0], "iface") == 0) {
|
if (strcmp(token[0], "iface") == 0) {
|
||||||
@@ -211,6 +226,33 @@ void ifparser_init (const char *eni_file, int quiet)
|
|||||||
add_block(token[0], token[i]);
|
add_block(token[0], token[i]);
|
||||||
skip_to_block = 0;
|
skip_to_block = 0;
|
||||||
}
|
}
|
||||||
|
// source stanza takes one or more filepaths as parameters
|
||||||
|
else if (strcmp(token[0], "source") == 0) {
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
skip_to_block = 0;
|
||||||
|
|
||||||
|
if (toknum == 1) {
|
||||||
|
if (!quiet)
|
||||||
|
g_warning ("Error: Invalid source line without parameters\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i = 1; i < toknum; ++i) {
|
||||||
|
char *eni_file_copy;
|
||||||
|
char *en_dir;
|
||||||
|
|
||||||
|
eni_file_copy = strdup (eni_file);
|
||||||
|
if (!eni_file_copy) {
|
||||||
|
if (!quiet)
|
||||||
|
g_warning ("Error: Skipping interfaces file %s because strdup failed\n",
|
||||||
|
eni_file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
en_dir = dirname (eni_file_copy);
|
||||||
|
_ifparser_source (token[i], en_dir, quiet);
|
||||||
|
free (eni_file_copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (skip_to_block) {
|
if (skip_to_block) {
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
@@ -222,6 +264,46 @@ void ifparser_init (const char *eni_file, int quiet)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(inp);
|
fclose(inp);
|
||||||
|
|
||||||
|
if (!quiet)
|
||||||
|
g_message (" interface-parser: finished parsing file %s\n", eni_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ifparser_source (const char *path, const char *en_dir, int quiet)
|
||||||
|
{
|
||||||
|
// abs_path = en_dir + '/' + path + '\0'
|
||||||
|
char abs_path[strlen (en_dir) + strlen (path) + 2];
|
||||||
|
wordexp_t we;
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
if (path[0] == '/') {
|
||||||
|
strncpy (abs_path, path, sizeof (abs_path));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Convert relative path to absolute path
|
||||||
|
snprintf (abs_path, sizeof (abs_path), "%s/%s", en_dir, path);
|
||||||
|
}
|
||||||
|
if (!quiet)
|
||||||
|
g_message (" interface-parser: source line includes interfaces file(s) %s\n", abs_path);
|
||||||
|
|
||||||
|
// Recursively parse sourced in interfaces files
|
||||||
|
// (ifupdown uses WRDE_NOCMD for wordexp)
|
||||||
|
memset (&we, 0, sizeof (we));
|
||||||
|
if (wordexp (abs_path, &we, WRDE_NOCMD)) {
|
||||||
|
if (!quiet)
|
||||||
|
g_warning ("Error: word expansion for %s failed\n", abs_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < we.we_wordc; i++) {
|
||||||
|
_recursive_ifparser (we.we_wordv[i], quiet);
|
||||||
|
}
|
||||||
|
wordfree (&we);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ifparser_init (const char *eni_file, int quiet)
|
||||||
|
{
|
||||||
|
first = last = NULL;
|
||||||
|
_recursive_ifparser (eni_file, quiet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _destroy_data(if_data *ifd)
|
void _destroy_data(if_data *ifd)
|
||||||
|
@@ -903,6 +903,32 @@ test19_read_static_ipv4_plen (const char *path)
|
|||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test20_source_stanza (const char *path)
|
||||||
|
{
|
||||||
|
Expected *e;
|
||||||
|
ExpectedBlock *b;
|
||||||
|
|
||||||
|
e = expected_new ();
|
||||||
|
|
||||||
|
b = expected_block_new ("auto", "eth0");
|
||||||
|
expected_add_block (e, b);
|
||||||
|
b = expected_block_new ("iface", "eth0");
|
||||||
|
expected_add_block (e, b);
|
||||||
|
expected_block_add_key (b, expected_key_new ("inet", "dhcp"));
|
||||||
|
|
||||||
|
b = expected_block_new ("auto", "eth1");
|
||||||
|
expected_add_block (e, b);
|
||||||
|
b = expected_block_new ("iface", "eth1");
|
||||||
|
expected_add_block (e, b);
|
||||||
|
expected_block_add_key (b, expected_key_new ("inet", "dhcp"));
|
||||||
|
|
||||||
|
init_ifparser_with_file (path, "test20-source-stanza");
|
||||||
|
compare_expected_to_ifparser (e);
|
||||||
|
|
||||||
|
ifparser_destroy ();
|
||||||
|
expected_free (e);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
@@ -955,6 +981,8 @@ main (int argc, char **argv)
|
|||||||
(GTestDataFunc) test18_read_static_ipv6);
|
(GTestDataFunc) test18_read_static_ipv6);
|
||||||
g_test_add_data_func ("/ifupdate/read_static_ipv4_plen", TEST_ENI_DIR,
|
g_test_add_data_func ("/ifupdate/read_static_ipv4_plen", TEST_ENI_DIR,
|
||||||
(GTestDataFunc) test19_read_static_ipv4_plen);
|
(GTestDataFunc) test19_read_static_ipv4_plen);
|
||||||
|
g_test_add_data_func ("/ifupdate/source_stanza", TEST_ENI_DIR,
|
||||||
|
(GTestDataFunc) test20_source_stanza);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
1
src/settings/plugins/ifupdown/tests/test20-source-stanza
Normal file
1
src/settings/plugins/ifupdown/tests/test20-source-stanza
Normal file
@@ -0,0 +1 @@
|
|||||||
|
source test20-source-stanza.eth*
|
@@ -0,0 +1,2 @@
|
|||||||
|
auto eth0
|
||||||
|
iface eth0 inet dhcp
|
@@ -0,0 +1,2 @@
|
|||||||
|
auto eth1
|
||||||
|
iface eth1 inet dhcp
|
Reference in New Issue
Block a user