NetworkManager/src/ppp-manager/nm-pppd-plugin.c
Tambet Ingo b1e15de652 2007-08-15 Tambet Ingo <tambet@gmail.com>
* src/ppp-manager: Implement ppp-manager. It's sort of dead code
        * for now since
        nothing is using it at the moment, but it'll be all useful and
stuff later on.

        * libnm-util/nm-setting.h: Define NMSettingPPP.

        * libnm-util/nm-setting.c: Implement NMSettingPPP.

        * libnm-util/nm-connection.c (register_default_creators):
        * Register ppp setting.

        * src/Makefile.am: Add ppp-manager to SUBDIRS.

        * configure.in: Require ppp headers. Build Makefile for
        * ppp-manager.



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2695 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2007-08-15 14:30:06 +00:00

307 lines
7.2 KiB
C

/* -*- 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>
#include <glib.h>
#include <dbus/dbus.h>
#include "nm-pppd-plugin.h"
#include "nm-ppp-status.h"
#include "dbus-dict-helpers.h"
char pppd_version[] = VERSION;
static void
nm_phasechange (void *data, int arg)
{
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);
if (status != NM_PPP_STATUS_UNKNOWN) {
DBusConnection *connection = (DBusConnection *) data;
DBusMessage *message;
message = dbus_message_new_signal (NM_DBUS_PATH_PPP,
NM_DBUS_INTERFACE_PPP,
"Status");
if (!message) {
g_warning ("Couldn't allocate the dbus message");
return;
}
if (!dbus_message_append_args (message,
DBUS_TYPE_UINT32, &status,
DBUS_TYPE_INVALID)) {
g_warning ("could not append message args");
goto out;
}
if (!dbus_connection_send (connection, message, NULL)) {
g_warning ("could not send dbus message");
goto out;
}
out:
dbus_message_unref (message);
}
}
static const gchar *
ip4_address_as_string (guint32 ip)
{
struct in_addr tmp_addr;
gchar *ip_string;
tmp_addr.s_addr = ip;
ip_string = inet_ntoa (tmp_addr);
return ip_string;
}
static void
nm_ip_up (void *data, int arg)
{
DBusConnection *connection = (DBusConnection *) data;
DBusMessage *signal;
DBusMessageIter iter;
DBusMessageIter iter_dict;
guint32 ip4_address;
guint32 ip4_gateway;
guint32 ip4_dns_1;
guint32 ip4_dns_2;
guint32 ip4_wins_1;
guint32 ip4_wins_2;
guint32 ip4_netmask = 0xFFFFFFFF; /* Default mask of 255.255.255.255 */
if (!ifname) {
g_warning ("Didn't receive a tunnel device name");
return;
}
ip4_address = ipcp_gotoptions[ifunit].ouraddr;
if (!ip4_address) {
g_warning ("Didn't receive an internal IP from pppd");
return;
}
ip4_gateway = ipcp_gotoptions[ifunit].hisaddr;
ip4_dns_1 = ipcp_gotoptions[ifunit].dnsaddr[0];
ip4_dns_2 = ipcp_gotoptions[ifunit].dnsaddr[1];
ip4_wins_1 = ipcp_gotoptions[ifunit].winsaddr[0];
ip4_wins_2 = ipcp_gotoptions[ifunit].winsaddr[1];
g_message ("Got ip configuration");
g_message ("address: %s", ip4_address_as_string (ip4_address));
g_message ("gateway: %s", ip4_address_as_string (ip4_gateway));
g_message ("netmask: %s", ip4_address_as_string (ip4_netmask));
g_message ("DNS1: %s", ip4_address_as_string (ip4_dns_1));
g_message ("DNS2: %s", ip4_address_as_string (ip4_dns_2));
g_message ("WINS1: %s", ip4_address_as_string (ip4_wins_1));
g_message ("WINS2: %s", ip4_address_as_string (ip4_wins_2));
signal = dbus_message_new_signal (NM_DBUS_PATH_PPP,
NM_DBUS_INTERFACE_PPP,
"IP4Config");
if (!signal)
goto out;
dbus_message_iter_init_append (signal, &iter);
if (!nmu_dbus_dict_open_write (&iter, &iter_dict)) {
g_warning ("dict open write failed!");
goto out;
}
if (!nmu_dbus_dict_append_string (&iter_dict, "interface", ifname)) {
g_warning ("couldn't append interface to dict");
goto out;
}
if (!nmu_dbus_dict_append_uint32 (&iter_dict, "addres", ip4_address)) {
g_warning ("couldn't append address to dict");
goto out;
}
if (!nmu_dbus_dict_append_uint32 (&iter_dict, "netmask", ip4_netmask)) {
g_warning ("couldn't append netmask to dict");
goto out;
}
if (!nmu_dbus_dict_append_uint32 (&iter_dict, "gateway", ip4_gateway)) {
g_warning ("couldn't append gateway to dict");
goto out;
}
if (ip4_dns_1 || ip4_dns_2) {
guint32 ip4_dns[2];
guint32 ip4_dns_len = 0;
if (ip4_dns_1)
ip4_dns[ip4_dns_len++] = ip4_dns_1;
if (ip4_dns_2)
ip4_dns[ip4_dns_len++] = ip4_dns_2;
if (!nmu_dbus_dict_append_uint32_array (&iter_dict,
"dns_server",
ip4_dns,
ip4_dns_len)) {
g_warning ("couldn't append dns_servers to dict");
goto out;
}
}
if (ip4_wins_1 || ip4_wins_2) {
guint32 ip4_wins[2];
guint32 ip4_wins_len = 0;
if (ip4_wins_1)
ip4_wins[ip4_wins_len++] = ip4_wins_1;
if (ip4_wins_2)
ip4_wins[ip4_wins_len++] = ip4_wins_2;
if (!nmu_dbus_dict_append_uint32_array (&iter_dict,
"wins_server",
ip4_wins,
ip4_wins_len)) {
g_warning ("couldn't append wins_servers to dict");
goto out;
}
}
if (!nmu_dbus_dict_close_write (&iter, &iter_dict)) {
g_warning ("dict close write failed!");
goto out;
}
if (!dbus_connection_send (connection, signal, NULL)) {
g_warning ("could not send dbus message");
goto out;
}
out:
if (signal)
dbus_message_unref (signal);
}
static void
nm_exit_notify (void *data, int arg)
{
DBusConnection *connection = (DBusConnection *) data;
g_message ("exiting");
if (connection)
dbus_connection_unref (connection);
}
static DBusConnection *
nm_dbus_prepare_connection (void)
{
DBusConnection *connection;
DBusError err;
dbus_error_init (&err);
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
if (!connection || dbus_error_is_set (&err)) {
g_warning ("Could not get the system bus. Make sure the message bus daemon is running.");
goto out;
}
dbus_connection_set_exit_on_disconnect (connection, FALSE);
dbus_error_init (&err);
dbus_bus_request_name (connection, NM_DBUS_SERVICE_PPP, 0, &err);
if (dbus_error_is_set (&err)) {
g_warning ("Could not acquire the dbus service. dbus_bus_request_name() says: '%s'.", err.message);
goto out;
}
out:
if (dbus_error_is_set (&err)) {
dbus_error_free (&err);
connection = NULL;
}
return connection;
}
int
plugin_init (void)
{
DBusConnection *connection;
connection = nm_dbus_prepare_connection ();
if (connection) {
add_notifier (&phasechange, nm_phasechange, connection);
add_notifier (&ip_up_notifier, nm_ip_up, connection);
add_notifier (&exitnotify, nm_exit_notify, connection);
}
return connection ? 0 : -1;
}