mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 12:34:55 +00:00
2008-05-29 Dan Williams <dcbw@redhat.com>
* configure.in src/Makefile.am src/dnsmasq-manager/Makefile.am src/dnsmasq-manager/nm-dnsmasq-manager.c src/dnsmasq-manager/nm-dnsmasq-manager.h - Add a dnsmasq daemon manager to facilitate connection sharing git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3708 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
parent
3318502fb8
commit
f20d3695ff
|
@ -1,3 +1,12 @@
|
|||
2008-05-29 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
* configure.in
|
||||
src/Makefile.am
|
||||
src/dnsmasq-manager/Makefile.am
|
||||
src/dnsmasq-manager/nm-dnsmasq-manager.c
|
||||
src/dnsmasq-manager/nm-dnsmasq-manager.h
|
||||
- Add a dnsmasq daemon manager to facilitate connection sharing
|
||||
|
||||
2008-05-29 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
* src/nm-device-private.h
|
||||
|
|
|
@ -337,6 +337,7 @@ src/vpn-manager/Makefile
|
|||
src/dhcp-manager/Makefile
|
||||
src/supplicant-manager/Makefile
|
||||
src/ppp-manager/Makefile
|
||||
src/dnsmasq-manager/Makefile
|
||||
src/backends/Makefile
|
||||
libnm-util/libnm-util.pc
|
||||
libnm-util/Makefile
|
||||
|
|
|
@ -4,7 +4,8 @@ SUBDIRS= \
|
|||
dhcp-manager \
|
||||
supplicant-manager \
|
||||
ppp-manager \
|
||||
backends
|
||||
backends \
|
||||
dnsmasq-manager
|
||||
|
||||
INCLUDES = -I${top_srcdir} \
|
||||
-I${top_srcdir}/include \
|
||||
|
@ -13,6 +14,7 @@ INCLUDES = -I${top_srcdir} \
|
|||
-I${top_srcdir}/src/vpn-manager \
|
||||
-I${top_srcdir}/src/dhcp-manager \
|
||||
-I${top_srcdir}/src/supplicant-manager \
|
||||
-I${top_srcdir}/src/dnsmasq-manager \
|
||||
-I${top_srcdir}/libnm-util \
|
||||
-I${top_srcdir}/callouts
|
||||
|
||||
|
@ -139,6 +141,7 @@ NetworkManager_LDADD = \
|
|||
./vpn-manager/libvpn-manager.la \
|
||||
./dhcp-manager/libdhcp-manager.la \
|
||||
./supplicant-manager/libsupplicant-manager.la \
|
||||
./dnsmasq-manager/libdnsmasq-manager.la \
|
||||
./ppp-manager/libppp-manager.la \
|
||||
./backends/libnmbackend.la \
|
||||
$(top_builddir)/libnm-util/libnm-util.la
|
||||
|
|
16
src/dnsmasq-manager/Makefile.am
Normal file
16
src/dnsmasq-manager/Makefile.am
Normal file
|
@ -0,0 +1,16 @@
|
|||
INCLUDES = \
|
||||
-I${top_srcdir}/libnm-util \
|
||||
-I${top_srcdir}/src \
|
||||
-I${top_srcdir}/include
|
||||
|
||||
noinst_LTLIBRARIES = libdnsmasq-manager.la
|
||||
|
||||
libdnsmasq_manager_la_SOURCES = \
|
||||
nm-dnsmasq-manager.h \
|
||||
nm-dnsmasq-manager.c
|
||||
|
||||
libdnsmasq_manager_la_CPPFLAGS = \
|
||||
$(GTHREAD_CFLAGS) \
|
||||
-DLOCALSTATEDIR=\"$(localstatedir)\"
|
||||
|
||||
libdnsmasq_manager_la_LIBADD = $(GTHREAD_LIBS)
|
393
src/dnsmasq-manager/nm-dnsmasq-manager.c
Normal file
393
src/dnsmasq-manager/nm-dnsmasq-manager.c
Normal file
|
@ -0,0 +1,393 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nm-dnsmasq-manager.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
typedef struct {
|
||||
GPid pid;
|
||||
guint32 dm_watch_id;
|
||||
} NMDnsMasqManagerPrivate;
|
||||
|
||||
#define NM_DNSMASQ_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManagerPrivate))
|
||||
|
||||
G_DEFINE_TYPE (NMDnsMasqManager, nm_dnsmasq_manager, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
STATE_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
typedef enum {
|
||||
NM_DNSMASQ_MANAGER_ERROR_UNKOWN
|
||||
} NMDnsMasqManagerError;
|
||||
|
||||
GQuark
|
||||
nm_dnsmasq_manager_error_quark (void)
|
||||
{
|
||||
static GQuark quark;
|
||||
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("nm_dnsmasq_manager_error");
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_dnsmasq_manager_init (NMDnsMasqManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
static GObject *
|
||||
constructor (GType type,
|
||||
guint n_construct_params,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
return G_OBJECT_CLASS (nm_dnsmasq_manager_parent_class)->constructor (type,
|
||||
n_construct_params,
|
||||
construct_params);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
nm_dnsmasq_manager_stop (NM_DNSMASQ_MANAGER (object));
|
||||
|
||||
G_OBJECT_CLASS (nm_dnsmasq_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_dnsmasq_manager_class_init (NMDnsMasqManagerClass *manager_class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
|
||||
|
||||
g_type_class_add_private (manager_class, sizeof (NMDnsMasqManagerPrivate));
|
||||
|
||||
object_class->constructor = constructor;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
/* signals */
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new ("state-changed",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMDnsMasqManagerClass, state_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
}
|
||||
|
||||
NMDnsMasqManager *
|
||||
nm_dnsmasq_manager_new (void)
|
||||
{
|
||||
return (NMDnsMasqManager *) g_object_new (NM_TYPE_DNSMASQ_MANAGER, NULL);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GPtrArray *array;
|
||||
GStringChunk *chunk;
|
||||
} NMCmdLine;
|
||||
|
||||
static NMCmdLine *
|
||||
nm_cmd_line_new (void)
|
||||
{
|
||||
NMCmdLine *cmd;
|
||||
|
||||
cmd = g_slice_new (NMCmdLine);
|
||||
cmd->array = g_ptr_array_new ();
|
||||
cmd->chunk = g_string_chunk_new (1024);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_cmd_line_destroy (NMCmdLine *cmd)
|
||||
{
|
||||
g_ptr_array_free (cmd->array, TRUE);
|
||||
g_string_chunk_free (cmd->chunk);
|
||||
g_slice_free (NMCmdLine, cmd);
|
||||
}
|
||||
|
||||
static char *
|
||||
nm_cmd_line_to_str (NMCmdLine *cmd)
|
||||
{
|
||||
char *str;
|
||||
|
||||
g_ptr_array_add (cmd->array, NULL);
|
||||
str = g_strjoinv (" ", (gchar **) cmd->array->pdata);
|
||||
g_ptr_array_remove_index (cmd->array, cmd->array->len - 1);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_cmd_line_add_string (NMCmdLine *cmd, const char *str)
|
||||
{
|
||||
g_ptr_array_add (cmd->array, g_string_chunk_insert (cmd->chunk, str));
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
static inline const char *
|
||||
nm_find_dnsmasq (void)
|
||||
{
|
||||
static const char *dnsmasq_binary_paths[] =
|
||||
{
|
||||
"/usr/local/sbin/dnsmasq",
|
||||
"/usr/sbin/dnsmasq",
|
||||
"/sbin/dnsmasq",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char **dnsmasq_binary = dnsmasq_binary_paths;
|
||||
|
||||
while (*dnsmasq_binary != NULL) {
|
||||
if (g_file_test (*dnsmasq_binary, G_FILE_TEST_EXISTS))
|
||||
break;
|
||||
dnsmasq_binary++;
|
||||
}
|
||||
|
||||
return *dnsmasq_binary;
|
||||
}
|
||||
|
||||
static void
|
||||
dm_exit_code (guint dm_exit_status)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
switch (dm_exit_status) {
|
||||
case 1:
|
||||
msg = "Configuration problem";
|
||||
break;
|
||||
case 2:
|
||||
msg = "Network access problem (address in use; permissions; etc)";
|
||||
break;
|
||||
case 3:
|
||||
msg = "Filesystem problem (missing file/directory; permissions; etc)";
|
||||
break;
|
||||
case 4:
|
||||
msg = "Memory allocation failure";
|
||||
break;
|
||||
case 5:
|
||||
msg = "Other problem";
|
||||
break;
|
||||
default:
|
||||
if (dm_exit_status >= 11)
|
||||
msg = "Lease-script 'init' process failure";
|
||||
break;
|
||||
}
|
||||
|
||||
g_warning ("dnsmasq exited with error: %s (%d)", msg, dm_exit_status);
|
||||
}
|
||||
|
||||
static void
|
||||
dm_watch_cb (GPid pid, gint status, gpointer user_data)
|
||||
{
|
||||
NMDnsMasqManager *manager = NM_DNSMASQ_MANAGER (user_data);
|
||||
NMDnsMasqManagerPrivate *priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager);
|
||||
guint err;
|
||||
|
||||
if (WIFEXITED (status)) {
|
||||
err = WEXITSTATUS (status);
|
||||
if (err != 0)
|
||||
dm_exit_code (err);
|
||||
} else if (WIFSTOPPED (status))
|
||||
g_warning ("dnsmasq stopped unexpectedly with signal %d", WSTOPSIG (status));
|
||||
else if (WIFSIGNALED (status))
|
||||
g_warning ("dnsmasq died with signal %d", WTERMSIG (status));
|
||||
else
|
||||
g_warning ("dnsmasq died from an unknown cause");
|
||||
|
||||
/* Reap child if needed. */
|
||||
waitpid (pid, NULL, WNOHANG);
|
||||
|
||||
priv->pid = 0;
|
||||
|
||||
g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_DNSMASQ_STATUS_DEAD);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_pidfile_for_iface (const char *iface)
|
||||
{
|
||||
g_return_val_if_fail (iface != NULL, NULL);
|
||||
|
||||
return g_strdup_printf (LOCALSTATEDIR "/run/nm-dnsmasq-%s.pid", iface);
|
||||
}
|
||||
|
||||
static NMCmdLine *
|
||||
create_dm_cmd_line (const char *iface, GError **err)
|
||||
{
|
||||
const char *dm_binary;
|
||||
NMCmdLine *cmd;
|
||||
char *s, *pidfile;
|
||||
|
||||
dm_binary = nm_find_dnsmasq ();
|
||||
if (!dm_binary) {
|
||||
g_set_error (err, NM_DNSMASQ_MANAGER_ERROR, NM_DNSMASQ_MANAGER_ERROR,
|
||||
"Could not find dnsmasq binary.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create dnsmasq command line */
|
||||
cmd = nm_cmd_line_new ();
|
||||
nm_cmd_line_add_string (cmd, dm_binary);
|
||||
|
||||
nm_cmd_line_add_string (cmd, "--no-hosts");
|
||||
nm_cmd_line_add_string (cmd, "--keep-in-foreground");
|
||||
nm_cmd_line_add_string (cmd, "--listen-address=10.42.43.1");
|
||||
nm_cmd_line_add_string (cmd, "--bind-interfaces");
|
||||
nm_cmd_line_add_string (cmd, "--no-poll");
|
||||
nm_cmd_line_add_string (cmd, "--dhcp-range=10.42.43.10,10.42.43.100,60m");
|
||||
nm_cmd_line_add_string (cmd, "--dhcp-option=option:router,0.0.0.0");
|
||||
nm_cmd_line_add_string (cmd, "--dhcp-lease-max=50");
|
||||
|
||||
pidfile = get_pidfile_for_iface (iface);
|
||||
s = g_strdup_printf ("--pid-file=%s", pidfile);
|
||||
g_free (pidfile);
|
||||
nm_cmd_line_add_string (cmd, s);
|
||||
g_free (s);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static void
|
||||
dm_child_setup (gpointer user_data G_GNUC_UNUSED)
|
||||
{
|
||||
/* We are in the child process at this point */
|
||||
pid_t pid = getpid ();
|
||||
setpgid (pid, pid);
|
||||
}
|
||||
|
||||
static void
|
||||
kill_existing_for_iface (const char *iface)
|
||||
{
|
||||
char *pidfile;
|
||||
char *contents = NULL;
|
||||
glong pid;
|
||||
char *proc_path = NULL;
|
||||
char *cmdline_contents = NULL;
|
||||
|
||||
pidfile = get_pidfile_for_iface (iface);
|
||||
if (!g_file_get_contents (pidfile, &contents, NULL, NULL))
|
||||
goto out;
|
||||
|
||||
pid = strtol (contents, NULL, 10);
|
||||
if (pid < 1 || pid > INT_MAX)
|
||||
goto out;
|
||||
|
||||
proc_path = g_strdup_printf ("/proc/%ld/cmdline", pid);
|
||||
if (!g_file_get_contents (proc_path, &cmdline_contents, NULL, NULL))
|
||||
goto out;
|
||||
|
||||
if (strstr (cmdline_contents, "bin/dnsmasq")) {
|
||||
if (kill (pid, 0)) {
|
||||
nm_info ("Killing stale dnsmasq process %ld", pid);
|
||||
kill (pid, SIGKILL);
|
||||
}
|
||||
unlink (pidfile);
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (cmdline_contents);
|
||||
g_free (proc_path);
|
||||
g_free (contents);
|
||||
g_free (pidfile);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
|
||||
const char *iface,
|
||||
GError **err)
|
||||
{
|
||||
NMDnsMasqManagerPrivate *priv;
|
||||
NMCmdLine *dm_cmd;
|
||||
char *cmd_str;
|
||||
GSource *dm_watch;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DNSMASQ_MANAGER (manager), FALSE);
|
||||
g_return_val_if_fail (iface != NULL, FALSE);
|
||||
|
||||
kill_existing_for_iface (iface);
|
||||
|
||||
dm_cmd = create_dm_cmd_line (iface, err);
|
||||
if (!dm_cmd)
|
||||
return FALSE;
|
||||
|
||||
g_ptr_array_add (dm_cmd->array, NULL);
|
||||
|
||||
priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
nm_info ("Starting dnsmasq...");
|
||||
|
||||
cmd_str = nm_cmd_line_to_str (dm_cmd);
|
||||
nm_debug ("Command line: %s", cmd_str);
|
||||
g_free (cmd_str);
|
||||
|
||||
priv->pid = 0;
|
||||
if (!g_spawn_async (NULL, (char **) dm_cmd->array->pdata, NULL,
|
||||
G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
dm_child_setup,
|
||||
NULL, &priv->pid, err)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_debug ("dnsmasq started with pid %d", priv->pid);
|
||||
|
||||
dm_watch = g_child_watch_source_new (priv->pid);
|
||||
g_source_set_callback (dm_watch, (GSourceFunc) dm_watch_cb, manager, NULL);
|
||||
g_source_attach (dm_watch, NULL);
|
||||
priv->dm_watch_id = g_source_get_id (dm_watch);
|
||||
g_source_unref (dm_watch);
|
||||
|
||||
out:
|
||||
if (dm_cmd)
|
||||
nm_cmd_line_destroy (dm_cmd);
|
||||
|
||||
return priv->pid > 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_killed (gpointer data)
|
||||
{
|
||||
int pid = GPOINTER_TO_INT (data);
|
||||
|
||||
if (kill (pid, 0) == 0)
|
||||
kill (pid, SIGKILL);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_dnsmasq_manager_stop (NMDnsMasqManager *manager)
|
||||
{
|
||||
NMDnsMasqManagerPrivate *priv;
|
||||
|
||||
g_return_if_fail (NM_IS_DNSMASQ_MANAGER (manager));
|
||||
|
||||
priv = NM_DNSMASQ_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
if (priv->dm_watch_id) {
|
||||
g_source_remove (priv->dm_watch_id);
|
||||
priv->dm_watch_id = 0;
|
||||
}
|
||||
|
||||
if (priv->pid) {
|
||||
if (kill (priv->pid, SIGTERM) == 0)
|
||||
g_timeout_add (2000, ensure_killed, GINT_TO_POINTER (priv->pid));
|
||||
else
|
||||
kill (priv->pid, SIGKILL);
|
||||
|
||||
priv->pid = 0;
|
||||
}
|
||||
}
|
49
src/dnsmasq-manager/nm-dnsmasq-manager.h
Normal file
49
src/dnsmasq-manager/nm-dnsmasq-manager.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
|
||||
#ifndef NM_DNSMASQ_MANAGER_H
|
||||
#define NM_DNSMASQ_MANAGER_H
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#define NM_TYPE_DNSMASQ_MANAGER (nm_dnsmasq_manager_get_type ())
|
||||
#define NM_DNSMASQ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManager))
|
||||
#define NM_DNSMASQ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManagerClass))
|
||||
#define NM_IS_DNSMASQ_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DNSMASQ_MANAGER))
|
||||
#define NM_IS_DNSMASQ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DNSMASQ_MANAGER))
|
||||
#define NM_DNSMASQ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManagerClass))
|
||||
|
||||
typedef enum {
|
||||
NM_DNSMASQ_STATUS_UNKNOWN,
|
||||
|
||||
NM_DNSMASQ_STATUS_DEAD,
|
||||
NM_DNSMASQ_STATUS_RUNNING,
|
||||
} NMDnsMasqStatus;
|
||||
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
} NMDnsMasqManager;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
/* Signals */
|
||||
void (*state_changed) (NMDnsMasqManager *manager, NMDnsMasqStatus status);
|
||||
} NMDnsMasqManagerClass;
|
||||
|
||||
GType nm_dnsmasq_manager_get_type (void);
|
||||
|
||||
NMDnsMasqManager *nm_dnsmasq_manager_new (void);
|
||||
|
||||
gboolean nm_dnsmasq_manager_start (NMDnsMasqManager *manager,
|
||||
const char *device,
|
||||
GError **err);
|
||||
|
||||
void nm_dnsmasq_manager_stop (NMDnsMasqManager *manager);
|
||||
|
||||
#define NM_DNSMASQ_MANAGER_ERROR nm_dnsmasq_manager_error_quark()
|
||||
#define NM_TYPE_DNSMASQ_MANAGER_ERROR (nm_dnsmasq_manager_error_get_type ())
|
||||
|
||||
GQuark nm_dnsmasq_manager_error_quark (void);
|
||||
|
||||
#endif /* NM_DNSMASQ_MANAGER_H */
|
Loading…
Reference in a new issue