summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-04-18 08:27:13 +0200
committerThomas Haller <thaller@redhat.com>2023-04-18 08:27:13 +0200
commit5df19f5b26c5921a401e63fb329e844a02d6b1f2 (patch)
tree5db4c16959f279b2c62c07a1799ddb9e88d3e155
parent290bac0af9ad567f18ba59b5401dcfe4c571ee87 (diff)
parentafe80171b24d20151ecde0ff952a9800c15908d8 (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.am6
-rw-r--r--configure.ac17
-rw-r--r--meson.build10
-rw-r--r--src/core/ppp/meson.build6
-rw-r--r--src/core/ppp/nm-ppp-manager.c2
-rw-r--r--src/core/ppp/nm-ppp-mgr.c2
-rw-r--r--src/core/ppp/nm-ppp-status.h29
-rw-r--r--src/core/ppp/nm-pppd-compat.c304
-rw-r--r--src/core/ppp/nm-pppd-compat.h64
-rw-r--r--src/core/ppp/nm-pppd-plugin.c198
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;
}