1*baaa6b9aSyasuoka /* $OpenBSD: npppd.c,v 1.48 2018/07/25 02:18:36 yasuoka Exp $ */ 2e109dc18Syasuoka 30fbf3537Syasuoka /*- 44a39ccd0Sderaadt * Copyright (c) 2005-2008,2009 Internet Initiative Japan Inc. 50fbf3537Syasuoka * All rights reserved. 60fbf3537Syasuoka * 70fbf3537Syasuoka * Redistribution and use in source and binary forms, with or without 80fbf3537Syasuoka * modification, are permitted provided that the following conditions 90fbf3537Syasuoka * are met: 100fbf3537Syasuoka * 1. Redistributions of source code must retain the above copyright 110fbf3537Syasuoka * notice, this list of conditions and the following disclaimer. 120fbf3537Syasuoka * 2. Redistributions in binary form must reproduce the above copyright 130fbf3537Syasuoka * notice, this list of conditions and the following disclaimer in the 140fbf3537Syasuoka * documentation and/or other materials provided with the distribution. 150fbf3537Syasuoka * 160fbf3537Syasuoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 170fbf3537Syasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180fbf3537Syasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190fbf3537Syasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 200fbf3537Syasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210fbf3537Syasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220fbf3537Syasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230fbf3537Syasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240fbf3537Syasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250fbf3537Syasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260fbf3537Syasuoka * SUCH DAMAGE. 270fbf3537Syasuoka */ 280fbf3537Syasuoka /**@file 29f0a4e295Syasuoka * Next pppd(nppd). This file provides a npppd daemon process and operations 30f0a4e295Syasuoka * for npppd instance. 310fbf3537Syasuoka * @author Yasuoka Masahiko 32*baaa6b9aSyasuoka * $Id: npppd.c,v 1.48 2018/07/25 02:18:36 yasuoka Exp $ 330fbf3537Syasuoka */ 340fbf3537Syasuoka #include "version.h" 35dbad4650Sderaadt #include <sys/param.h> /* ALIGNED_POINTER */ 360fbf3537Syasuoka #include <sys/types.h> 370fbf3537Syasuoka #include <sys/socket.h> 380fbf3537Syasuoka #include <sys/sysctl.h> 395fefcc09Syasuoka #include <sys/wait.h> 400fbf3537Syasuoka #include <netinet/in.h> 410fbf3537Syasuoka #include <netinet/ip.h> 420fbf3537Syasuoka #include <net/route.h> 430fbf3537Syasuoka #include <arpa/inet.h> 440fbf3537Syasuoka #include <net/if_dl.h> 450fbf3537Syasuoka #include <unistd.h> 460fbf3537Syasuoka #include <time.h> 470fbf3537Syasuoka #include <syslog.h> 480fbf3537Syasuoka #include <string.h> 490fbf3537Syasuoka #include <stdlib.h> 500fbf3537Syasuoka #include <stdio.h> 510fbf3537Syasuoka #include <signal.h> 520fbf3537Syasuoka #include <netdb.h> 530fbf3537Syasuoka #include <libgen.h> 540fbf3537Syasuoka #include <fcntl.h> 550fbf3537Syasuoka #include <event.h> 560fbf3537Syasuoka #include <errno.h> 570fbf3537Syasuoka #include <ifaddrs.h> 584a78f66bSyasuoka #include <err.h> 594a78f66bSyasuoka #include <pwd.h> 600fbf3537Syasuoka 610fbf3537Syasuoka #include "pathnames.h" 620fbf3537Syasuoka #include "debugutil.h" 630fbf3537Syasuoka #include "addr_range.h" 640fbf3537Syasuoka #include "npppd_subr.h" 650fbf3537Syasuoka #include "npppd_local.h" 660fbf3537Syasuoka #include "npppd_auth.h" 670fbf3537Syasuoka #include "radish.h" 680fbf3537Syasuoka #include "net_utils.h" 690fbf3537Syasuoka #include "time_utils.h" 700fbf3537Syasuoka 71b56612b6Smarkus #include "l2tp_local.h" /* XXX sa_cookie */ 72b56612b6Smarkus 730fbf3537Syasuoka #ifdef USE_NPPPD_ARP 740fbf3537Syasuoka #include "npppd_arp.h" 750fbf3537Syasuoka #endif 760fbf3537Syasuoka 770fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 780fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 790fbf3537Syasuoka #include "pppoe_local.h" 800fbf3537Syasuoka #endif /* USE_NPPPD_PPPOE */ 810fbf3537Syasuoka #include "psm-opt.h" 820fbf3537Syasuoka #include <sys/ioctl.h> 830fbf3537Syasuoka #include <net/pipex.h> 840fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 850fbf3537Syasuoka 8659408346Syasuoka #include "accept.h" 8759408346Syasuoka #include "log.h" 8859408346Syasuoka 890fbf3537Syasuoka static npppd s_npppd; /* singleton */ 900fbf3537Syasuoka 910fbf3537Syasuoka static void npppd_reload0 (npppd *); 92821f7c56Syasuoka static void npppd_update_pool_reference (npppd *); 930fbf3537Syasuoka static int npppd_rd_walktree_delete(struct radish_head *); 940cd27c4aSyasuoka static __dead void usage (void); 950fbf3537Syasuoka static void npppd_stop_really (npppd *); 960fbf3537Syasuoka static uint32_t str_hash(const void *, int); 970fbf3537Syasuoka static void npppd_on_sighup (int, short, void *); 980fbf3537Syasuoka static void npppd_on_sigterm (int, short, void *); 990fbf3537Syasuoka static void npppd_on_sigint (int, short, void *); 1005fefcc09Syasuoka static void npppd_on_sigchld (int, short, void *); 1010fbf3537Syasuoka static void npppd_reset_timer(npppd *); 1020fbf3537Syasuoka static void npppd_timer(int, short, void *); 1030fbf3537Syasuoka static void npppd_auth_finalizer_periodic(npppd *); 1040fbf3537Syasuoka static int rd2slist_walk (struct radish *, void *); 1050fbf3537Syasuoka static int rd2slist (struct radish_head *, slist *); 10634682664Syasuoka static slist *npppd_get_ppp_by_user (npppd *, const char *); 10734682664Syasuoka static int npppd_get_all_users (npppd *, slist *); 1082a5607d2Sgoda static struct ipcpstat 1092a5607d2Sgoda *npppd_get_ipcp_stat(struct ipcpstat_head *, const char *); 1102a5607d2Sgoda static void npppd_destroy_ipcp_stats(struct ipcpstat_head *); 1112a5607d2Sgoda static void npppd_ipcp_stats_reload(npppd *); 1120fbf3537Syasuoka 1130fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1140fbf3537Syasuoka static struct in_addr loop; /* initialize at npppd_init() */ 1150fbf3537Syasuoka #endif 1160fbf3537Syasuoka static uint32_t str_hash(const void *, int); 1170fbf3537Syasuoka 1180fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 1190fbf3537Syasuoka static int npppd_ppp_pipex_ip_disable(npppd *, npppd_ppp *); 1200fbf3537Syasuoka static void pipex_periodic(npppd *); 1210fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 1220fbf3537Syasuoka 1230fbf3537Syasuoka #ifdef NPPPD_DEBUG 1240fbf3537Syasuoka #define NPPPD_DBG(x) log_printf x 1250fbf3537Syasuoka #define NPPPD_ASSERT(x) ASSERT(x) 1260fbf3537Syasuoka #else 1270fbf3537Syasuoka #define NPPPD_DBG(x) 1280fbf3537Syasuoka #define NPPPD_ASSERT(x) 1290fbf3537Syasuoka #endif 1300fbf3537Syasuoka 1310fbf3537Syasuoka /*********************************************************************** 132f0a4e295Syasuoka * Daemon process 1330fbf3537Syasuoka ***********************************************************************/ 1340fbf3537Syasuoka int main (int, char *[]); 135821f7c56Syasuoka int debugsyslog = 0; /* used by log.c */ 1360fbf3537Syasuoka 1370fbf3537Syasuoka int 1380fbf3537Syasuoka main(int argc, char *argv[]) 1390fbf3537Syasuoka { 140821f7c56Syasuoka int ch, stop_by_error, runasdaemon = 1, nflag = 0; 1410fbf3537Syasuoka extern char *optarg; 1420fbf3537Syasuoka const char *npppd_conf0 = DEFAULT_NPPPD_CONF; 1434a78f66bSyasuoka struct passwd *pw; 1440fbf3537Syasuoka 1450cd27c4aSyasuoka while ((ch = getopt(argc, argv, "nf:d")) != -1) { 1460fbf3537Syasuoka switch (ch) { 147821f7c56Syasuoka case 'n': 148821f7c56Syasuoka nflag = 1; 1490fbf3537Syasuoka break; 150821f7c56Syasuoka case 'f': 1510fbf3537Syasuoka npppd_conf0 = optarg; 1520fbf3537Syasuoka break; 1530fbf3537Syasuoka case 'd': 1540fbf3537Syasuoka debuglevel++; 155821f7c56Syasuoka runasdaemon = 0; 1560fbf3537Syasuoka break; 1570cd27c4aSyasuoka default: 1580fbf3537Syasuoka usage(); 1590fbf3537Syasuoka } 1600fbf3537Syasuoka } 161821f7c56Syasuoka argc -= optind; 162821f7c56Syasuoka argv += optind; 1630cd27c4aSyasuoka if (argc != 0) 164821f7c56Syasuoka usage(); 165821f7c56Syasuoka if (nflag) { 166821f7c56Syasuoka debuglevel++; 167821f7c56Syasuoka runasdaemon = 0; 168821f7c56Syasuoka } 169821f7c56Syasuoka 170821f7c56Syasuoka /* for log.c */ 171821f7c56Syasuoka log_init(debuglevel); 1720fbf3537Syasuoka if (debuglevel > 0) { 173821f7c56Syasuoka /* for ../common/debugutil.c */ 1740fbf3537Syasuoka debug_set_debugfp(stderr); 1750fbf3537Syasuoka debug_use_syslog(0); 176821f7c56Syasuoka } 1770fbf3537Syasuoka if (runasdaemon) 1780fbf3537Syasuoka daemon(0, 0); 1790fbf3537Syasuoka 1804a78f66bSyasuoka /* check for root privileges */ 1814a78f66bSyasuoka if (geteuid()) 1824a78f66bSyasuoka errx(1, "need root privileges"); 1834a78f66bSyasuoka /* check for npppd user */ 1844a78f66bSyasuoka if (getpwnam(NPPPD_USER) == NULL) 1854a78f66bSyasuoka errx(1, "unknown user %s", NPPPD_USER); 1864a78f66bSyasuoka 1874a78f66bSyasuoka if (privsep_init() != 0) 1884a78f66bSyasuoka err(1, "cannot drop privileges"); 1894a78f66bSyasuoka 190821f7c56Syasuoka if (nflag) { 191821f7c56Syasuoka if (npppd_config_check(npppd_conf0) == 0) { 192821f7c56Syasuoka fprintf(stderr, "configuration OK\n"); 193821f7c56Syasuoka exit(EXIT_SUCCESS); 194821f7c56Syasuoka } 195821f7c56Syasuoka exit(EXIT_FAILURE); 196821f7c56Syasuoka } 1979a200ddfSyasuoka if (npppd_init(&s_npppd, npppd_conf0) != 0) 1989a200ddfSyasuoka exit(EXIT_FAILURE); 1994a78f66bSyasuoka 2004a78f66bSyasuoka if ((pw = getpwnam(NPPPD_USER)) == NULL) 2019a200ddfSyasuoka err(EXIT_FAILURE, "gwpwnam"); 2024a78f66bSyasuoka if (chroot(pw->pw_dir) == -1) 2039a200ddfSyasuoka err(EXIT_FAILURE, "chroot"); 2044a78f66bSyasuoka if (chdir("/") == -1) 2059a200ddfSyasuoka err(EXIT_FAILURE, "chdir(\"/\")"); 2064a78f66bSyasuoka if (setgroups(1, &pw->pw_gid) || 2074a78f66bSyasuoka setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 2084a78f66bSyasuoka setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 2099a200ddfSyasuoka err(EXIT_FAILURE, "cannot drop privileges"); 2104a78f66bSyasuoka /* privileges is dropped */ 2114a78f66bSyasuoka 2120fbf3537Syasuoka npppd_start(&s_npppd); 2139a200ddfSyasuoka stop_by_error = s_npppd.stop_by_error; 2140fbf3537Syasuoka npppd_fini(&s_npppd); 2154a78f66bSyasuoka privsep_fini(); 2160fbf3537Syasuoka log_printf(LOG_NOTICE, "Terminate npppd."); 2170fbf3537Syasuoka 2189a200ddfSyasuoka exit((!stop_by_error)? EXIT_SUCCESS : EXIT_FAILURE); 2190fbf3537Syasuoka } 2200fbf3537Syasuoka 2210cd27c4aSyasuoka static __dead void 2220cd27c4aSyasuoka usage(void) 2230fbf3537Syasuoka { 2240cd27c4aSyasuoka fprintf(stderr, "usage: npppd [-dn] [-f config_file]\n"); 2250cd27c4aSyasuoka exit(1); 2260fbf3537Syasuoka } 2270fbf3537Syasuoka 228f0a4e295Syasuoka /** Returns the singleton npppd instance */ 2290fbf3537Syasuoka npppd * 2300fbf3537Syasuoka npppd_get_npppd() 2310fbf3537Syasuoka { 2320fbf3537Syasuoka return &s_npppd; 2330fbf3537Syasuoka } 2340fbf3537Syasuoka 2350fbf3537Syasuoka /*********************************************************************** 236f0a4e295Syasuoka * Operations to npppd itself (initialize/finalize/start/stop) 2370fbf3537Syasuoka ***********************************************************************/ 238f0a4e295Syasuoka /** Initialize the npppd */ 2390fbf3537Syasuoka int 2400fbf3537Syasuoka npppd_init(npppd *_this, const char *config_file) 2410fbf3537Syasuoka { 2424c9b8a40Syasuoka int i, status = -1, value; 2430fbf3537Syasuoka const char *pidpath0; 2440fbf3537Syasuoka FILE *pidfp = NULL; 2454c9b8a40Syasuoka struct tunnconf *tunn; 2462a5607d2Sgoda struct ipcpconf *ipcpconf; 2472a5607d2Sgoda struct ipcpstat *ipcpstat; 2484c9b8a40Syasuoka int mib[] = { CTL_NET, PF_PIPEX, PIPEXCTL_ENABLE }; 2494c9b8a40Syasuoka size_t size; 2500fbf3537Syasuoka 2510fbf3537Syasuoka memset(_this, 0, sizeof(npppd)); 252cd8e09b9Sdlg #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 2530fbf3537Syasuoka loop.s_addr = htonl(INADDR_LOOPBACK); 254cd8e09b9Sdlg #endif 2550fbf3537Syasuoka 2560fbf3537Syasuoka NPPPD_ASSERT(config_file != NULL); 2570fbf3537Syasuoka 2580fbf3537Syasuoka pidpath0 = NULL; 2590fbf3537Syasuoka _this->pid = getpid(); 2600fbf3537Syasuoka slist_init(&_this->realms); 261821f7c56Syasuoka npppd_conf_init(&_this->conf); 2620fbf3537Syasuoka 2630fbf3537Syasuoka log_printf(LOG_NOTICE, "Starting npppd pid=%u version=%s", 2640fbf3537Syasuoka _this->pid, VERSION); 2650fbf3537Syasuoka #if defined(BUILD_DATE) && defined(BUILD_TIME) 2660fbf3537Syasuoka log_printf(LOG_INFO, "Build %s %s ", BUILD_DATE, BUILD_TIME); 2670fbf3537Syasuoka #endif 2680fbf3537Syasuoka if (get_nanotime() == INT64_MIN) { 2690fbf3537Syasuoka log_printf(LOG_ERR, "get_nanotime() failed: %m"); 2700fbf3537Syasuoka return 1; 2710fbf3537Syasuoka } 2720fbf3537Syasuoka 2730fbf3537Syasuoka if (realpath(config_file, _this->config_file) == NULL) { 2740fbf3537Syasuoka log_printf(LOG_ERR, "realpath(%s,) failed in %s(): %m", 2750fbf3537Syasuoka config_file, __func__); 2760fbf3537Syasuoka return 1; 2770fbf3537Syasuoka } 278f0a4e295Syasuoka /* we assume 4.4 compatible realpath(). See realpath(3) on BSD. */ 2790fbf3537Syasuoka NPPPD_ASSERT(_this->config_file[0] == '/'); 2800fbf3537Syasuoka 281c2307f15Syasuoka _this->boot_id = arc4random(); 2828daf7599Syasuoka 28306adecbeSyasuoka #ifdef USE_NPPPD_L2TP 28406adecbeSyasuoka if (l2tpd_init(&_this->l2tpd) != 0) 28506adecbeSyasuoka return (-1); 28606adecbeSyasuoka #endif 28706adecbeSyasuoka #ifdef USE_NPPPD_PPTP 28806adecbeSyasuoka if (pptpd_init(&_this->pptpd) != 0) 28906adecbeSyasuoka return (-1); 29006adecbeSyasuoka #endif 29106adecbeSyasuoka #ifdef USE_NPPPD_PPPOE 29206adecbeSyasuoka if (pppoed_init(&_this->pppoed) != 0) 29306adecbeSyasuoka return (-1); 29406adecbeSyasuoka #endif 2952a5607d2Sgoda LIST_INIT(&_this->ipcpstats); 2962a5607d2Sgoda 297f0a4e295Syasuoka /* load configuration */ 2980fbf3537Syasuoka if ((status = npppd_reload_config(_this)) != 0) 2990fbf3537Syasuoka return status; 3000fbf3537Syasuoka 3014c9b8a40Syasuoka TAILQ_FOREACH(tunn, &_this->conf.tunnconfs, entry) { 3024c9b8a40Syasuoka if (tunn->pipex) { 3034c9b8a40Syasuoka size = sizeof(value); 3044c9b8a40Syasuoka if (!sysctl(mib, nitems(mib), &value, &size, NULL, 0) 3054c9b8a40Syasuoka && value == 0) 3064c9b8a40Syasuoka log_printf(LOG_WARNING, 3074c9b8a40Syasuoka "pipex(4) is disabled by sysctl"); 3084c9b8a40Syasuoka break; 3094c9b8a40Syasuoka } 3104c9b8a40Syasuoka } 3114c9b8a40Syasuoka 3120fbf3537Syasuoka if ((_this->map_user_ppp = hash_create( 3130fbf3537Syasuoka (int (*) (const void *, const void *))strcmp, str_hash, 3140fbf3537Syasuoka NPPPD_USER_HASH_SIZ)) == NULL) { 3150fbf3537Syasuoka log_printf(LOG_ERR, "hash_create() failed in %s(): %m", 3160fbf3537Syasuoka __func__); 3170fbf3537Syasuoka return -1; 3180fbf3537Syasuoka } 3190fbf3537Syasuoka 3200fbf3537Syasuoka if (npppd_ifaces_load_config(_this) != 0) { 3210fbf3537Syasuoka return -1; 3220fbf3537Syasuoka } 3230fbf3537Syasuoka 3242a5607d2Sgoda TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry) { 3252a5607d2Sgoda ipcpstat = malloc(sizeof(*ipcpstat)); 3262a5607d2Sgoda if (ipcpstat == NULL) { 3272a5607d2Sgoda log_printf(LOG_ERR, "initializing ipcp_stats failed : %m"); 3282a5607d2Sgoda npppd_destroy_ipcp_stats(&_this->ipcpstats); 3292a5607d2Sgoda return -1; 3302a5607d2Sgoda } 3312a5607d2Sgoda memset(ipcpstat, 0, sizeof(*ipcpstat)); 3322a5607d2Sgoda strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpstat->name)); 3332a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry); 3342a5607d2Sgoda } 3352a5607d2Sgoda 3360fbf3537Syasuoka pidpath0 = DEFAULT_NPPPD_PIDFILE; 3370fbf3537Syasuoka 338f0a4e295Syasuoka /* initialize event(3) */ 3390fbf3537Syasuoka event_init(); 34034682664Syasuoka _this->ctl_sock.cs_name = NPPPD_SOCKET; 34134682664Syasuoka _this->ctl_sock.cs_ctx = _this; 34234682664Syasuoka if (control_init(&_this->ctl_sock) == -1) { 34334682664Syasuoka log_printf(LOG_ERR, "control_init() failed %s(): %m", 34434682664Syasuoka __func__); 34534682664Syasuoka return (-1); 34634682664Syasuoka } 34734682664Syasuoka if (control_listen(&_this->ctl_sock) == -1) { 34834682664Syasuoka log_printf(LOG_ERR, "control_listen() failed %s(): %m", 34934682664Syasuoka __func__); 35034682664Syasuoka return (-1); 35134682664Syasuoka } 35259408346Syasuoka accept_init(); 35359408346Syasuoka 354f0a4e295Syasuoka /* ignore signals */ 3550fbf3537Syasuoka signal(SIGPIPE, SIG_IGN); 3560fbf3537Syasuoka signal(SIGURG, SIG_IGN); 357f0a4e295Syasuoka 358f0a4e295Syasuoka /* set signal handlers */ 3590fbf3537Syasuoka signal_set(&_this->ev_sigterm, SIGTERM, npppd_on_sigterm, _this); 3600fbf3537Syasuoka signal_set(&_this->ev_sigint, SIGINT, npppd_on_sigint, _this); 3610fbf3537Syasuoka signal_set(&_this->ev_sighup, SIGHUP, npppd_on_sighup, _this); 3625fefcc09Syasuoka signal_set(&_this->ev_sigchld, SIGCHLD, npppd_on_sigchld, _this); 3630fbf3537Syasuoka signal_add(&_this->ev_sigterm, NULL); 3640fbf3537Syasuoka signal_add(&_this->ev_sigint, NULL); 3650fbf3537Syasuoka signal_add(&_this->ev_sighup, NULL); 3665fefcc09Syasuoka signal_add(&_this->ev_sigchld, NULL); 3670fbf3537Syasuoka 3680fbf3537Syasuoka evtimer_set(&_this->ev_timer, npppd_timer, _this); 3690fbf3537Syasuoka 370f0a4e295Syasuoka /* start tun(4) or pppac(4) */ 3710fbf3537Syasuoka status = 0; 3720fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) { 3730fbf3537Syasuoka if (_this->iface[i].initialized != 0) 3740fbf3537Syasuoka status |= npppd_iface_start(&_this->iface[i]); 3750fbf3537Syasuoka } 3760fbf3537Syasuoka if (status != 0) 3770fbf3537Syasuoka return -1; 3780fbf3537Syasuoka 3790fbf3537Syasuoka /* 380f0a4e295Syasuoka * If the npppd can start(open) interfaces successfully, it can 381f0a4e295Syasuoka * act as only one npppd process on the system and overwrite the pid 382f0a4e295Syasuoka * file. 3830fbf3537Syasuoka */ 3840fbf3537Syasuoka if ((pidfp = fopen(pidpath0, "w+")) == NULL) { 3850fbf3537Syasuoka log_printf(LOG_ERR, "fopen(%s,w+) failed in %s(): %m", 3860fbf3537Syasuoka pidpath0, __func__); 3870fbf3537Syasuoka return -1; 3880fbf3537Syasuoka } 3890fbf3537Syasuoka strlcpy(_this->pidpath, pidpath0, sizeof(_this->pidpath)); 3900fbf3537Syasuoka fprintf(pidfp, "%u\n", _this->pid); 3910fbf3537Syasuoka fclose(pidfp); 3920fbf3537Syasuoka pidfp = NULL; 3930fbf3537Syasuoka #ifdef USE_NPPPD_ARP 3940fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); 3950fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) 3960fbf3537Syasuoka arp_sock_init(); 3970fbf3537Syasuoka #endif 398821f7c56Syasuoka if ((status = npppd_modules_reload(_this)) != 0) 399821f7c56Syasuoka return status; 400821f7c56Syasuoka 401821f7c56Syasuoka npppd_update_pool_reference(_this); 402821f7c56Syasuoka 403821f7c56Syasuoka return 0; 4040fbf3537Syasuoka } 4050fbf3537Syasuoka 406f0a4e295Syasuoka /** start the npppd */ 4070fbf3537Syasuoka void 4080fbf3537Syasuoka npppd_start(npppd *_this) 4090fbf3537Syasuoka { 4100fbf3537Syasuoka int rval = 0; 4110fbf3537Syasuoka 4120fbf3537Syasuoka npppd_reset_timer(_this); 413f65d56a4Syasuoka while ((rval = event_loop(EVLOOP_ONCE)) == 0) { 4140fbf3537Syasuoka if (_this->finalized != 0) 4150fbf3537Syasuoka break; 4160fbf3537Syasuoka } 417f65d56a4Syasuoka if (rval != 0) { 4180fbf3537Syasuoka log_printf(LOG_CRIT, "event_loop() failed: %m"); 419f65d56a4Syasuoka abort(); 420f65d56a4Syasuoka } 4210fbf3537Syasuoka } 4220fbf3537Syasuoka 423f0a4e295Syasuoka /** stop the npppd */ 4240fbf3537Syasuoka void 4250fbf3537Syasuoka npppd_stop(npppd *_this) 4260fbf3537Syasuoka { 4270fbf3537Syasuoka int i; 4280fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4290fbf3537Syasuoka l2tpd_stop(&_this->l2tpd); 4300fbf3537Syasuoka #endif 4310fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4320fbf3537Syasuoka pptpd_stop(&_this->pptpd); 4330fbf3537Syasuoka #endif 4340fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 4350fbf3537Syasuoka pppoed_stop(&_this->pppoed); 4360fbf3537Syasuoka #endif 4370fbf3537Syasuoka #ifdef USE_NPPPD_ARP 4380fbf3537Syasuoka arp_sock_fini(); 4390fbf3537Syasuoka #endif 44034682664Syasuoka close(_this->ctl_sock.cs_fd); 44134682664Syasuoka control_cleanup(&_this->ctl_sock); 44234682664Syasuoka 4430fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 4440fbf3537Syasuoka if (_this->iface[i].initialized != 0) 4450fbf3537Syasuoka npppd_iface_stop(&_this->iface[i]); 4460fbf3537Syasuoka } 4470fbf3537Syasuoka npppd_set_radish(_this, NULL); 4480fbf3537Syasuoka 4490fbf3537Syasuoka _this->finalizing = 1; 4500fbf3537Syasuoka npppd_reset_timer(_this); 4510fbf3537Syasuoka } 4520fbf3537Syasuoka 4530fbf3537Syasuoka static void 4540fbf3537Syasuoka npppd_stop_really(npppd *_this) 4550fbf3537Syasuoka { 4560fbf3537Syasuoka int i; 4570fbf3537Syasuoka #if defined(USE_NPPPD_L2TP) || defined(USE_NPPPD_PPTP) 4580fbf3537Syasuoka int wait_again; 4590fbf3537Syasuoka 4600fbf3537Syasuoka wait_again = 0; 4610fbf3537Syasuoka 4620fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4630fbf3537Syasuoka if (!l2tpd_is_stopped(&_this->l2tpd)) 4640fbf3537Syasuoka wait_again |= 1; 4650fbf3537Syasuoka #endif 4660fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4670fbf3537Syasuoka if (!pptpd_is_stopped(&_this->pptpd)) 4680fbf3537Syasuoka wait_again |= 1; 4690fbf3537Syasuoka #endif 4700fbf3537Syasuoka if (wait_again != 0) { 4710fbf3537Syasuoka npppd_reset_timer(_this); 4720fbf3537Syasuoka return; 4730fbf3537Syasuoka } 4740fbf3537Syasuoka #endif 4750fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 4760fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]); 4770fbf3537Syasuoka } 4780fbf3537Syasuoka _this->finalized = 1; 4790fbf3537Syasuoka } 4800fbf3537Syasuoka 481f0a4e295Syasuoka /** finalize the npppd */ 4820fbf3537Syasuoka void 4830fbf3537Syasuoka npppd_fini(npppd *_this) 4840fbf3537Syasuoka { 4850fbf3537Syasuoka int i; 4860fbf3537Syasuoka npppd_auth_base *auth_base; 4870fbf3537Syasuoka 4880fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4890fbf3537Syasuoka l2tpd_uninit(&_this->l2tpd); 4900fbf3537Syasuoka #endif 4910fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4920fbf3537Syasuoka pptpd_uninit(&_this->pptpd); 4930fbf3537Syasuoka #endif 4940fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 4950fbf3537Syasuoka pppoed_uninit(&_this->pppoed); 4960fbf3537Syasuoka #endif 4970fbf3537Syasuoka for (slist_itr_first(&_this->realms); 4980fbf3537Syasuoka slist_itr_has_next(&_this->realms);) { 4990fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms); 5000fbf3537Syasuoka npppd_auth_destroy(auth_base); 5010fbf3537Syasuoka } 5020fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 5030fbf3537Syasuoka if (_this->iface[i].initialized != 0) 5040fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]); 5050fbf3537Syasuoka } 5060fbf3537Syasuoka 5070fbf3537Syasuoka for (i = countof(_this->pool) - 1; i >= 0; i--) { 5080fbf3537Syasuoka if (_this->pool[i].initialized != 0) 5090fbf3537Syasuoka npppd_pool_uninit(&_this->pool[i]); 5100fbf3537Syasuoka } 5110fbf3537Syasuoka 5122a5607d2Sgoda npppd_destroy_ipcp_stats(&_this->ipcpstats); 5132a5607d2Sgoda 5140fbf3537Syasuoka signal_del(&_this->ev_sigterm); 5150fbf3537Syasuoka signal_del(&_this->ev_sigint); 5160fbf3537Syasuoka signal_del(&_this->ev_sighup); 5175fefcc09Syasuoka signal_del(&_this->ev_sigchld); 5180fbf3537Syasuoka 519821f7c56Syasuoka npppd_conf_fini(&_this->conf); 5200fbf3537Syasuoka 5210fbf3537Syasuoka slist_fini(&_this->realms); 5220fbf3537Syasuoka 5230fbf3537Syasuoka if (_this->map_user_ppp != NULL) 5240fbf3537Syasuoka hash_free(_this->map_user_ppp); 5250fbf3537Syasuoka } 5260fbf3537Syasuoka 5270fbf3537Syasuoka /*********************************************************************** 528f0a4e295Syasuoka * Timer related functions 5290fbf3537Syasuoka ***********************************************************************/ 5300fbf3537Syasuoka static void 5310fbf3537Syasuoka npppd_reset_timer(npppd *_this) 5320fbf3537Syasuoka { 5330fbf3537Syasuoka struct timeval tv; 5340fbf3537Syasuoka 5350fbf3537Syasuoka if (_this->finalizing != 0) { 536f0a4e295Syasuoka /* we can use the timer exclusively on finalizing */ 5370fbf3537Syasuoka tv.tv_usec = 500000; 5380fbf3537Syasuoka tv.tv_sec = 0; 5390fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 5400fbf3537Syasuoka } else { 5410fbf3537Syasuoka tv.tv_usec = 0; 5420fbf3537Syasuoka tv.tv_sec = NPPPD_TIMER_TICK_IVAL; 5430fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 5440fbf3537Syasuoka } 5450fbf3537Syasuoka } 5460fbf3537Syasuoka 5470fbf3537Syasuoka static void 5480fbf3537Syasuoka npppd_timer(int fd, short evtype, void *ctx) 5490fbf3537Syasuoka { 5500fbf3537Syasuoka npppd *_this; 5510fbf3537Syasuoka 5520fbf3537Syasuoka _this = ctx; 5530fbf3537Syasuoka if (_this->finalizing != 0) { 554f0a4e295Syasuoka npppd_stop_really(_this); /* The timer has been reset */ 555f0a4e295Syasuoka return; /* we can use the timer exclusively on finalizing */ 5560fbf3537Syasuoka } 5570fbf3537Syasuoka _this->secs += NPPPD_TIMER_TICK_IVAL; 5580fbf3537Syasuoka if (_this->reloading_count > 0) { 5590fbf3537Syasuoka _this->reloading_count -= NPPPD_TIMER_TICK_IVAL; 5600fbf3537Syasuoka if (_this->reloading_count <= 0) { 5610fbf3537Syasuoka npppd_reload0(_this); 5620fbf3537Syasuoka _this->reloading_count = 0; 5630fbf3537Syasuoka } 5640fbf3537Syasuoka } else { 5650fbf3537Syasuoka if ((_this->secs % TIMER_TICK_RUP( 5660fbf3537Syasuoka NPPPD_AUTH_REALM_FINALIZER_INTERVAL)) == 0) 5670fbf3537Syasuoka npppd_auth_finalizer_periodic(_this); 5680fbf3537Syasuoka } 5690fbf3537Syasuoka 5700fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 5710fbf3537Syasuoka if (pppoed_need_polling(&_this->pppoed)) 5720fbf3537Syasuoka pppoed_reload_listeners(&_this->pppoed); 5730fbf3537Syasuoka #endif 5740fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 5750fbf3537Syasuoka pipex_periodic(_this); 5760fbf3537Syasuoka #endif 5770fbf3537Syasuoka 5780fbf3537Syasuoka npppd_reset_timer(_this); 5790fbf3537Syasuoka } 5800fbf3537Syasuoka 5810fbf3537Syasuoka int 5820fbf3537Syasuoka npppd_reset_routing_table(npppd *_this, int pool_only) 5830fbf3537Syasuoka { 5840fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 5850fbf3537Syasuoka slist rtlist0; 5860fbf3537Syasuoka 587cd8e09b9Sdlg if (_this->iface[0].using_pppx) 588cd8e09b9Sdlg return 0; 589cd8e09b9Sdlg 5900fbf3537Syasuoka slist_init(&rtlist0); 5910fbf3537Syasuoka if (rd2slist(_this->rd, &rtlist0) != 0) 5920fbf3537Syasuoka return 1; 5930fbf3537Syasuoka 5940fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0); ) { 5950fbf3537Syasuoka struct radish *rd; 5960fbf3537Syasuoka struct sockaddr_npppd *snp; 5970fbf3537Syasuoka npppd_ppp *ppp; 5980fbf3537Syasuoka int is_first; 5990fbf3537Syasuoka 6000fbf3537Syasuoka rd = slist_itr_next(&rtlist0); 6010fbf3537Syasuoka snp = rd->rd_rtent; 6020fbf3537Syasuoka 6030fbf3537Syasuoka is_first = 1; 6040fbf3537Syasuoka for (snp = rd->rd_rtent; snp != NULL; snp = snp->snp_next) { 6050fbf3537Syasuoka switch (snp->snp_type) { 6060fbf3537Syasuoka case SNP_POOL: 6070fbf3537Syasuoka case SNP_DYN_POOL: 6080fbf3537Syasuoka if (is_first) 6090fbf3537Syasuoka in_route_add(&snp->snp_addr, 6100fbf3537Syasuoka &snp->snp_mask, &loop, 6110fbf3537Syasuoka LOOPBACK_IFNAME, RTF_BLACKHOLE, 0); 6120fbf3537Syasuoka break; 6130fbf3537Syasuoka 6140fbf3537Syasuoka case SNP_PPP: 6150fbf3537Syasuoka if (pool_only) 6160fbf3537Syasuoka break; 6170fbf3537Syasuoka ppp = snp->snp_data_ptr; 6180fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr 6190fbf3537Syasuoka == 0xffffffffL) { 6200fbf3537Syasuoka in_host_route_add(&ppp-> 6210fbf3537Syasuoka ppp_framed_ip_address, 6220fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 6230fbf3537Syasuoka ppp_iface(ppp)->ifname, 6240fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 6250fbf3537Syasuoka } else { 6260fbf3537Syasuoka in_route_add(&ppp-> 6270fbf3537Syasuoka ppp_framed_ip_address, 6280fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 6290fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 6300fbf3537Syasuoka ppp_iface(ppp)->ifname, 0, 6310fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 6320fbf3537Syasuoka } 6330fbf3537Syasuoka break; 6340fbf3537Syasuoka } 6350fbf3537Syasuoka is_first = 0; 6360fbf3537Syasuoka } 6370fbf3537Syasuoka 6380fbf3537Syasuoka } 6390fbf3537Syasuoka 6400fbf3537Syasuoka slist_fini(&rtlist0); 6410fbf3537Syasuoka #endif 6420fbf3537Syasuoka return 0; 6430fbf3537Syasuoka } 6440fbf3537Syasuoka 6450fbf3537Syasuoka /*********************************************************************** 646f0a4e295Syasuoka * Other npppd related functions. 6470fbf3537Syasuoka ***********************************************************************/ 6480fbf3537Syasuoka /** 649f0a4e295Syasuoka * Get the user's password. Return 0 on success. 6500fbf3537Syasuoka * 651f0a4e295Syasuoka * @param username Username who acquires password 652f0a4e295Syasuoka * @param password A pointer to a buffer space to store the password. 653f0a4e295Syasuoka * Use NULL when you need to know only the length of 654f0a4e295Syasuoka * the password. 655f0a4e295Syasuoka * @param plpassword A pointer to the length of the password parameter. 656f0a4e295Syasuoka * This function uses this parameter value and stores 657f0a4e295Syasuoka * the required length value pointed to by this 658f0a4e295Syasuoka * parameter. Use NULL when use don't need to know 659f0a4e295Syasuoka * the password and its length. 660f0a4e295Syasuoka * @return If the function succeeds, 0 is returned. The function returns 661f0a4e295Syasuoka * 1 if the username is unknown, returns 2 if the password buffer 662f0a4e295Syasuoka * length is not enough. It returns negative value for other 663f0a4e295Syasuoka * errors. 6640fbf3537Syasuoka */ 6650fbf3537Syasuoka int 6660fbf3537Syasuoka npppd_get_user_password(npppd *_this, npppd_ppp *ppp, 6670fbf3537Syasuoka const char *username, char *password, int *plpassword) 6680fbf3537Syasuoka { 6690fbf3537Syasuoka char buf0[MAX_USERNAME_LENGTH]; 6700fbf3537Syasuoka 6710fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 6720fbf3537Syasuoka return npppd_auth_get_user_password(ppp->realm, 6730fbf3537Syasuoka npppd_auth_username_for_auth(ppp->realm, username, buf0), password, 6740fbf3537Syasuoka plpassword); 6750fbf3537Syasuoka } 6760fbf3537Syasuoka 677f0a4e295Syasuoka /** Get the Framed-IP-Address attribute of the user */ 6780fbf3537Syasuoka struct in_addr * 6790fbf3537Syasuoka npppd_get_user_framed_ip_address(npppd *_this, npppd_ppp *ppp, 6800fbf3537Syasuoka const char *username) 6810fbf3537Syasuoka { 6820fbf3537Syasuoka 6830fbf3537Syasuoka if (ppp->peer_auth == 0) { 6840fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = 0; 6850fbf3537Syasuoka goto do_default; 6860fbf3537Syasuoka } 6870fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 6880fbf3537Syasuoka 689821f7c56Syasuoka if (ppp->realm_framed_ip_address.s_addr != 0) 6900fbf3537Syasuoka return &ppp->realm_framed_ip_address; 6910fbf3537Syasuoka 692f0a4e295Syasuoka /* assign by the authentication realm */ 6930fbf3537Syasuoka if (npppd_auth_get_framed_ip(ppp->realm, username, 6940fbf3537Syasuoka &ppp->realm_framed_ip_address, 6950fbf3537Syasuoka &ppp->realm_framed_ip_netmask) != 0) 6960fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = 0; 6970fbf3537Syasuoka 6980fbf3537Syasuoka do_default: 699f0a4e295Syasuoka /* Use USER_SELECT if the realm doesn't specify the ip address */ 7000fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == 0) 7010fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_USER_SELECT; 702821f7c56Syasuoka 703821f7c56Syasuoka 7040fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) { 705f0a4e295Syasuoka /* Use NAS_SELECT if USER_SELECT is not allowed by the config */ 706821f7c56Syasuoka if (!ppp_ipcp(ppp)->allow_user_select) 7070fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_NAS_SELECT; 7080fbf3537Syasuoka } 7090fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() = %s", __func__, 7100fbf3537Syasuoka inet_ntoa(ppp->realm_framed_ip_address))); 7110fbf3537Syasuoka 7120fbf3537Syasuoka return &ppp->realm_framed_ip_address; 7130fbf3537Syasuoka } 7140fbf3537Syasuoka 7150fbf3537Syasuoka /** XXX */ 7160fbf3537Syasuoka int 7170fbf3537Syasuoka npppd_check_calling_number(npppd *_this, npppd_ppp *ppp) 7180fbf3537Syasuoka { 719821f7c56Syasuoka struct tunnconf *conf; 720821f7c56Syasuoka int lnumber, rval; 7210fbf3537Syasuoka char number[NPPPD_PHONE_NUMBER_LEN + 1]; 7220fbf3537Syasuoka 723821f7c56Syasuoka conf = ppp_get_tunnconf(ppp); 724821f7c56Syasuoka if (conf->callnum_check != 0) { 7250fbf3537Syasuoka lnumber = sizeof(number); 7260fbf3537Syasuoka if ((rval = npppd_auth_get_calling_number(ppp->realm, 727821f7c56Syasuoka ppp->username, number, &lnumber)) == 0) 7280fbf3537Syasuoka return 7290fbf3537Syasuoka (strcmp(number, ppp->calling_number) == 0)? 1 : 0; 730821f7c56Syasuoka if ((conf->callnum_check & NPPPD_CALLNUM_CHECK_STRICT) != 0) 7310fbf3537Syasuoka return 0; 7320fbf3537Syasuoka } 7330fbf3537Syasuoka 7340fbf3537Syasuoka return 1; 7350fbf3537Syasuoka } 7360fbf3537Syasuoka 7370fbf3537Syasuoka /** 738f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that is assigned the 739f0a4e295Syasuoka * specified ip address and returns it 740f0a4e295Syasuoka * @param ipaddr IP Address(Specify in network byte order) 7410fbf3537Syasuoka */ 7420fbf3537Syasuoka npppd_ppp * 7430fbf3537Syasuoka npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr) 7440fbf3537Syasuoka { 7450fbf3537Syasuoka struct sockaddr_npppd *snp; 7460fbf3537Syasuoka struct radish *rdp; 747f0a4e295Syasuoka struct sockaddr_in npppd_get_ppp_by_ip_sin4; 7480fbf3537Syasuoka 749f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_family = AF_INET; 750f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_len = sizeof(struct sockaddr_in); 7510fbf3537Syasuoka npppd_get_ppp_by_ip_sin4.sin_addr = ipaddr; 7520fbf3537Syasuoka if (_this->rd == NULL) 753f0a4e295Syasuoka return NULL; /* no radix tree on startup */ 7540fbf3537Syasuoka if (rd_match((struct sockaddr *)&npppd_get_ppp_by_ip_sin4, _this->rd, 7550fbf3537Syasuoka &rdp)) { 7560fbf3537Syasuoka snp = rdp->rd_rtent; 7570fbf3537Syasuoka if (snp->snp_type == SNP_PPP) 7580fbf3537Syasuoka return snp->snp_data_ptr; 7590fbf3537Syasuoka } 7600fbf3537Syasuoka return NULL; 7610fbf3537Syasuoka } 7620fbf3537Syasuoka 7630fbf3537Syasuoka /** 764f0a4e295Syasuoka * This function finds {@link npppd_ppp} instances that are authenticated 765f0a4e295Syasuoka * as the specified username and returns them as a {@link slist} list. 766f0a4e295Syasuoka * @param username PPP Username. 767f0a4e295Syasuoka * @return {@link slist} that contans the {@link npppd_ppp} instances. 768f0a4e295Syasuoka * NULL may be returned if no instance has been found. 7690fbf3537Syasuoka */ 77034682664Syasuoka static slist * 7710fbf3537Syasuoka npppd_get_ppp_by_user(npppd *_this, const char *username) 7720fbf3537Syasuoka { 7730fbf3537Syasuoka hash_link *hl; 7740fbf3537Syasuoka 7750fbf3537Syasuoka if ((hl = hash_lookup(_this->map_user_ppp, username)) != NULL) 7760fbf3537Syasuoka return hl->item; 7770fbf3537Syasuoka 7780fbf3537Syasuoka return NULL; 7790fbf3537Syasuoka } 7800fbf3537Syasuoka 7810fbf3537Syasuoka /** 782f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that matches the specified 783f0a4e295Syasuoka * ppp id and returns it. 784f0a4e295Syasuoka * @param id {@link npppd_ppp#id ppp's id} 785f0a4e295Syasuoka * @return This function returns the pointer if the instance which has 786f0a4e295Syasuoka * specified ID is found, otherwise it returns NULL. 7870fbf3537Syasuoka */ 7880fbf3537Syasuoka npppd_ppp * 789363e4d4bSyasuoka npppd_get_ppp_by_id(npppd *_this, u_int ppp_id) 7900fbf3537Syasuoka { 7910fbf3537Syasuoka slist users; 7920fbf3537Syasuoka npppd_ppp *ppp0, *ppp; 7930fbf3537Syasuoka 7940fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 7950fbf3537Syasuoka 7960fbf3537Syasuoka ppp = NULL; 7970fbf3537Syasuoka slist_init(&users); 7980fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 7990fbf3537Syasuoka log_printf(LOG_WARNING, 8000fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__); 8010fbf3537Syasuoka } else { 802f0a4e295Syasuoka /* FIXME: This linear search eats CPU. */ 8030fbf3537Syasuoka for (slist_itr_first(&users); slist_itr_has_next(&users); ) { 8040fbf3537Syasuoka ppp0 = slist_itr_next(&users); 8050fbf3537Syasuoka if (ppp0->id == ppp_id) { 8060fbf3537Syasuoka ppp = ppp0; 8070fbf3537Syasuoka break; 8080fbf3537Syasuoka } 8090fbf3537Syasuoka } 8100fbf3537Syasuoka } 8110fbf3537Syasuoka slist_fini(&users); 8120fbf3537Syasuoka 8130fbf3537Syasuoka return ppp; 8140fbf3537Syasuoka } 8150fbf3537Syasuoka 8162a5607d2Sgoda static struct ipcpstat * 8172a5607d2Sgoda npppd_get_ipcp_stat(struct ipcpstat_head *head , const char *ipcp_name) 8182a5607d2Sgoda { 8192a5607d2Sgoda struct ipcpstat *ipcpstat = NULL; 8202a5607d2Sgoda 8212a5607d2Sgoda LIST_FOREACH(ipcpstat, head, entry) { 8222a5607d2Sgoda if (strncmp(ipcpstat->name, ipcp_name, 8232a5607d2Sgoda sizeof(ipcpstat->name)) == 0) 8242a5607d2Sgoda return ipcpstat; 8252a5607d2Sgoda } 8262a5607d2Sgoda 8272a5607d2Sgoda return NULL; 8282a5607d2Sgoda } 8292a5607d2Sgoda 8302a5607d2Sgoda static void 8312a5607d2Sgoda npppd_destroy_ipcp_stats(struct ipcpstat_head *head) 8322a5607d2Sgoda { 8332a5607d2Sgoda struct ipcpstat *ipcpstat, *tipcpstat; 8342a5607d2Sgoda npppd_ppp *ppp, *tppp; 8352a5607d2Sgoda 8362a5607d2Sgoda LIST_FOREACH_SAFE(ipcpstat, head, entry, tipcpstat) { 8372a5607d2Sgoda LIST_FOREACH_SAFE(ppp, &ipcpstat->ppp, ipcpstat_entry, tppp) { 8382a5607d2Sgoda ppp->ipcpstat = NULL; 8392a5607d2Sgoda LIST_REMOVE(ppp, ipcpstat_entry); 8402a5607d2Sgoda } 8412a5607d2Sgoda free(ipcpstat); 8422a5607d2Sgoda } 8432a5607d2Sgoda } 8442a5607d2Sgoda 8452a5607d2Sgoda static void 8462a5607d2Sgoda npppd_ipcp_stats_reload(npppd *_this) 8472a5607d2Sgoda { 8482a5607d2Sgoda struct ipcpstat *ipcpstat, *tipcpstat; 8492a5607d2Sgoda struct ipcpconf *ipcpconf; 8502a5607d2Sgoda struct ipcpstat_head destroy_list; 8512a5607d2Sgoda 8522a5607d2Sgoda LIST_INIT(&destroy_list); 8532a5607d2Sgoda LIST_FOREACH_SAFE(ipcpstat, &_this->ipcpstats, entry, tipcpstat) { 8542a5607d2Sgoda LIST_REMOVE(ipcpstat, entry); 8552a5607d2Sgoda LIST_INSERT_HEAD(&destroy_list, ipcpstat, entry); 8562a5607d2Sgoda } 8572a5607d2Sgoda 8582a5607d2Sgoda TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry) { 8592a5607d2Sgoda ipcpstat = npppd_get_ipcp_stat(&destroy_list, ipcpconf->name); 8602a5607d2Sgoda if (ipcpstat != NULL) { 8612a5607d2Sgoda LIST_REMOVE(ipcpstat, entry); 8622a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry); 8632a5607d2Sgoda continue; 8642a5607d2Sgoda } 8652a5607d2Sgoda 8662a5607d2Sgoda ipcpstat = malloc(sizeof(*ipcpstat)); 8672a5607d2Sgoda if (ipcpstat == NULL) { 8682a5607d2Sgoda log_printf(LOG_ERR, "initializing ipcp_stats failed : %m"); 8692a5607d2Sgoda continue; 8702a5607d2Sgoda } 8712a5607d2Sgoda memset(ipcpstat, 0, sizeof(*ipcpstat)); 8722a5607d2Sgoda strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpconf->name)); 8732a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry); 8742a5607d2Sgoda } 8752a5607d2Sgoda npppd_destroy_ipcp_stats(&destroy_list); 8762a5607d2Sgoda } 8772a5607d2Sgoda 8780fbf3537Syasuoka /** 879f0a4e295Syasuoka * Checks whether the user reaches the maximum session limit 880f0a4e295Syasuoka * (user_max_serssion). 881f0a4e295Syasuoka * @return This function returns 1(true) if the user does not reach the 882f0a4e295Syasuoka * limit, otherwise it returns 0(false). 8830fbf3537Syasuoka */ 8840fbf3537Syasuoka int 8850fbf3537Syasuoka npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp) 8860fbf3537Syasuoka { 887d50b169aSgoda int global_count, realm_count; 8880fbf3537Syasuoka npppd_ppp *ppp1; 8890fbf3537Syasuoka slist *uppp; 8900fbf3537Syasuoka 891f0a4e295Syasuoka /* user_max_session == 0 means unlimit */ 892d50b169aSgoda if (_this->conf.user_max_session == 0 && 893d50b169aSgoda npppd_auth_user_session_unlimited(ppp->realm)) 8940fbf3537Syasuoka return 1; 8950fbf3537Syasuoka 896d50b169aSgoda global_count = realm_count = 0; 8970fbf3537Syasuoka if ((uppp = npppd_get_ppp_by_user(_this, ppp->username)) != NULL) { 8980fbf3537Syasuoka for (slist_itr_first(uppp); slist_itr_has_next(uppp); ) { 8990fbf3537Syasuoka ppp1 = slist_itr_next(uppp); 900d50b169aSgoda if (ppp->realm == ppp1->realm) 901d50b169aSgoda realm_count++; 902d50b169aSgoda global_count++; 9030fbf3537Syasuoka } 9040fbf3537Syasuoka } 9050fbf3537Syasuoka 906d50b169aSgoda if (npppd_check_auth_user_max_session(ppp->realm, realm_count)) { 907d50b169aSgoda ppp_log(ppp, LOG_WARNING, 908d50b169aSgoda "user %s exceeds user-max-session limit per auth", 909d50b169aSgoda ppp->username); 910d50b169aSgoda return 0; 911d50b169aSgoda } else if (_this->conf.user_max_session != 0 && 912d50b169aSgoda _this->conf.user_max_session <= global_count) { 913d50b169aSgoda ppp_log(ppp, LOG_WARNING, 914d50b169aSgoda "user %s exceeds user-max-session limit", ppp->username); 915d50b169aSgoda return 0; 916d50b169aSgoda } else 917d50b169aSgoda return 1; 9180fbf3537Syasuoka } 9190fbf3537Syasuoka 9200fbf3537Syasuoka /*********************************************************************** 921f0a4e295Syasuoka * Network I/O ralated functions. 9220fbf3537Syasuoka ***********************************************************************/ 9230fbf3537Syasuoka /** 924f0a4e295Syasuoka * Call this function to output packets to the network(tun). This function 925f0a4e295Syasuoka * currently assumes the packet is a IPv4 datagram. 9260fbf3537Syasuoka */ 9270fbf3537Syasuoka void 9280fbf3537Syasuoka npppd_network_output(npppd *_this, npppd_ppp *ppp, int proto, u_char *pktp, 9290fbf3537Syasuoka int lpktp) 9300fbf3537Syasuoka { 9310fbf3537Syasuoka struct ip *pip; 9320fbf3537Syasuoka int lbuf; 933f0a4e295Syasuoka u_char buf[256]; /* enough size for TCP/IP header */ 9340fbf3537Syasuoka 9350fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 9360fbf3537Syasuoka 9370fbf3537Syasuoka if (!ppp_ip_assigned(ppp)) 9380fbf3537Syasuoka return; 9390fbf3537Syasuoka 9400fbf3537Syasuoka if (lpktp < sizeof(struct ip)) { 9410fbf3537Syasuoka ppp_log(ppp, LOG_DEBUG, "Received IP packet is too small"); 9420fbf3537Syasuoka return; 9430fbf3537Syasuoka } 944dbad4650Sderaadt lbuf = MINIMUM(lpktp, sizeof(buf)); 9450fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip)) { 9460fbf3537Syasuoka memcpy(buf, pktp, lbuf); 9470fbf3537Syasuoka pip = (struct ip *)buf; 9480fbf3537Syasuoka } else { 9490fbf3537Syasuoka pip = (struct ip *)pktp; 9500fbf3537Syasuoka } 9510fbf3537Syasuoka 9523b5b2d97Syasuoka if (ppp->ingress_filter != 0 && 9533b5b2d97Syasuoka (pip->ip_src.s_addr & ppp->ppp_framed_ip_netmask.s_addr) 9543b5b2d97Syasuoka != (ppp->ppp_framed_ip_address.s_addr & 9550fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr)) { 9560fbf3537Syasuoka char logbuf[80]; 9570fbf3537Syasuoka strlcpy(logbuf, inet_ntoa(pip->ip_dst), sizeof(logbuf)); 9580fbf3537Syasuoka ppp_log(ppp, LOG_INFO, 9590fbf3537Syasuoka "Drop packet by ingress filter. %s => %s", 9600fbf3537Syasuoka inet_ntoa(pip->ip_src), logbuf); 9610fbf3537Syasuoka 9620fbf3537Syasuoka return; 9630fbf3537Syasuoka } 9640fbf3537Syasuoka if (ppp->timeout_sec > 0 && !ip_is_idle_packet(pip, lbuf)) 9650fbf3537Syasuoka ppp_reset_idle_timeout(ppp); 9660fbf3537Syasuoka 9670fbf3537Syasuoka #ifndef NO_ADJUST_MSS 9680fbf3537Syasuoka if (ppp->adjust_mss) { 9690fbf3537Syasuoka if (lpktp == lbuf) { 9700fbf3537Syasuoka /* 971f0a4e295Syasuoka * We can assume the packet length is less than 972f0a4e295Syasuoka * sizeof(buf). 9730fbf3537Syasuoka */ 9740fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip)) 9750fbf3537Syasuoka pktp = buf; 9760fbf3537Syasuoka adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru)); 9770fbf3537Syasuoka } 9780fbf3537Syasuoka } 9790fbf3537Syasuoka #endif 98041d69f6eSyasuoka npppd_iface_write(ppp_iface(ppp), ppp, proto, pktp, lpktp); 9810fbf3537Syasuoka } 9820fbf3537Syasuoka 9830fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 984f0a4e295Syasuoka /*********************************************************************** 985f0a4e295Syasuoka * PIPEX related functions 986f0a4e295Syasuoka ***********************************************************************/ 9870fbf3537Syasuoka static void 9880fbf3537Syasuoka pipex_setup_common(npppd_ppp *ppp, struct pipex_session_req *req) 9890fbf3537Syasuoka { 9900fbf3537Syasuoka memset(req, 0, sizeof(*req)); 9910fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, acfc)) 9920fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ENABLED; 9930fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, acfc)) 9940fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ACCEPTED; 9950fbf3537Syasuoka 9960fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, pfc)) 9970fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ACCEPTED; 9980fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, pfc)) 9990fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ENABLED; 10000fbf3537Syasuoka 10010fbf3537Syasuoka if (ppp->has_acf != 0) 10020fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_HAS_ACF; 10030fbf3537Syasuoka 10040fbf3537Syasuoka if (ppp->adjust_mss != 0) 10050fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ADJUST_TCPMSS; 10063b5b2d97Syasuoka if (ppp->ingress_filter != 0) 10073b5b2d97Syasuoka req->pr_ppp_flags |= PIPEX_PPP_INGRESS_FILTER; 10080fbf3537Syasuoka 1009cd8e09b9Sdlg req->pr_ip_srcaddr = ppp->pppd->iface[0].ip4addr; 10100fbf3537Syasuoka req->pr_ip_address = ppp->ppp_framed_ip_address; 10110fbf3537Syasuoka req->pr_ip_netmask = ppp->ppp_framed_ip_netmask; 10120fbf3537Syasuoka req->pr_peer_mru = ppp->peer_mru; 10130fbf3537Syasuoka req->pr_ppp_id = ppp->id; 10140fbf3537Syasuoka 10150fbf3537Syasuoka req->pr_timeout_sec = ppp->timeout_sec; 10160fbf3537Syasuoka 10170fbf3537Syasuoka #ifdef USE_NPPPD_MPPE 10180fbf3537Syasuoka req->pr_ccp_id = ppp->ccp.fsm.id; 1019de0a2dd6Syasuoka if (ppp->mppe.send.keybits > 0) { 10200fbf3537Syasuoka memcpy(req->pr_mppe_send.master_key, 1021de0a2dd6Syasuoka ppp->mppe.send.master_key, 1022de0a2dd6Syasuoka sizeof(req->pr_mppe_send.master_key)); 10230fbf3537Syasuoka req->pr_mppe_send.stateless = ppp->mppe.send.stateless; 10240fbf3537Syasuoka req->pr_mppe_send.keylenbits = ppp->mppe.send.keybits; 1025de0a2dd6Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ENABLED; 1026de0a2dd6Syasuoka } 1027de0a2dd6Syasuoka if (ppp->mppe.recv.keybits > 0) { 10280fbf3537Syasuoka memcpy(req->pr_mppe_recv.master_key, 1029de0a2dd6Syasuoka ppp->mppe.recv.master_key, 1030de0a2dd6Syasuoka sizeof(req->pr_mppe_recv.master_key)); 10310fbf3537Syasuoka req->pr_mppe_recv.stateless = ppp->mppe.recv.stateless; 10320fbf3537Syasuoka req->pr_mppe_recv.keylenbits = ppp->mppe.recv.keybits; 10330fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED; 10340fbf3537Syasuoka } 10350fbf3537Syasuoka if (ppp->mppe.required) 10360fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_REQUIRED; 10370fbf3537Syasuoka #endif /* USE_NPPPD_MPPE */ 10380fbf3537Syasuoka } 10390fbf3537Syasuoka 1040f0a4e295Syasuoka /** Enable PIPEX of the {@link npppd_ppp ppp} */ 10410fbf3537Syasuoka int 10420fbf3537Syasuoka npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) 10430fbf3537Syasuoka { 10440fbf3537Syasuoka struct pipex_session_req req; 10450fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 10460fbf3537Syasuoka pppoe_session *pppoe; 10470fbf3537Syasuoka #endif 10480fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 10490fbf3537Syasuoka pptp_call *call; 10500fbf3537Syasuoka #endif 1051886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1052886d2b78Syasuoka l2tp_call *l2tp; 1053886d2b78Syasuoka l2tp_ctrl *l2tpctrl; 1054886d2b78Syasuoka #endif 10550fbf3537Syasuoka int error; 10560fbf3537Syasuoka 10570fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 10580fbf3537Syasuoka NPPPD_ASSERT(ppp->phy_context != NULL); 10590fbf3537Syasuoka NPPPD_ASSERT(ppp->use_pipex != 0); 10600fbf3537Syasuoka 10610fbf3537Syasuoka pipex_setup_common(ppp, &req); 10620fbf3537Syasuoka 10630fbf3537Syasuoka switch (ppp->tunnel_type) { 10640fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 1065821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE: 1066886d2b78Syasuoka { 1067886d2b78Syasuoka struct sockaddr *sa; 1068886d2b78Syasuoka struct ether_header *eh; 10690fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 10700fbf3537Syasuoka 1071f0a4e295Syasuoka /* PPPoE specific informations */ 10720fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPPOE; 10730fbf3537Syasuoka req.pr_session_id = pppoe->session_id; 10740fbf3537Syasuoka req.pr_peer_session_id = 0; 10750fbf3537Syasuoka strlcpy(req.pr_proto.pppoe.over_ifname, 10760fbf3537Syasuoka pppoe_session_listen_ifname(pppoe), 10770fbf3537Syasuoka sizeof(req.pr_proto.pppoe.over_ifname)); 1078886d2b78Syasuoka 1079bdfe8fd0Syasuoka sa = (struct sockaddr *)&req.pr_peer_address; 1080886d2b78Syasuoka sa->sa_family = AF_UNSPEC; 1081886d2b78Syasuoka sa->sa_len = sizeof(struct sockaddr); 1082886d2b78Syasuoka 1083886d2b78Syasuoka eh = (struct ether_header *)sa->sa_data; 1084886d2b78Syasuoka eh->ether_type = htons(ETHERTYPE_PPPOE); 1085886d2b78Syasuoka memcpy(eh->ether_dhost, pppoe->ether_addr, ETHER_ADDR_LEN); 1086886d2b78Syasuoka memset(eh->ether_shost, 0, ETHER_ADDR_LEN); 10870fbf3537Syasuoka 10880fbf3537Syasuoka break; 1089886d2b78Syasuoka } 10900fbf3537Syasuoka #endif 10910fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 1092821f7c56Syasuoka case NPPPD_TUNNEL_PPTP: 10930fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 10940fbf3537Syasuoka 1095f0a4e295Syasuoka /* PPTP specific informations */ 10960fbf3537Syasuoka req.pr_session_id = call->id; 10970fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPTP; 10980fbf3537Syasuoka 10990fbf3537Syasuoka req.pr_peer_session_id = call->peers_call_id; 11000fbf3537Syasuoka req.pr_proto.pptp.snd_nxt = call->snd_nxt; 11010fbf3537Syasuoka req.pr_proto.pptp.snd_una = call->snd_una; 11020fbf3537Syasuoka req.pr_proto.pptp.rcv_nxt = call->rcv_nxt; 11030fbf3537Syasuoka req.pr_proto.pptp.rcv_acked = call->rcv_acked; 11040fbf3537Syasuoka req.pr_proto.pptp.winsz = call->winsz; 11050fbf3537Syasuoka req.pr_proto.pptp.maxwinsz = call->maxwinsz; 11060fbf3537Syasuoka req.pr_proto.pptp.peer_maxwinsz = call->peers_maxwinsz; 11070fbf3537Syasuoka 11080fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->peer.ss_family == AF_INET); 11090fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->our.ss_family == AF_INET); 1110886d2b78Syasuoka 1111bdfe8fd0Syasuoka memcpy(&req.pr_peer_address, &call->ctrl->peer, 1112886d2b78Syasuoka call->ctrl->peer.ss_len); 1113bdfe8fd0Syasuoka memcpy(&req.pr_local_address, &call->ctrl->our, 1114886d2b78Syasuoka call->ctrl->our.ss_len); 1115886d2b78Syasuoka break; 1116886d2b78Syasuoka #endif 1117886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1118821f7c56Syasuoka case NPPPD_TUNNEL_L2TP: 1119886d2b78Syasuoka l2tp = (l2tp_call *)ppp->phy_context; 1120886d2b78Syasuoka l2tpctrl = l2tp->ctrl; 1121886d2b78Syasuoka 1122886d2b78Syasuoka /* L2TPv2 specific context */ 1123886d2b78Syasuoka /* Session KEYS */ 1124886d2b78Syasuoka req.pr_protocol = PIPEX_PROTO_L2TP; 1125886d2b78Syasuoka req.pr_proto.l2tp.tunnel_id = l2tpctrl->tunnel_id; 1126886d2b78Syasuoka req.pr_proto.l2tp.peer_tunnel_id = l2tpctrl->peer_tunnel_id; 1127886d2b78Syasuoka req.pr_session_id = l2tp->session_id; 1128886d2b78Syasuoka req.pr_peer_session_id = l2tp->peer_session_id; 1129886d2b78Syasuoka 1130886d2b78Syasuoka if (l2tpctrl->data_use_seq) 1131886d2b78Syasuoka req.pr_proto.l2tp.option_flags |= 1132886d2b78Syasuoka PIPEX_L2TP_USE_SEQUENCING; 1133886d2b78Syasuoka 1134886d2b78Syasuoka /* transmission control contexts */ 1135886d2b78Syasuoka req.pr_proto.l2tp.ns_nxt = l2tp->snd_nxt; 1136886d2b78Syasuoka req.pr_proto.l2tp.nr_nxt = l2tp->rcv_nxt; 1137886d2b78Syasuoka 1138bdfe8fd0Syasuoka memcpy(&req.pr_peer_address, &l2tpctrl->peer, 1139886d2b78Syasuoka l2tpctrl->peer.ss_len); 1140bdfe8fd0Syasuoka memcpy(&req.pr_local_address, &l2tpctrl->sock, 1141886d2b78Syasuoka l2tpctrl->sock.ss_len); 1142a5018c90Syasuoka #ifdef USE_SA_COOKIE 1143a5018c90Syasuoka if (l2tpctrl->sa_cookie != NULL) { 1144a5018c90Syasuoka req.pr_proto.l2tp.ipsecflowinfo = 1145a5018c90Syasuoka ((struct in_ipsec_sa_cookie *)l2tpctrl->sa_cookie) 1146a5018c90Syasuoka ->ipsecflow; 1147a5018c90Syasuoka } 1148886d2b78Syasuoka #endif 11490fbf3537Syasuoka break; 11500fbf3537Syasuoka #endif 11510fbf3537Syasuoka default: 11520fbf3537Syasuoka return 1; 11530fbf3537Syasuoka } 11540fbf3537Syasuoka 11550fbf3537Syasuoka if ((error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXASESSION, &req)) 11560fbf3537Syasuoka != 0) { 11570fbf3537Syasuoka if (errno == ENXIO) /* pipex is disabled on runtime */ 11580fbf3537Syasuoka error = 0; 11590fbf3537Syasuoka ppp->pipex_enabled = 0; 11600fbf3537Syasuoka return error; 11610fbf3537Syasuoka } 11620fbf3537Syasuoka 1163cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx) { 1164cd8e09b9Sdlg struct pipex_session_descr_req descr_req; 1165cd8e09b9Sdlg 1166cd8e09b9Sdlg descr_req.pdr_protocol = req.pr_protocol; 1167cd8e09b9Sdlg descr_req.pdr_session_id = req.pr_session_id; 1168cd8e09b9Sdlg memset(descr_req.pdr_descr, 0, sizeof(descr_req.pdr_descr)); 1169cd8e09b9Sdlg strlcpy(descr_req.pdr_descr, ppp->username, sizeof(descr_req.pdr_descr)); 1170cd8e09b9Sdlg error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXSIFDESCR, &descr_req); 1171cd8e09b9Sdlg if (error != 0) { 1172cd8e09b9Sdlg log_printf(LOG_WARNING, "PIPEXSIFDESCR(%s) failed: %d\n", ppp->username, error); 1173cd8e09b9Sdlg } 1174cd8e09b9Sdlg } 1175cd8e09b9Sdlg 11760fbf3537Syasuoka ppp->pipex_enabled = 1; 11770fbf3537Syasuoka if (ppp->timeout_sec > 0) { 1178f0a4e295Syasuoka /* Stop the npppd's idle-timer. We use pipex's idle-timer */ 11790fbf3537Syasuoka ppp->timeout_sec = 0; 11800fbf3537Syasuoka ppp_reset_idle_timeout(ppp); 11810fbf3537Syasuoka } 11820fbf3537Syasuoka 11830fbf3537Syasuoka return error; 11840fbf3537Syasuoka } 11850fbf3537Syasuoka 1186f0a4e295Syasuoka /** Disable PIPEX of the {@link npppd_ppp ppp} */ 11870fbf3537Syasuoka int 11880fbf3537Syasuoka npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) 11890fbf3537Syasuoka { 11900fbf3537Syasuoka struct pipex_session_close_req req; 11910fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 11920fbf3537Syasuoka pppoe_session *pppoe; 11930fbf3537Syasuoka #endif 11940fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 11950fbf3537Syasuoka pptp_call *call; 11960fbf3537Syasuoka #endif 1197886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1198886d2b78Syasuoka l2tp_call *l2tp; 1199886d2b78Syasuoka #endif 12000fbf3537Syasuoka int error; 12010fbf3537Syasuoka 12020fbf3537Syasuoka if (ppp->pipex_started == 0) 12030fbf3537Syasuoka return 0; /* not started */ 12040fbf3537Syasuoka 12050fbf3537Syasuoka bzero(&req, sizeof(req)); 12060fbf3537Syasuoka switch(ppp->tunnel_type) { 12070fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 1208821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE: 12090fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 12100fbf3537Syasuoka 1211f0a4e295Syasuoka /* PPPoE specific informations */ 12120fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPPOE; 12130fbf3537Syasuoka req.pcr_session_id = pppoe->session_id; 12140fbf3537Syasuoka break; 12150fbf3537Syasuoka #endif 12160fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 1217821f7c56Syasuoka case NPPPD_TUNNEL_PPTP: 12180fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 12190fbf3537Syasuoka 1220f0a4e295Syasuoka /* PPTP specific informations */ 12210fbf3537Syasuoka req.pcr_session_id = call->id; 12220fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPTP; 12230fbf3537Syasuoka break; 12240fbf3537Syasuoka #endif 1225fd218b06Smarkus #ifdef USE_NPPPD_L2TP 1226821f7c56Syasuoka case NPPPD_TUNNEL_L2TP: 1227fd218b06Smarkus l2tp = (l2tp_call *)ppp->phy_context; 1228fd218b06Smarkus 1229fd218b06Smarkus /* L2TP specific context */ 1230fd218b06Smarkus req.pcr_session_id = l2tp->session_id; 1231fd218b06Smarkus req.pcr_protocol = PIPEX_PROTO_L2TP; 1232fd218b06Smarkus break; 1233fd218b06Smarkus #endif 12340fbf3537Syasuoka default: 12350fbf3537Syasuoka return 1; 12360fbf3537Syasuoka } 12370fbf3537Syasuoka 12380fbf3537Syasuoka error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXDSESSION, &req); 12390fbf3537Syasuoka if (error == 0) { 12400fbf3537Syasuoka ppp->ipackets += req.pcr_stat.ipackets; 12410fbf3537Syasuoka ppp->opackets += req.pcr_stat.opackets; 12420fbf3537Syasuoka ppp->ierrors += req.pcr_stat.ierrors; 12430fbf3537Syasuoka ppp->oerrors += req.pcr_stat.oerrors; 12440fbf3537Syasuoka ppp->ibytes += req.pcr_stat.ibytes; 12450fbf3537Syasuoka ppp->obytes += req.pcr_stat.obytes; 12460fbf3537Syasuoka ppp->pipex_enabled = 0; 12470fbf3537Syasuoka } 12480fbf3537Syasuoka 12490fbf3537Syasuoka return error; 12500fbf3537Syasuoka } 12510fbf3537Syasuoka 1252f0a4e295Syasuoka /* XXX: s/npppd_ppp_pipex_ip_disable/npppd_ppp_pipex_stop/ ?? */ 1253f0a4e295Syasuoka 1254f0a4e295Syasuoka /** Stop PIPEX of the {@link npppd_ppp ppp} */ 12550fbf3537Syasuoka static int 12560fbf3537Syasuoka npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) 12570fbf3537Syasuoka { 12580fbf3537Syasuoka struct pipex_session_config_req req; 12590fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 12600fbf3537Syasuoka pppoe_session *pppoe; 12610fbf3537Syasuoka #endif 12620fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 12630fbf3537Syasuoka pptp_call *call; 12640fbf3537Syasuoka #endif 1265886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1266886d2b78Syasuoka l2tp_call *l2tp; 1267886d2b78Syasuoka #endif 12680fbf3537Syasuoka if (ppp->pipex_started == 0) 12690fbf3537Syasuoka return 0; /* not started */ 12700fbf3537Syasuoka 12710fbf3537Syasuoka bzero(&req, sizeof(req)); 12720fbf3537Syasuoka switch(ppp->tunnel_type) { 12730fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 1274821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE: 12750fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 12760fbf3537Syasuoka 1277f0a4e295Syasuoka /* PPPoE specific informations */ 12780fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPPOE; 12790fbf3537Syasuoka req.pcr_session_id = pppoe->session_id; 12800fbf3537Syasuoka break; 12810fbf3537Syasuoka #endif 12820fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 1283821f7c56Syasuoka case NPPPD_TUNNEL_PPTP: 12840fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 12850fbf3537Syasuoka 1286f0a4e295Syasuoka /* PPTP specific informations */ 12870fbf3537Syasuoka req.pcr_session_id = call->id; 12880fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPTP; 12890fbf3537Syasuoka break; 12900fbf3537Syasuoka #endif 1291886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1292821f7c56Syasuoka case NPPPD_TUNNEL_L2TP: 1293886d2b78Syasuoka l2tp = (l2tp_call *)ppp->phy_context; 1294886d2b78Syasuoka 1295886d2b78Syasuoka /* L2TP specific context */ 1296886d2b78Syasuoka req.pcr_session_id = l2tp->session_id; 1297886d2b78Syasuoka req.pcr_protocol = PIPEX_PROTO_L2TP; 1298886d2b78Syasuoka break; 1299886d2b78Syasuoka #endif 13000fbf3537Syasuoka default: 13010fbf3537Syasuoka return 1; 13020fbf3537Syasuoka } 13030fbf3537Syasuoka req.pcr_ip_forward = 0; 13040fbf3537Syasuoka 13050fbf3537Syasuoka return ioctl(_this->iface[ppp->ifidx].devf, PIPEXCSESSION, &req); 13060fbf3537Syasuoka } 13070fbf3537Syasuoka 13080fbf3537Syasuoka static void 13090fbf3537Syasuoka pipex_periodic(npppd *_this) 13100fbf3537Syasuoka { 13110fbf3537Syasuoka struct pipex_session_list_req req; 13120fbf3537Syasuoka npppd_ppp *ppp; 1313ec8bab80Syasuoka int i, devf, error; 1314363e4d4bSyasuoka u_int ppp_id; 13150fbf3537Syasuoka slist dlist, users; 13160fbf3537Syasuoka 13170fbf3537Syasuoka slist_init(&dlist); 13180fbf3537Syasuoka slist_init(&users); 1319ec8bab80Syasuoka 1320ec8bab80Syasuoka devf = -1; 1321ec8bab80Syasuoka for (i = 0; i < nitems(_this->iface); i++) { 1322ec8bab80Syasuoka if (_this->iface[i].initialized != 0) { 1323ec8bab80Syasuoka devf = _this->iface[i].devf; 1324ec8bab80Syasuoka break; 1325ec8bab80Syasuoka } 1326ec8bab80Syasuoka } 1327ec8bab80Syasuoka if (devf >= 0) { 13280fbf3537Syasuoka do { 1329ec8bab80Syasuoka error = ioctl(devf, PIPEXGCLOSED, &req); 13300fbf3537Syasuoka if (error) { 13310fbf3537Syasuoka if (errno != ENXIO) 13320fbf3537Syasuoka log_printf(LOG_WARNING, 13330fbf3537Syasuoka "PIPEXGCLOSED failed: %m"); 13340fbf3537Syasuoka break; 13350fbf3537Syasuoka } 13360fbf3537Syasuoka for (i = 0; i < req.plr_ppp_id_count; i++) { 13370fbf3537Syasuoka ppp_id = req.plr_ppp_id[i]; 1338c46ae403Syasuoka slist_add(&dlist, (void *)(uintptr_t)ppp_id); 13390fbf3537Syasuoka } 13400fbf3537Syasuoka } while (req.plr_flags & PIPEX_LISTREQ_MORE); 1341ec8bab80Syasuoka } 13420fbf3537Syasuoka 13430fbf3537Syasuoka if (slist_length(&dlist) <= 0) 13440fbf3537Syasuoka goto pipex_done; 13450fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 13460fbf3537Syasuoka log_printf(LOG_WARNING, 13470fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__); 13480fbf3537Syasuoka slist_fini(&users); 13490fbf3537Syasuoka goto pipex_done; 13500fbf3537Syasuoka } 13510fbf3537Syasuoka 1352f0a4e295Syasuoka /* Disconnect request */ 13530fbf3537Syasuoka slist_itr_first(&dlist); 13540fbf3537Syasuoka while (slist_itr_has_next(&dlist)) { 1355f0a4e295Syasuoka /* FIXME: Linear search by PPP Id eats CPU */ 1356c46ae403Syasuoka ppp_id = (uintptr_t)slist_itr_next(&dlist); 13570fbf3537Syasuoka slist_itr_first(&users); 13580fbf3537Syasuoka ppp = NULL; 13590fbf3537Syasuoka while (slist_itr_has_next(&users)) { 13600fbf3537Syasuoka ppp = slist_itr_next(&users); 13610fbf3537Syasuoka if (ppp_id == ppp->id) { 13620fbf3537Syasuoka /* found */ 13630fbf3537Syasuoka slist_itr_remove(&users); 13640fbf3537Syasuoka break; 13650fbf3537Syasuoka } 13660fbf3537Syasuoka ppp = NULL; 13670fbf3537Syasuoka } 13680fbf3537Syasuoka if (ppp == NULL) { 13690fbf3537Syasuoka log_printf(LOG_WARNING, 13700fbf3537Syasuoka "kernel requested a ppp down, but it's not found. " 13710fbf3537Syasuoka "ppp=%d", ppp_id); 13720fbf3537Syasuoka continue; 13730fbf3537Syasuoka } 13740fbf3537Syasuoka ppp_log(ppp, LOG_INFO, "Stop requested by the kernel"); 13758daf7599Syasuoka /* TODO: PIPEX doesn't return the disconect reason */ 13768daf7599Syasuoka #ifdef USE_NPPPD_RADIUS 13778daf7599Syasuoka ppp_set_radius_terminate_cause(ppp, 13788daf7599Syasuoka RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT); 13798daf7599Syasuoka #endif 13800fbf3537Syasuoka ppp_stop(ppp, NULL); 13810fbf3537Syasuoka } 13820fbf3537Syasuoka pipex_done: 13830fbf3537Syasuoka slist_fini(&users); 13840fbf3537Syasuoka slist_fini(&dlist); 13850fbf3537Syasuoka } 13860fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 13870fbf3537Syasuoka 13880fbf3537Syasuoka /*********************************************************************** 1389f0a4e295Syasuoka * IP address assignment related functions 13900fbf3537Syasuoka ***********************************************************************/ 1391f0a4e295Syasuoka /** Prepare to use IP */ 13920fbf3537Syasuoka int 13930fbf3537Syasuoka npppd_prepare_ip(npppd *_this, npppd_ppp *ppp) 13940fbf3537Syasuoka { 1395821f7c56Syasuoka 13960fbf3537Syasuoka if (ppp_ipcp(ppp) == NULL) 13970fbf3537Syasuoka return 1; 13980fbf3537Syasuoka 13990fbf3537Syasuoka npppd_get_user_framed_ip_address(_this, ppp, ppp->username); 14000fbf3537Syasuoka 14010fbf3537Syasuoka if (npppd_iface_ip_is_ready(ppp_iface(ppp))) 14020fbf3537Syasuoka ppp->ipcp.ip4_our = ppp_iface(ppp)->ip4addr; 14030fbf3537Syasuoka else if (npppd_iface_ip_is_ready(&_this->iface[0])) 14040fbf3537Syasuoka ppp->ipcp.ip4_our = _this->iface[0].ip4addr; 14050fbf3537Syasuoka else 14060fbf3537Syasuoka return -1; 1407821f7c56Syasuoka ppp->ipcp.dns_pri = ppp_ipcp(ppp)->dns_servers[0]; 1408821f7c56Syasuoka ppp->ipcp.dns_sec = ppp_ipcp(ppp)->dns_servers[1]; 1409821f7c56Syasuoka ppp->ipcp.nbns_pri = ppp_ipcp(ppp)->nbns_servers[0]; 1410821f7c56Syasuoka ppp->ipcp.nbns_sec = ppp_ipcp(ppp)->nbns_servers[1]; 14110fbf3537Syasuoka 14120fbf3537Syasuoka return 0; 14130fbf3537Syasuoka } 14140fbf3537Syasuoka 1415f0a4e295Syasuoka /** Notify stop using IP to npppd and release the resources. */ 14160fbf3537Syasuoka void 14170fbf3537Syasuoka npppd_release_ip(npppd *_this, npppd_ppp *ppp) 14180fbf3537Syasuoka { 14190fbf3537Syasuoka 14200fbf3537Syasuoka if (!ppp_ip_assigned(ppp)) 14210fbf3537Syasuoka return; 14220fbf3537Syasuoka 14230fbf3537Syasuoka npppd_set_ip_enabled(_this, ppp, 0); 14240fbf3537Syasuoka npppd_pool_release_ip(ppp->assigned_pool, ppp); 14250fbf3537Syasuoka ppp->assigned_pool = NULL; 14260fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = 0; 14270fbf3537Syasuoka } 14280fbf3537Syasuoka 1429f0a4e295Syasuoka /** 1430f0a4e295Syasuoka * Change IP enableness. When the enableness is change, npppd will operate 1431f0a4e295Syasuoka * the route entry. 1432f0a4e295Syasuoka */ 14330fbf3537Syasuoka void 14340fbf3537Syasuoka npppd_set_ip_enabled(npppd *_this, npppd_ppp *ppp, int enabled) 14350fbf3537Syasuoka { 14360fbf3537Syasuoka int was_enabled, found; 14370fbf3537Syasuoka slist *u; 14380fbf3537Syasuoka hash_link *hl; 14390fbf3537Syasuoka npppd_ppp *ppp1; 14400fbf3537Syasuoka 14410fbf3537Syasuoka NPPPD_ASSERT(ppp_ip_assigned(ppp)); 14420fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 14430fbf3537Syasuoka "npppd_set_ip_enabled(%s/%s, %s)", ppp->username, 14440fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address), 14450fbf3537Syasuoka (enabled)?"true" : "false")); 1446f0a4e295Syasuoka 14470fbf3537Syasuoka /* 1448f0a4e295Syasuoka * Don't do anything if the enableness is not change. Changing route 1449f0a4e295Syasuoka * makes many programs will wake up and do heavy operations, it causes 1450f0a4e295Syasuoka * system overload, so we refrain useless changing route. 14510fbf3537Syasuoka */ 14520fbf3537Syasuoka enabled = (enabled)? 1 : 0; 14530fbf3537Syasuoka was_enabled = (ppp->assigned_ip4_enabled != 0)? 1 : 0; 14540fbf3537Syasuoka if (enabled == was_enabled) 14550fbf3537Syasuoka return; 1456f0a4e295Syasuoka 14570fbf3537Syasuoka ppp->assigned_ip4_enabled = enabled; 14580fbf3537Syasuoka if (enabled) { 14590fbf3537Syasuoka if (ppp->username[0] != '\0') { 14600fbf3537Syasuoka if ((u = npppd_get_ppp_by_user(_this, ppp->username)) 14610fbf3537Syasuoka == NULL) { 14620fbf3537Syasuoka if ((u = malloc(sizeof(slist))) == NULL) { 14630fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 14640fbf3537Syasuoka "Out of memory on %s: %m", 14650fbf3537Syasuoka __func__); 14660fbf3537Syasuoka } else { 14670fbf3537Syasuoka slist_init(u); 14680fbf3537Syasuoka slist_set_size(u, 4); 14690fbf3537Syasuoka hash_insert(_this->map_user_ppp, 14700fbf3537Syasuoka ppp->username, u); 14710fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 14720fbf3537Syasuoka "hash_insert(user->ppp, %s)", 14730fbf3537Syasuoka ppp->username)); 14740fbf3537Syasuoka } 14750fbf3537Syasuoka } 1476f0a4e295Syasuoka if (u != NULL) /* above malloc() may failed */ 14770fbf3537Syasuoka slist_add(u, ppp); 14780fbf3537Syasuoka } 14790fbf3537Syasuoka 14800fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1481cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) { 14820fbf3537Syasuoka if (ppp->snp.snp_next != NULL) 1483f0a4e295Syasuoka /* 1484f0a4e295Syasuoka * There is a blackhole route that has same 1485f0a4e295Syasuoka * address/mask. 1486f0a4e295Syasuoka */ 14870fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address, 1488cd8e09b9Sdlg &ppp->ppp_framed_ip_netmask, &loop, 1489cd8e09b9Sdlg RTF_BLACKHOLE); 14900fbf3537Syasuoka /* See the comment for MRU_IPMTU() on ppp.h */ 14910fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) { 14920fbf3537Syasuoka in_host_route_add(&ppp->ppp_framed_ip_address, 1493cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr, 1494cd8e09b9Sdlg ppp_iface(ppp)->ifname, 14950fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 14960fbf3537Syasuoka } else { 14970fbf3537Syasuoka in_route_add(&ppp->ppp_framed_ip_address, 14980fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 1499cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr, 1500cd8e09b9Sdlg ppp_iface(ppp)->ifname, 0, 15010fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 15020fbf3537Syasuoka } 1503cd8e09b9Sdlg } 15040fbf3537Syasuoka #endif 15050fbf3537Syasuoka } else { 15060fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1507cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) { 15080fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) { 15090fbf3537Syasuoka in_host_route_delete(&ppp->ppp_framed_ip_address, 15100fbf3537Syasuoka &ppp_iface(ppp)->ip4addr); 15110fbf3537Syasuoka } else { 15120fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address, 15130fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 15140fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 0); 15150fbf3537Syasuoka } 15160fbf3537Syasuoka if (ppp->snp.snp_next != NULL) 1517f0a4e295Syasuoka /* 1518f0a4e295Syasuoka * There is a blackhole route that has same 1519f0a4e295Syasuoka * address/mask. 1520f0a4e295Syasuoka */ 1521cd8e09b9Sdlg in_route_add(&ppp->snp.snp_addr, 1522cd8e09b9Sdlg &ppp->snp.snp_mask, &loop, LOOPBACK_IFNAME, 1523cd8e09b9Sdlg RTF_BLACKHOLE, 0); 1524cd8e09b9Sdlg } 15250fbf3537Syasuoka #endif 15260fbf3537Syasuoka if (ppp->username[0] != '\0') { 15270fbf3537Syasuoka hl = hash_lookup(_this->map_user_ppp, ppp->username); 15280fbf3537Syasuoka NPPPD_ASSERT(hl != NULL); 15290fbf3537Syasuoka if (hl == NULL) { 15300fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 15310fbf3537Syasuoka "Unexpected error: cannot find user(%s) " 15320fbf3537Syasuoka "from user database", ppp->username); 15330fbf3537Syasuoka return; 15340fbf3537Syasuoka } 15350fbf3537Syasuoka found = 0; 15360fbf3537Syasuoka u = hl->item; 15370fbf3537Syasuoka for (slist_itr_first(u); slist_itr_has_next(u);) { 15380fbf3537Syasuoka ppp1 = slist_itr_next(u); 15390fbf3537Syasuoka if (ppp1 == ppp) { 15400fbf3537Syasuoka slist_itr_remove(u); 15410fbf3537Syasuoka found++; 15420fbf3537Syasuoka break; 15430fbf3537Syasuoka } 15440fbf3537Syasuoka } 15450fbf3537Syasuoka if (found == 0) { 15460fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 15470fbf3537Syasuoka "Unexpected error: PPP instance is " 15480fbf3537Syasuoka "not found in the user's list."); 15490fbf3537Syasuoka } 15500fbf3537Syasuoka NPPPD_ASSERT(found != 0); 15510fbf3537Syasuoka if (slist_length(u) <= 0) { 1552f0a4e295Syasuoka /* The last PPP */ 15530fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 15540fbf3537Syasuoka "hash_delete(user->ppp, %s)", 15550fbf3537Syasuoka ppp->username)); 15560fbf3537Syasuoka if (hash_delete(_this->map_user_ppp, 15570fbf3537Syasuoka ppp->username, 0) != 0) { 15580fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 15590fbf3537Syasuoka "Unexpected error: cannot delete " 15600fbf3537Syasuoka "user(%s) from user database", 15610fbf3537Syasuoka ppp->username); 15620fbf3537Syasuoka } 15630fbf3537Syasuoka slist_fini(u); 15640fbf3537Syasuoka free(u); 15650fbf3537Syasuoka } else { 1566f0a4e295Syasuoka /* Replace the reference. */ 15670fbf3537Syasuoka ppp1 = slist_get(u, 0); 15680fbf3537Syasuoka hl->key = ppp1->username; 15690fbf3537Syasuoka } 15700fbf3537Syasuoka } 15710fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 15720fbf3537Syasuoka if (npppd_ppp_pipex_ip_disable(_this, ppp) != 0) 15730fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 15740fbf3537Syasuoka "npppd_ppp_pipex_ip_disable() failed: %m"); 15750fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 15760fbf3537Syasuoka } 15770fbf3537Syasuoka } 15780fbf3537Syasuoka 15790fbf3537Syasuoka /** 1580f0a4e295Syasuoka * Assign the IP address. Returning "struct in_addr" is stored IP address 1581f0a4e295Syasuoka * in network byte order. 1582f0a4e295Syasuoka * @param req_ip4 IP address request to assign. If the address is used 1583f0a4e295Syasuoka * already, this function will return fail. 15840fbf3537Syasuoka */ 15850fbf3537Syasuoka int 15860fbf3537Syasuoka npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) 15870fbf3537Syasuoka { 15880fbf3537Syasuoka uint32_t ip4, ip4mask; 1589821f7c56Syasuoka int dyna, rval, fallback_dyna; 15900fbf3537Syasuoka const char *reason = "out of the pool"; 15910fbf3537Syasuoka struct sockaddr_npppd *snp; 15920fbf3537Syasuoka npppd_pool *pool; 15930fbf3537Syasuoka npppd_auth_base *realm; 15940fbf3537Syasuoka 15950fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() assigned=%s", __func__, 15960fbf3537Syasuoka (ppp_ip_assigned(ppp))? "true" : "false")); 15970fbf3537Syasuoka if (ppp_ip_assigned(ppp)) 15980fbf3537Syasuoka return 0; 15990fbf3537Syasuoka 16000fbf3537Syasuoka ip4 = INADDR_ANY; 16010fbf3537Syasuoka ip4mask = 0xffffffffL; 16020fbf3537Syasuoka realm = ppp->realm; 16030fbf3537Syasuoka dyna = 0; 16040fbf3537Syasuoka fallback_dyna = 0; 16050fbf3537Syasuoka pool = NULL; 16060fbf3537Syasuoka 16070fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) { 16080fbf3537Syasuoka if (req_ip4 == INADDR_ANY) 16090fbf3537Syasuoka dyna = 1; 16100fbf3537Syasuoka } else if (ppp->realm_framed_ip_address.s_addr == INADDR_NAS_SELECT) { 16110fbf3537Syasuoka dyna = 1; 16120fbf3537Syasuoka } else { 16130fbf3537Syasuoka NPPPD_ASSERT(realm != NULL); 16140fbf3537Syasuoka fallback_dyna = 1; 16150fbf3537Syasuoka req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr); 16160fbf3537Syasuoka ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr); 16170fbf3537Syasuoka } 16180fbf3537Syasuoka if (!dyna) { 16190fbf3537Syasuoka /* 1620f0a4e295Syasuoka * Realm requires the fixed IP address, but the address 1621f0a4e295Syasuoka * doesn't belong any address pool. Fallback to dynamic 1622f0a4e295Syasuoka * assignment. 16230fbf3537Syasuoka */ 1624821f7c56Syasuoka pool = ppp_pool(ppp); 1625821f7c56Syasuoka rval = npppd_pool_get_assignability(pool, req_ip4, ip4mask, 1626821f7c56Syasuoka &snp); 16270fbf3537Syasuoka switch (rval) { 16280fbf3537Syasuoka case ADDRESS_OK: 16290fbf3537Syasuoka if (snp->snp_type == SNP_POOL) { 16300fbf3537Syasuoka /* 1631821f7c56Syasuoka * Fixed address pool can be used only if the 1632821f7c56Syasuoka * realm specified to use it. 16330fbf3537Syasuoka */ 16340fbf3537Syasuoka if (ppp->realm_framed_ip_address 16350fbf3537Syasuoka .s_addr != INADDR_USER_SELECT) 16360fbf3537Syasuoka ip4 = req_ip4; 16370fbf3537Syasuoka break; 16380fbf3537Syasuoka } 16390fbf3537Syasuoka ppp->assign_dynapool = 1; 16400fbf3537Syasuoka ip4 = req_ip4; 16410fbf3537Syasuoka break; 16420fbf3537Syasuoka case ADDRESS_RESERVED: 16430fbf3537Syasuoka reason = "reserved"; 1644821f7c56Syasuoka break; 16450fbf3537Syasuoka case ADDRESS_OUT_OF_POOL: 16460fbf3537Syasuoka reason = "out of the pool"; 1647821f7c56Syasuoka break; 16480fbf3537Syasuoka case ADDRESS_BUSY: 16490fbf3537Syasuoka fallback_dyna = 0; 16500fbf3537Syasuoka reason = "busy"; 16510fbf3537Syasuoka break; 16520fbf3537Syasuoka default: 16530fbf3537Syasuoka case ADDRESS_INVALID: 16540fbf3537Syasuoka fallback_dyna = 0; 16550fbf3537Syasuoka reason = "invalid"; 16560fbf3537Syasuoka break; 16570fbf3537Syasuoka } 16580fbf3537Syasuoka #define IP_4OCT(v) ((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16),\ 16590fbf3537Syasuoka ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v)) 16600fbf3537Syasuoka if (ip4 == 0) { 16610fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 16620fbf3537Syasuoka "Requested IP address (%d.%d.%d.%d)/%d " 16630fbf3537Syasuoka "is %s", IP_4OCT(req_ip4), 1664*baaa6b9aSyasuoka netmask2prefixlen(ip4mask), reason); 16650fbf3537Syasuoka if (fallback_dyna) 16660fbf3537Syasuoka goto dyna_assign; 16670fbf3537Syasuoka return 1; 16680fbf3537Syasuoka } 166932012184Syasuoka ppp->assigned_pool = pool; 16700fbf3537Syasuoka 16710fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4); 16720fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(ip4mask); 1673b0b96f97Syasuoka ppp->acct_framed_ip_address = ppp->ppp_framed_ip_address; 16740fbf3537Syasuoka } else { 16750fbf3537Syasuoka dyna_assign: 1676821f7c56Syasuoka pool = ppp_pool(ppp); 16770fbf3537Syasuoka ip4 = npppd_pool_get_dynamic(pool, ppp); 16780fbf3537Syasuoka if (ip4 == 0) { 16790fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 16800fbf3537Syasuoka "No free address in the pool."); 16810fbf3537Syasuoka return 1; 16820fbf3537Syasuoka } 16830fbf3537Syasuoka ppp->assigned_pool = pool; 16840fbf3537Syasuoka ppp->assign_dynapool = 1; 16850fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4); 16860fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(0xffffffffL); 1687b0b96f97Syasuoka ppp->acct_framed_ip_address = ppp->ppp_framed_ip_address; 16880fbf3537Syasuoka } 16890fbf3537Syasuoka 16900fbf3537Syasuoka return npppd_pool_assign_ip(ppp->assigned_pool, ppp); 16910fbf3537Syasuoka } 16920fbf3537Syasuoka 16930fbf3537Syasuoka static void * 16940fbf3537Syasuoka rtlist_remove(slist *prtlist, struct radish *radish) 16950fbf3537Syasuoka { 16960fbf3537Syasuoka struct radish *r; 16970fbf3537Syasuoka 16980fbf3537Syasuoka slist_itr_first(prtlist); 16990fbf3537Syasuoka while (slist_itr_has_next(prtlist)) { 17000fbf3537Syasuoka r = slist_itr_next(prtlist); 17010fbf3537Syasuoka if (!sockaddr_npppd_match(radish->rd_route, r->rd_route) || 17020fbf3537Syasuoka !sockaddr_npppd_match(radish->rd_mask, r->rd_mask)) 17030fbf3537Syasuoka continue; 17040fbf3537Syasuoka 17050fbf3537Syasuoka return slist_itr_remove(prtlist); 17060fbf3537Syasuoka } 17070fbf3537Syasuoka 17080fbf3537Syasuoka return NULL; 17090fbf3537Syasuoka } 17100fbf3537Syasuoka 1711f0a4e295Syasuoka /** Set {@link ::npppd#rd the only radish of npppd} */ 17120fbf3537Syasuoka int 17130fbf3537Syasuoka npppd_set_radish(npppd *_this, void *radish_head) 17140fbf3537Syasuoka { 17150fbf3537Syasuoka int rval, delppp0, count; 17160fbf3537Syasuoka struct sockaddr_npppd *snp; 17170fbf3537Syasuoka struct radish *radish, *r; 17180fbf3537Syasuoka slist rtlist0, rtlist1, delppp; 17190fbf3537Syasuoka npppd_ppp *ppp; 17200fbf3537Syasuoka void *dummy; 17210fbf3537Syasuoka 17220fbf3537Syasuoka slist_init(&rtlist0); 17230fbf3537Syasuoka slist_init(&rtlist1); 17240fbf3537Syasuoka slist_init(&delppp); 17250fbf3537Syasuoka 17260fbf3537Syasuoka if (radish_head != NULL) { 17270fbf3537Syasuoka if (rd2slist(radish_head, &rtlist1) != 0) { 17280fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m"); 1729f0a4e295Syasuoka goto fail; 17300fbf3537Syasuoka } 17310fbf3537Syasuoka } 17320fbf3537Syasuoka if (_this->rd != NULL) { 17330fbf3537Syasuoka if (rd2slist(_this->rd, &rtlist0) != 0) { 17340fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m"); 1735f0a4e295Syasuoka goto fail; 17360fbf3537Syasuoka } 17370fbf3537Syasuoka } 17380fbf3537Syasuoka if (_this->rd != NULL && radish_head != NULL) { 17390fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { 17400fbf3537Syasuoka radish = slist_itr_next(&rtlist0); 17410fbf3537Syasuoka snp = radish->rd_rtent; 17420fbf3537Syasuoka /* 1743f0a4e295Syasuoka * replace the pool address 17440fbf3537Syasuoka */ 17450fbf3537Syasuoka if (snp->snp_type == SNP_POOL || 17460fbf3537Syasuoka snp->snp_type == SNP_DYN_POOL) { 17470fbf3537Syasuoka if (rd_lookup(radish->rd_route, radish->rd_mask, 17480fbf3537Syasuoka radish_head) == NULL) 17490fbf3537Syasuoka continue; 1750f0a4e295Syasuoka /* don't add */ 17510fbf3537Syasuoka rtlist_remove(&rtlist1, radish); 1752f0a4e295Syasuoka /* don't delete */ 17530fbf3537Syasuoka slist_itr_remove(&rtlist0); 17540fbf3537Syasuoka continue; 17550fbf3537Syasuoka } 17560fbf3537Syasuoka /* 1757f0a4e295Syasuoka * handle the active PPP sessions. 17580fbf3537Syasuoka */ 17590fbf3537Syasuoka NPPPD_ASSERT(snp->snp_type == SNP_PPP); 17600fbf3537Syasuoka ppp = snp->snp_data_ptr; 17610fbf3537Syasuoka 1762f0a4e295Syasuoka /* Don't delete the route of active PPP session */ 17630fbf3537Syasuoka slist_itr_remove(&rtlist0); 17640fbf3537Syasuoka 1765f0a4e295Syasuoka /* clear informations about old pool configuration */ 17660fbf3537Syasuoka snp->snp_next = NULL; 17670fbf3537Syasuoka 17680fbf3537Syasuoka delppp0 = 0; 17690fbf3537Syasuoka if (!rd_match((struct sockaddr *)snp, radish_head, &r)){ 17700fbf3537Syasuoka /* 1771f0a4e295Syasuoka * If the address doesn't belong the new pools, 1772f0a4e295Syasuoka * add the PPP session to the deletion list. 17730fbf3537Syasuoka */ 17740fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr); 17750fbf3537Syasuoka delppp0 = 1; 17760fbf3537Syasuoka } else { 17770fbf3537Syasuoka NPPPD_ASSERT( 17780fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent) 17790fbf3537Syasuoka ->snp_type == SNP_POOL || 17800fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent) 17810fbf3537Syasuoka ->snp_type == SNP_DYN_POOL); 17820fbf3537Syasuoka /* 1783f0a4e295Syasuoka * If there is a pool entry that has same 1784f0a4e295Syasuoka * address/mask, then make the RADISH entry a 1785f0a4e295Syasuoka * list. Set SNP_PPP as the first in the list, 1786f0a4e295Syasuoka * set current entry in snp->snp_next and 1787f0a4e295Syasuoka * delete it. 17880fbf3537Syasuoka */ 17890fbf3537Syasuoka if (sockaddr_npppd_match( 17900fbf3537Syasuoka radish->rd_route, r->rd_route) && 17910fbf3537Syasuoka sockaddr_npppd_match( 17920fbf3537Syasuoka radish->rd_mask, r->rd_mask)) { 1793f0a4e295Syasuoka /* 1794f0a4e295Syasuoka * Releasing it, so remove it from the 1795f0a4e295Syasuoka * new routing list. 1796f0a4e295Syasuoka */ 17970fbf3537Syasuoka rtlist_remove(&rtlist1, radish); 1798f0a4e295Syasuoka /* set as snp_snp_next */ 17990fbf3537Syasuoka snp->snp_next = r->rd_rtent; 18000fbf3537Syasuoka rval = rd_delete(r->rd_route, 18010fbf3537Syasuoka r->rd_mask, radish_head, &dummy); 18020fbf3537Syasuoka NPPPD_ASSERT(rval == 0); 18030fbf3537Syasuoka } 18040fbf3537Syasuoka } 1805f0a4e295Syasuoka /* Register to the new radish */ 18060fbf3537Syasuoka rval = rd_insert(radish->rd_route, radish->rd_mask, 18070fbf3537Syasuoka radish_head, snp); 18080fbf3537Syasuoka if (rval != 0) { 18090fbf3537Syasuoka errno = rval; 18100fbf3537Syasuoka ppp_log(((npppd_ppp *)snp->snp_data_ptr), 18110fbf3537Syasuoka LOG_ERR, 18120fbf3537Syasuoka "Fatal error on %s, cannot continue " 18130fbf3537Syasuoka "this ppp session: %m", __func__); 18140fbf3537Syasuoka if (!delppp0) 18150fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr); 18160fbf3537Syasuoka } 18170fbf3537Syasuoka } 18180fbf3537Syasuoka } 18190fbf3537Syasuoka count = 0; 18200fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1821cd8e09b9Sdlg if (_this->iface[0].using_pppx == 0) { 18220fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { 18230fbf3537Syasuoka radish = slist_itr_next(&rtlist0); 18240fbf3537Syasuoka in_route_delete(&SIN(radish->rd_route)->sin_addr, 1825cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop, 1826cd8e09b9Sdlg RTF_BLACKHOLE); 18270fbf3537Syasuoka count++; 18280fbf3537Syasuoka } 18290fbf3537Syasuoka if (count > 0) 18300fbf3537Syasuoka log_printf(LOG_INFO, 18310fbf3537Syasuoka "Deleted %d routes for old pool addresses", count); 18320fbf3537Syasuoka 18330fbf3537Syasuoka count = 0; 18340fbf3537Syasuoka for (slist_itr_first(&rtlist1); slist_itr_has_next(&rtlist1);) { 18350fbf3537Syasuoka radish = slist_itr_next(&rtlist1); 18360fbf3537Syasuoka in_route_add(&(SIN(radish->rd_route)->sin_addr), 1837cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop, 1838cd8e09b9Sdlg LOOPBACK_IFNAME, RTF_BLACKHOLE, 0); 18390fbf3537Syasuoka count++; 18400fbf3537Syasuoka } 18410fbf3537Syasuoka if (count > 0) 18420fbf3537Syasuoka log_printf(LOG_INFO, 1843cd8e09b9Sdlg "Added %d routes for new pool addresses", 1844cd8e09b9Sdlg count); 1845cd8e09b9Sdlg } 18460fbf3537Syasuoka #endif 18470fbf3537Syasuoka slist_fini(&rtlist0); 18480fbf3537Syasuoka slist_fini(&rtlist1); 18490fbf3537Syasuoka 1850230b2897Syasuoka if (_this->rd != NULL) { 18510fbf3537Syasuoka npppd_rd_walktree_delete(_this->rd); 1852230b2897Syasuoka _this->rd = NULL; 1853230b2897Syasuoka } 185484c9ec02Syasuoka if (radish_head == NULL) 185584c9ec02Syasuoka npppd_get_all_users(_this, &delppp); 18563089d6fcSyasuoka _this->rd = radish_head; 18570fbf3537Syasuoka 18580fbf3537Syasuoka for (slist_itr_first(&delppp); slist_itr_has_next(&delppp);) { 18590fbf3537Syasuoka ppp = slist_itr_next(&delppp); 18600fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 18610fbf3537Syasuoka "stop. IP address of this ppp is out of the pool.: %s", 18620fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address)); 18630fbf3537Syasuoka ppp_stop(ppp, NULL); 18640fbf3537Syasuoka } 18650fbf3537Syasuoka slist_fini(&delppp); 18660fbf3537Syasuoka 18670fbf3537Syasuoka return 0; 1868f0a4e295Syasuoka fail: 18690fbf3537Syasuoka slist_fini(&rtlist0); 18700fbf3537Syasuoka slist_fini(&rtlist1); 18710fbf3537Syasuoka slist_fini(&delppp); 18720fbf3537Syasuoka 18730fbf3537Syasuoka return 1; 18740fbf3537Syasuoka } 18750fbf3537Syasuoka 18760fbf3537Syasuoka /** 1877f0a4e295Syasuoka * This function stores all users to {@link slist} and returns them. 1878f0a4e295Syasuoka * References to {@link ::npppd_ppp} will be stored in users. 18790fbf3537Syasuoka */ 188034682664Syasuoka static int 18810fbf3537Syasuoka npppd_get_all_users(npppd *_this, slist *users) 18820fbf3537Syasuoka { 18830fbf3537Syasuoka int rval; 18840fbf3537Syasuoka struct radish *rd; 18850fbf3537Syasuoka struct sockaddr_npppd *snp; 18860fbf3537Syasuoka slist list; 18870fbf3537Syasuoka 18880fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 18890fbf3537Syasuoka 18900fbf3537Syasuoka slist_init(&list); 189184c9ec02Syasuoka if (_this->rd == NULL) 189284c9ec02Syasuoka return 0; 18930fbf3537Syasuoka rval = rd2slist(_this->rd, &list); 18940fbf3537Syasuoka if (rval != 0) 18950fbf3537Syasuoka return rval; 18960fbf3537Syasuoka 18970fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) { 18980fbf3537Syasuoka rd = slist_itr_next(&list); 18990fbf3537Syasuoka snp = rd->rd_rtent; 19000fbf3537Syasuoka if (snp->snp_type == SNP_PPP) { 19010fbf3537Syasuoka if (slist_add(users, snp->snp_data_ptr) == NULL) { 19020fbf3537Syasuoka log_printf(LOG_ERR, 19030fbf3537Syasuoka "slist_add() failed in %s: %m", __func__); 1904f0a4e295Syasuoka goto fail; 19050fbf3537Syasuoka } 19060fbf3537Syasuoka } 19070fbf3537Syasuoka } 19080fbf3537Syasuoka slist_fini(&list); 19090fbf3537Syasuoka 19100fbf3537Syasuoka return 0; 1911f0a4e295Syasuoka fail: 19120fbf3537Syasuoka slist_fini(&list); 19130fbf3537Syasuoka 19140fbf3537Syasuoka return 1; 19150fbf3537Syasuoka } 19160fbf3537Syasuoka 19170fbf3537Syasuoka static int 19180fbf3537Syasuoka rd2slist_walk(struct radish *rd, void *list0) 19190fbf3537Syasuoka { 19200fbf3537Syasuoka slist *list = list0; 19210fbf3537Syasuoka void *r; 19220fbf3537Syasuoka 19230fbf3537Syasuoka r = slist_add(list, rd); 19240fbf3537Syasuoka if (r == NULL) 19250fbf3537Syasuoka return -1; 19260fbf3537Syasuoka return 0; 19270fbf3537Syasuoka } 19280fbf3537Syasuoka static int 19290fbf3537Syasuoka rd2slist(struct radish_head *h, slist *list) 19300fbf3537Syasuoka { 19310fbf3537Syasuoka return rd_walktree(h, rd2slist_walk, list); 19320fbf3537Syasuoka } 19330fbf3537Syasuoka 19340fbf3537Syasuoka static void 19350fbf3537Syasuoka npppd_reload0(npppd *_this) 19360fbf3537Syasuoka { 1937821f7c56Syasuoka int i; 1938821f7c56Syasuoka 19390fbf3537Syasuoka npppd_reload_config(_this); 19400fbf3537Syasuoka #ifdef USE_NPPPD_ARP 19410fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); 19420fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) 19430fbf3537Syasuoka arp_sock_init(); 19440fbf3537Syasuoka else 19450fbf3537Syasuoka arp_sock_fini(); 19460fbf3537Syasuoka #endif 19470fbf3537Syasuoka npppd_modules_reload(_this); 19480fbf3537Syasuoka npppd_ifaces_load_config(_this); 1949821f7c56Syasuoka npppd_update_pool_reference(_this); 19500fbf3537Syasuoka npppd_auth_finalizer_periodic(_this); 19512a5607d2Sgoda npppd_ipcp_stats_reload(_this); 1952821f7c56Syasuoka 1953821f7c56Syasuoka for (i = 0; i < countof(_this->iface); i++) { 1954821f7c56Syasuoka if (_this->iface[i].initialized != 0 && 1955821f7c56Syasuoka _this->iface[i].started == 0) 1956821f7c56Syasuoka npppd_iface_start(&_this->iface[i]); 1957821f7c56Syasuoka } 1958821f7c56Syasuoka } 1959821f7c56Syasuoka 1960821f7c56Syasuoka static void 1961821f7c56Syasuoka npppd_update_pool_reference(npppd *_this) 1962821f7c56Syasuoka { 1963821f7c56Syasuoka int i, j; 1964821f7c56Syasuoka /* update iface to pool reference */ 1965821f7c56Syasuoka for (i = 0; i < countof(_this->iface_pool); i++) { 1966821f7c56Syasuoka _this->iface_pool[i] = NULL; 1967821f7c56Syasuoka if (_this->iface[i].initialized == 0) 1968821f7c56Syasuoka continue; 1969821f7c56Syasuoka if (_this->iface[i].ipcpconf == NULL) 1970821f7c56Syasuoka continue; /* no IPCP for this interface */ 1971821f7c56Syasuoka 1972821f7c56Syasuoka for (j = 0; j < countof(_this->pool); j++) { 1973821f7c56Syasuoka if (_this->pool[j].initialized == 0) 1974821f7c56Syasuoka continue; 1975821f7c56Syasuoka if (strcmp(_this->iface[i].ipcpconf->name, 1976821f7c56Syasuoka _this->pool[j].ipcp_name) == 0) { 1977821f7c56Syasuoka /* found the ipcp that has the pool */ 1978821f7c56Syasuoka _this->iface_pool[i] = &_this->pool[j]; 1979821f7c56Syasuoka break; 1980821f7c56Syasuoka } 1981821f7c56Syasuoka } 1982821f7c56Syasuoka } 19830fbf3537Syasuoka } 19840fbf3537Syasuoka 19850fbf3537Syasuoka /*********************************************************************** 1986f0a4e295Syasuoka * Signal handlers 19870fbf3537Syasuoka ***********************************************************************/ 19880fbf3537Syasuoka static void 19890fbf3537Syasuoka npppd_on_sighup(int fd, short ev_type, void *ctx) 19900fbf3537Syasuoka { 19910fbf3537Syasuoka npppd *_this; 19920fbf3537Syasuoka 19930fbf3537Syasuoka _this = ctx; 19940fbf3537Syasuoka #ifndef NO_DELAYED_RELOAD 19950fbf3537Syasuoka if (_this->delayed_reload > 0) 19960fbf3537Syasuoka _this->reloading_count = _this->delayed_reload; 19970fbf3537Syasuoka else 19980fbf3537Syasuoka #endif 19990fbf3537Syasuoka npppd_reload0(_this); 20000fbf3537Syasuoka } 20010fbf3537Syasuoka 20020fbf3537Syasuoka static void 20030fbf3537Syasuoka npppd_on_sigterm(int fd, short ev_type, void *ctx) 20040fbf3537Syasuoka { 20050fbf3537Syasuoka npppd *_this; 20060fbf3537Syasuoka 20070fbf3537Syasuoka _this = ctx; 20080fbf3537Syasuoka npppd_stop(_this); 20090fbf3537Syasuoka } 20100fbf3537Syasuoka 20110fbf3537Syasuoka static void 20120fbf3537Syasuoka npppd_on_sigint(int fd, short ev_type, void *ctx) 20130fbf3537Syasuoka { 20140fbf3537Syasuoka npppd *_this; 20150fbf3537Syasuoka 20160fbf3537Syasuoka _this = ctx; 20170fbf3537Syasuoka npppd_stop(_this); 20180fbf3537Syasuoka } 20190fbf3537Syasuoka 20205fefcc09Syasuoka static void 20215fefcc09Syasuoka npppd_on_sigchld(int fd, short ev_type, void *ctx) 20225fefcc09Syasuoka { 20235fefcc09Syasuoka int status; 20245fefcc09Syasuoka pid_t wpid; 20255fefcc09Syasuoka npppd *_this; 20265fefcc09Syasuoka 20275fefcc09Syasuoka _this = ctx; 20285fefcc09Syasuoka wpid = privsep_priv_pid(); 20295fefcc09Syasuoka if (wait4(wpid, &status, WNOHANG, NULL) == wpid) { 20305fefcc09Syasuoka if (WIFSIGNALED(status)) 20315fefcc09Syasuoka log_printf(LOG_WARNING, 20329a200ddfSyasuoka "privileged process exits abnormaly. signal=%d", 20335fefcc09Syasuoka WTERMSIG(status)); 20345fefcc09Syasuoka else 20355fefcc09Syasuoka log_printf(LOG_WARNING, 20369a200ddfSyasuoka "privileged process exits abnormaly. status=%d", 20375fefcc09Syasuoka WEXITSTATUS(status)); 20385fefcc09Syasuoka _this->stop_by_error = 1; 20395fefcc09Syasuoka npppd_stop(_this); 20405fefcc09Syasuoka } 20415fefcc09Syasuoka } 20420fbf3537Syasuoka /*********************************************************************** 2043f0a4e295Syasuoka * Miscellaneous functions 20440fbf3537Syasuoka ***********************************************************************/ 20450fbf3537Syasuoka static uint32_t 20460fbf3537Syasuoka str_hash(const void *ptr, int sz) 20470fbf3537Syasuoka { 20480fbf3537Syasuoka uint32_t hash = 0; 20490fbf3537Syasuoka int i, len; 20500fbf3537Syasuoka const char *str; 20510fbf3537Syasuoka 20520fbf3537Syasuoka str = ptr; 20530fbf3537Syasuoka len = strlen(str); 20540fbf3537Syasuoka for (i = 0; i < len; i++) 20550fbf3537Syasuoka hash = hash*0x1F + str[i]; 20560fbf3537Syasuoka hash = (hash << 16) ^ (hash & 0xffff); 20570fbf3537Syasuoka 20580fbf3537Syasuoka return hash % sz; 20590fbf3537Syasuoka } 20600fbf3537Syasuoka 20610fbf3537Syasuoka /** 2062f0a4e295Syasuoka * Select a authentication realm that is for given {@link ::npppd_ppp PPP}. 2063f0a4e295Syasuoka * Return 0 on success. 20640fbf3537Syasuoka */ 20650fbf3537Syasuoka int 20660fbf3537Syasuoka npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int 20670fbf3537Syasuoka eap_required) 20680fbf3537Syasuoka { 2069821f7c56Syasuoka struct confbind *bind; 20700fbf3537Syasuoka npppd_auth_base *realm = NULL, *realm0 = NULL, *realm1 = NULL; 2071821f7c56Syasuoka char buf1[MAX_USERNAME_LENGTH]; 207234379bfeSyasuoka int lsuffix, lusername, lmax; 20730fbf3537Syasuoka 20740fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 20750fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 20760fbf3537Syasuoka NPPPD_ASSERT(username != NULL); 20770fbf3537Syasuoka 20780fbf3537Syasuoka /* 2079f0a4e295Syasuoka * If the PPP suffix is the longest, and the length of the suffix is 2080f0a4e295Syasuoka * same, select the first one. 20810fbf3537Syasuoka */ 20820fbf3537Syasuoka lusername = strlen(username); 20830fbf3537Syasuoka lmax = -1; 20840fbf3537Syasuoka realm = NULL; 20850fbf3537Syasuoka 2086821f7c56Syasuoka TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) { 2087821f7c56Syasuoka if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) 20880fbf3537Syasuoka continue; 20890fbf3537Syasuoka 20900fbf3537Syasuoka realm0 = NULL; 20910fbf3537Syasuoka slist_itr_first(&_this->realms); 20920fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) { 20930fbf3537Syasuoka realm1 = slist_itr_next(&_this->realms); 20940fbf3537Syasuoka if (!npppd_auth_is_usable(realm1)) 20950fbf3537Syasuoka continue; 2096821f7c56Syasuoka if (eap_required && !npppd_auth_is_eap_capable(realm1)) 20970fbf3537Syasuoka continue; 2098821f7c56Syasuoka if (strcmp(npppd_auth_get_name(realm1), 2099821f7c56Syasuoka bind->authconf->name) == 0) { 21000fbf3537Syasuoka realm0 = realm1; 21010fbf3537Syasuoka break; 21020fbf3537Syasuoka } 21030fbf3537Syasuoka } 21040fbf3537Syasuoka if (realm0 == NULL) 21050fbf3537Syasuoka continue; 2106821f7c56Syasuoka 21070fbf3537Syasuoka lsuffix = strlen(npppd_auth_get_suffix(realm0)); 21080fbf3537Syasuoka if (lsuffix > lmax && 2109821f7c56Syasuoka (lsuffix == 0 || 2110821f7c56Syasuoka (lsuffix < lusername && strcmp(username + lusername 2111821f7c56Syasuoka - lsuffix, npppd_auth_get_suffix(realm0)) 2112821f7c56Syasuoka == 0))) { 21130fbf3537Syasuoka lmax = lsuffix; 21140fbf3537Syasuoka realm = realm0; 21150fbf3537Syasuoka } 21160fbf3537Syasuoka } 2117821f7c56Syasuoka 21180fbf3537Syasuoka if (realm == NULL) { 21190fbf3537Syasuoka log_printf(LOG_INFO, "user='%s' could not bind any realms", 21200fbf3537Syasuoka username); 21210fbf3537Syasuoka return 1; 21220fbf3537Syasuoka } 2123821f7c56Syasuoka NPPPD_DBG((LOG_DEBUG, "bind realm %s", npppd_auth_get_name(realm))); 21240fbf3537Syasuoka 21250fbf3537Syasuoka if (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL) 21260fbf3537Syasuoka /* hook the auto reload */ 21270fbf3537Syasuoka npppd_auth_get_user_password(realm, 21280fbf3537Syasuoka npppd_auth_username_for_auth(realm1, username, buf1), NULL, 21290fbf3537Syasuoka NULL); 21300fbf3537Syasuoka ppp->realm = realm; 21310fbf3537Syasuoka 21320fbf3537Syasuoka return 0; 21330fbf3537Syasuoka } 21340fbf3537Syasuoka 2135f0a4e295Syasuoka /** Is assigned realm a LOCAL authentication? */ 21360fbf3537Syasuoka int 21370fbf3537Syasuoka npppd_ppp_is_realm_local(npppd *_this, npppd_ppp *ppp) 21380fbf3537Syasuoka { 21390fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 21400fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 21410fbf3537Syasuoka 21420fbf3537Syasuoka if (ppp->realm == NULL) 21430fbf3537Syasuoka return 0; 21440fbf3537Syasuoka 21450fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_LOCAL) 21460fbf3537Syasuoka ? 1 : 0; 21470fbf3537Syasuoka } 21480fbf3537Syasuoka 2149f0a4e295Syasuoka /** Is assigned realm a RADIUS authentication? */ 21500fbf3537Syasuoka int 21510fbf3537Syasuoka npppd_ppp_is_realm_radius(npppd *_this, npppd_ppp *ppp) 21520fbf3537Syasuoka { 21530fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 21540fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 21550fbf3537Syasuoka 21560fbf3537Syasuoka if (ppp->realm == NULL) 21570fbf3537Syasuoka return 0; 21580fbf3537Syasuoka 21590fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_RADIUS) 21600fbf3537Syasuoka ? 1 : 0; 21610fbf3537Syasuoka } 21620fbf3537Syasuoka 2163f0a4e295Syasuoka /** Is assigned realm usable? */ 21640fbf3537Syasuoka int 21650fbf3537Syasuoka npppd_ppp_is_realm_ready(npppd *_this, npppd_ppp *ppp) 21660fbf3537Syasuoka { 21670fbf3537Syasuoka if (ppp->realm == NULL) 21680fbf3537Syasuoka return 0; 21690fbf3537Syasuoka 21700fbf3537Syasuoka return npppd_auth_is_ready(ppp->realm); 21710fbf3537Syasuoka } 21720fbf3537Syasuoka 2173f0a4e295Syasuoka /** Return the name of assigned realm */ 21740fbf3537Syasuoka const char * 21750fbf3537Syasuoka npppd_ppp_get_realm_name(npppd *_this, npppd_ppp *ppp) 21760fbf3537Syasuoka { 21770fbf3537Syasuoka if (ppp->realm == NULL) 21780fbf3537Syasuoka return "(none)"; 21790fbf3537Syasuoka return npppd_auth_get_name(ppp->realm); 21800fbf3537Syasuoka } 21810fbf3537Syasuoka 2182f0a4e295Syasuoka /** Return the interface name that bound given {@link ::npppd_ppp PPP} */ 21830fbf3537Syasuoka const char * 21840fbf3537Syasuoka npppd_ppp_get_iface_name(npppd *_this, npppd_ppp *ppp) 21850fbf3537Syasuoka { 21860fbf3537Syasuoka if (ppp == NULL || ppp->ifidx < 0) 21870fbf3537Syasuoka return "(not binding)"; 21880fbf3537Syasuoka return ppp_iface(ppp)->ifname; 21890fbf3537Syasuoka } 21900fbf3537Syasuoka 2191f0a4e295Syasuoka /** Is the interface usable? */ 21920fbf3537Syasuoka int 21930fbf3537Syasuoka npppd_ppp_iface_is_ready(npppd *_this, npppd_ppp *ppp) 21940fbf3537Syasuoka { 21950fbf3537Syasuoka return (npppd_iface_ip_is_ready(ppp_iface(ppp)) && 21960fbf3537Syasuoka ppp_ipcp(ppp) != NULL)? 1 : 0; 21970fbf3537Syasuoka } 21980fbf3537Syasuoka 2199f0a4e295Syasuoka /** Select a suitable interface for {@link :npppd_ppp PPP} and bind them */ 22000fbf3537Syasuoka int 22010fbf3537Syasuoka npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp) 22020fbf3537Syasuoka { 2203821f7c56Syasuoka int i, ifidx; 2204821f7c56Syasuoka struct confbind *bind; 22052a5607d2Sgoda struct ipcpstat *ipcpstat; 22060fbf3537Syasuoka 22070fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 22080fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 22090fbf3537Syasuoka 22100fbf3537Syasuoka if (ppp->ifidx >= 0) 22110fbf3537Syasuoka return 0; 22120fbf3537Syasuoka 2213821f7c56Syasuoka TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) { 2214821f7c56Syasuoka if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) 2215821f7c56Syasuoka continue; 2216821f7c56Syasuoka if (ppp->realm == NULL) { 2217821f7c56Syasuoka if (bind->authconf == NULL) 2218821f7c56Syasuoka break; 2219821f7c56Syasuoka } else if (strcmp(bind->authconf->name, 2220821f7c56Syasuoka npppd_auth_get_name(ppp->realm)) == 0) 2221821f7c56Syasuoka break; 2222821f7c56Syasuoka } 2223821f7c56Syasuoka if (bind == NULL) 22240fbf3537Syasuoka return 1; 22250fbf3537Syasuoka 2226f0a4e295Syasuoka /* Search a interface */ 22270fbf3537Syasuoka ifidx = -1; 22280fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) { 22290fbf3537Syasuoka if (_this->iface[i].initialized == 0) 22300fbf3537Syasuoka continue; 2231821f7c56Syasuoka if (strcmp(_this->iface[i].ifname, bind->iface->name) == 0) 22320fbf3537Syasuoka ifidx = i; 22330fbf3537Syasuoka } 22340fbf3537Syasuoka if (ifidx < 0) 22350fbf3537Syasuoka return 1; 22360fbf3537Syasuoka 22372a5607d2Sgoda ppp->ifidx = ifidx; 22382a5607d2Sgoda NPPPD_ASSERT(ppp_ipcp(ppp) != NULL); 22392a5607d2Sgoda ipcpstat = npppd_get_ipcp_stat(&_this->ipcpstats, ppp_ipcp(ppp)->name); 22402a5607d2Sgoda if (ipcpstat == NULL) { 22412a5607d2Sgoda ppp_log(ppp, LOG_WARNING, "Unknown IPCP %s", 22422a5607d2Sgoda ppp_ipcp(ppp)->name); 22432a5607d2Sgoda ppp->ifidx = -1; /* unbind inteface */ 22442a5607d2Sgoda return 1; 22452a5607d2Sgoda } 22462a5607d2Sgoda if (ppp_ipcp(ppp)->max_session > 0 && 22472a5607d2Sgoda ipcpstat->nsession >= ppp_ipcp(ppp)->max_session) { 22482a5607d2Sgoda ppp_log(ppp, LOG_WARNING, 22492a5607d2Sgoda "Number of sessions per IPCP reaches out of the limit=%d", 22502a5607d2Sgoda ppp_ipcp(ppp)->max_session); 22512a5607d2Sgoda ppp->ifidx = -1; /* unbind inteface */ 22522a5607d2Sgoda return 1; 22532a5607d2Sgoda } 22542a5607d2Sgoda 2255e43db91eSyasuoka if (_this->conf.max_session > 0 && 22564080edd5Syasuoka _this->nsession >= _this->conf.max_session) { 22570fbf3537Syasuoka ppp_log(ppp, LOG_WARNING, 22580fbf3537Syasuoka "Number of sessions reaches out of the limit=%d", 2259e43db91eSyasuoka _this->conf.max_session); 22602a5607d2Sgoda ppp->ifidx = -1; /* unbind inteface */ 22610fbf3537Syasuoka return 1; 22620fbf3537Syasuoka } 22634080edd5Syasuoka _this->nsession++; 22640fbf3537Syasuoka 22652a5607d2Sgoda LIST_INSERT_HEAD(&ipcpstat->ppp, ppp, ipcpstat_entry); 22662a5607d2Sgoda ppp->ipcpstat = ipcpstat; 22672a5607d2Sgoda ipcpstat->nsession++; 22682a5607d2Sgoda 22690fbf3537Syasuoka return 0; 22700fbf3537Syasuoka } 22710fbf3537Syasuoka 2272f0a4e295Syasuoka /** Unbind the interface from the {@link ::npppd_ppp PPP} */ 22730fbf3537Syasuoka void 22740fbf3537Syasuoka npppd_ppp_unbind_iface(npppd *_this, npppd_ppp *ppp) 22750fbf3537Syasuoka { 22762a5607d2Sgoda if (ppp->ifidx >= 0) { 2277821f7c56Syasuoka _this->nsession--; 22782a5607d2Sgoda if (ppp->ipcpstat!= NULL) { 22792a5607d2Sgoda ppp->ipcpstat->nsession--; 22802a5607d2Sgoda LIST_REMOVE(ppp, ipcpstat_entry); 22812a5607d2Sgoda } 22822a5607d2Sgoda } 22830fbf3537Syasuoka ppp->ifidx = -1; 22840fbf3537Syasuoka } 22850fbf3537Syasuoka 22860fbf3537Syasuoka static int 22870fbf3537Syasuoka npppd_rd_walktree_delete(struct radish_head *rh) 22880fbf3537Syasuoka { 22890fbf3537Syasuoka void *dummy; 22900fbf3537Syasuoka struct radish *rd; 22910fbf3537Syasuoka slist list; 22920fbf3537Syasuoka 22930fbf3537Syasuoka slist_init(&list); 22940fbf3537Syasuoka if (rd2slist(rh, &list) != 0) 22950fbf3537Syasuoka return 1; 22960fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) { 22970fbf3537Syasuoka rd = slist_itr_next(&list); 22980fbf3537Syasuoka rd_delete(rd->rd_route, rd->rd_mask, rh, &dummy); 22990fbf3537Syasuoka } 23000fbf3537Syasuoka slist_fini(&list); 23010fbf3537Syasuoka 23020fbf3537Syasuoka free(rh); 23030fbf3537Syasuoka 23040fbf3537Syasuoka return 0; 23050fbf3537Syasuoka } 23060fbf3537Syasuoka 23070fbf3537Syasuoka #ifdef USE_NPPPD_RADIUS 2308f0a4e295Syasuoka /** 2309f0a4e295Syasuoka * Return radius_req_setting for the given {@link ::npppd_ppp PPP}. 2310f0a4e295Syasuoka * @return return NULL if no usable RADIUS setting. 2311f0a4e295Syasuoka */ 23120fbf3537Syasuoka void * 23138daf7599Syasuoka npppd_get_radius_auth_setting(npppd *_this, npppd_ppp *ppp) 23140fbf3537Syasuoka { 23150fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 23160fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 23170fbf3537Syasuoka 23180fbf3537Syasuoka if (ppp->realm == NULL) 23190fbf3537Syasuoka return NULL; 23200fbf3537Syasuoka if (!npppd_ppp_is_realm_radius(_this, ppp)) 23210fbf3537Syasuoka return NULL; 23220fbf3537Syasuoka 23238daf7599Syasuoka return npppd_auth_radius_get_radius_auth_setting(ppp->realm); 23240fbf3537Syasuoka } 23250fbf3537Syasuoka #endif 23260fbf3537Syasuoka 2327f0a4e295Syasuoka /** Finalize authentication realm */ 23280fbf3537Syasuoka static void 23290fbf3537Syasuoka npppd_auth_finalizer_periodic(npppd *_this) 23300fbf3537Syasuoka { 23310fbf3537Syasuoka int ndisposing = 0, refcnt; 23320fbf3537Syasuoka slist users; 23330fbf3537Syasuoka npppd_auth_base *auth_base; 23340fbf3537Syasuoka npppd_ppp *ppp; 23350fbf3537Syasuoka 23360fbf3537Syasuoka /* 2337f0a4e295Syasuoka * For the realms with disposing flag, if the realm has assigned PPPs, 2338f0a4e295Syasuoka * disconnect them. If all PPPs are disconnected then free the realm. 23390fbf3537Syasuoka */ 23400fbf3537Syasuoka NPPPD_DBG((DEBUG_LEVEL_2, "%s() called", __func__)); 23410fbf3537Syasuoka slist_itr_first(&_this->realms); 23420fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) { 23430fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms); 23440fbf3537Syasuoka if (!npppd_auth_is_disposing(auth_base)) 23450fbf3537Syasuoka continue; 23460fbf3537Syasuoka refcnt = 0; 23470fbf3537Syasuoka if (ndisposing++ == 0) { 23480fbf3537Syasuoka slist_init(&users); 23490fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 23500fbf3537Syasuoka log_printf(LOG_WARNING, 23510fbf3537Syasuoka "npppd_get_all_users() failed in %s(): %m", 23520fbf3537Syasuoka __func__); 23530fbf3537Syasuoka break; 23540fbf3537Syasuoka } 23550fbf3537Syasuoka } 23560fbf3537Syasuoka slist_itr_first(&users); 23570fbf3537Syasuoka while (slist_itr_has_next(&users)) { 23580fbf3537Syasuoka ppp = slist_itr_next(&users); 23590fbf3537Syasuoka if (ppp->realm == auth_base) { 23600fbf3537Syasuoka refcnt++; 23610fbf3537Syasuoka ppp_stop(ppp, NULL); 23620fbf3537Syasuoka ppp_log(ppp, LOG_INFO, 23630fbf3537Syasuoka "Stop request by npppd. Binding " 23640fbf3537Syasuoka "authentication realm is disposing. " 23650fbf3537Syasuoka "realm=%s", npppd_auth_get_name(auth_base)); 23660fbf3537Syasuoka slist_itr_remove(&users); 23670fbf3537Syasuoka } 23680fbf3537Syasuoka } 23698daf7599Syasuoka if (refcnt == 0) { 23700fbf3537Syasuoka npppd_auth_destroy(auth_base); 23718daf7599Syasuoka slist_itr_remove(&_this->realms); 23728daf7599Syasuoka } 23730fbf3537Syasuoka } 23740fbf3537Syasuoka if (ndisposing > 0) 23750fbf3537Syasuoka slist_fini(&users); 23760fbf3537Syasuoka } 23770fbf3537Syasuoka 2378f0a4e295Syasuoka /** compare sockaddr_npppd. return 0 if matches */ 23790fbf3537Syasuoka int 23800fbf3537Syasuoka sockaddr_npppd_match(void *a0, void *b0) 23810fbf3537Syasuoka { 23820fbf3537Syasuoka struct sockaddr_npppd *a, *b; 23830fbf3537Syasuoka 23840fbf3537Syasuoka a = a0; 23850fbf3537Syasuoka b = b0; 23860fbf3537Syasuoka 23870fbf3537Syasuoka return (a->snp_addr.s_addr == b->snp_addr.s_addr)? 1 : 0; 23880fbf3537Syasuoka } 23890fbf3537Syasuoka 23900fbf3537Syasuoka /** 2391f0a4e295Syasuoka * This function stores the username for authentication to the space specified 2392f0a4e295Syasuoka * by username_buffer and returns it. username_buffer must have space more 2393f0a4e295Syasuoka * than MAX_USERNAME_LENGTH. 23940fbf3537Syasuoka */ 23950fbf3537Syasuoka const char * 23960fbf3537Syasuoka npppd_ppp_get_username_for_auth(npppd *_this, npppd_ppp *ppp, 23970fbf3537Syasuoka const char *username, char *username_buffer) 23980fbf3537Syasuoka { 23990fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 24000fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 24010fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 24020fbf3537Syasuoka 24030fbf3537Syasuoka return npppd_auth_username_for_auth(ppp->realm, username, 24040fbf3537Syasuoka username_buffer); 24050fbf3537Syasuoka } 24060fbf3537Syasuoka 2407363e4d4bSyasuoka const char * 2408821f7c56Syasuoka npppd_tunnel_protocol_name(int tunn_protocol) 2409363e4d4bSyasuoka { 2410821f7c56Syasuoka switch (tunn_protocol) { 2411821f7c56Syasuoka case NPPPD_TUNNEL_NONE: 2412363e4d4bSyasuoka return "None"; 2413821f7c56Syasuoka case NPPPD_TUNNEL_L2TP: 2414363e4d4bSyasuoka return "L2TP"; 2415821f7c56Syasuoka case NPPPD_TUNNEL_PPTP: 2416363e4d4bSyasuoka return "PPTP"; 2417821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE: 2418363e4d4bSyasuoka return "PPPoE"; 2419821f7c56Syasuoka case NPPPD_TUNNEL_SSTP: 2420363e4d4bSyasuoka return "SSTP"; 2421363e4d4bSyasuoka } 2422363e4d4bSyasuoka 2423363e4d4bSyasuoka return "Error"; 2424363e4d4bSyasuoka } 2425821f7c56Syasuoka 2426821f7c56Syasuoka const char * 2427821f7c56Syasuoka npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp) 2428821f7c56Syasuoka { 2429821f7c56Syasuoka return npppd_tunnel_protocol_name(ppp->tunnel_type); 2430821f7c56Syasuoka } 2431821f7c56Syasuoka 2432821f7c56Syasuoka struct tunnconf * 2433821f7c56Syasuoka npppd_get_tunnconf(npppd *_this, const char *name) 2434821f7c56Syasuoka { 2435821f7c56Syasuoka struct tunnconf *conf; 2436821f7c56Syasuoka 2437821f7c56Syasuoka TAILQ_FOREACH(conf, &_this->conf.tunnconfs, entry) { 2438821f7c56Syasuoka if (strcmp(conf->name, name) == 0) 2439821f7c56Syasuoka return conf; 2440821f7c56Syasuoka } 2441821f7c56Syasuoka 2442821f7c56Syasuoka return NULL; 2443821f7c56Syasuoka } 2444821f7c56Syasuoka 244534682664Syasuoka void 244634682664Syasuoka npppd_on_ppp_start(npppd *_this, npppd_ppp *ppp) 244734682664Syasuoka { 244834682664Syasuoka struct ctl_conn *c; 244934682664Syasuoka 245034682664Syasuoka TAILQ_FOREACH(c, &ctl_conns, entry) { 245134682664Syasuoka if (npppd_ctl_add_started_ppp_id(c->ctx, ppp->id) == 0) { 245234682664Syasuoka npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); 245334682664Syasuoka imsg_event_add(&c->iev); 245434682664Syasuoka } 245534682664Syasuoka } 245634682664Syasuoka } 245734682664Syasuoka 245834682664Syasuoka void 245934682664Syasuoka npppd_on_ppp_stop(npppd *_this, npppd_ppp *ppp) 246034682664Syasuoka { 246134682664Syasuoka struct ctl_conn *c; 246234682664Syasuoka 246334682664Syasuoka TAILQ_FOREACH(c, &ctl_conns, entry) { 246434682664Syasuoka if (npppd_ctl_add_stopped_ppp(c->ctx, ppp) == 0) { 246534682664Syasuoka npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); 246634682664Syasuoka imsg_event_add(&c->iev); 246734682664Syasuoka } 246834682664Syasuoka } 246934682664Syasuoka } 247034682664Syasuoka 247134682664Syasuoka void 247234682664Syasuoka imsg_event_add(struct imsgev *iev) 247334682664Syasuoka { 247434682664Syasuoka iev->events = EV_READ; 247534682664Syasuoka if (iev->ibuf.w.queued) 247634682664Syasuoka iev->events |= EV_WRITE; 247734682664Syasuoka 247834682664Syasuoka event_del(&iev->ev); 247934682664Syasuoka event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); 248034682664Syasuoka event_add(&iev->ev, NULL); 248134682664Syasuoka } 2482