2007-08-15 14:30:06 +00:00
|
|
|
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
|
|
|
|
|
|
|
|
|
|
#include <pppd/pppd.h>
|
|
|
|
|
#include <pppd/fsm.h>
|
|
|
|
|
#include <pppd/ipcp.h>
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
2007-10-10 14:36:31 +00:00
|
|
|
#include <glib/gtypes.h>
|
|
|
|
|
#include <glib-object.h>
|
|
|
|
|
#include <dbus/dbus-glib.h>
|
2007-08-15 14:30:06 +00:00
|
|
|
|
|
|
|
|
#include "nm-pppd-plugin.h"
|
|
|
|
|
#include "nm-ppp-status.h"
|
2007-10-10 14:36:31 +00:00
|
|
|
#include "nm-pppd-plugin-glue.h"
|
2007-08-15 14:30:06 +00:00
|
|
|
|
|
|
|
|
char pppd_version[] = VERSION;
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
#define NM_TYPE_PPPD_PLUGIN (nm_pppd_plugin_get_type ())
|
|
|
|
|
#define NM_PPPD_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PPPD_PLUGIN, NMPppdPlugin))
|
|
|
|
|
#define NM_PPPD_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PPPD_PLUGIN, NMPppdPluginClass))
|
|
|
|
|
#define NM_IS_PPPD_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PPPD_PLUGIN))
|
|
|
|
|
#define NM_IS_PPPD_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_PPPD_PLUGIN))
|
|
|
|
|
#define NM_PPPD_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PPPD_PLUGIN, NMPppdPluginClass))
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GObject parent;
|
|
|
|
|
} NMPppdPlugin;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GObjectClass parent;
|
|
|
|
|
|
|
|
|
|
void (*state_changed) (NMPppdPlugin *plugin,
|
|
|
|
|
NMPPPStatus status);
|
|
|
|
|
void (*ip4_config) (NMPppdPlugin *plugin,
|
|
|
|
|
GHashTable *ip4_config);
|
|
|
|
|
} NMPppdPluginClass;
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (NMPppdPlugin, nm_pppd_plugin, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
#define NM_PPPD_PLUGIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PPPD_PLUGIN, NMPppdPluginPrivate))
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
DBusGConnection *bus;
|
|
|
|
|
} NMPppdPluginPrivate;
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
STATE_CHANGED,
|
|
|
|
|
IP4_CONFIG,
|
|
|
|
|
|
|
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_pppd_plugin_init (NMPppdPlugin *plugin)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
finalize (GObject *object)
|
|
|
|
|
{
|
|
|
|
|
dbus_g_connection_unref (NM_PPPD_PLUGIN_GET_PRIVATE (object)->bus);
|
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_pppd_plugin_parent_class)->finalize (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_pppd_plugin_class_init (NMPppdPluginClass *plugin_class)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (plugin_class);
|
|
|
|
|
|
|
|
|
|
g_type_class_add_private (object_class, sizeof (NMPppdPluginPrivate));
|
|
|
|
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (plugin_class),
|
|
|
|
|
&dbus_glib_nm_pppd_plugin_object_info);
|
|
|
|
|
|
|
|
|
|
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 (NMPppdPluginClass, state_changed),
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
g_cclosure_marshal_VOID__UINT,
|
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
|
G_TYPE_UINT);
|
|
|
|
|
|
|
|
|
|
signals[IP4_CONFIG] =
|
|
|
|
|
g_signal_new ("ip4-config",
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
|
G_STRUCT_OFFSET (NMPppdPluginClass, ip4_config),
|
|
|
|
|
NULL, NULL,
|
|
|
|
|
g_cclosure_marshal_VOID__BOXED,
|
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
|
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMPppdPlugin *
|
|
|
|
|
nm_pppd_plugin_new (DBusGConnection *bus)
|
|
|
|
|
{
|
|
|
|
|
GObject *obj;
|
|
|
|
|
|
|
|
|
|
obj = g_object_new (NM_TYPE_PPPD_PLUGIN, NULL);
|
|
|
|
|
if (!obj)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
NM_PPPD_PLUGIN_GET_PRIVATE (obj)->bus = dbus_g_connection_ref (bus);
|
|
|
|
|
dbus_g_connection_register_g_object (bus, NM_DBUS_PATH_PPP, obj);
|
|
|
|
|
|
|
|
|
|
return (NMPppdPlugin *) obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_pppd_plugin_state_changed (NMPppdPlugin *plugin, NMPPPStatus status)
|
|
|
|
|
{
|
|
|
|
|
g_signal_emit (plugin, signals[STATE_CHANGED], 0, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_pppd_plugin_ip4_config (NMPppdPlugin *plugin, GHashTable *ip4_config)
|
|
|
|
|
{
|
|
|
|
|
g_signal_emit (plugin, signals[IP4_CONFIG], 0, ip4_config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2007-08-15 14:30:06 +00:00
|
|
|
static void
|
|
|
|
|
nm_phasechange (void *data, int arg)
|
|
|
|
|
{
|
2007-10-10 14:36:31 +00:00
|
|
|
NMPppdPlugin *plugin = NM_PPPD_PLUGIN (data);
|
2007-08-15 14:30:06 +00:00
|
|
|
NMPPPStatus status = NM_PPP_STATUS_UNKNOWN;
|
|
|
|
|
char *phase;
|
|
|
|
|
|
|
|
|
|
switch (arg) {
|
|
|
|
|
case PHASE_DEAD:
|
|
|
|
|
status = NM_PPP_STATUS_DEAD;
|
|
|
|
|
phase = "dead";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_INITIALIZE:
|
|
|
|
|
status = NM_PPP_STATUS_INITIALIZE;
|
|
|
|
|
phase = "initialize";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_SERIALCONN:
|
|
|
|
|
status = NM_PPP_STATUS_SERIALCONN;
|
|
|
|
|
phase = "serial connection";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_DORMANT:
|
|
|
|
|
status = NM_PPP_STATUS_DORMANT;
|
|
|
|
|
phase = "dormant";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_ESTABLISH:
|
|
|
|
|
status = NM_PPP_STATUS_ESTABLISH;
|
|
|
|
|
phase = "establish";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_AUTHENTICATE:
|
|
|
|
|
status = NM_PPP_STATUS_AUTHENTICATE;
|
|
|
|
|
phase = "authenticate";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_CALLBACK:
|
|
|
|
|
status = NM_PPP_STATUS_CALLBACK;
|
|
|
|
|
phase = "callback";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_NETWORK:
|
|
|
|
|
status = NM_PPP_STATUS_NETWORK;
|
|
|
|
|
phase = "network";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_RUNNING:
|
|
|
|
|
status = NM_PPP_STATUS_RUNNING;
|
|
|
|
|
phase = "running";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_TERMINATE:
|
|
|
|
|
status = NM_PPP_STATUS_TERMINATE;
|
|
|
|
|
phase = "terminate";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_DISCONNECT:
|
|
|
|
|
status = NM_PPP_STATUS_DISCONNECT;
|
|
|
|
|
phase = "disconnect";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_HOLDOFF:
|
|
|
|
|
status = NM_PPP_STATUS_HOLDOFF;
|
|
|
|
|
phase = "holdoff";
|
|
|
|
|
break;
|
|
|
|
|
case PHASE_MASTER:
|
|
|
|
|
status = NM_PPP_STATUS_MASTER;
|
|
|
|
|
phase = "master";
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
phase = "unknown";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_message ("pppd reported new phase: %s", phase);
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
if (status != NM_PPP_STATUS_UNKNOWN)
|
|
|
|
|
nm_pppd_plugin_state_changed (plugin, status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GValue *
|
|
|
|
|
str_to_gvalue (const char *str)
|
|
|
|
|
{
|
|
|
|
|
GValue *val;
|
|
|
|
|
|
|
|
|
|
val = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (val, G_TYPE_STRING);
|
|
|
|
|
g_value_set_string (val, str);
|
|
|
|
|
|
|
|
|
|
return val;
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
static GValue *
|
|
|
|
|
uint_to_gvalue (guint32 i)
|
2007-08-15 14:30:06 +00:00
|
|
|
{
|
2007-10-10 14:36:31 +00:00
|
|
|
GValue *val;
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
val = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (val, G_TYPE_UINT);
|
|
|
|
|
g_value_set_uint (val, i);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
value_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
GValue *val = (GValue *) data;
|
|
|
|
|
|
|
|
|
|
g_value_unset (val);
|
|
|
|
|
g_slice_free (GValue, val);
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_ip_up (void *data, int arg)
|
|
|
|
|
{
|
2007-10-10 14:36:31 +00:00
|
|
|
NMPppdPlugin *plugin = NM_PPPD_PLUGIN (data);
|
|
|
|
|
ipcp_options opts = ipcp_gotoptions[ifunit];
|
|
|
|
|
GHashTable *hash;
|
|
|
|
|
GArray *array;
|
|
|
|
|
GValue *val;
|
|
|
|
|
|
|
|
|
|
if (!opts.ouraddr) {
|
2007-08-15 14:30:06 +00:00
|
|
|
g_warning ("Didn't receive an internal IP from pppd");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
hash = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
|
|
|
NULL, value_destroy);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_INTERFACE,
|
|
|
|
|
str_to_gvalue (ifname));
|
|
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_ADDRESS,
|
|
|
|
|
uint_to_gvalue (opts.ouraddr));
|
|
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_GATEWAY,
|
|
|
|
|
uint_to_gvalue (opts.hisaddr));
|
|
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_NETMASK,
|
|
|
|
|
uint_to_gvalue (0xFFFFFFFF));
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
if (opts.dnsaddr[0] || opts.dnsaddr[1]) {
|
|
|
|
|
array = g_array_new (FALSE, FALSE, sizeof (guint32));
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
if (opts.dnsaddr[0])
|
|
|
|
|
g_array_append_val (array, opts.dnsaddr[0]);
|
|
|
|
|
if (opts.dnsaddr[1])
|
|
|
|
|
g_array_append_val (array, opts.dnsaddr[1]);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
val = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
|
|
|
|
|
g_value_set_boxed (val, array);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_DNS, val);
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
if (opts.winsaddr[0] || opts.winsaddr[1]) {
|
|
|
|
|
array = g_array_new (FALSE, FALSE, sizeof (guint32));
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
if (opts.winsaddr[0])
|
|
|
|
|
g_array_append_val (array, opts.winsaddr[0]);
|
|
|
|
|
if (opts.winsaddr[1])
|
|
|
|
|
g_array_append_val (array, opts.winsaddr[1]);
|
|
|
|
|
|
|
|
|
|
val = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (val, DBUS_TYPE_G_UINT_ARRAY);
|
|
|
|
|
g_value_set_boxed (val, array);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
g_hash_table_insert (hash, NM_PPP_IP4_CONFIG_WINS, val);
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
nm_pppd_plugin_ip4_config (plugin, hash);
|
|
|
|
|
g_hash_table_destroy (hash);
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_exit_notify (void *data, int arg)
|
|
|
|
|
{
|
2007-10-10 14:36:31 +00:00
|
|
|
NMPppdPlugin *plugin = NM_PPPD_PLUGIN (data);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
|
|
|
|
g_message ("exiting");
|
2007-10-10 14:36:31 +00:00
|
|
|
g_object_unref (plugin);
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
int
|
|
|
|
|
plugin_init (void)
|
2007-08-15 14:30:06 +00:00
|
|
|
{
|
2007-10-10 14:36:31 +00:00
|
|
|
DBusGConnection *bus;
|
|
|
|
|
DBusGProxy *bus_proxy;
|
|
|
|
|
NMPppdPlugin *plugin;
|
|
|
|
|
guint request_name_result;
|
|
|
|
|
GError *err = NULL;
|
|
|
|
|
|
|
|
|
|
g_type_init ();
|
|
|
|
|
|
|
|
|
|
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
|
|
|
|
|
if (!bus) {
|
|
|
|
|
g_warning ("Couldn't connect to system bus: %s", err->message);
|
|
|
|
|
g_error_free (err);
|
|
|
|
|
return -1;
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
bus_proxy = dbus_g_proxy_new_for_name (bus,
|
|
|
|
|
"org.freedesktop.DBus",
|
|
|
|
|
"/org/freedesktop/DBus",
|
|
|
|
|
"org.freedesktop.DBus");
|
|
|
|
|
|
|
|
|
|
if (!dbus_g_proxy_call (bus_proxy, "RequestName", &err,
|
|
|
|
|
G_TYPE_STRING, NM_DBUS_SERVICE_PPP,
|
|
|
|
|
G_TYPE_UINT, 0,
|
|
|
|
|
G_TYPE_INVALID,
|
|
|
|
|
G_TYPE_UINT, &request_name_result,
|
|
|
|
|
G_TYPE_INVALID)) {
|
|
|
|
|
g_warning ("Failed to acquire '" NM_DBUS_SERVICE_PPP "'");
|
|
|
|
|
g_error_free (err);
|
|
|
|
|
dbus_g_connection_unref (bus);
|
|
|
|
|
g_object_unref (bus_proxy);
|
|
|
|
|
|
|
|
|
|
return -1;
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|
|
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
g_object_unref (bus_proxy);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
plugin = nm_pppd_plugin_new (bus);
|
|
|
|
|
dbus_g_connection_unref (bus);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
add_notifier (&phasechange, nm_phasechange, plugin);
|
|
|
|
|
add_notifier (&ip_up_notifier, nm_ip_up, plugin);
|
|
|
|
|
add_notifier (&exitnotify, nm_exit_notify, plugin);
|
2007-08-15 14:30:06 +00:00
|
|
|
|
2007-10-10 14:36:31 +00:00
|
|
|
return 0;
|
2007-08-15 14:30:06 +00:00
|
|
|
}
|