mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
Tue Feb 14 16:23:25 IST 2007 Mark McLoughlin <markmc@redhat.com>
* qemud/iptables.[ch]: add code for managing iptables rules. * qemud/Makefile.am: add iptables.[ch]. * qemud/qemud.c: add and remove iptables rules as appropriate. * qemud/conf.c: when starting a guess, add a rule allowing it to forward packets across the networks bridge. * qemud/internal.h: add iptables context ptr * configure.in: add --with-iptables-dir and --with-iptables-prefix to allow us to put our rules in a chain with the given prefix and save the rules in files in the given dir so as to integrate with the proposed "service iptables restart" solution in: https://bugzilla.redhat.com/227011
This commit is contained in:
parent
e89a1c33f5
commit
3ea88b568d
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
|||||||
|
Tue Feb 14 16:23:25 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||||
|
|
||||||
|
* qemud/iptables.[ch]: add code for managing iptables
|
||||||
|
rules.
|
||||||
|
|
||||||
|
* qemud/Makefile.am: add iptables.[ch].
|
||||||
|
|
||||||
|
* qemud/qemud.c: add and remove iptables rules as
|
||||||
|
appropriate.
|
||||||
|
|
||||||
|
* qemud/conf.c: when starting a guess, add a rule
|
||||||
|
allowing it to forward packets across the networks
|
||||||
|
bridge.
|
||||||
|
|
||||||
|
* qemud/internal.h: add iptables context ptr
|
||||||
|
|
||||||
|
* configure.in: add --with-iptables-dir and
|
||||||
|
--with-iptables-prefix to allow us to put our rules
|
||||||
|
in a chain with the given prefix and save the rules
|
||||||
|
in files in the given dir so as to integrate with
|
||||||
|
the proposed "service iptables restart" solution
|
||||||
|
in:
|
||||||
|
|
||||||
|
https://bugzilla.redhat.com/227011
|
||||||
|
|
||||||
Tue Feb 14 16:21:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
Tue Feb 14 16:21:18 IST 2007 Mark McLoughlin <markmc@redhat.com>
|
||||||
|
|
||||||
* src/xml.c: with <interface type="network"> connect the
|
* src/xml.c: with <interface type="network"> connect the
|
||||||
|
25
configure.in
25
configure.in
@ -78,6 +78,31 @@ dnl
|
|||||||
CFLAGS="-g -O -W -Wformat -Wunused -Wimplicit -Wreturn-type -Wswitch -Wcomment -Wtrigraphs -Wformat -Wchar-subscripts -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls -Wall"
|
CFLAGS="-g -O -W -Wformat -Wunused -Wimplicit -Wreturn-type -Wswitch -Wcomment -Wtrigraphs -Wformat -Wchar-subscripts -Wuninitialized -Wparentheses -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wredundant-decls -Wall"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl
|
||||||
|
dnl allow the creation of iptables rules in chains with a
|
||||||
|
dnl specific prefix rather than in the standard toplevel chains
|
||||||
|
dnl
|
||||||
|
AC_ARG_WITH(iptables-prefix,
|
||||||
|
AC_HELP_STRING([--with-iptables-prefix=prefix],
|
||||||
|
[prefix used for iptables chains, default is to use standard toplevel chains]),
|
||||||
|
[IPTABLES_PREFIX=$withval])
|
||||||
|
AC_DEFINE_UNQUOTED(IPTABLES_PREFIX, "$IPTABLES_PREFIX", [prefix used for iptables chains])
|
||||||
|
|
||||||
|
dnl
|
||||||
|
dnl also support saving the various chains to files
|
||||||
|
dnl in e.g. /etc/sysconfig/iptables.d
|
||||||
|
dnl
|
||||||
|
AC_ARG_WITH(iptables-dir,
|
||||||
|
AC_HELP_STRING([--with-iptables-dir=path],
|
||||||
|
[directory used to save iptables chains, defaults to not saving]),
|
||||||
|
[IPTABLES_DIR=$withval])
|
||||||
|
if test x"$IPTABLES_DIR" != "x"; then
|
||||||
|
AC_DEFINE_UNQUOTED(IPTABLES_DIR, "$IPTABLES_DIR", [directory used for saving iptables chains])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_PATH_PROG(IPTABLES_PATH, iptables, /sbin/iptables)
|
||||||
|
AC_DEFINE_UNQUOTED(IPTABLES_PATH, "$IPTABLES_PATH", [path to iptables binary])
|
||||||
|
|
||||||
dnl
|
dnl
|
||||||
dnl Specify the xen-distribution directory to be able to compile on a
|
dnl Specify the xen-distribution directory to be able to compile on a
|
||||||
dnl non-xenified host
|
dnl non-xenified host
|
||||||
|
@ -8,7 +8,8 @@ libvirt_qemud_SOURCES = qemud.c internal.h protocol.h \
|
|||||||
driver.c driver.h \
|
driver.c driver.h \
|
||||||
dispatch.c dispatch.h \
|
dispatch.c dispatch.h \
|
||||||
conf.c conf.h \
|
conf.c conf.h \
|
||||||
bridge.c bridge.h
|
bridge.c bridge.h \
|
||||||
|
iptables.c iptables.h
|
||||||
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
|
#-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L
|
||||||
libvirt_qemud_CFLAGS = \
|
libvirt_qemud_CFLAGS = \
|
||||||
-I$(top_srcdir)/include -I$(top_builddir)/include $(LIBXML_CFLAGS) \
|
-I$(top_srcdir)/include -I$(top_builddir)/include $(LIBXML_CFLAGS) \
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
#include "iptables.h"
|
||||||
|
|
||||||
static int qemudParseUUID(const char *uuid,
|
static int qemudParseUUID(const char *uuid,
|
||||||
unsigned char *rawuuid) {
|
unsigned char *rawuuid) {
|
||||||
@ -860,6 +861,13 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = iptablesAddPhysdevForward(server->iptables, net->dst.network.tapifname))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"Failed to add iptables rule to allow bridging from '%s' :%s",
|
||||||
|
net->dst.network.tapifname, strerror(err));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=", tapfd);
|
snprintf(tapfdstr, sizeof(tapfdstr), "tap,fd=%d,script=", tapfd);
|
||||||
|
|
||||||
if (!(retval = strdup(tapfdstr)))
|
if (!(retval = strdup(tapfdstr)))
|
||||||
@ -875,6 +883,7 @@ qemudNetworkIfaceConnect(struct qemud_server *server,
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
no_memory:
|
no_memory:
|
||||||
|
iptablesRemovePhysdevForward(server->iptables, net->dst.network.tapifname);
|
||||||
qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
|
qemudReportError(server, VIR_ERR_NO_MEMORY, "tapfds");
|
||||||
error:
|
error:
|
||||||
if (retval)
|
if (retval)
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "bridge.h"
|
#include "bridge.h"
|
||||||
|
#include "iptables.h"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#ifdef HAVE_ANSIDECL_H
|
#ifdef HAVE_ANSIDECL_H
|
||||||
@ -283,6 +284,7 @@ struct qemud_server {
|
|||||||
int ninactivenetworks;
|
int ninactivenetworks;
|
||||||
struct qemud_network *inactivenetworks;
|
struct qemud_network *inactivenetworks;
|
||||||
brControl *brctl;
|
brControl *brctl;
|
||||||
|
iptablesContext *iptables;
|
||||||
char configDir[PATH_MAX];
|
char configDir[PATH_MAX];
|
||||||
char networkConfigDir[PATH_MAX];
|
char networkConfigDir[PATH_MAX];
|
||||||
char errorMessage[QEMUD_MAX_ERROR_LEN];
|
char errorMessage[QEMUD_MAX_ERROR_LEN];
|
||||||
|
699
qemud/iptables.c
Normal file
699
qemud/iptables.c
Normal file
@ -0,0 +1,699 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <markmc@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include "iptables.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADD = 0,
|
||||||
|
REMOVE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WITH_ERRORS = 0,
|
||||||
|
NO_ERRORS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *table;
|
||||||
|
char *chain;
|
||||||
|
|
||||||
|
#ifdef IPTABLES_DIR
|
||||||
|
|
||||||
|
char dir[PATH_MAX];
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
int nrules;
|
||||||
|
char **rules;
|
||||||
|
|
||||||
|
#endif /* IPTABLES_DIR */
|
||||||
|
|
||||||
|
} iptRules;
|
||||||
|
|
||||||
|
struct _iptablesContext
|
||||||
|
{
|
||||||
|
iptRules *input_filter;
|
||||||
|
iptRules *forward_filter;
|
||||||
|
iptRules *nat_postrouting;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef IPTABLES_DIR
|
||||||
|
static int
|
||||||
|
writeRules(const char *path,
|
||||||
|
char * const *rules,
|
||||||
|
int nrules)
|
||||||
|
{
|
||||||
|
char tmp[PATH_MAX];
|
||||||
|
FILE *f;
|
||||||
|
int istmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (nrules == 0 && unlink(path) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (snprintf(tmp, PATH_MAX, "%s.new", path) >= PATH_MAX)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
istmp = 1;
|
||||||
|
|
||||||
|
if (!(f = fopen(tmp, "w"))) {
|
||||||
|
istmp = 0;
|
||||||
|
if (!(f = fopen(path, "w")))
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nrules; i++) {
|
||||||
|
if (fputs(rules[i], f) == EOF ||
|
||||||
|
fputc('\n', f) == EOF) {
|
||||||
|
fclose(f);
|
||||||
|
if (istmp)
|
||||||
|
unlink(tmp);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (istmp && rename(tmp, path) < 0) {
|
||||||
|
unlink(tmp);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (istmp)
|
||||||
|
unlink(tmp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ensureDir(const char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
char parent[PATH_MAX];
|
||||||
|
char *p;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (stat(path, &st) >= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
strncpy(parent, path, PATH_MAX);
|
||||||
|
parent[PATH_MAX - 1] = '\0';
|
||||||
|
|
||||||
|
if (!(p = strrchr(parent, '/')))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (p == parent)
|
||||||
|
return EPERM;
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
if ((err = ensureDir(parent)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (mkdir(path, 0700) < 0 && errno != EEXIST)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
buildDir(const char *table,
|
||||||
|
char *path,
|
||||||
|
int maxlen)
|
||||||
|
{
|
||||||
|
if (snprintf(path, maxlen, IPTABLES_DIR "/%s", table) >= maxlen)
|
||||||
|
return EINVAL;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
buildPath(const char *table,
|
||||||
|
const char *chain,
|
||||||
|
char *path,
|
||||||
|
int maxlen)
|
||||||
|
{
|
||||||
|
if (snprintf(path, maxlen, IPTABLES_DIR "/%s/%s.chain", table, chain) >= maxlen)
|
||||||
|
return EINVAL;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptRulesAppend(iptRules *rules,
|
||||||
|
const char *rule)
|
||||||
|
{
|
||||||
|
char **r;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!(r = (char **)realloc(rules->rules, sizeof(char *) * (rules->nrules+1))))
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
rules->rules = r;
|
||||||
|
|
||||||
|
if (!(rules->rules[rules->nrules] = strdup(rule)))
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
rules->nrules++;
|
||||||
|
|
||||||
|
if ((err = ensureDir(rules->dir)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if ((err = writeRules(rules->path, rules->rules, rules->nrules)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptRulesRemove(iptRules *rules,
|
||||||
|
const char *rule)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
for (i = 0; i < rules->nrules; i++)
|
||||||
|
if (!strcmp(rules->rules[i], rule))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i >= rules->nrules)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
free(rules->rules[i]);
|
||||||
|
|
||||||
|
memmove(&rules->rules[i],
|
||||||
|
&rules->rules[i+1],
|
||||||
|
(rules->nrules - i - 1) * sizeof (char *));
|
||||||
|
|
||||||
|
rules->nrules--;
|
||||||
|
|
||||||
|
if ((err = writeRules(rules->path, rules->rules, rules->nrules)))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* IPTABLES_DIR */
|
||||||
|
|
||||||
|
static void
|
||||||
|
iptRulesFree(iptRules *rules)
|
||||||
|
{
|
||||||
|
if (rules->table) {
|
||||||
|
free(rules->chain);
|
||||||
|
rules->chain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rules->chain) {
|
||||||
|
free(rules->chain);
|
||||||
|
rules->chain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef IPTABLES_DIR
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
rules->dir[0] = '\0';
|
||||||
|
rules->path[0] = '\0';
|
||||||
|
|
||||||
|
for (i = 0; i < rules->nrules; i++) {
|
||||||
|
free(rules->rules[i]);
|
||||||
|
rules->rules[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rules->nrules = 0;
|
||||||
|
|
||||||
|
if (rules->rules) {
|
||||||
|
free(rules->rules);
|
||||||
|
rules->rules = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* IPTABLES_DIR */
|
||||||
|
|
||||||
|
free(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
static iptRules *
|
||||||
|
iptRulesNew(const char *table,
|
||||||
|
const char *chain)
|
||||||
|
{
|
||||||
|
iptRules *rules;
|
||||||
|
|
||||||
|
if (!(rules = (iptRules *)malloc(sizeof (iptRules))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset (rules, 0, sizeof (iptRules));
|
||||||
|
|
||||||
|
if (!(rules->table = strdup(table)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(rules->chain = strdup(chain)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
#ifdef IPTABLES_DIR
|
||||||
|
if (buildDir(table, rules->dir, sizeof(rules->dir)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (buildPath(table, chain, rules->path, sizeof(rules->path)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
rules->rules = NULL;
|
||||||
|
rules->nrules = 0;
|
||||||
|
#endif /* IPTABLES_DIR */
|
||||||
|
|
||||||
|
return rules;
|
||||||
|
|
||||||
|
error:
|
||||||
|
iptRulesFree(rules);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesSpawn(int errors, char * const *argv)
|
||||||
|
{
|
||||||
|
pid_t pid, ret;
|
||||||
|
int status;
|
||||||
|
int null = -1;
|
||||||
|
|
||||||
|
if (errors == NO_ERRORS && (null = open(_PATH_DEVNULL, O_RDONLY)) < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
if (errors == NO_ERRORS)
|
||||||
|
close(null);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) { /* child */
|
||||||
|
int i, open_max = sysconf(_SC_OPEN_MAX);
|
||||||
|
|
||||||
|
for (i = 0; i < open_max; i++) {
|
||||||
|
if (i != STDOUT_FILENO &&
|
||||||
|
i != STDERR_FILENO &&
|
||||||
|
i != STDIN_FILENO)
|
||||||
|
close(i);
|
||||||
|
else if (errors == NO_ERRORS)
|
||||||
|
dup2(null, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
|
||||||
|
_exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors == NO_ERRORS)
|
||||||
|
close(null);
|
||||||
|
|
||||||
|
while ((ret = waitpid(pid, &status, 0) == -1) && errno == EINTR);
|
||||||
|
if (ret == -1)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
if (errors == NO_ERRORS)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? 0 : EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesAddRemoveChain(iptRules *rules, int action)
|
||||||
|
{
|
||||||
|
char **argv;
|
||||||
|
int retval = ENOMEM;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = 1 + /* /sbin/iptables */
|
||||||
|
2 + /* --table foo */
|
||||||
|
2; /* --new-chain bar */
|
||||||
|
|
||||||
|
if (!(argv = (char **)malloc(sizeof(char *) * (n+1))))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(argv, 0, sizeof(char *) * (n + 1));
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(IPTABLES_PATH)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup("--table")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(rules->table)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(action == ADD ? "--new-chain" : "--delete-chain")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(rules->chain)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
retval = iptablesSpawn(NO_ERRORS, argv);
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (argv) {
|
||||||
|
n = 0;
|
||||||
|
while (argv[n])
|
||||||
|
free(argv[n++]);
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesAddRemoveRule(iptRules *rules, int action, const char *arg, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int retval = ENOMEM;
|
||||||
|
char **argv;
|
||||||
|
char *rule = NULL, *p;
|
||||||
|
const char *s;
|
||||||
|
int n, rulelen;
|
||||||
|
|
||||||
|
n = 1 + /* /sbin/iptables */
|
||||||
|
2 + /* --table foo */
|
||||||
|
2 + /* --insert bar */
|
||||||
|
1; /* arg */
|
||||||
|
|
||||||
|
rulelen = strlen(arg) + 1;
|
||||||
|
|
||||||
|
va_start(args, arg);
|
||||||
|
while ((s = va_arg(args, const char *))) {
|
||||||
|
n++;
|
||||||
|
rulelen += strlen(s) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (!(argv = (char **)malloc(sizeof(char *) * (n + 1))))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(rule = (char *)malloc(rulelen)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(argv, 0, sizeof(char *) * (n + 1));
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(IPTABLES_PATH)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup("--table")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(rules->table)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(action == ADD ? "--insert" : "--delete")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(rules->chain)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(argv[n++] = strdup(arg)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
p = strcpy(rule, arg);
|
||||||
|
p += strlen(arg);
|
||||||
|
|
||||||
|
va_start(args, arg);
|
||||||
|
|
||||||
|
while ((s = va_arg(args, const char *))) {
|
||||||
|
if (!(argv[n++] = strdup(s)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
*(p++) = ' ';
|
||||||
|
strcpy(p, s);
|
||||||
|
p += strlen(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
if (action == ADD &&
|
||||||
|
(retval = iptablesAddRemoveChain(rules, action)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if ((retval = iptablesSpawn(WITH_ERRORS, argv)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (action == REMOVE &&
|
||||||
|
(retval = iptablesAddRemoveChain(rules, action)))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
#ifdef IPTABLES_DIR
|
||||||
|
if (action == ADD)
|
||||||
|
retval = iptRulesAppend(rules, rule);
|
||||||
|
else
|
||||||
|
retval = iptRulesRemove(rules, rule);
|
||||||
|
#endif /* IPTABLES_DIR */
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (rule)
|
||||||
|
free(rule);
|
||||||
|
|
||||||
|
if (argv) {
|
||||||
|
n = 0;
|
||||||
|
while (argv[n])
|
||||||
|
free(argv[n++]);
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
iptablesContext *
|
||||||
|
iptablesContextNew(void)
|
||||||
|
{
|
||||||
|
iptablesContext *ctx;
|
||||||
|
|
||||||
|
if (!(ctx = (iptablesContext *) malloc(sizeof (iptablesContext))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(ctx->input_filter = iptRulesNew("filter", IPTABLES_PREFIX "INPUT")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(ctx->forward_filter = iptRulesNew("filter", IPTABLES_PREFIX "FORWARD")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!(ctx->nat_postrouting = iptRulesNew("nat", IPTABLES_PREFIX "POSTROUTING")))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
|
||||||
|
error:
|
||||||
|
iptablesContextFree(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iptablesContextFree(iptablesContext *ctx)
|
||||||
|
{
|
||||||
|
iptRulesFree(ctx->input_filter);
|
||||||
|
iptRulesFree(ctx->forward_filter);
|
||||||
|
iptRulesFree(ctx->nat_postrouting);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesInput(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port,
|
||||||
|
int action,
|
||||||
|
int tcp)
|
||||||
|
{
|
||||||
|
char portstr[32];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(portstr, sizeof(portstr), "%d", port);
|
||||||
|
portstr[sizeof(portstr) - 1] = '\0';
|
||||||
|
|
||||||
|
ret = iptablesAddRemoveRule(ctx->input_filter,
|
||||||
|
action,
|
||||||
|
"--in-interface", iface,
|
||||||
|
"--protocol", tcp ? "tcp" : "udp",
|
||||||
|
"--destination-port", portstr,
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddTcpInput(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
return iptablesInput(ctx, iface, port, ADD, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemoveTcpInput(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
return iptablesInput(ctx, iface, port, REMOVE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddUdpInput(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
return iptablesInput(ctx, iface, port, ADD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemoveUdpInput(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
return iptablesInput(ctx, iface, port, REMOVE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesPhysdevForward(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int action)
|
||||||
|
{
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--match", "physdev",
|
||||||
|
"--physdev-in", iface,
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddPhysdevForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesPhysdevForward(ctx, iface, ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemovePhysdevForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesPhysdevForward(ctx, iface, REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesInterfaceForward(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int action)
|
||||||
|
{
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--in-interface", iface,
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddInterfaceForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesInterfaceForward(ctx, iface, ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemoveInterfaceForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesInterfaceForward(ctx, iface, REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesStateForward(iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int action)
|
||||||
|
{
|
||||||
|
return iptablesAddRemoveRule(ctx->forward_filter,
|
||||||
|
action,
|
||||||
|
"--out-interface", iface,
|
||||||
|
"--match", "state",
|
||||||
|
"--state", "ESTABLISHED,RELATED",
|
||||||
|
"--jump", "ACCEPT",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddStateForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesStateForward(ctx, iface, ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemoveStateForward(iptablesContext *ctx,
|
||||||
|
const char *iface)
|
||||||
|
{
|
||||||
|
return iptablesStateForward(ctx, iface, REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iptablesNonBridgedMasq(iptablesContext *ctx,
|
||||||
|
int action)
|
||||||
|
{
|
||||||
|
return iptablesAddRemoveRule(ctx->nat_postrouting,
|
||||||
|
action,
|
||||||
|
"--match", "physdev",
|
||||||
|
"!", "--physdev-is-bridged",
|
||||||
|
"--jump", "MASQUERADE",
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesAddNonBridgedMasq(iptablesContext *ctx)
|
||||||
|
{
|
||||||
|
return iptablesNonBridgedMasq(ctx, ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
iptablesRemoveNonBridgedMasq(iptablesContext *ctx)
|
||||||
|
{
|
||||||
|
return iptablesNonBridgedMasq(ctx, REMOVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* c-indent-level: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* End:
|
||||||
|
*/
|
71
qemud/iptables.h
Normal file
71
qemud/iptables.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2007 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Mark McLoughlin <markmc@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __QEMUD_IPTABLES_H__
|
||||||
|
#define __QEMUD_IPTABLES_H__
|
||||||
|
|
||||||
|
typedef struct _iptablesContext iptablesContext;
|
||||||
|
|
||||||
|
iptablesContext *iptablesContextNew (void);
|
||||||
|
void iptablesContextFree (iptablesContext *ctx);
|
||||||
|
|
||||||
|
int iptablesAddTcpInput (iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port);
|
||||||
|
int iptablesRemoveTcpInput (iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
int iptablesAddUdpInput (iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port);
|
||||||
|
int iptablesRemoveUdpInput (iptablesContext *ctx,
|
||||||
|
const char *iface,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
int iptablesAddPhysdevForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
int iptablesRemovePhysdevForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
|
||||||
|
int iptablesAddInterfaceForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
int iptablesRemoveInterfaceForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
|
||||||
|
int iptablesAddStateForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
int iptablesRemoveStateForward (iptablesContext *ctx,
|
||||||
|
const char *iface);
|
||||||
|
|
||||||
|
int iptablesAddNonBridgedMasq (iptablesContext *ctx);
|
||||||
|
int iptablesRemoveNonBridgedMasq (iptablesContext *ctx);
|
||||||
|
|
||||||
|
#endif /* __QEMUD_IPTABLES_H__ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* indent-tabs-mode: nil
|
||||||
|
* c-indent-level: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* tab-width: 4
|
||||||
|
* End:
|
||||||
|
*/
|
147
qemud/qemud.c
147
qemud/qemud.c
@ -50,6 +50,7 @@
|
|||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "iptables.h"
|
||||||
|
|
||||||
static void reapchild(int sig ATTRIBUTE_UNUSED) {
|
static void reapchild(int sig ATTRIBUTE_UNUSED) {
|
||||||
/* We explicitly waitpid the child later */
|
/* We explicitly waitpid the child later */
|
||||||
@ -659,11 +660,10 @@ static int qemudVMData(struct qemud_server *server ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
qemudNetworkIfaceDisconnect(struct qemud_server *server ATTRIBUTE_UNUSED,
|
qemudNetworkIfaceDisconnect(struct qemud_server *server,
|
||||||
struct qemud_vm *vm ATTRIBUTE_UNUSED,
|
struct qemud_vm *vm ATTRIBUTE_UNUSED,
|
||||||
struct qemud_vm_net_def *net) {
|
struct qemud_vm_net_def *net) {
|
||||||
/* FIXME: will be needed to remove iptables rules */
|
iptablesRemovePhysdevForward(server->iptables, net->dst.network.tapifname);
|
||||||
net = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
int qemudShutdownVMDaemon(struct qemud_server *server, struct qemud_vm *vm) {
|
||||||
@ -845,6 +845,129 @@ dhcpStartDhcpDaemon(struct qemud_server *server,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemudAddIptablesRules(struct qemud_server *server,
|
||||||
|
struct qemud_network *network) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!server->iptables && !(server->iptables = iptablesContextNew())) {
|
||||||
|
qemudReportError(server, VIR_ERR_NO_MEMORY, "iptables support");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow bridging from the bridge interface itself */
|
||||||
|
if ((err = iptablesAddPhysdevForward(server->iptables, network->bridge))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow bridging from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow forwarding packets from the bridge interface */
|
||||||
|
if ((err = iptablesAddInterfaceForward(server->iptables, network->bridge))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow forwarding from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow forwarding packets to the bridge interface if they are part of an existing connection */
|
||||||
|
if ((err = iptablesAddStateForward(server->iptables, network->bridge))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow forwarding to '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable masquerading */
|
||||||
|
if ((err = iptablesAddNonBridgedMasq(server->iptables))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to enable masquerading : %s\n",
|
||||||
|
strerror(err));
|
||||||
|
goto err4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow DHCP requests through to dnsmasq */
|
||||||
|
if ((err = iptablesAddTcpInput(server->iptables, network->bridge, 67))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow DHCP requests from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 67))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow DHCP requests from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allow DNS requests through to dnsmasq */
|
||||||
|
if ((err = iptablesAddTcpInput(server->iptables, network->bridge, 53))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow DNS requests from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err7;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = iptablesAddUdpInput(server->iptables, network->bridge, 53))) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to add iptables rule to allow DNS requests from '%s' : %s\n",
|
||||||
|
network->bridge, strerror(err));
|
||||||
|
goto err8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err8:
|
||||||
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
|
||||||
|
err7:
|
||||||
|
iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
|
||||||
|
err6:
|
||||||
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
||||||
|
err5:
|
||||||
|
iptablesRemoveNonBridgedMasq(server->iptables);
|
||||||
|
err4:
|
||||||
|
iptablesRemoveStateForward(server->iptables, network->bridge);
|
||||||
|
err3:
|
||||||
|
iptablesRemoveInterfaceForward(server->iptables, network->bridge);
|
||||||
|
err2:
|
||||||
|
iptablesRemovePhysdevForward(server->iptables, network->bridge);
|
||||||
|
err1:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
qemudRemoveIptablesRules(struct qemud_server *server,
|
||||||
|
struct qemud_network *network) {
|
||||||
|
iptablesRemoveUdpInput(server->iptables, network->bridge, 53);
|
||||||
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 53);
|
||||||
|
iptablesRemoveUdpInput(server->iptables, network->bridge, 67);
|
||||||
|
iptablesRemoveTcpInput(server->iptables, network->bridge, 67);
|
||||||
|
iptablesRemoveNonBridgedMasq(server->iptables);
|
||||||
|
iptablesRemoveStateForward(server->iptables, network->bridge);
|
||||||
|
iptablesRemoveInterfaceForward(server->iptables, network->bridge);
|
||||||
|
iptablesRemovePhysdevForward(server->iptables, network->bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemudEnableIpForwarding(void)
|
||||||
|
{
|
||||||
|
#define PROC_IP_FORWARD "/proc/sys/net/ipv4/ip_forward"
|
||||||
|
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if ((fd = open(PROC_IP_FORWARD, O_WRONLY|O_TRUNC)) == -1 ||
|
||||||
|
write(fd, "1\n", 2) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#undef PROC_IP_FORWARD
|
||||||
|
}
|
||||||
|
|
||||||
int qemudStartNetworkDaemon(struct qemud_server *server,
|
int qemudStartNetworkDaemon(struct qemud_server *server,
|
||||||
struct qemud_network *network) {
|
struct qemud_network *network) {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -899,14 +1022,26 @@ int qemudStartNetworkDaemon(struct qemud_server *server,
|
|||||||
goto err_delbr;
|
goto err_delbr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qemudAddIptablesRules(server, network))
|
||||||
|
goto err_delbr1;
|
||||||
|
|
||||||
|
if (!qemudEnableIpForwarding()) {
|
||||||
|
qemudReportError(server, VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"failed to enable IP forwarding : %s\n", strerror(err));
|
||||||
|
goto err_delbr2;
|
||||||
|
}
|
||||||
|
|
||||||
if (network->def.ranges &&
|
if (network->def.ranges &&
|
||||||
dhcpStartDhcpDaemon(server, network) < 0)
|
dhcpStartDhcpDaemon(server, network) < 0)
|
||||||
goto err_delbr1;
|
goto err_delbr2;
|
||||||
|
|
||||||
network->active = 1;
|
network->active = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_delbr2:
|
||||||
|
qemudRemoveIptablesRules(server, network);
|
||||||
|
|
||||||
err_delbr1:
|
err_delbr1:
|
||||||
if (network->def.ipAddress[0] &&
|
if (network->def.ipAddress[0] &&
|
||||||
(err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
|
(err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
|
||||||
@ -935,6 +1070,8 @@ int qemudShutdownNetworkDaemon(struct qemud_server *server,
|
|||||||
if (network->dnsmasqPid > 0)
|
if (network->dnsmasqPid > 0)
|
||||||
kill(network->dnsmasqPid, SIGTERM);
|
kill(network->dnsmasqPid, SIGTERM);
|
||||||
|
|
||||||
|
qemudRemoveIptablesRules(server, network);
|
||||||
|
|
||||||
if (network->def.ipAddress[0] &&
|
if (network->def.ipAddress[0] &&
|
||||||
(err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
|
(err = brSetInterfaceUp(server->brctl, network->bridge, 0))) {
|
||||||
printf("Damn! Failed to bring down bridge '%s' : %s\n",
|
printf("Damn! Failed to bring down bridge '%s' : %s\n",
|
||||||
@ -1182,6 +1319,8 @@ static void qemudCleanup(struct qemud_server *server) {
|
|||||||
}
|
}
|
||||||
if (server->brctl)
|
if (server->brctl)
|
||||||
brShutdown(server->brctl);
|
brShutdown(server->brctl);
|
||||||
|
if (server->iptables)
|
||||||
|
iptablesContextFree(server->iptables);
|
||||||
free(server);
|
free(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user