diff --git a/Makefile.am b/Makefile.am index 4ff3ce2b26..72918243da 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3297,12 +3297,15 @@ 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-pppd-compat.h \ src/core/ppp/nm-ppp-status.h src_core_ppp_nm_pppd_plugin_la_LDFLAGS = \ diff --git a/config.h.meson b/config.h.meson index a9fd32475a..7337165082 100644 --- a/config.h.meson +++ b/config.h.meson @@ -236,9 +236,6 @@ /* Define if you have PPP support */ #mesondefine WITH_PPP -/* Define if you have a more recent version of pppd */ -#mesondefine WITH_PPP_VERSION_2_5_OR_NEWER - /* Define to path of pppd binary */ #mesondefine PPPD_PATH diff --git a/configure.ac b/configure.ac index aa68cdc609..3809cda9df 100644 --- a/configure.ac +++ b/configure.ac @@ -754,24 +754,27 @@ 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]) fi AM_CONDITIONAL(WITH_PPP, test "${enable_ppp}" = "yes") -PPPD_VERSION=2.4.9 -PKG_CHECK_EXISTS([pppd], [ - PPPD_VERSION=`$PKG_CONFIG --modversion pppd` -]) - 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 @@ -790,11 +793,6 @@ fi AC_DEFINE_UNQUOTED(PPPD_PATH, "$PPPD_PATH", [Define to path of pppd binary]) AC_SUBST(PPPD_PATH) -AC_CHECK_HEADERS(pppd/chap.h) -if test "x$ac_cv_header_pppd_chap_h" = xyes; then - AC_DEFINE(WITH_PPP_VERSION_2_5_OR_NEWER, 1, "Defined if one has a recent version of pppd headers installed") -fi - # ModemManager1 with libmm-glib AC_ARG_WITH(modem-manager-1, AS_HELP_STRING([--with-modem-manager-1], diff --git a/meson.build b/meson.build index b967ccae5a..9747065e7a 100644 --- a/meson.build +++ b/meson.build @@ -561,12 +561,11 @@ 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 @@ -583,10 +582,6 @@ if enable_ppp if pppd_plugin_dir == '' pppd_plugin_dir = join_paths(nm_libdir, 'pppd', pppd_version) endif - - if (pppd_dep.found()) - config_h.set10('WITH_PPP_VERSION_2_5_OR_NEWER', 1) - 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 . */ + 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 +#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 + +#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 +#include +#include +#include +#include + +#if PPP_VERSION_2_5_OR_NEWER +#include +#else +#include +#include +#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 +#include + +#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 index 08bdedfab9..11376e360e 100644 --- a/src/core/ppp/nm-pppd-compat.h +++ b/src/core/ppp/nm-pppd-compat.h @@ -1,122 +1,64 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* - * Copyright (C) Eivind Næss, eivnaes@yahoo.com + * Copyright (C) 2023 Eivind Næss, eivnaes@yahoo.com */ #ifndef __NM_PPPD_COMPAT_H__ #define __NM_PPPD_COMPAT_H__ -/* Define INET6 to compile with IPv6 support against older pppd headers, - pppd >= 2.5.0 use PPP_WITH_IPV6CP and is defined in pppdconf.h */ -#define INET6 1 +#define NM_PPPD_COMPAT_MAXNAMELEN 256 +#define NM_PPPD_COMPAT_MAXSECRETLEN 256 -/* PPP < 2.5.0 defines and exports VERSION which overlaps with current package VERSION define. - this silly macro magic is to work around that. */ -#undef VERSION -#include +int nm_pppd_compat_get_ifunit(void); -#ifndef PPPD_VERSION -#define PPPD_VERSION VERSION -#endif +const char *nm_pppd_compat_get_ifname(void); +void nm_pppd_compat_set_ifname(const char *ifname); -#include -#include -#include -#include -#include +const char *nm_pppd_compat_get_ipparam(void); -#ifdef WITH_PPP_VERSION_2_5_OR_NEWER -#include -#else -#include -#include -#endif +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; -#ifndef PPP_PROTO_CHAP -#define PPP_PROTO_CHAP 0xc223 -#endif +void nm_pppd_compat_get_ipcp_options(NMPppdCompatIPCPOptions *out_got, + NMPppdCompatIPCPOptions *out_his); -#ifndef PPP_PROTO_EAP -#define PPP_PROTO_EAP 0xc227 -#endif +typedef struct { + /* has information from "ipv6cp_options" */ + guint64 ourid; + guint64 hisid; +} NMPppdCompatIPV6CPOptions; -#ifndef WITH_PPP_VERSION_2_5_OR_NEWER +void nm_pppd_compat_get_ipv6cp_options(NMPppdCompatIPV6CPOptions *out_got, + NMPppdCompatIPV6CPOptions *out_his); -static inline bool -debug_on(void) -{ - return debug; -} +void nm_pppd_compat_set_chap_passwd_hook(int (*hook)(char *user, char *password)); -static inline const char * -ppp_ipparam(void) -{ - return ipparam; -} +void nm_pppd_compat_set_chap_check_hook(int (*hook)(void)); -static inline int -ppp_ifunit(void) -{ - return ifunit; -} +void nm_pppd_compat_set_pap_passwd_hook(int (*hook)(char *user, char *passwd)); -static inline const char * -ppp_ifname(void) -{ - return ifname; -} +void nm_pppd_compat_set_pap_check_hook(int (*hook)(void)); -static inline int -ppp_get_mtu(int idx) -{ - return netif_get_mtu(idx); -} +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; -static inline void -ppp_set_ifname(const char *new_name) -{ - g_strlcpy(ifname, new_name, IF_NAMESIZE); -} +gboolean +nm_pppd_compat_add_notify(NMPppdCompatNotifyT type, void (*func)(void *ctx, int arg), void *ctx); -typedef enum ppp_notify { - NF_PID_CHANGE, - NF_PHASE_CHANGE, - NF_EXIT, - NF_SIGNALED, - NF_IP_UP, - NF_IP_DOWN, - NF_IPV6_UP, - NF_IPV6_DOWN, - NF_AUTH_UP, - NF_LINK_DOWN, - NF_FORK, - NF_MAX_NOTIFY -} ppp_notify_t; - -typedef void(ppp_notify_fn)(void *ctx, int arg); - -static inline void -ppp_add_notify(ppp_notify_t type, ppp_notify_fn *func, void *ctx) -{ - static struct notifier **list[NF_MAX_NOTIFY] = { - [NF_PID_CHANGE] = &pidchange, - [NF_PHASE_CHANGE] = &phasechange, - [NF_EXIT] = &exitnotify, - [NF_SIGNALED] = &sigreceived, - [NF_IP_UP] = &ip_up_notifier, - [NF_IP_DOWN] = &ip_down_notifier, - [NF_IPV6_UP] = &ipv6_up_notifier, - [NF_IPV6_DOWN] = &ipv6_down_notifier, - [NF_AUTH_UP] = &auth_up_notifier, - [NF_LINK_DOWN] = &link_down_notifier, - [NF_FORK] = &fork_notifier, - }; - - struct notifier **notify = list[type]; - if (notify) { - add_notifier(notify, func, ctx); - } -} - -#endif /* #ifndef WITH_PPP_VERSION_2_5_OR_NEWER */ #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 59a2dcc94b..93425f382c 100644 --- a/src/core/ppp/nm-pppd-plugin.c +++ b/src/core/ppp/nm-pppd-plugin.c @@ -4,8 +4,9 @@ * Copyright (C) 2008 Red Hat, Inc. */ -#include -#define ___CONFIG_H__ +#include "libnm-glib-aux/nm-default-glib.h" + +#include "nm-pppd-plugin.h" #include #include @@ -14,17 +15,12 @@ #include #include -#include "nm-pppd-plugin.h" #include "nm-pppd-compat.h" #include "nm-ppp-status.h" - -#include "libnm-glib-aux/nm-default-glib.h" #include "nm-dbus-interface.h" int plugin_init(void); -char pppd_version[] = PPPD_VERSION; - static struct { GDBusConnection *dbus_connection; char *ipparam; @@ -33,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, @@ -119,7 +105,7 @@ nm_phasechange(int arg) char new_name[IF_NAMESIZE]; int ifindex; - ifindex = if_nametoindex(ppp_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 @@ -137,11 +123,12 @@ nm_phasechange(int arg) NULL); /* Update the name in pppd if NM changed it */ - if (if_indextoname(ifindex, new_name) && !nm_streq0(ppp_ifname(), new_name)) { + 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'", - ppp_ifname(), + nm_pppd_compat_get_ifname(), new_name); - ppp_set_ifname(new_name); + nm_pppd_compat_set_ifname(new_name); } } } @@ -150,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); @@ -159,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 + ppp_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; } @@ -182,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(ppp_ifname())); + g_variant_new_string(nm_pppd_compat_get_ifname())); g_variant_builder_add(&builder, "{sv}", @@ -259,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 @@ -288,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(ppp_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 */ @@ -364,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; } @@ -378,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"); @@ -386,31 +370,6 @@ nm_exit_notify(void *data, int arg) nm_clear_g_free(&gl.ipparam); } -static void -add_ip6_notifier(void) -{ -#if WITH_PPP_VERSION < PPP_VERSION(2, 5, 0) - 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"); -#else - ppp_add_notify(NF_IPV6_UP, nm_ip6_up, NULL); -#endif -} - int plugin_init(void) { @@ -427,16 +386,16 @@ plugin_init(void) return -1; } - gl.ipparam = g_strdup(ppp_ipparam()); + gl.ipparam = g_strdup(nm_pppd_compat_get_ipparam()); - chap_passwd_hook = get_credentials; - chap_check_hook = get_chap_check; - pap_passwd_hook = get_credentials; - pap_check_hook = get_pap_check; + 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); - ppp_add_notify(NF_PHASE_CHANGE, nm_phasechange_hook, NULL); - ppp_add_notify(NF_IP_UP, nm_ip_up, NULL); - ppp_add_notify(NF_EXIT, nm_exit_notify, NULL); - add_ip6_notifier(); + 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; }