diff options
Diffstat (limited to 'accel-pptpd/extra/pppd_compat.c')
-rw-r--r-- | accel-pptpd/extra/pppd_compat.c | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/accel-pptpd/extra/pppd_compat.c b/accel-pptpd/extra/pppd_compat.c deleted file mode 100644 index f897dd68..00000000 --- a/accel-pptpd/extra/pppd_compat.c +++ /dev/null @@ -1,523 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <signal.h> -#include <unistd.h> -#include <sched.h> -#include <limits.h> -#include <sys/ioctl.h> -#include <netinet/in.h> -#include "linux_ppp.h" - -#include "triton.h" - -#include "events.h" -#include "ppp.h" -#include "log.h" -#include "utils.h" -#include "sigchld.h" - -#ifdef RADIUS -#include "radius.h" -#endif - -#include "memdebug.h" - -static char *conf_ip_up = "/etc/ppp/ip-up"; -static char *conf_ip_pre_up; -static char *conf_ip_down = "/etc/ppp/ip-down"; -static char *conf_ip_change; -static char *conf_radattr_prefix = "/var/run/radattr."; -static int conf_verbose = 0; - -static void *pd_key; - -struct pppd_compat_pd_t -{ - struct ppp_pd_t pd; - struct ppp_t *ppp; - struct sigchld_handler_t ip_pre_up_hnd; - struct sigchld_handler_t ip_up_hnd; - struct sigchld_handler_t ip_change_hnd; - struct sigchld_handler_t ip_down_hnd; -#ifdef RADIUS - int radattr_saved:1; -#endif - int started:1; - int res; - int bytes_sent; - int bytes_rcvd; -}; - -static struct pppd_compat_pd_t *find_pd(struct ppp_t *ppp); -static void fill_argv(char **argv, struct ppp_t *ppp, char *path); -static void fill_env(char **env, struct pppd_compat_pd_t *pd); -#ifdef RADIUS -static void remove_radattr(struct ppp_t *ppp); -static void write_radattr(struct ppp_t *ppp, struct rad_packet_t *pack, int save_old); -#endif - -static void ip_pre_up_handler(struct sigchld_handler_t *h, int status) -{ - struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_pre_up_hnd); - if (conf_verbose) { - log_switch(NULL, pd->ppp); - log_ppp_info2("pppd_compat: ip-pre-up finished (%i)\n", status); - pd->res = status; - } - sched_yield(); - triton_context_wakeup(pd->ppp->ctrl->ctx); -} - -static void ip_up_handler(struct sigchld_handler_t *h, int status) -{ - struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_up_hnd); - if (conf_verbose) { - log_switch(NULL, pd->ppp); - log_ppp_info2("pppd_compat: ip-up finished (%i)\n", status); - } -} - -static void ip_down_handler(struct sigchld_handler_t *h, int status) -{ - struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_down_hnd); - if (conf_verbose) { - log_switch(NULL, pd->ppp); - log_ppp_info2("pppd_compat: ip-down finished (%i)\n", status); - } - sched_yield(); - triton_context_wakeup(pd->ppp->ctrl->ctx); -} - -static void ip_change_handler(struct sigchld_handler_t *h, int status) -{ - struct pppd_compat_pd_t *pd = container_of(h, typeof(*pd), ip_change_hnd); - if (conf_verbose) { - log_switch(NULL, pd->ppp); - log_ppp_info2("pppd_compat: ip-change finished (%i)\n", status); - } - sched_yield(); - pd->res = status; - triton_context_wakeup(pd->ppp->ctrl->ctx); -} - -static void ev_ppp_starting(struct ppp_t *ppp) -{ - struct pppd_compat_pd_t *pd = _malloc(sizeof(*pd)); - - if (!pd) { - log_emerg("pppd_compat: out of memory\n"); - return; - } - - memset(pd, 0, sizeof(*pd)); - pd->pd.key = &pd_key; - pd->ppp = ppp; - pd->ip_pre_up_hnd.handler = ip_pre_up_handler; - pd->ip_up_hnd.handler = ip_up_handler; - pd->ip_down_hnd.handler = ip_down_handler; - pd->ip_change_hnd.handler = ip_change_handler; - list_add_tail(&pd->pd.entry, &ppp->pd_list); -} - -static void ev_ppp_pre_up(struct ppp_t *ppp) -{ - pid_t pid; - char *argv[8]; - char *env[2]; - char ipaddr[17]; - char peer_ipaddr[17]; - char peername[64]; - struct pppd_compat_pd_t *pd = find_pd(ppp); - - if (!pd) - return; - - argv[4] = ipaddr; - argv[5] = peer_ipaddr; - fill_argv(argv, ppp, conf_ip_up); - - env[0] = peername; - env[1] = NULL; - fill_env(env, pd); - - if (conf_ip_pre_up) { - sigchld_lock(); - pid = fork(); - if (pid > 0) { - pd->ip_pre_up_hnd.pid = pid; - sigchld_register_handler(&pd->ip_pre_up_hnd); - if (conf_verbose) - log_ppp_info2("pppd_compat: ip-pre-up started (pid %i)\n", pid); - sigchld_unlock(); - triton_context_schedule(); - pthread_mutex_lock(&pd->ip_pre_up_hnd.lock); - pthread_mutex_unlock(&pd->ip_pre_up_hnd.lock); - if (pd->res != 0) { - ppp_terminate(ppp, 0, pd->res < 0 ? TERM_NAS_ERROR : TERM_ADMIN_RESET); - return; - } - } else if (pid == 0) { - execve(conf_ip_pre_up, argv, env); - log_emerg("pppd_compat: exec '%s': %s\n", conf_ip_pre_up, strerror(errno)); - _exit(EXIT_FAILURE); - } else - log_error("pppd_compat: fork: %s\n", strerror(errno)); - } -} - -static void ev_ppp_started(struct ppp_t *ppp) -{ - pid_t pid; - char *argv[8]; - char *env[2]; - char ipaddr[17]; - char peer_ipaddr[17]; - char peername[64]; - struct pppd_compat_pd_t *pd = find_pd(ppp); - - if (!pd) - return; - - argv[4] = ipaddr; - argv[5] = peer_ipaddr; - fill_argv(argv, ppp, conf_ip_up); - - env[0] = peername; - env[1] = NULL; - fill_env(env, pd); - - if (conf_ip_up) { - sigchld_lock(); - pid = fork(); - if (pid > 0) { - pd->ip_up_hnd.pid = pid; - sigchld_register_handler(&pd->ip_up_hnd); - if (conf_verbose) - log_ppp_info2("pppd_compat: ip-up started (pid %i)\n", pid); - sigchld_unlock(); - } else if (pid == 0) { - execve(conf_ip_up, argv, env); - log_emerg("pppd_compat: exec '%s': %s\n", conf_ip_up, strerror(errno)); - _exit(EXIT_FAILURE); - } else - log_error("pppd_compat: fork: %s\n", strerror(errno)); - } - - pd->started = 1; -} - -static void ev_ppp_finishing(struct ppp_t *ppp) -{ - struct ifpppstatsreq ifreq; - struct pppd_compat_pd_t *pd = find_pd(ppp); - - if (!pd) - return; - - memset(&ifreq, 0, sizeof(ifreq)); - ifreq.stats_ptr = (void *)&ifreq.stats; - strcpy(ifreq.ifr__name, ppp->ifname); - - if (ioctl(sock_fd, SIOCGPPPSTATS, &ifreq)) { - log_ppp_error("pppd_compat: failed to get ppp statistics: %s\n", strerror(errno)); - return; - } - - pd->bytes_sent = ifreq.stats.p.ppp_obytes; - pd->bytes_rcvd = ifreq.stats.p.ppp_ibytes; -} - -static void ev_ppp_finished(struct ppp_t *ppp) -{ - pid_t pid; - char *argv[8]; - char *env[5]; - char ipaddr[17]; - char peer_ipaddr[17]; - char peername[64]; - char connect_time[24]; - char bytes_sent[24]; - char bytes_rcvd[24]; - struct pppd_compat_pd_t *pd = find_pd(ppp); - - if (!pd) - return; - - if (!pd->started) - goto skip; - - pthread_mutex_lock(&pd->ip_up_hnd.lock); - if (pd->ip_up_hnd.pid) { - log_ppp_warn("pppd_compat: ip-up is not yet finished, terminating it ...\n"); - kill(pd->ip_up_hnd.pid, SIGTERM); - } - pthread_mutex_unlock(&pd->ip_up_hnd.lock); - - argv[4] = ipaddr; - argv[5] = peer_ipaddr; - fill_argv(argv, pd->ppp, conf_ip_down); - - env[0] = peername; - env[1] = connect_time; - env[2] = bytes_sent; - env[3] = bytes_rcvd; - env[4] = NULL; - fill_env(env, pd); - - sigchld_lock(); - pid = fork(); - if (pid > 0) { - pd->ip_down_hnd.pid = pid; - sigchld_register_handler(&pd->ip_down_hnd); - if (conf_verbose) - log_ppp_info2("pppd_compat: ip-down started (pid %i)\n", pid); - sigchld_unlock(); - triton_context_schedule(); - pthread_mutex_lock(&pd->ip_down_hnd.lock); - pthread_mutex_unlock(&pd->ip_down_hnd.lock); - } else if (pid == 0) { - execve(conf_ip_down, argv, env); - log_emerg("pppd_compat: exec '%s': %s\n", conf_ip_down, strerror(errno)); - _exit(EXIT_FAILURE); - } else - log_error("pppd_compat: fork: %s\n", strerror(errno)); - - pthread_mutex_lock(&pd->ip_up_hnd.lock); - if (pd->ip_up_hnd.pid) { - log_ppp_warn("pppd_compat: ip-up is not yet finished, killing it ...\n"); - kill(pd->ip_up_hnd.pid, SIGKILL); - pthread_mutex_unlock(&pd->ip_up_hnd.lock); - sigchld_unregister_handler(&pd->ip_up_hnd); - } else - pthread_mutex_unlock(&pd->ip_up_hnd.lock); - -skip: -#ifdef RADIUS - if (pd->radattr_saved) - remove_radattr(ppp); -#endif - - list_del(&pd->pd.entry); - _free(pd); -} - -#ifdef RADIUS -static void ev_radius_access_accept(struct ev_radius_t *ev) -{ - struct pppd_compat_pd_t *pd = find_pd(ev->ppp); - - write_radattr(ev->ppp, ev->reply, 0); - - pd->radattr_saved = 1; -} - -static void ev_radius_coa(struct ev_radius_t *ev) -{ - pid_t pid; - char *argv[8]; - char *env[2]; - char ipaddr[17]; - char peer_ipaddr[17]; - char peername[64]; - struct pppd_compat_pd_t *pd = find_pd(ev->ppp); - - if (!pd) - return; - - write_radattr(ev->ppp, ev->request, 1); - - argv[4] = ipaddr; - argv[5] = peer_ipaddr; - fill_argv(argv, pd->ppp, conf_ip_change); - - env[0] = peername; - env[1] = NULL; - fill_env(env, pd); - - sigchld_lock(); - pid = fork(); - if (pid > 0) { - pd->ip_change_hnd.pid = pid; - sigchld_register_handler(&pd->ip_change_hnd); - sigchld_unlock(); - if (conf_verbose) - log_ppp_info2("pppd_compat: ip-change started (pid %i)\n", pid); - triton_context_schedule(); - if (!ev->res) - ev->res = pd->res; - } else if (pid == 0) { - execve(conf_ip_change, argv, env); - log_emerg("pppd_compat: exec '%s': %s\n", conf_ip_change, strerror(errno)); - _exit(EXIT_FAILURE); - } else - log_error("pppd_compat: fork: %s\n", strerror(errno)); -} - -static void remove_radattr(struct ppp_t *ppp) -{ - char *fname; - - fname = _malloc(PATH_MAX); - if (!fname) { - log_emerg("pppd_compat: out of memory\n"); - return; - } - - sprintf(fname, "%s.%s", conf_radattr_prefix, ppp->ifname); - if (unlink(fname)) { - log_ppp_warn("pppd_compat: failed to remove '%s': %s\n", fname, strerror(errno)); - } - sprintf(fname, "%s_old.%s", conf_radattr_prefix, ppp->ifname); - unlink(fname); - - _free(fname); -} - -static void write_radattr(struct ppp_t *ppp, struct rad_packet_t *pack, int save_old) -{ - struct rad_attr_t *attr; - struct rad_dict_value_t *val; - FILE *f; - char *fname1, *fname2 = NULL; - int i; - - fname1 = _malloc(PATH_MAX); - if (!fname1) { - log_emerg("pppd_compat: out of memory\n"); - return; - } - - if (save_old) { - fname2 = _malloc(PATH_MAX); - if (!fname2) { - log_emerg("pppd_compat: out of memory\n"); - _free(fname1); - return; - } - } - - sprintf(fname1, "%s.%s", conf_radattr_prefix, ppp->ifname); - if (save_old) { - sprintf(fname2, "%s_old.%s", conf_radattr_prefix, ppp->ifname); - if (rename(fname1, fname2)) { - log_ppp_warn("pppd_compat: rename: %s\n", strerror(errno)); - } - } - - f = fopen(fname1, "w"); - if (f) { - list_for_each_entry(attr, &pack->attrs, entry) { - fprintf(f, "%s ", attr->attr->name); - switch (attr->attr->type) { - case ATTR_TYPE_INTEGER: - val = rad_dict_find_val(attr->attr, attr->val); - if (val) - fprintf(f, "%s\n", val->name); - else - fprintf(f, "%i\n", attr->val.integer); - break; - case ATTR_TYPE_STRING: - fprintf(f, "%s\n", attr->val.string); - break; - case ATTR_TYPE_OCTETS: - for (i = 0; i < attr->len; i++) - fprintf(f, "%02X", attr->val.octets[i]); - fprintf(f, "\n"); - break; - case ATTR_TYPE_IPADDR: - fprintf(f, "%i.%i.%i.%i\n", attr->val.ipaddr & 0xff, (attr->val.ipaddr >> 8) & 0xff, (attr->val.ipaddr >> 16) & 0xff, (attr->val.ipaddr >> 24) & 0xff); - break; - case ATTR_TYPE_DATE: - fprintf(f, "%lu\n", attr->val.date); - break; - } - } - fclose(f); - } else - log_ppp_warn("pppd_compat: failed to create '%s': %s\n", fname1, strerror(errno)); - - _free(fname1); - if (save_old) - _free(fname2); -} -#endif - -static struct pppd_compat_pd_t *find_pd(struct ppp_t *ppp) -{ - struct ppp_pd_t *pd; - struct pppd_compat_pd_t *cpd; - - list_for_each_entry(pd, &ppp->pd_list, entry) { - if (pd->key == &pd_key) { - cpd = container_of(pd, typeof(*cpd), pd); - return cpd; - } - } - - log_ppp_warn("pppd_compat: pd not found\n"); - return NULL; -} - -static void fill_argv(char **argv, struct ppp_t *ppp, char *path) -{ - argv[0] = path; - argv[1] = ppp->ifname; - argv[2] = "none"; - argv[3] = "0"; - u_inet_ntoa(ppp->ipaddr, argv[4]); - u_inet_ntoa(ppp->peer_ipaddr, argv[5]); - argv[6] = ppp->ctrl->calling_station_id; - argv[7] = NULL; -} - -static void fill_env(char **env, struct pppd_compat_pd_t *pd) -{ - snprintf(env[0], 64, "PEERNAME=%s", pd->ppp->username); - - if (pd->ppp->stop_time && env[1]) { - snprintf(env[1], 24, "CONNECT_TIME=%lu", pd->ppp->stop_time - pd->ppp->start_time); - snprintf(env[2], 24, "BYTES_SENT=%u", pd->bytes_sent); - snprintf(env[3], 24, "BYTES_RCVD=%u", pd->bytes_rcvd); - } -} - -static void __init init(void) -{ - char *opt; - - opt = conf_get_opt("pppd-compat", "ip-pre-up"); - if (opt) - conf_ip_pre_up = _strdup(opt); - - opt = conf_get_opt("pppd-compat", "ip-up"); - if (opt) - conf_ip_up = _strdup(opt); - - opt = conf_get_opt("pppd-compat", "ip-down"); - if (opt) - conf_ip_down = _strdup(opt); - - opt = conf_get_opt("pppd-compat", "ip-change"); - if (opt) - conf_ip_change = _strdup(opt); - - opt = conf_get_opt("pppd-compat", "radattr-prefix"); - if (opt) - conf_radattr_prefix = _strdup(opt); - - opt = conf_get_opt("pppd-compat", "verbose"); - if (opt && atoi(opt) > 0) - conf_verbose = 1; - - triton_event_register_handler(EV_PPP_STARTING, (triton_event_func)ev_ppp_starting); - triton_event_register_handler(EV_PPP_PRE_UP, (triton_event_func)ev_ppp_pre_up); - triton_event_register_handler(EV_PPP_STARTED, (triton_event_func)ev_ppp_started); - triton_event_register_handler(EV_PPP_FINISHING, (triton_event_func)ev_ppp_finishing); - triton_event_register_handler(EV_PPP_FINISHED, (triton_event_func)ev_ppp_finished); -#ifdef RADIUS - triton_event_register_handler(EV_RADIUS_ACCESS_ACCEPT, (triton_event_func)ev_radius_access_accept); - triton_event_register_handler(EV_RADIUS_COA, (triton_event_func)ev_radius_coa); -#endif -} |