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:
Michael Wisheu
2013-09-04 16:21:20 +02:00
committed by Thomas Haller
parent fc7468131c
commit 48ed1abca7
5 changed files with 120 additions and 5 deletions

View File

@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wordexp.h>
#include <libgen.h>
#include "nm-utils.h"
if_block* first;
@@ -96,21 +98,33 @@ static char *join_values_with_spaces(char *dst, char **src)
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];
int skip_to_block = 1;
int skip_long_line = 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 (!quiet)
g_warning ("Error: Can't open %s\n", eni_file);
return;
}
if (!quiet)
g_message (" interface-parser: parsing file %s\n", eni_file);
first = last = NULL;
while (!feof(inp))
{
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;
}
// There are four different stanzas:
// iface, mapping, auto and allow-*. Create a block for each of them.
// There are five different stanzas:
// iface, mapping, auto, allow-* and source.
// Create a block for each of them except source.
// iface stanza takes at least 3 parameters
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]);
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 {
if (skip_to_block) {
if (!quiet) {
@@ -222,6 +264,46 @@ void ifparser_init (const char *eni_file, int quiet)
}
}
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)

View File

@@ -903,6 +903,32 @@ test19_read_static_ipv4_plen (const char *path)
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
main (int argc, char **argv)
@@ -955,6 +981,8 @@ main (int argc, char **argv)
(GTestDataFunc) test18_read_static_ipv6);
g_test_add_data_func ("/ifupdate/read_static_ipv4_plen", TEST_ENI_DIR,
(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 ();
}

View File

@@ -0,0 +1 @@
source test20-source-stanza.eth*

View File

@@ -0,0 +1,2 @@
auto eth0
iface eth0 inet dhcp

View File

@@ -0,0 +1,2 @@
auto eth1
iface eth1 inet dhcp