diff options
author | Thomas Haller <thaller@redhat.com> | 2023-04-18 08:27:13 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-04-18 08:27:13 +0200 |
commit | 5df19f5b26c5921a401e63fb329e844a02d6b1f2 (patch) | |
tree | 5db4c16959f279b2c62c07a1799ddb9e88d3e155 | |
parent | 290bac0af9ad567f18ba59b5401dcfe4c571ee87 (diff) | |
parent | afe80171b24d20151ecde0ff952a9800c15908d8 (diff) |
ppp: merge branch 'th/ppp25'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1272
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1558
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1607
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | configure.ac | 17 | ||||
-rw-r--r-- | meson.build | 10 | ||||
-rw-r--r-- | src/core/ppp/meson.build | 6 | ||||
-rw-r--r-- | src/core/ppp/nm-ppp-manager.c | 2 | ||||
-rw-r--r-- | src/core/ppp/nm-ppp-mgr.c | 2 | ||||
-rw-r--r-- | src/core/ppp/nm-ppp-status.h | 29 | ||||
-rw-r--r-- | src/core/ppp/nm-pppd-compat.c | 304 | ||||
-rw-r--r-- | src/core/ppp/nm-pppd-compat.h | 64 | ||||
-rw-r--r-- | src/core/ppp/nm-pppd-plugin.c | 198 |
10 files changed, 493 insertions, 145 deletions
diff --git a/Makefile.am b/Makefile.am index cd30c7201e..72918243da 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3297,9 +3297,13 @@ src_core_ppp_nm_pppd_plugin_la_CPPFLAGS = \ -I$(builddir)/src \ -I$(builddir)/src/libnm-core-public \ -I$(srcdir)/src/libnm-core-public \ - $(GLIB_CFLAGS) + $(GLIB_CFLAGS) \ + $(PPPD_CFLAGS) \ + $(NULL) src_core_ppp_nm_pppd_plugin_la_SOURCES = \ + src/core/ppp/nm-pppd-compat.c \ + src/core/ppp/nm-pppd-compat.h \ src/core/ppp/nm-pppd-plugin.c \ src/core/ppp/nm-pppd-plugin.h \ src/core/ppp/nm-ppp-status.h diff --git a/configure.ac b/configure.ac index 4a550cb5ae..3809cda9df 100644 --- a/configure.ac +++ b/configure.ac @@ -754,13 +754,21 @@ fi AC_SUBST(DBUS_SYS_DIR) # pppd +PPPD_VERSION=2.4.9 +PKG_CHECK_EXISTS([pppd], [ + PPPD_VERSION=`$PKG_CONFIG --modversion pppd` + PPPD_CFLAGS=`$PKG_CONFIG --cflags pppd` +]) + AC_ARG_ENABLE(ppp, AS_HELP_STRING([--enable-ppp], [enable PPP/PPPoE support]), [enable_ppp=${enableval}], [enable_ppp=yes]) if test "${enable_ppp}" = "yes"; then - AC_CHECK_HEADERS(pppd/pppd.h,, - AC_MSG_ERROR("couldn't find pppd.h. pppd development headers are required.")) - + if test -z "$PPPD_CFLAGS" ; then + AC_CHECK_HEADERS(pppd/pppd.h,, + AC_MSG_ERROR("couldn't find pppd.h. pppd development headers are required."),) + fi + AC_SUBST(PPPD_CFLAGS, ["$PPPD_CFLAGS"]) AC_DEFINE(WITH_PPP, 1, [Define if you have PPP support]) else AC_DEFINE(WITH_PPP, 0, [Define if you have PPP support]) @@ -769,11 +777,10 @@ AM_CONDITIONAL(WITH_PPP, test "${enable_ppp}" = "yes") AC_ARG_WITH([pppd-plugin-dir], AS_HELP_STRING([--with-pppd-plugin-dir=DIR], [path to the pppd plugins directory])) - if test -n "$with_pppd_plugin_dir" ; then PPPD_PLUGIN_DIR="$with_pppd_plugin_dir" else - PPPD_PLUGIN_DIR="${libdir}/pppd/2.4.5" + PPPD_PLUGIN_DIR="${libdir}/pppd/$PPPD_VERSION" fi AC_SUBST(PPPD_PLUGIN_DIR) diff --git a/meson.build b/meson.build index b41597cab9..9747065e7a 100644 --- a/meson.build +++ b/meson.build @@ -561,7 +561,13 @@ config_h.set10('WITH_FIREWALLD_ZONE', enable_firewalld_zone) # pppd enable_ppp = get_option('ppp') if enable_ppp - assert(cc.has_header('pppd/pppd.h'), 'couldn\'t find pppd.h. pppd development headers are required') + pppd_dep = dependency('pppd', required: false) + if (pppd_dep.found()) + pppd_version = pppd_dep.version() + else + assert(cc.has_header('pppd/pppd.h'), 'couldn\'t find pppd.h. pppd development headers are required') + pppd_version = '2.4.9' + endif pppd_path = get_option('pppd') if pppd_path == '' @@ -574,7 +580,7 @@ if enable_ppp pppd_plugin_dir = get_option('pppd_plugin_dir') if pppd_plugin_dir == '' - pppd_plugin_dir = join_paths(nm_libdir, 'pppd', '2.4.5') + pppd_plugin_dir = join_paths(nm_libdir, 'pppd', pppd_version) endif endif config_h.set10('WITH_PPP', enable_ppp) diff --git a/src/core/ppp/meson.build b/src/core/ppp/meson.build index 9ee46113f5..2365ffa8fb 100644 --- a/src/core/ppp/meson.build +++ b/src/core/ppp/meson.build @@ -3,7 +3,10 @@ nm_pppd_plugin = shared_module( 'nm-pppd-plugin', name_prefix: '', - sources: 'nm-pppd-plugin.c', + sources: [ + 'nm-pppd-compat.c', + 'nm-pppd-plugin.c', + ], include_directories: [ src_inc, top_inc, @@ -11,6 +14,7 @@ nm_pppd_plugin = shared_module( dependencies: [ libnm_core_public_dep, glib_dep, + pppd_dep, ], link_with: [ libnm_core_impl, diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 14cd57317e..bb043a7e41 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -428,7 +428,7 @@ impl_ppp_manager_set_state(NMDBusObject *obj, if (ppp_state >= NM_PPP_STATUS_INTERN_DEAD) { /* we don't expect an intern state to be reported by the plugin. */ - ppp_state = NM_PPP_STATUS_UNKNOWN; + ppp_state = NM_PPP_STATUS_INTERN_UNKNOWN; } g_signal_emit(self, signals[STATE_CHANGED], 0, (guint) ppp_state); diff --git a/src/core/ppp/nm-ppp-mgr.c b/src/core/ppp/nm-ppp-mgr.c index bebffaf37c..91d9a021b2 100644 --- a/src/core/ppp/nm-ppp-mgr.c +++ b/src/core/ppp/nm-ppp-mgr.c @@ -257,7 +257,7 @@ _ppp_signal_state_changed(NMPPPManager *ppp_manager, guint ppp_state_u, gpointer const char *reason_msg; if ((guint) ppp_state != ppp_state_u) - ppp_state = NM_PPP_STATUS_UNKNOWN; + ppp_state = NM_PPP_STATUS_INTERN_UNKNOWN; switch (ppp_state) { case NM_PPP_STATUS_DISCONNECT: diff --git a/src/core/ppp/nm-ppp-status.h b/src/core/ppp/nm-ppp-status.h index df0ac10ba2..57b48fe922 100644 --- a/src/core/ppp/nm-ppp-status.h +++ b/src/core/ppp/nm-ppp-status.h @@ -8,23 +8,24 @@ #define __NM_PPP_STATUS_H__ typedef enum { - NM_PPP_STATUS_UNKNOWN, - NM_PPP_STATUS_DEAD, - NM_PPP_STATUS_INITIALIZE, - NM_PPP_STATUS_SERIALCONN, - NM_PPP_STATUS_DORMANT, - NM_PPP_STATUS_ESTABLISH, - NM_PPP_STATUS_AUTHENTICATE, - NM_PPP_STATUS_CALLBACK, - NM_PPP_STATUS_NETWORK, - NM_PPP_STATUS_RUNNING, - NM_PPP_STATUS_TERMINATE, - NM_PPP_STATUS_DISCONNECT, - NM_PPP_STATUS_HOLDOFF, - NM_PPP_STATUS_MASTER, + /* The numeric values correspond to the PHASE_{DEAD,} defines from <pppd/pppd.h>. */ + NM_PPP_STATUS_DEAD = 0, + NM_PPP_STATUS_INITIALIZE = 1, + NM_PPP_STATUS_SERIALCONN = 2, + NM_PPP_STATUS_DORMANT = 3, + NM_PPP_STATUS_ESTABLISH = 4, + NM_PPP_STATUS_AUTHENTICATE = 5, + NM_PPP_STATUS_CALLBACK = 6, + NM_PPP_STATUS_NETWORK = 7, + NM_PPP_STATUS_RUNNING = 8, + NM_PPP_STATUS_TERMINATE = 9, + NM_PPP_STATUS_DISCONNECT = 10, + NM_PPP_STATUS_HOLDOFF = 11, + NM_PPP_STATUS_MASTER = 12, /* these states are internal and not announced by the pppd plugin. */ + NM_PPP_STATUS_INTERN_UNKNOWN = 20, NM_PPP_STATUS_INTERN_DEAD, } NMPPPStatus; diff --git a/src/core/ppp/nm-pppd-compat.c b/src/core/ppp/nm-pppd-compat.c new file mode 100644 index 0000000000..fd67eb3493 --- /dev/null +++ b/src/core/ppp/nm-pppd-compat.c @@ -0,0 +1,304 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023 Eivind Næss, eivnaes@yahoo.com + */ + +/*****************************************************************************/ + +/* PPP headers define some symbols as we do. We need to be careful to handle + * the conflict, and include stuff in a certain order. */ + +#include <config.h> +#define ___CONFIG_H__ + +/*****************************************************************************/ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"") +#define _NM_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop") +#elif defined(__clang__) +_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") + _Pragma("clang diagnostic ignored \"-Wstrict-prototypes\"") +#define _NM_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop") +#else +#define _NM_PRAGMA_WARNING_REENABLE +#endif + +/*****************************************************************************/ + +#define INET6 1 + +#include <pppd/pppd.h> + +#ifdef DATE +/* Before ppp 2.5, pppd/patchlevel.h defined "DATE". Use that for detection. */ +#define PPP_VERSION_2_5_OR_NEWER 0 +#else +#define PPP_VERSION_2_5_OR_NEWER 1 +#endif + +#include <pppd/eui64.h> +#include <pppd/fsm.h> +#include <pppd/ipcp.h> +#include <pppd/ipv6cp.h> +#include <pppd/upap.h> + +#if PPP_VERSION_2_5_OR_NEWER +#include <pppd/chap.h> +#else +#include <pppd/chap-new.h> +#include <pppd/chap_ms.h> +#endif + + char pppd_version[] = ( +#if PPP_VERSION_2_5_OR_NEWER + PPPD_VERSION +#else + VERSION +#endif + ); + +#undef VERSION + +_NM_PRAGMA_WARNING_REENABLE; + +/*****************************************************************************/ + +#include "libnm-glib-aux/nm-default-glib.h" + +#include "nm-pppd-compat.h" + +#include <net/if.h> +#include <dlfcn.h> + +#include "nm-ppp-status.h" + +/*****************************************************************************/ + +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DEAD == PHASE_DEAD); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_INITIALIZE == PHASE_INITIALIZE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_SERIALCONN == PHASE_SERIALCONN); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DORMANT == PHASE_DORMANT); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_ESTABLISH == PHASE_ESTABLISH); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_AUTHENTICATE == PHASE_AUTHENTICATE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_CALLBACK == PHASE_CALLBACK); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_NETWORK == PHASE_NETWORK); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_RUNNING == PHASE_RUNNING); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_TERMINATE == PHASE_TERMINATE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DISCONNECT == PHASE_DISCONNECT); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_HOLDOFF == PHASE_HOLDOFF); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_MASTER == PHASE_MASTER); + +G_STATIC_ASSERT(NM_PPPD_COMPAT_MAXNAMELEN == MAXNAMELEN); +G_STATIC_ASSERT(NM_PPPD_COMPAT_MAXSECRETLEN == MAXSECRETLEN); + +/*****************************************************************************/ + +int +nm_pppd_compat_get_ifunit(void) +{ + int i; + +#if PPP_VERSION_2_5_OR_NEWER + i = ppp_ifunit(); +#else + i = ifunit; +#endif + + return i; +} + +const char * +nm_pppd_compat_get_ifname(void) +{ + const char *s; + +#if PPP_VERSION_2_5_OR_NEWER + s = ppp_ifname(); +#else + s = ifname; +#endif + + nm_assert(s); + nm_assert(strlen(s) < IFNAMSIZ); + return s; +} + +void +nm_pppd_compat_set_ifname(const char *arg_ifname) +{ + nm_assert(arg_ifname); + nm_assert(strlen(arg_ifname) < IFNAMSIZ); + +#if PPP_VERSION_2_5_OR_NEWER + ppp_set_ifname(arg_ifname); +#else + g_strlcpy(ifname, arg_ifname, IFNAMSIZ); +#endif +} + +const char * +nm_pppd_compat_get_ipparam(void) +{ + const char *s; + +#if PPP_VERSION_2_5_OR_NEWER + s = ppp_ipparam(); +#else + s = ipparam; +#endif + + return s; +} + +void +nm_pppd_compat_get_ipcp_options(NMPppdCompatIPCPOptions *out_got, NMPppdCompatIPCPOptions *out_his) +{ + const ipcp_options *const got = &ipcp_gotoptions[0]; + const ipcp_options *const his = &ipcp_hisoptions[0]; + + nm_assert(out_got); + nm_assert(out_his); + + *out_got = (NMPppdCompatIPCPOptions){ + .ouraddr = got->ouraddr, + .hisaddr = got->hisaddr, + .dnsaddr = {got->dnsaddr[0], got->dnsaddr[1]}, + .winsaddr = {got->winsaddr[0], got->winsaddr[1]}, + }; + + *out_his = (NMPppdCompatIPCPOptions){ + .ouraddr = his->ouraddr, + .hisaddr = his->hisaddr, + .dnsaddr = {his->dnsaddr[0], his->dnsaddr[1]}, + .winsaddr = {his->winsaddr[0], his->winsaddr[1]}, + }; +} + +void +nm_pppd_compat_get_ipv6cp_options(NMPppdCompatIPV6CPOptions *out_got, + NMPppdCompatIPV6CPOptions *out_his) +{ + const ipv6cp_options *const his = &ipv6cp_hisoptions[0]; + const ipv6cp_options *const got = &ipv6cp_gotoptions[0]; + + G_STATIC_ASSERT(sizeof(guint64) == sizeof(eui64_t)); + + nm_assert(out_got); + nm_assert(out_his); + + *out_got = (NMPppdCompatIPV6CPOptions){}; + memcpy(&out_got->ourid, &got->ourid, sizeof(guint64)); + memcpy(&out_got->hisid, &got->hisid, sizeof(guint64)); + + *out_his = (NMPppdCompatIPV6CPOptions){}; + memcpy(&out_his->ourid, &his->ourid, sizeof(guint64)); + memcpy(&out_his->hisid, &his->hisid, sizeof(guint64)); +} + +void +nm_pppd_compat_set_chap_passwd_hook(int (*hook)(char *user, char *password)) +{ + chap_passwd_hook = hook; +} + +void +nm_pppd_compat_set_chap_check_hook(int (*hook)(void)) +{ + chap_check_hook = hook; +} + +void +nm_pppd_compat_set_pap_passwd_hook(int (*hook)(char *user, char *passwd)) +{ + pap_passwd_hook = hook; +} + +void +nm_pppd_compat_set_pap_check_hook(int (*hook)(void)) +{ + pap_check_hook = hook; +} + +gboolean +nm_pppd_compat_add_notify(NMPppdCompatNotifyT type, void (*func)(void *ctx, int arg), void *ctx) +{ + nm_assert(NM_IN_SET(type, + NM_PPPD_COMPAT_NF_PID_CHANGE, + NM_PPPD_COMPAT_NF_PHASE_CHANGE, + NM_PPPD_COMPAT_NF_EXIT, + NM_PPPD_COMPAT_NF_SIGNALED, + NM_PPPD_COMPAT_NF_IP_UP, + NM_PPPD_COMPAT_NF_IP_DOWN, + NM_PPPD_COMPAT_NF_IPV6_UP, + NM_PPPD_COMPAT_NF_IPV6_DOWN, + NM_PPPD_COMPAT_NF_AUTH_UP, + NM_PPPD_COMPAT_NF_LINK_DOWN, + NM_PPPD_COMPAT_NF_FORK)); + nm_assert(func); + +#if PPP_VERSION_2_5_OR_NEWER + { + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_PID_CHANGE == NF_PID_CHANGE); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_PHASE_CHANGE == NF_PHASE_CHANGE); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_EXIT == NF_EXIT); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_SIGNALED == NF_SIGNALED); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IP_UP == NF_IP_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IP_DOWN == NF_IP_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IPV6_UP == NF_IPV6_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IPV6_DOWN == NF_IPV6_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_AUTH_UP == NF_AUTH_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_LINK_DOWN == NF_LINK_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_FORK == NF_FORK); + + ppp_add_notify((gint64) type, func, ctx); + return TRUE; + } +#else + { + static struct notifier **list[] = { + [NM_PPPD_COMPAT_NF_PID_CHANGE] = &pidchange, + [NM_PPPD_COMPAT_NF_PHASE_CHANGE] = &phasechange, + [NM_PPPD_COMPAT_NF_EXIT] = &exitnotify, + [NM_PPPD_COMPAT_NF_SIGNALED] = &sigreceived, + [NM_PPPD_COMPAT_NF_IP_UP] = &ip_up_notifier, + [NM_PPPD_COMPAT_NF_IP_DOWN] = &ip_down_notifier, + [NM_PPPD_COMPAT_NF_IPV6_UP] = NULL /* ipv6_up_notifier */, + [NM_PPPD_COMPAT_NF_IPV6_DOWN] = NULL /* ipv6_down_notifier */, + [NM_PPPD_COMPAT_NF_AUTH_UP] = &auth_up_notifier, + [NM_PPPD_COMPAT_NF_LINK_DOWN] = &link_down_notifier, + [NM_PPPD_COMPAT_NF_FORK] = &fork_notifier, + }; + struct notifier **notifier; + + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(list)); + + if (NM_IN_SET(type, NM_PPPD_COMPAT_NF_IPV6_UP, NM_PPPD_COMPAT_NF_IPV6_DOWN)) { + static gsize load_once = 0; + + /* pppd might be build without IPv6 support. Load the symbols dynamically. */ + if (g_once_init_enter(&load_once)) { + void *handle; + + handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); + if (handle) { + list[NM_PPPD_COMPAT_NF_IPV6_UP] = dlsym(handle, "ipv6_up_notifier"); + list[NM_PPPD_COMPAT_NF_IPV6_DOWN] = dlsym(handle, "ipv6_down_notifier"); + dlclose(handle); + } + g_once_init_leave(&load_once, 1); + } + + notifier = list[type]; + } else { + notifier = list[type]; + nm_assert(notifier); + } + + if (notifier) + add_notifier(notifier, func, ctx); + + return !!notifier; + } +#endif +} diff --git a/src/core/ppp/nm-pppd-compat.h b/src/core/ppp/nm-pppd-compat.h new file mode 100644 index 0000000000..11376e360e --- /dev/null +++ b/src/core/ppp/nm-pppd-compat.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023 Eivind Næss, eivnaes@yahoo.com + */ + +#ifndef __NM_PPPD_COMPAT_H__ +#define __NM_PPPD_COMPAT_H__ + +#define NM_PPPD_COMPAT_MAXNAMELEN 256 +#define NM_PPPD_COMPAT_MAXSECRETLEN 256 + +int nm_pppd_compat_get_ifunit(void); + +const char *nm_pppd_compat_get_ifname(void); +void nm_pppd_compat_set_ifname(const char *ifname); + +const char *nm_pppd_compat_get_ipparam(void); + +typedef struct { + /* has information from "ipcp_options" */ + in_addr_t ouraddr; + in_addr_t hisaddr; + in_addr_t dnsaddr[2]; + in_addr_t winsaddr[2]; +} NMPppdCompatIPCPOptions; + +void nm_pppd_compat_get_ipcp_options(NMPppdCompatIPCPOptions *out_got, + NMPppdCompatIPCPOptions *out_his); + +typedef struct { + /* has information from "ipv6cp_options" */ + guint64 ourid; + guint64 hisid; +} NMPppdCompatIPV6CPOptions; + +void nm_pppd_compat_get_ipv6cp_options(NMPppdCompatIPV6CPOptions *out_got, + NMPppdCompatIPV6CPOptions *out_his); + +void nm_pppd_compat_set_chap_passwd_hook(int (*hook)(char *user, char *password)); + +void nm_pppd_compat_set_chap_check_hook(int (*hook)(void)); + +void nm_pppd_compat_set_pap_passwd_hook(int (*hook)(char *user, char *passwd)); + +void nm_pppd_compat_set_pap_check_hook(int (*hook)(void)); + +typedef enum { + NM_PPPD_COMPAT_NF_PID_CHANGE, + NM_PPPD_COMPAT_NF_PHASE_CHANGE, + NM_PPPD_COMPAT_NF_EXIT, + NM_PPPD_COMPAT_NF_SIGNALED, + NM_PPPD_COMPAT_NF_IP_UP, + NM_PPPD_COMPAT_NF_IP_DOWN, + NM_PPPD_COMPAT_NF_IPV6_UP, + NM_PPPD_COMPAT_NF_IPV6_DOWN, + NM_PPPD_COMPAT_NF_AUTH_UP, + NM_PPPD_COMPAT_NF_LINK_DOWN, + NM_PPPD_COMPAT_NF_FORK, +} NMPppdCompatNotifyT; + +gboolean +nm_pppd_compat_add_notify(NMPppdCompatNotifyT type, void (*func)(void *ctx, int arg), void *ctx); + +#endif /* #ifdef __NM_PPPD_COMPAT_H__ */ diff --git a/src/core/ppp/nm-pppd-plugin.c b/src/core/ppp/nm-pppd-plugin.c index e2e34d2aaf..93425f382c 100644 --- a/src/core/ppp/nm-pppd-plugin.c +++ b/src/core/ppp/nm-pppd-plugin.c @@ -4,33 +4,23 @@ * Copyright (C) 2008 Red Hat, Inc. */ -#include <config.h> -#define ___CONFIG_H__ +#include "libnm-glib-aux/nm-default-glib.h" + +#include "nm-pppd-plugin.h" -#include <pppd/pppd.h> -#include <pppd/fsm.h> -#include <pppd/ipcp.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> #include <dlfcn.h> +#include <glib.h> -#define INET6 -#include <pppd/eui64.h> -#include <pppd/ipv6cp.h> - -#include "libnm-glib-aux/nm-default-glib.h" - -#include "nm-dbus-interface.h" - -#include "nm-pppd-plugin.h" +#include "nm-pppd-compat.h" #include "nm-ppp-status.h" +#include "nm-dbus-interface.h" int plugin_init(void); -char pppd_version[] = VERSION; - static struct { GDBusConnection *dbus_connection; char *ipparam; @@ -39,73 +29,63 @@ static struct { static void nm_phasechange(int arg) { - NMPPPStatus ppp_status = NM_PPP_STATUS_UNKNOWN; + NMPPPStatus ppp_status; char *ppp_phase; g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); + ppp_status = arg; + switch (arg) { - case PHASE_DEAD: - ppp_status = NM_PPP_STATUS_DEAD; - ppp_phase = "dead"; + case NM_PPP_STATUS_DEAD: + ppp_phase = "dead"; break; - case PHASE_INITIALIZE: - ppp_status = NM_PPP_STATUS_INITIALIZE; - ppp_phase = "initialize"; + case NM_PPP_STATUS_INITIALIZE: + ppp_phase = "initialize"; break; - case PHASE_SERIALCONN: - ppp_status = NM_PPP_STATUS_SERIALCONN; - ppp_phase = "serial connection"; + case NM_PPP_STATUS_SERIALCONN: + ppp_phase = "serial connection"; break; - case PHASE_DORMANT: - ppp_status = NM_PPP_STATUS_DORMANT; - ppp_phase = "dormant"; + case NM_PPP_STATUS_DORMANT: + ppp_phase = "dormant"; break; - case PHASE_ESTABLISH: - ppp_status = NM_PPP_STATUS_ESTABLISH; - ppp_phase = "establish"; + case NM_PPP_STATUS_ESTABLISH: + ppp_phase = "establish"; break; - case PHASE_AUTHENTICATE: - ppp_status = NM_PPP_STATUS_AUTHENTICATE; - ppp_phase = "authenticate"; + case NM_PPP_STATUS_AUTHENTICATE: + ppp_phase = "authenticate"; break; - case PHASE_CALLBACK: - ppp_status = NM_PPP_STATUS_CALLBACK; - ppp_phase = "callback"; + case NM_PPP_STATUS_CALLBACK: + ppp_phase = "callback"; break; - case PHASE_NETWORK: - ppp_status = NM_PPP_STATUS_NETWORK; - ppp_phase = "network"; + case NM_PPP_STATUS_NETWORK: + ppp_phase = "network"; break; - case PHASE_RUNNING: - ppp_status = NM_PPP_STATUS_RUNNING; - ppp_phase = "running"; + case NM_PPP_STATUS_RUNNING: + ppp_phase = "running"; break; - case PHASE_TERMINATE: - ppp_status = NM_PPP_STATUS_TERMINATE; - ppp_phase = "terminate"; + case NM_PPP_STATUS_TERMINATE: + ppp_phase = "terminate"; break; - case PHASE_DISCONNECT: - ppp_status = NM_PPP_STATUS_DISCONNECT; - ppp_phase = "disconnect"; + case NM_PPP_STATUS_DISCONNECT: + ppp_phase = "disconnect"; break; - case PHASE_HOLDOFF: - ppp_status = NM_PPP_STATUS_HOLDOFF; - ppp_phase = "holdoff"; + case NM_PPP_STATUS_HOLDOFF: + ppp_phase = "holdoff"; break; - case PHASE_MASTER: - ppp_status = NM_PPP_STATUS_MASTER; - ppp_phase = "master"; + case NM_PPP_STATUS_MASTER: + ppp_phase = "master"; break; default: - ppp_phase = "unknown"; + ppp_status = NM_PPP_STATUS_INTERN_UNKNOWN; + ppp_phase = "unknown"; break; } g_message("nm-ppp-plugin: status %d / phase '%s'", ppp_status, ppp_phase); - if (ppp_status != NM_PPP_STATUS_UNKNOWN) { + if (ppp_status != NM_PPP_STATUS_INTERN_UNKNOWN) { g_dbus_connection_call(gl.dbus_connection, NM_DBUS_SERVICE, gl.ipparam, @@ -125,7 +105,7 @@ nm_phasechange(int arg) char new_name[IF_NAMESIZE]; int ifindex; - ifindex = if_nametoindex(ifname); + ifindex = if_nametoindex(nm_pppd_compat_get_ifname()); /* Make a sync call to ensure that when the call * terminates the interface already has its final @@ -143,9 +123,12 @@ nm_phasechange(int arg) NULL); /* Update the name in pppd if NM changed it */ - if (if_indextoname(ifindex, new_name) && !nm_streq0(ifname, new_name)) { - g_message("nm-ppp-plugin: interface name changed from '%s' to '%s'", ifname, new_name); - g_strlcpy(ifname, new_name, IF_NAMESIZE); + if (if_indextoname(ifindex, new_name) + && !nm_streq0(nm_pppd_compat_get_ifname(), new_name)) { + g_message("nm-ppp-plugin: interface name changed from '%s' to '%s'", + nm_pppd_compat_get_ifname(), + new_name); + nm_pppd_compat_set_ifname(new_name); } } } @@ -154,7 +137,7 @@ static void nm_phasechange_hook(void *data, int arg) { /* We send the nofication in exitnotify instead */ - if (arg == PHASE_DEAD) + if (arg == NM_PPP_STATUS_DEAD) return; nm_phasechange(arg); @@ -163,18 +146,21 @@ nm_phasechange_hook(void *data, int arg) static void nm_ip_up(void *data, int arg) { - ipcp_options opts = ipcp_gotoptions[0]; - ipcp_options peer_opts = ipcp_hisoptions[0]; - GVariantBuilder builder; - guint32 pppd_made_up_address = htonl(0x0a404040 + ifunit); + NMPppdCompatIPCPOptions opts; + NMPppdCompatIPCPOptions peer_opts; + GVariantBuilder builder; + const in_addr_t pppd_made_up_address = + htonl(0x0a404040u + ((guint) nm_pppd_compat_get_ifunit())); g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); g_message("nm-ppp-plugin: ip-up event"); + nm_pppd_compat_get_ipcp_options(&opts, &peer_opts); + if (!opts.ouraddr) { g_warning("nm-ppp-plugin: didn't receive an internal IP from pppd!"); - nm_phasechange(PHASE_DEAD); + nm_phasechange(NM_PPP_STATUS_DEAD); return; } @@ -186,7 +172,7 @@ nm_ip_up(void *data, int arg) g_variant_builder_add(&builder, "{sv}", NM_PPP_IP4_CONFIG_INTERFACE, - g_variant_new_string(ifname)); + g_variant_new_string(nm_pppd_compat_get_ifname())); g_variant_builder_add(&builder, "{sv}", @@ -263,28 +249,19 @@ nm_ip_up(void *data, int arg) NULL); } -static GVariant * -eui64_to_variant(eui64_t eui) -{ - guint64 iid; - - G_STATIC_ASSERT(sizeof(iid) == sizeof(eui)); - - memcpy(&iid, &eui, sizeof(eui)); - return g_variant_new_uint64(iid); -} - static void nm_ip6_up(void *data, int arg) { - ipv6cp_options *ho = &ipv6cp_hisoptions[0]; - ipv6cp_options *go = &ipv6cp_gotoptions[0]; - GVariantBuilder builder; + NMPppdCompatIPV6CPOptions his; + NMPppdCompatIPV6CPOptions got; + GVariantBuilder builder; g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); g_message("nm-ppp-plugin: ip6-up event"); + nm_pppd_compat_get_ipv6cp_options(&got, &his); + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); /* Keep sending the interface name to be backwards compatible * with older versions of NM during a package upgrade, where @@ -292,12 +269,15 @@ nm_ip6_up(void *data, int arg) g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_INTERFACE, - g_variant_new_string(ifname)); - g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_OUR_IID, eui64_to_variant(go->ourid)); + g_variant_new_string(nm_pppd_compat_get_ifname())); + g_variant_builder_add(&builder, + "{sv}", + NM_PPP_IP6_CONFIG_OUR_IID, + g_variant_new_uint64(got.ourid)); g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_PEER_IID, - eui64_to_variant(ho->hisid)); + g_variant_new_uint64(his.hisid)); /* DNS is done via DHCPv6 or router advertisements */ @@ -368,8 +348,8 @@ get_credentials(char *username, char *password) g_variant_get(ret, "(&s&s)", &my_username, &my_password); - g_strlcpy(username, my_username, MAXNAMELEN); - g_strlcpy(password, my_password, MAXSECRETLEN); + g_strlcpy(username, my_username, NM_PPPD_COMPAT_MAXNAMELEN); + g_strlcpy(password, my_password, NM_PPPD_COMPAT_MAXSECRETLEN); return 1; } @@ -382,7 +362,7 @@ nm_exit_notify(void *data, int arg) /* We wait until this point to notify dead phase to make sure that * the serial port has recovered already its original settings. */ - nm_phasechange(PHASE_DEAD); + nm_phasechange(NM_PPP_STATUS_DEAD); g_message("nm-ppp-plugin: cleaning up"); @@ -390,27 +370,6 @@ nm_exit_notify(void *data, int arg) nm_clear_g_free(&gl.ipparam); } -static void -add_ip6_notifier(void) -{ - static struct notifier **notifier = NULL; - static gsize load_once = 0; - - if (g_once_init_enter(&load_once)) { - void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); - - if (handle) { - notifier = dlsym(handle, "ipv6_up_notifier"); - dlclose(handle); - } - g_once_init_leave(&load_once, 1); - } - if (notifier) - add_notifier(notifier, nm_ip6_up, NULL); - else - g_message("nm-ppp-plugin: no IPV6CP notifier support; IPv6 not available"); -} - int plugin_init(void) { @@ -427,17 +386,16 @@ plugin_init(void) return -1; } - gl.ipparam = g_strdup(ipparam); - - chap_passwd_hook = get_credentials; - chap_check_hook = get_chap_check; - pap_passwd_hook = get_credentials; - pap_check_hook = get_pap_check; + gl.ipparam = g_strdup(nm_pppd_compat_get_ipparam()); - add_notifier(&phasechange, nm_phasechange_hook, NULL); - add_notifier(&ip_up_notifier, nm_ip_up, NULL); - add_notifier(&exitnotify, nm_exit_notify, NULL); - add_ip6_notifier(); + nm_pppd_compat_set_chap_passwd_hook(get_credentials); + nm_pppd_compat_set_chap_check_hook(get_chap_check); + nm_pppd_compat_set_pap_passwd_hook(get_credentials); + nm_pppd_compat_set_pap_check_hook(get_pap_check); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_PHASE_CHANGE, nm_phasechange_hook, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_IP_UP, nm_ip_up, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_EXIT, nm_exit_notify, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_IPV6_UP, nm_ip6_up, NULL); return 0; } |