/* 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 }