1*363e4d4bSyasuoka /* $OpenBSD: npppd.c,v 1.14 2012/01/18 03:13:04 yasuoka Exp $ */ 2e109dc18Syasuoka 30fbf3537Syasuoka /*- 40fbf3537Syasuoka * Copyright (c) 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*363e4d4bSyasuoka * $Id: npppd.c,v 1.14 2012/01/18 03:13:04 yasuoka Exp $ 330fbf3537Syasuoka */ 340fbf3537Syasuoka #include <sys/cdefs.h> 350fbf3537Syasuoka #include "version.h" 360fbf3537Syasuoka #ifndef LINT 370fbf3537Syasuoka __COPYRIGHT( 380fbf3537Syasuoka "@(#) npppd - PPP daemon for PPP Access Concentrators\n" 390fbf3537Syasuoka "@(#) Version " VERSION "\n" 400fbf3537Syasuoka "@(#) \n" 410fbf3537Syasuoka "@(#) Copyright 2005-2008\n" 420fbf3537Syasuoka "@(#) Internet Initiative Japan Inc. All rights reserved.\n" 430fbf3537Syasuoka "@(#) \n" 440fbf3537Syasuoka "@(#) \n" 450fbf3537Syasuoka "@(#) \n" 460fbf3537Syasuoka ); 470fbf3537Syasuoka #endif 480fbf3537Syasuoka #include <sys/types.h> 490fbf3537Syasuoka #include <sys/socket.h> 500fbf3537Syasuoka #include <sys/param.h> 510fbf3537Syasuoka #include <sys/sysctl.h> 525fefcc09Syasuoka #include <sys/wait.h> 530fbf3537Syasuoka #include <netinet/in.h> 540fbf3537Syasuoka #include <netinet/in_systm.h> 550fbf3537Syasuoka #include <netinet/ip.h> 560fbf3537Syasuoka #include <net/route.h> 570fbf3537Syasuoka #include <arpa/inet.h> 580fbf3537Syasuoka #include <net/if_dl.h> 590fbf3537Syasuoka #include <unistd.h> 600fbf3537Syasuoka #include <time.h> 610fbf3537Syasuoka #include <syslog.h> 620fbf3537Syasuoka #include <string.h> 630fbf3537Syasuoka #include <stdlib.h> 640fbf3537Syasuoka #include <stdio.h> 650fbf3537Syasuoka #include <signal.h> 660fbf3537Syasuoka #include <netdb.h> 670fbf3537Syasuoka #include <libgen.h> 680fbf3537Syasuoka #include <fcntl.h> 690fbf3537Syasuoka #include <event.h> 700fbf3537Syasuoka #include <errno.h> 710fbf3537Syasuoka #include <ifaddrs.h> 724a78f66bSyasuoka #include <err.h> 734a78f66bSyasuoka #include <pwd.h> 740fbf3537Syasuoka 750fbf3537Syasuoka #include "pathnames.h" 760fbf3537Syasuoka #include "debugutil.h" 770fbf3537Syasuoka #include "addr_range.h" 780fbf3537Syasuoka #include "npppd_subr.h" 790fbf3537Syasuoka #include "npppd_local.h" 800fbf3537Syasuoka #include "npppd_auth.h" 810fbf3537Syasuoka #include "radish.h" 820fbf3537Syasuoka #include "rtev.h" 830fbf3537Syasuoka #include "net_utils.h" 840fbf3537Syasuoka #include "time_utils.h" 850fbf3537Syasuoka 860fbf3537Syasuoka #ifdef USE_NPPPD_ARP 870fbf3537Syasuoka #include "npppd_arp.h" 880fbf3537Syasuoka #endif 890fbf3537Syasuoka 900fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 910fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 920fbf3537Syasuoka #include "pppoe_local.h" 930fbf3537Syasuoka #endif /* USE_NPPPD_PPPOE */ 940fbf3537Syasuoka #include "psm-opt.h" 950fbf3537Syasuoka #include <sys/ioctl.h> 960fbf3537Syasuoka #if defined(__NetBSD__) 970fbf3537Syasuoka #include <net/if_ether.h> 980fbf3537Syasuoka #else 990fbf3537Syasuoka #include <netinet/if_ether.h> 1000fbf3537Syasuoka #endif 101886d2b78Syasuoka #include <netinet/ip_var.h> 102886d2b78Syasuoka #include <net/if_types.h> 1030fbf3537Syasuoka #include <net/pipex.h> 1040fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 1050fbf3537Syasuoka 1060fbf3537Syasuoka static npppd s_npppd; /* singleton */ 1070fbf3537Syasuoka 1080fbf3537Syasuoka static void npppd_reload0(npppd *); 1090fbf3537Syasuoka static int npppd_rd_walktree_delete(struct radish_head *); 1100fbf3537Syasuoka static void usage (void); 1110fbf3537Syasuoka static void npppd_start (npppd *); 1120fbf3537Syasuoka static void npppd_stop_really (npppd *); 1130fbf3537Syasuoka static uint32_t str_hash(const void *, int); 1140fbf3537Syasuoka static void npppd_on_sighup (int, short, void *); 1150fbf3537Syasuoka static void npppd_on_sigterm (int, short, void *); 1160fbf3537Syasuoka static void npppd_on_sigint (int, short, void *); 1175fefcc09Syasuoka static void npppd_on_sigchld (int, short, void *); 1180fbf3537Syasuoka static void npppd_reset_timer(npppd *); 1190fbf3537Syasuoka static void npppd_timer(int, short, void *); 1200fbf3537Syasuoka static void npppd_auth_finalizer_periodic(npppd *); 1210fbf3537Syasuoka static int rd2slist_walk (struct radish *, void *); 1220fbf3537Syasuoka static int rd2slist (struct radish_head *, slist *); 1230fbf3537Syasuoka static inline void seed_random(long *); 1240fbf3537Syasuoka 1250fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1260fbf3537Syasuoka static struct in_addr loop; /* initialize at npppd_init() */ 1270fbf3537Syasuoka #endif 1280fbf3537Syasuoka static uint32_t str_hash(const void *, int); 1290fbf3537Syasuoka 1300fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 1310fbf3537Syasuoka static int npppd_ppp_pipex_ip_disable(npppd *, npppd_ppp *); 1320fbf3537Syasuoka static void pipex_periodic(npppd *); 1330fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 1340fbf3537Syasuoka 1350fbf3537Syasuoka #ifdef NPPPD_DEBUG 1360fbf3537Syasuoka #define NPPPD_DBG(x) log_printf x 1370fbf3537Syasuoka #define NPPPD_ASSERT(x) ASSERT(x) 1380fbf3537Syasuoka #else 1390fbf3537Syasuoka #define NPPPD_DBG(x) 1400fbf3537Syasuoka #define NPPPD_ASSERT(x) 1410fbf3537Syasuoka #endif 1420fbf3537Syasuoka 1430fbf3537Syasuoka /*********************************************************************** 144f0a4e295Syasuoka * Daemon process 1450fbf3537Syasuoka ***********************************************************************/ 1460fbf3537Syasuoka int main (int, char *[]); 1470fbf3537Syasuoka 1480fbf3537Syasuoka int 1490fbf3537Syasuoka main(int argc, char *argv[]) 1500fbf3537Syasuoka { 1515fefcc09Syasuoka int ch, retstatus, ll_adjust = 0, runasdaemon = 0; 1520fbf3537Syasuoka extern char *optarg; 1530fbf3537Syasuoka const char *npppd_conf0 = DEFAULT_NPPPD_CONF; 1544a78f66bSyasuoka struct passwd *pw; 1550fbf3537Syasuoka 1565fefcc09Syasuoka retstatus = EXIT_SUCCESS; 1570fbf3537Syasuoka while ((ch = getopt(argc, argv, "Dc:dhs")) != -1) { 1580fbf3537Syasuoka switch (ch) { 1590fbf3537Syasuoka case 's': 1600fbf3537Syasuoka ll_adjust++; 1610fbf3537Syasuoka break; 1620fbf3537Syasuoka case 'c': 1630fbf3537Syasuoka npppd_conf0 = optarg; 1640fbf3537Syasuoka break; 1650fbf3537Syasuoka case 'D': 1660fbf3537Syasuoka runasdaemon = 1; 1670fbf3537Syasuoka break; 1680fbf3537Syasuoka case 'd': 1690fbf3537Syasuoka debuglevel++; 1700fbf3537Syasuoka break; 1710fbf3537Syasuoka case '?': 1720fbf3537Syasuoka case 'h': 1730fbf3537Syasuoka usage(); 1740fbf3537Syasuoka exit(1); 1750fbf3537Syasuoka } 1760fbf3537Syasuoka } 1770fbf3537Syasuoka if (debuglevel > 0) { 1780fbf3537Syasuoka debug_set_debugfp(stderr); 1790fbf3537Syasuoka debug_use_syslog(0); 1800fbf3537Syasuoka } else { 1810fbf3537Syasuoka debug_set_syslog_level_adjust(ll_adjust); 1820fbf3537Syasuoka openlog(NULL, LOG_PID, LOG_NPPPD); 1830fbf3537Syasuoka if (runasdaemon) 1840fbf3537Syasuoka daemon(0, 0); 1850fbf3537Syasuoka } 1860fbf3537Syasuoka 1874a78f66bSyasuoka /* check for root privileges */ 1884a78f66bSyasuoka if (geteuid()) 1894a78f66bSyasuoka errx(1, "need root privileges"); 1904a78f66bSyasuoka /* check for npppd user */ 1914a78f66bSyasuoka if (getpwnam(NPPPD_USER) == NULL) 1924a78f66bSyasuoka errx(1, "unknown user %s", NPPPD_USER); 1934a78f66bSyasuoka 1944a78f66bSyasuoka if (privsep_init() != 0) 1954a78f66bSyasuoka err(1, "cannot drop privileges"); 1964a78f66bSyasuoka 1970fbf3537Syasuoka if (npppd_init(&s_npppd, npppd_conf0) != 0) { 1985fefcc09Syasuoka retstatus = EXIT_FAILURE; 199f0a4e295Syasuoka goto fail; 2000fbf3537Syasuoka } 2014a78f66bSyasuoka 2024a78f66bSyasuoka if ((pw = getpwnam(NPPPD_USER)) == NULL) 2034a78f66bSyasuoka err(1, "gwpwnam"); 2044a78f66bSyasuoka if (chroot(pw->pw_dir) == -1) 2054a78f66bSyasuoka err(1, "chroot"); 2064a78f66bSyasuoka if (chdir("/") == -1) 2074a78f66bSyasuoka err(1, "chdir(\"/\")"); 2084a78f66bSyasuoka if (setgroups(1, &pw->pw_gid) || 2094a78f66bSyasuoka setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 2104a78f66bSyasuoka setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 2114a78f66bSyasuoka err(1, "cannot drop privileges"); 2124a78f66bSyasuoka /* privileges is dropped */ 2134a78f66bSyasuoka 2140fbf3537Syasuoka npppd_start(&s_npppd); 2155fefcc09Syasuoka if (s_npppd.stop_by_error != 0) 2165fefcc09Syasuoka retstatus = EXIT_FAILURE; 2170fbf3537Syasuoka npppd_fini(&s_npppd); 2184a78f66bSyasuoka /* FALLTHROUGH */ 219f0a4e295Syasuoka fail: 2204a78f66bSyasuoka privsep_fini(); 2210fbf3537Syasuoka log_printf(LOG_NOTICE, "Terminate npppd."); 2220fbf3537Syasuoka 2235fefcc09Syasuoka exit(retstatus); 2240fbf3537Syasuoka } 2250fbf3537Syasuoka 2260fbf3537Syasuoka static void 2270fbf3537Syasuoka usage() 2280fbf3537Syasuoka { 2290fbf3537Syasuoka fprintf(stderr, 2300fbf3537Syasuoka "usage: npppd [-sDdh] [-c config_file]\n" 2310fbf3537Syasuoka "\t-d: increase debuglevel. Output log to standard error.\n" 2320fbf3537Syasuoka "\t-c: specify configuration file. default=\"%s\".\n" 2330fbf3537Syasuoka "\t-s: adjust syslog level to be silent.\n" 2340fbf3537Syasuoka "\t-D: run as a daemon.\n" 2350fbf3537Syasuoka "\t-h: show usage.\n" 2360fbf3537Syasuoka , DEFAULT_NPPPD_CONF 2370fbf3537Syasuoka ); 2380fbf3537Syasuoka } 2390fbf3537Syasuoka 240f0a4e295Syasuoka /** Returns the singleton npppd instance */ 2410fbf3537Syasuoka npppd * 2420fbf3537Syasuoka npppd_get_npppd() 2430fbf3537Syasuoka { 2440fbf3537Syasuoka return &s_npppd; 2450fbf3537Syasuoka } 2460fbf3537Syasuoka 2470fbf3537Syasuoka /*********************************************************************** 248f0a4e295Syasuoka * Operations to npppd itself (initialize/finalize/start/stop) 2490fbf3537Syasuoka ***********************************************************************/ 250f0a4e295Syasuoka /** Initialize the npppd */ 2510fbf3537Syasuoka int 2520fbf3537Syasuoka npppd_init(npppd *_this, const char *config_file) 2530fbf3537Syasuoka { 2540fbf3537Syasuoka int i, status = -1; 2550fbf3537Syasuoka char pidpath[MAXPATHLEN]; 2560fbf3537Syasuoka const char *pidpath0; 2570fbf3537Syasuoka const char *coredir; 2580fbf3537Syasuoka FILE *pidfp = NULL; 2590fbf3537Syasuoka char cwd[MAXPATHLEN]; 2600fbf3537Syasuoka long seed; 2610fbf3537Syasuoka 2620fbf3537Syasuoka memset(_this, 0, sizeof(npppd)); 263cd8e09b9Sdlg #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 2640fbf3537Syasuoka loop.s_addr = htonl(INADDR_LOOPBACK); 265cd8e09b9Sdlg #endif 2660fbf3537Syasuoka 2670fbf3537Syasuoka NPPPD_ASSERT(config_file != NULL); 2680fbf3537Syasuoka 2690fbf3537Syasuoka pidpath0 = NULL; 2700fbf3537Syasuoka _this->pid = getpid(); 2710fbf3537Syasuoka slist_init(&_this->realms); 2720fbf3537Syasuoka 2730fbf3537Syasuoka log_printf(LOG_NOTICE, "Starting npppd pid=%u version=%s", 2740fbf3537Syasuoka _this->pid, VERSION); 2750fbf3537Syasuoka #if defined(BUILD_DATE) && defined(BUILD_TIME) 2760fbf3537Syasuoka log_printf(LOG_INFO, "Build %s %s ", BUILD_DATE, BUILD_TIME); 2770fbf3537Syasuoka #endif 2780fbf3537Syasuoka if (get_nanotime() == INT64_MIN) { 2790fbf3537Syasuoka log_printf(LOG_ERR, "get_nanotime() failed: %m"); 2800fbf3537Syasuoka return 1; 2810fbf3537Syasuoka } 2820fbf3537Syasuoka 2830fbf3537Syasuoka if (realpath(config_file, _this->config_file) == NULL) { 2840fbf3537Syasuoka log_printf(LOG_ERR, "realpath(%s,) failed in %s(): %m", 2850fbf3537Syasuoka config_file, __func__); 2860fbf3537Syasuoka return 1; 2870fbf3537Syasuoka } 288f0a4e295Syasuoka /* we assume 4.4 compatible realpath(). See realpath(3) on BSD. */ 2890fbf3537Syasuoka NPPPD_ASSERT(_this->config_file[0] == '/'); 2900fbf3537Syasuoka 2910fbf3537Syasuoka /* initialize random seeds */ 2920fbf3537Syasuoka seed_random(&seed); 2930fbf3537Syasuoka srandom(seed); 2940fbf3537Syasuoka 2958daf7599Syasuoka _this->boot_id = (uint32_t)random(); 2968daf7599Syasuoka 297f0a4e295Syasuoka /* load configuration */ 2980fbf3537Syasuoka if ((status = npppd_reload_config(_this)) != 0) 2990fbf3537Syasuoka return status; 3000fbf3537Syasuoka 3010fbf3537Syasuoka if ((_this->map_user_ppp = hash_create( 3020fbf3537Syasuoka (int (*) (const void *, const void *))strcmp, str_hash, 3030fbf3537Syasuoka NPPPD_USER_HASH_SIZ)) == NULL) { 3040fbf3537Syasuoka log_printf(LOG_ERR, "hash_create() failed in %s(): %m", 3050fbf3537Syasuoka __func__); 3060fbf3537Syasuoka return -1; 3070fbf3537Syasuoka } 3080fbf3537Syasuoka 3090fbf3537Syasuoka if (npppd_ifaces_load_config(_this) != 0) { 3100fbf3537Syasuoka return -1; 3110fbf3537Syasuoka } 3120fbf3537Syasuoka 3130fbf3537Syasuoka if ((pidpath0 = npppd_config_str(_this, "pidfile")) == NULL) 3140fbf3537Syasuoka pidpath0 = DEFAULT_NPPPD_PIDFILE; 3150fbf3537Syasuoka 316f0a4e295Syasuoka /* Runtime directory */ 3170fbf3537Syasuoka if ((coredir = npppd_config_str(_this, "coredir")) == NULL) { 318f0a4e295Syasuoka /* diretory for pid file */ 3190fbf3537Syasuoka strlcpy(pidpath, pidpath0, sizeof(pidpath)); 3200fbf3537Syasuoka strlcpy(cwd, dirname(pidpath), sizeof(cwd)); 3210fbf3537Syasuoka } 3220fbf3537Syasuoka else { 323f0a4e295Syasuoka /* directory for dumping core */ 3240fbf3537Syasuoka strlcpy(cwd, coredir, sizeof(cwd)); 3250fbf3537Syasuoka } 3260fbf3537Syasuoka if (chdir(cwd) != 0) { 3270fbf3537Syasuoka log_printf(LOG_ERR, "chdir(%s,) failed in %s(): %m", __func__, 3280fbf3537Syasuoka cwd); 3290fbf3537Syasuoka return -1; 3300fbf3537Syasuoka } 3310fbf3537Syasuoka 332f0a4e295Syasuoka /* initialize event(3) */ 3330fbf3537Syasuoka event_init(); 3340fbf3537Syasuoka 335f0a4e295Syasuoka /* initialize rtev */ 3360fbf3537Syasuoka rtev_libevent_init( 3370fbf3537Syasuoka npppd_config_int(_this, "rtsock.event_delay", 3380fbf3537Syasuoka DEFAULT_RTSOCK_EVENT_DELAY), 3390fbf3537Syasuoka npppd_config_int(_this, "rtsock.send_wait_millisec", 3400fbf3537Syasuoka DEFAULT_RTSOCK_SEND_WAIT_MILLISEC), 3410fbf3537Syasuoka npppd_config_int(_this, "rtsock.send_npkts", 3420fbf3537Syasuoka DEFAULT_RTSOCK_SEND_NPKTS), 0); 343f0a4e295Syasuoka 3440fbf3537Syasuoka _this->rtev_event_serial = -1; 3450fbf3537Syasuoka 346f0a4e295Syasuoka /* ignore signals */ 3470fbf3537Syasuoka signal(SIGPIPE, SIG_IGN); 3480fbf3537Syasuoka signal(SIGURG, SIG_IGN); 349f0a4e295Syasuoka 350f0a4e295Syasuoka /* set signal handlers */ 3510fbf3537Syasuoka signal_set(&_this->ev_sigterm, SIGTERM, npppd_on_sigterm, _this); 3520fbf3537Syasuoka signal_set(&_this->ev_sigint, SIGINT, npppd_on_sigint, _this); 3530fbf3537Syasuoka signal_set(&_this->ev_sighup, SIGHUP, npppd_on_sighup, _this); 3545fefcc09Syasuoka signal_set(&_this->ev_sigchld, SIGCHLD, npppd_on_sigchld, _this); 3550fbf3537Syasuoka signal_add(&_this->ev_sigterm, NULL); 3560fbf3537Syasuoka signal_add(&_this->ev_sigint, NULL); 3570fbf3537Syasuoka signal_add(&_this->ev_sighup, NULL); 3585fefcc09Syasuoka signal_add(&_this->ev_sigchld, NULL); 3590fbf3537Syasuoka 3600fbf3537Syasuoka evtimer_set(&_this->ev_timer, npppd_timer, _this); 3610fbf3537Syasuoka 362f0a4e295Syasuoka /* start tun(4) or pppac(4) */ 3630fbf3537Syasuoka status = 0; 3640fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) { 3650fbf3537Syasuoka if (_this->iface[i].initialized != 0) 3660fbf3537Syasuoka status |= npppd_iface_start(&_this->iface[i]); 3670fbf3537Syasuoka } 3680fbf3537Syasuoka if (status != 0) 3690fbf3537Syasuoka return -1; 3700fbf3537Syasuoka 3710fbf3537Syasuoka /* 372f0a4e295Syasuoka * If the npppd can start(open) interfaces successfully, it can 373f0a4e295Syasuoka * act as only one npppd process on the system and overwrite the pid 374f0a4e295Syasuoka * file. 3750fbf3537Syasuoka */ 3760fbf3537Syasuoka if ((pidfp = fopen(pidpath0, "w+")) == NULL) { 3770fbf3537Syasuoka log_printf(LOG_ERR, "fopen(%s,w+) failed in %s(): %m", 3780fbf3537Syasuoka pidpath0, __func__); 3790fbf3537Syasuoka return -1; 3800fbf3537Syasuoka } 3810fbf3537Syasuoka strlcpy(_this->pidpath, pidpath0, sizeof(_this->pidpath)); 3820fbf3537Syasuoka fprintf(pidfp, "%u\n", _this->pid); 3830fbf3537Syasuoka fclose(pidfp); 3840fbf3537Syasuoka pidfp = NULL; 3850fbf3537Syasuoka #ifdef USE_NPPPD_ARP 3860fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); 3870fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) 3880fbf3537Syasuoka arp_sock_init(); 3890fbf3537Syasuoka #endif 390*363e4d4bSyasuoka npppd_ctl_init(&_this->ctl, _this, NPPPD_CTL_SOCK_PATH); 391*363e4d4bSyasuoka if ((status = npppd_ctl_start(&_this->ctl)) != 0) 392*363e4d4bSyasuoka return status; 3930fbf3537Syasuoka return npppd_modules_reload(_this); 3940fbf3537Syasuoka } 3950fbf3537Syasuoka 396f0a4e295Syasuoka /** start the npppd */ 3970fbf3537Syasuoka void 3980fbf3537Syasuoka npppd_start(npppd *_this) 3990fbf3537Syasuoka { 4000fbf3537Syasuoka int rval = 0; 4010fbf3537Syasuoka 4020fbf3537Syasuoka npppd_reset_timer(_this); 4030fbf3537Syasuoka while ((event_loop(EVLOOP_ONCE)) == 0) { 4040fbf3537Syasuoka if (_this->finalized != 0) 4050fbf3537Syasuoka break; 4060fbf3537Syasuoka } 4070fbf3537Syasuoka if (rval != 0) 4080fbf3537Syasuoka log_printf(LOG_CRIT, "event_loop() failed: %m"); 4090fbf3537Syasuoka } 4100fbf3537Syasuoka 411f0a4e295Syasuoka /** stop the npppd */ 4120fbf3537Syasuoka void 4130fbf3537Syasuoka npppd_stop(npppd *_this) 4140fbf3537Syasuoka { 4150fbf3537Syasuoka int i; 4160fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4170fbf3537Syasuoka l2tpd_stop(&_this->l2tpd); 4180fbf3537Syasuoka #endif 4190fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4200fbf3537Syasuoka pptpd_stop(&_this->pptpd); 4210fbf3537Syasuoka #endif 4220fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 4230fbf3537Syasuoka pppoed_stop(&_this->pppoed); 4240fbf3537Syasuoka #endif 4250fbf3537Syasuoka #ifdef USE_NPPPD_NPPPD_CTL 4260fbf3537Syasuoka npppd_ctl_stop(&_this->ctl); 4270fbf3537Syasuoka #endif 4280fbf3537Syasuoka #ifdef USE_NPPPD_ARP 4290fbf3537Syasuoka arp_sock_fini(); 4300fbf3537Syasuoka #endif 4310fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 4320fbf3537Syasuoka if (_this->iface[i].initialized != 0) 4330fbf3537Syasuoka npppd_iface_stop(&_this->iface[i]); 4340fbf3537Syasuoka } 4350fbf3537Syasuoka npppd_set_radish(_this, NULL); 4360fbf3537Syasuoka 4370fbf3537Syasuoka _this->finalizing = 1; 4380fbf3537Syasuoka npppd_reset_timer(_this); 4390fbf3537Syasuoka } 4400fbf3537Syasuoka 4410fbf3537Syasuoka static void 4420fbf3537Syasuoka npppd_stop_really(npppd *_this) 4430fbf3537Syasuoka { 4440fbf3537Syasuoka int i; 4450fbf3537Syasuoka #if defined(USE_NPPPD_L2TP) || defined(USE_NPPPD_PPTP) 4460fbf3537Syasuoka int wait_again; 4470fbf3537Syasuoka 4480fbf3537Syasuoka wait_again = 0; 4490fbf3537Syasuoka 4500fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4510fbf3537Syasuoka if (!l2tpd_is_stopped(&_this->l2tpd)) 4520fbf3537Syasuoka wait_again |= 1; 4530fbf3537Syasuoka #endif 4540fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4550fbf3537Syasuoka if (!pptpd_is_stopped(&_this->pptpd)) 4560fbf3537Syasuoka wait_again |= 1; 4570fbf3537Syasuoka #endif 4580fbf3537Syasuoka if (wait_again != 0) { 4590fbf3537Syasuoka npppd_reset_timer(_this); 4600fbf3537Syasuoka return; 4610fbf3537Syasuoka } 4620fbf3537Syasuoka #endif 4630fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 4640fbf3537Syasuoka if (_this->iface[i].initialized != 0) 4650fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]); 4660fbf3537Syasuoka } 4670fbf3537Syasuoka _this->finalized = 1; 4680fbf3537Syasuoka } 4690fbf3537Syasuoka 470f0a4e295Syasuoka /** finalize the npppd */ 4710fbf3537Syasuoka void 4720fbf3537Syasuoka npppd_fini(npppd *_this) 4730fbf3537Syasuoka { 4740fbf3537Syasuoka int i; 4750fbf3537Syasuoka npppd_auth_base *auth_base; 4760fbf3537Syasuoka 4770fbf3537Syasuoka #ifdef USE_NPPPD_L2TP 4780fbf3537Syasuoka l2tpd_uninit(&_this->l2tpd); 4790fbf3537Syasuoka #endif 4800fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 4810fbf3537Syasuoka pptpd_uninit(&_this->pptpd); 4820fbf3537Syasuoka #endif 4830fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 4840fbf3537Syasuoka pppoed_uninit(&_this->pppoed); 4850fbf3537Syasuoka #endif 4860fbf3537Syasuoka for (slist_itr_first(&_this->realms); 4870fbf3537Syasuoka slist_itr_has_next(&_this->realms);) { 4880fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms); 4890fbf3537Syasuoka npppd_auth_destroy(auth_base); 4900fbf3537Syasuoka } 4910fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) { 4920fbf3537Syasuoka if (_this->iface[i].initialized != 0) 4930fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]); 4940fbf3537Syasuoka } 4950fbf3537Syasuoka for (i = 0; i < countof(_this->iface_bind); i++) 4960fbf3537Syasuoka slist_fini(&_this->iface_bind[i].pools); 4970fbf3537Syasuoka 4980fbf3537Syasuoka for (i = countof(_this->pool) - 1; i >= 0; i--) { 4990fbf3537Syasuoka if (_this->pool[i].initialized != 0) 5000fbf3537Syasuoka npppd_pool_uninit(&_this->pool[i]); 5010fbf3537Syasuoka } 5020fbf3537Syasuoka 5030fbf3537Syasuoka signal_del(&_this->ev_sigterm); 5040fbf3537Syasuoka signal_del(&_this->ev_sigint); 5050fbf3537Syasuoka signal_del(&_this->ev_sighup); 5065fefcc09Syasuoka signal_del(&_this->ev_sigchld); 5070fbf3537Syasuoka 5080fbf3537Syasuoka if (_this->properties != NULL) 5090fbf3537Syasuoka properties_destroy(_this->properties); 5100fbf3537Syasuoka 5110fbf3537Syasuoka slist_fini(&_this->realms); 5120fbf3537Syasuoka 5130fbf3537Syasuoka if (_this->map_user_ppp != NULL) 5140fbf3537Syasuoka hash_free(_this->map_user_ppp); 5150fbf3537Syasuoka 5160fbf3537Syasuoka rtev_fini(); 5170fbf3537Syasuoka } 5180fbf3537Syasuoka 5190fbf3537Syasuoka /*********************************************************************** 520f0a4e295Syasuoka * Timer related functions 5210fbf3537Syasuoka ***********************************************************************/ 5220fbf3537Syasuoka static void 5230fbf3537Syasuoka npppd_reset_timer(npppd *_this) 5240fbf3537Syasuoka { 5250fbf3537Syasuoka struct timeval tv; 5260fbf3537Syasuoka 5270fbf3537Syasuoka if (_this->finalizing != 0) { 528f0a4e295Syasuoka /* we can use the timer exclusively on finalizing */ 5290fbf3537Syasuoka tv.tv_usec = 500000; 5300fbf3537Syasuoka tv.tv_sec = 0; 5310fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 5320fbf3537Syasuoka } else { 5330fbf3537Syasuoka tv.tv_usec = 0; 5340fbf3537Syasuoka tv.tv_sec = NPPPD_TIMER_TICK_IVAL; 5350fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv); 5360fbf3537Syasuoka } 5370fbf3537Syasuoka } 5380fbf3537Syasuoka 5390fbf3537Syasuoka static void 5400fbf3537Syasuoka npppd_timer(int fd, short evtype, void *ctx) 5410fbf3537Syasuoka { 5420fbf3537Syasuoka npppd *_this; 5430fbf3537Syasuoka 5440fbf3537Syasuoka _this = ctx; 5450fbf3537Syasuoka if (_this->finalizing != 0) { 546f0a4e295Syasuoka npppd_stop_really(_this); /* The timer has been reset */ 547f0a4e295Syasuoka return; /* we can use the timer exclusively on finalizing */ 5480fbf3537Syasuoka } 5490fbf3537Syasuoka _this->secs += NPPPD_TIMER_TICK_IVAL; 5500fbf3537Syasuoka if (_this->reloading_count > 0) { 5510fbf3537Syasuoka _this->reloading_count -= NPPPD_TIMER_TICK_IVAL; 5520fbf3537Syasuoka if (_this->reloading_count <= 0) { 5530fbf3537Syasuoka npppd_reload0(_this); 5540fbf3537Syasuoka _this->reloading_count = 0; 5550fbf3537Syasuoka } 5560fbf3537Syasuoka } else { 5570fbf3537Syasuoka if ((_this->secs % TIMER_TICK_RUP( 5580fbf3537Syasuoka NPPPD_AUTH_REALM_FINALIZER_INTERVAL)) == 0) 5590fbf3537Syasuoka npppd_auth_finalizer_periodic(_this); 5600fbf3537Syasuoka } 5610fbf3537Syasuoka 5620fbf3537Syasuoka if (_this->rtev_event_serial != rtev_get_event_serial()) { 5630fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 5640fbf3537Syasuoka if (pppoed_need_polling(&_this->pppoed)) 5650fbf3537Syasuoka pppoed_reload_listeners(&_this->pppoed); 5660fbf3537Syasuoka #endif 5670fbf3537Syasuoka } 5680fbf3537Syasuoka _this->rtev_event_serial = rtev_get_event_serial(); 5690fbf3537Syasuoka 5700fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 5710fbf3537Syasuoka pipex_periodic(_this); 5720fbf3537Syasuoka #endif 5730fbf3537Syasuoka 5740fbf3537Syasuoka npppd_reset_timer(_this); 5750fbf3537Syasuoka } 5760fbf3537Syasuoka 5770fbf3537Syasuoka int 5780fbf3537Syasuoka npppd_reset_routing_table(npppd *_this, int pool_only) 5790fbf3537Syasuoka { 5800fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 5810fbf3537Syasuoka slist rtlist0; 5820fbf3537Syasuoka 583cd8e09b9Sdlg if (_this->iface[0].using_pppx) 584cd8e09b9Sdlg return 0; 585cd8e09b9Sdlg 5860fbf3537Syasuoka slist_init(&rtlist0); 5870fbf3537Syasuoka if (rd2slist(_this->rd, &rtlist0) != 0) 5880fbf3537Syasuoka return 1; 5890fbf3537Syasuoka 5900fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0); ) { 5910fbf3537Syasuoka struct radish *rd; 5920fbf3537Syasuoka struct sockaddr_npppd *snp; 5930fbf3537Syasuoka npppd_ppp *ppp; 5940fbf3537Syasuoka int is_first; 5950fbf3537Syasuoka 5960fbf3537Syasuoka rd = slist_itr_next(&rtlist0); 5970fbf3537Syasuoka snp = rd->rd_rtent; 5980fbf3537Syasuoka 5990fbf3537Syasuoka is_first = 1; 6000fbf3537Syasuoka for (snp = rd->rd_rtent; snp != NULL; snp = snp->snp_next) { 6010fbf3537Syasuoka switch (snp->snp_type) { 6020fbf3537Syasuoka case SNP_POOL: 6030fbf3537Syasuoka case SNP_DYN_POOL: 6040fbf3537Syasuoka if (is_first) 6050fbf3537Syasuoka in_route_add(&snp->snp_addr, 6060fbf3537Syasuoka &snp->snp_mask, &loop, 6070fbf3537Syasuoka LOOPBACK_IFNAME, RTF_BLACKHOLE, 0); 6080fbf3537Syasuoka break; 6090fbf3537Syasuoka 6100fbf3537Syasuoka case SNP_PPP: 6110fbf3537Syasuoka if (pool_only) 6120fbf3537Syasuoka break; 6130fbf3537Syasuoka ppp = snp->snp_data_ptr; 6140fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr 6150fbf3537Syasuoka == 0xffffffffL) { 6160fbf3537Syasuoka in_host_route_add(&ppp-> 6170fbf3537Syasuoka ppp_framed_ip_address, 6180fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 6190fbf3537Syasuoka ppp_iface(ppp)->ifname, 6200fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 6210fbf3537Syasuoka } else { 6220fbf3537Syasuoka in_route_add(&ppp-> 6230fbf3537Syasuoka ppp_framed_ip_address, 6240fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 6250fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 6260fbf3537Syasuoka ppp_iface(ppp)->ifname, 0, 6270fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 6280fbf3537Syasuoka } 6290fbf3537Syasuoka break; 6300fbf3537Syasuoka } 6310fbf3537Syasuoka is_first = 0; 6320fbf3537Syasuoka } 6330fbf3537Syasuoka 6340fbf3537Syasuoka } 6350fbf3537Syasuoka 6360fbf3537Syasuoka slist_fini(&rtlist0); 6370fbf3537Syasuoka #endif 6380fbf3537Syasuoka return 0; 6390fbf3537Syasuoka } 6400fbf3537Syasuoka 6410fbf3537Syasuoka /*********************************************************************** 642f0a4e295Syasuoka * Other npppd related functions. 6430fbf3537Syasuoka ***********************************************************************/ 6440fbf3537Syasuoka /** 645f0a4e295Syasuoka * Get the user's password. Return 0 on success. 6460fbf3537Syasuoka * 647f0a4e295Syasuoka * @param username Username who acquires password 648f0a4e295Syasuoka * @param password A pointer to a buffer space to store the password. 649f0a4e295Syasuoka * Use NULL when you need to know only the length of 650f0a4e295Syasuoka * the password. 651f0a4e295Syasuoka * @param plpassword A pointer to the length of the password parameter. 652f0a4e295Syasuoka * This function uses this parameter value and stores 653f0a4e295Syasuoka * the required length value pointed to by this 654f0a4e295Syasuoka * parameter. Use NULL when use don't need to know 655f0a4e295Syasuoka * the password and its length. 656f0a4e295Syasuoka * @return If the function succeeds, 0 is returned. The function returns 657f0a4e295Syasuoka * 1 if the username is unknown, returns 2 if the password buffer 658f0a4e295Syasuoka * length is not enough. It returns negative value for other 659f0a4e295Syasuoka * errors. 6600fbf3537Syasuoka */ 6610fbf3537Syasuoka int 6620fbf3537Syasuoka npppd_get_user_password(npppd *_this, npppd_ppp *ppp, 6630fbf3537Syasuoka const char *username, char *password, int *plpassword) 6640fbf3537Syasuoka { 6650fbf3537Syasuoka char buf0[MAX_USERNAME_LENGTH]; 6660fbf3537Syasuoka 6670fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 6680fbf3537Syasuoka return npppd_auth_get_user_password(ppp->realm, 6690fbf3537Syasuoka npppd_auth_username_for_auth(ppp->realm, username, buf0), password, 6700fbf3537Syasuoka plpassword); 6710fbf3537Syasuoka } 6720fbf3537Syasuoka 673f0a4e295Syasuoka /** Get the Framed-IP-Address attribute of the user */ 6740fbf3537Syasuoka struct in_addr * 6750fbf3537Syasuoka npppd_get_user_framed_ip_address(npppd *_this, npppd_ppp *ppp, 6760fbf3537Syasuoka const char *username) 6770fbf3537Syasuoka { 6780fbf3537Syasuoka 6790fbf3537Syasuoka if (ppp->peer_auth == 0) { 6800fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = 0; 6810fbf3537Syasuoka goto do_default; 6820fbf3537Syasuoka } 6830fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 6840fbf3537Syasuoka 6850fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr != 0) { 6860fbf3537Syasuoka #if 1 6870fbf3537Syasuoka /* 688f0a4e295Syasuoka * FIXME: This fix is ad hok, it overwrites the ip address here if assigning 689f0a4e295Syasuoka * FIXME: IP address by RADIUS is prohibited. This will make a bug when a 690f0a4e295Syasuoka * FIXME: new authentication type is add. Fix this until then. 6910fbf3537Syasuoka */ 6920fbf3537Syasuoka if ((ppp_ipcp(ppp)->ip_assign_flags & NPPPD_IP_ASSIGN_RADIUS) 6930fbf3537Syasuoka == 0) { 6940fbf3537Syasuoka ppp->realm_framed_ip_netmask.s_addr = 0; 6950fbf3537Syasuoka } else 6960fbf3537Syasuoka #endif 6970fbf3537Syasuoka return &ppp->realm_framed_ip_address; 6980fbf3537Syasuoka } 6990fbf3537Syasuoka 7000fbf3537Syasuoka ppp->realm_framed_ip_netmask.s_addr = 0xffffffffL; 7010fbf3537Syasuoka if ((ppp_ipcp(ppp)->ip_assign_flags & NPPPD_IP_ASSIGN_FIXED) != 0) { 702f0a4e295Syasuoka /* assign by the authentication realm */ 7030fbf3537Syasuoka if (npppd_auth_get_framed_ip(ppp->realm, username, 7040fbf3537Syasuoka &ppp->realm_framed_ip_address, 7050fbf3537Syasuoka &ppp->realm_framed_ip_netmask) != 0) 7060fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = 0; 7070fbf3537Syasuoka } 7080fbf3537Syasuoka 7090fbf3537Syasuoka do_default: 710f0a4e295Syasuoka /* Use USER_SELECT if the realm doesn't specify the ip address */ 7110fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == 0) 7120fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_USER_SELECT; 7130fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) { 714f0a4e295Syasuoka /* Use NAS_SELECT if USER_SELECT is not allowed by the config */ 7150fbf3537Syasuoka if ((ppp_ipcp(ppp)->ip_assign_flags & 7160fbf3537Syasuoka NPPPD_IP_ASSIGN_USER_SELECT) == 0) 7170fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_NAS_SELECT; 7180fbf3537Syasuoka } 7190fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() = %s", __func__, 7200fbf3537Syasuoka inet_ntoa(ppp->realm_framed_ip_address))); 7210fbf3537Syasuoka 7220fbf3537Syasuoka return &ppp->realm_framed_ip_address; 7230fbf3537Syasuoka } 7240fbf3537Syasuoka 7250fbf3537Syasuoka /** XXX */ 7260fbf3537Syasuoka int 7270fbf3537Syasuoka npppd_check_calling_number(npppd *_this, npppd_ppp *ppp) 7280fbf3537Syasuoka { 7290fbf3537Syasuoka int lnumber, rval, strict, loose; 7300fbf3537Syasuoka char number[NPPPD_PHONE_NUMBER_LEN + 1]; 7310fbf3537Syasuoka 7320fbf3537Syasuoka strict = ppp_config_str_equal(ppp, "check_callnum", "strict", 0); 7330fbf3537Syasuoka loose = ppp_config_str_equal(ppp, "check_callnum", "loose", 0); 7340fbf3537Syasuoka 7350fbf3537Syasuoka if (strict || loose) { 7360fbf3537Syasuoka lnumber = sizeof(number); 7370fbf3537Syasuoka if ((rval = npppd_auth_get_calling_number(ppp->realm, 7380fbf3537Syasuoka ppp->username, 7390fbf3537Syasuoka number, &lnumber)) == 0) 7400fbf3537Syasuoka return 7410fbf3537Syasuoka (strcmp(number, ppp->calling_number) == 0)? 1 : 0; 7420fbf3537Syasuoka if (strict) 7430fbf3537Syasuoka return 0; 7440fbf3537Syasuoka } 7450fbf3537Syasuoka 7460fbf3537Syasuoka return 1; 7470fbf3537Syasuoka } 7480fbf3537Syasuoka 7490fbf3537Syasuoka /** 750f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that is assigned the 751f0a4e295Syasuoka * specified ip address and returns it 752f0a4e295Syasuoka * @param ipaddr IP Address(Specify in network byte order) 7530fbf3537Syasuoka */ 7540fbf3537Syasuoka npppd_ppp * 7550fbf3537Syasuoka npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr) 7560fbf3537Syasuoka { 7570fbf3537Syasuoka struct sockaddr_npppd *snp; 7580fbf3537Syasuoka struct radish *rdp; 759f0a4e295Syasuoka struct sockaddr_in npppd_get_ppp_by_ip_sin4; 7600fbf3537Syasuoka 761f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_family = AF_INET; 762f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_len = sizeof(struct sockaddr_in); 7630fbf3537Syasuoka npppd_get_ppp_by_ip_sin4.sin_addr = ipaddr; 7640fbf3537Syasuoka if (_this->rd == NULL) 765f0a4e295Syasuoka return NULL; /* no radix tree on startup */ 7660fbf3537Syasuoka if (rd_match((struct sockaddr *)&npppd_get_ppp_by_ip_sin4, _this->rd, 7670fbf3537Syasuoka &rdp)) { 7680fbf3537Syasuoka snp = rdp->rd_rtent; 7690fbf3537Syasuoka if (snp->snp_type == SNP_PPP) 7700fbf3537Syasuoka return snp->snp_data_ptr; 7710fbf3537Syasuoka } 7720fbf3537Syasuoka return NULL; 7730fbf3537Syasuoka } 7740fbf3537Syasuoka 7750fbf3537Syasuoka /** 776f0a4e295Syasuoka * This function finds {@link npppd_ppp} instances that are authenticated 777f0a4e295Syasuoka * as the specified username and returns them as a {@link slist} list. 778f0a4e295Syasuoka * @param username PPP Username. 779f0a4e295Syasuoka * @return {@link slist} that contans the {@link npppd_ppp} instances. 780f0a4e295Syasuoka * NULL may be returned if no instance has been found. 7810fbf3537Syasuoka */ 7820fbf3537Syasuoka slist * 7830fbf3537Syasuoka npppd_get_ppp_by_user(npppd *_this, const char *username) 7840fbf3537Syasuoka { 7850fbf3537Syasuoka hash_link *hl; 7860fbf3537Syasuoka 7870fbf3537Syasuoka if ((hl = hash_lookup(_this->map_user_ppp, username)) != NULL) 7880fbf3537Syasuoka return hl->item; 7890fbf3537Syasuoka 7900fbf3537Syasuoka return NULL; 7910fbf3537Syasuoka } 7920fbf3537Syasuoka 7930fbf3537Syasuoka /** 794f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that matches the specified 795f0a4e295Syasuoka * ppp id and returns it. 796f0a4e295Syasuoka * @param id {@link npppd_ppp#id ppp's id} 797f0a4e295Syasuoka * @return This function returns the pointer if the instance which has 798f0a4e295Syasuoka * specified ID is found, otherwise it returns NULL. 7990fbf3537Syasuoka */ 8000fbf3537Syasuoka npppd_ppp * 801*363e4d4bSyasuoka npppd_get_ppp_by_id(npppd *_this, u_int ppp_id) 8020fbf3537Syasuoka { 8030fbf3537Syasuoka slist users; 8040fbf3537Syasuoka npppd_ppp *ppp0, *ppp; 8050fbf3537Syasuoka 8060fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 8070fbf3537Syasuoka 8080fbf3537Syasuoka ppp = NULL; 8090fbf3537Syasuoka slist_init(&users); 8100fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 8110fbf3537Syasuoka log_printf(LOG_WARNING, 8120fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__); 8130fbf3537Syasuoka } else { 814f0a4e295Syasuoka /* FIXME: This linear search eats CPU. */ 8150fbf3537Syasuoka for (slist_itr_first(&users); slist_itr_has_next(&users); ) { 8160fbf3537Syasuoka ppp0 = slist_itr_next(&users); 8170fbf3537Syasuoka if (ppp0->id == ppp_id) { 8180fbf3537Syasuoka ppp = ppp0; 8190fbf3537Syasuoka break; 8200fbf3537Syasuoka } 8210fbf3537Syasuoka } 8220fbf3537Syasuoka } 8230fbf3537Syasuoka slist_fini(&users); 8240fbf3537Syasuoka 8250fbf3537Syasuoka return ppp; 8260fbf3537Syasuoka } 8270fbf3537Syasuoka 8280fbf3537Syasuoka /** 829f0a4e295Syasuoka * Checks whether the user reaches the maximum session limit 830f0a4e295Syasuoka * (user_max_serssion). 831f0a4e295Syasuoka * @return This function returns 1(true) if the user does not reach the 832f0a4e295Syasuoka * limit, otherwise it returns 0(false). 8330fbf3537Syasuoka */ 8340fbf3537Syasuoka int 8350fbf3537Syasuoka npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp) 8360fbf3537Syasuoka { 8370fbf3537Syasuoka int count; 8380fbf3537Syasuoka npppd_ppp *ppp1; 8390fbf3537Syasuoka slist *uppp; 8400fbf3537Syasuoka 841f0a4e295Syasuoka /* user_max_session == 0 means unlimit */ 842f0a4e295Syasuoka if (ppp_iface(ppp)->user_max_session == 0) 8430fbf3537Syasuoka return 1; 8440fbf3537Syasuoka 8450fbf3537Syasuoka count = 0; 8460fbf3537Syasuoka if ((uppp = npppd_get_ppp_by_user(_this, ppp->username)) != NULL) { 8470fbf3537Syasuoka for (slist_itr_first(uppp); slist_itr_has_next(uppp); ) { 8480fbf3537Syasuoka ppp1 = slist_itr_next(uppp); 8490fbf3537Syasuoka if (strcmp(ppp_iface(ppp)->ifname, 8500fbf3537Syasuoka ppp_iface(ppp1)->ifname) == 0) 8510fbf3537Syasuoka count++; 8520fbf3537Syasuoka } 8530fbf3537Syasuoka } 8540fbf3537Syasuoka 8550fbf3537Syasuoka return (count < ppp_iface(ppp)->user_max_session)? 1 : 0; 8560fbf3537Syasuoka } 8570fbf3537Syasuoka 8580fbf3537Syasuoka /*********************************************************************** 859f0a4e295Syasuoka * Network I/O ralated functions. 8600fbf3537Syasuoka ***********************************************************************/ 8610fbf3537Syasuoka /** 862f0a4e295Syasuoka * Call this function to output packets to the network(tun). This function 863f0a4e295Syasuoka * currently assumes the packet is a IPv4 datagram. 8640fbf3537Syasuoka */ 8650fbf3537Syasuoka void 8660fbf3537Syasuoka npppd_network_output(npppd *_this, npppd_ppp *ppp, int proto, u_char *pktp, 8670fbf3537Syasuoka int lpktp) 8680fbf3537Syasuoka { 8690fbf3537Syasuoka struct ip *pip; 8700fbf3537Syasuoka int lbuf; 871f0a4e295Syasuoka u_char buf[256]; /* enough size for TCP/IP header */ 8720fbf3537Syasuoka 8730fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 8740fbf3537Syasuoka 8750fbf3537Syasuoka if (!ppp_ip_assigned(ppp)) 8760fbf3537Syasuoka return; 8770fbf3537Syasuoka 8780fbf3537Syasuoka if (lpktp < sizeof(struct ip)) { 8790fbf3537Syasuoka ppp_log(ppp, LOG_DEBUG, "Received IP packet is too small"); 8800fbf3537Syasuoka return; 8810fbf3537Syasuoka } 8820fbf3537Syasuoka lbuf = MIN(lpktp, sizeof(buf)); 8830fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip)) { 8840fbf3537Syasuoka memcpy(buf, pktp, lbuf); 8850fbf3537Syasuoka pip = (struct ip *)buf; 8860fbf3537Syasuoka } else { 8870fbf3537Syasuoka pip = (struct ip *)pktp; 8880fbf3537Syasuoka } 8890fbf3537Syasuoka 8900fbf3537Syasuoka #ifndef NO_INGRES_FILTER 8910fbf3537Syasuoka if ((pip->ip_src.s_addr & ppp->ppp_framed_ip_netmask.s_addr) != 8920fbf3537Syasuoka (ppp->ppp_framed_ip_address.s_addr & 8930fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr)) { 8940fbf3537Syasuoka char logbuf[80]; 8950fbf3537Syasuoka strlcpy(logbuf, inet_ntoa(pip->ip_dst), sizeof(logbuf)); 8960fbf3537Syasuoka ppp_log(ppp, LOG_INFO, 8970fbf3537Syasuoka "Drop packet by ingress filter. %s => %s", 8980fbf3537Syasuoka inet_ntoa(pip->ip_src), logbuf); 8990fbf3537Syasuoka 9000fbf3537Syasuoka return; 9010fbf3537Syasuoka } 9020fbf3537Syasuoka #endif 9030fbf3537Syasuoka if (ppp->timeout_sec > 0 && !ip_is_idle_packet(pip, lbuf)) 9040fbf3537Syasuoka ppp_reset_idle_timeout(ppp); 9050fbf3537Syasuoka 9060fbf3537Syasuoka #ifndef NO_ADJUST_MSS 9070fbf3537Syasuoka if (ppp->adjust_mss) { 9080fbf3537Syasuoka if (lpktp == lbuf) { 9090fbf3537Syasuoka /* 910f0a4e295Syasuoka * We can assume the packet length is less than 911f0a4e295Syasuoka * sizeof(buf). 9120fbf3537Syasuoka */ 9130fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip)) 9140fbf3537Syasuoka pktp = buf; 9150fbf3537Syasuoka adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru)); 9160fbf3537Syasuoka } 9170fbf3537Syasuoka } 9180fbf3537Syasuoka #endif 9190fbf3537Syasuoka npppd_iface_write(ppp_iface(ppp), proto, pktp, lpktp); 9200fbf3537Syasuoka } 9210fbf3537Syasuoka 9220fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 923f0a4e295Syasuoka /*********************************************************************** 924f0a4e295Syasuoka * PIPEX related functions 925f0a4e295Syasuoka ***********************************************************************/ 9260fbf3537Syasuoka static void 9270fbf3537Syasuoka pipex_setup_common(npppd_ppp *ppp, struct pipex_session_req *req) 9280fbf3537Syasuoka { 9290fbf3537Syasuoka memset(req, 0, sizeof(*req)); 9300fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, acfc)) 9310fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ENABLED; 9320fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, acfc)) 9330fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ACCEPTED; 9340fbf3537Syasuoka 9350fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, pfc)) 9360fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ACCEPTED; 9370fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, pfc)) 9380fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ENABLED; 9390fbf3537Syasuoka 9400fbf3537Syasuoka if (ppp->has_acf != 0) 9410fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_HAS_ACF; 9420fbf3537Syasuoka 9430fbf3537Syasuoka if (ppp->adjust_mss != 0) 9440fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ADJUST_TCPMSS; 9450fbf3537Syasuoka 946cd8e09b9Sdlg req->pr_ip_srcaddr = ppp->pppd->iface[0].ip4addr; 9470fbf3537Syasuoka req->pr_ip_address = ppp->ppp_framed_ip_address; 9480fbf3537Syasuoka req->pr_ip_netmask = ppp->ppp_framed_ip_netmask; 9490fbf3537Syasuoka req->pr_peer_mru = ppp->peer_mru; 9500fbf3537Syasuoka req->pr_ppp_id = ppp->id; 9510fbf3537Syasuoka 9520fbf3537Syasuoka req->pr_timeout_sec = ppp->timeout_sec; 9530fbf3537Syasuoka 9540fbf3537Syasuoka #ifdef USE_NPPPD_MPPE 9550fbf3537Syasuoka req->pr_ccp_id = ppp->ccp.fsm.id; 9560fbf3537Syasuoka memcpy(req->pr_mppe_send.master_key, 9570fbf3537Syasuoka ppp->mppe.send.master_key, sizeof(req->pr_mppe_send.master_key)); 9580fbf3537Syasuoka req->pr_mppe_send.stateless = ppp->mppe.send.stateless; 9590fbf3537Syasuoka req->pr_mppe_send.keylenbits = ppp->mppe.send.keybits; 9600fbf3537Syasuoka 9610fbf3537Syasuoka memcpy(req->pr_mppe_recv.master_key, 9620fbf3537Syasuoka ppp->mppe.recv.master_key, sizeof(req->pr_mppe_recv.master_key)); 9630fbf3537Syasuoka req->pr_mppe_recv.stateless = ppp->mppe.recv.stateless; 9640fbf3537Syasuoka req->pr_mppe_recv.keylenbits = ppp->mppe.recv.keybits; 9650fbf3537Syasuoka 9660fbf3537Syasuoka if (ppp->mppe_started != 0) { 9670fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED; 9680fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ENABLED; 9690fbf3537Syasuoka } 9700fbf3537Syasuoka if (ppp->mppe.required) 9710fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_REQUIRED; 9720fbf3537Syasuoka #endif /* USE_NPPPD_MPPE */ 9730fbf3537Syasuoka } 9740fbf3537Syasuoka 975f0a4e295Syasuoka /** Enable PIPEX of the {@link npppd_ppp ppp} */ 9760fbf3537Syasuoka int 9770fbf3537Syasuoka npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) 9780fbf3537Syasuoka { 9790fbf3537Syasuoka struct pipex_session_req req; 9800fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 9810fbf3537Syasuoka pppoe_session *pppoe; 9820fbf3537Syasuoka #endif 9830fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 9840fbf3537Syasuoka pptp_call *call; 9850fbf3537Syasuoka #endif 986886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 987886d2b78Syasuoka l2tp_call *l2tp; 988886d2b78Syasuoka l2tp_ctrl *l2tpctrl; 989886d2b78Syasuoka #endif 9900fbf3537Syasuoka int error; 9910fbf3537Syasuoka 9920fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 9930fbf3537Syasuoka NPPPD_ASSERT(ppp->phy_context != NULL); 9940fbf3537Syasuoka NPPPD_ASSERT(ppp->use_pipex != 0); 9950fbf3537Syasuoka 9960fbf3537Syasuoka pipex_setup_common(ppp, &req); 9970fbf3537Syasuoka 9980fbf3537Syasuoka switch (ppp->tunnel_type) { 9990fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 10000fbf3537Syasuoka case PPP_TUNNEL_PPPOE: 1001886d2b78Syasuoka { 1002886d2b78Syasuoka struct sockaddr *sa; 1003886d2b78Syasuoka struct ether_header *eh; 10040fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 10050fbf3537Syasuoka 1006f0a4e295Syasuoka /* PPPoE specific informations */ 10070fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPPOE; 10080fbf3537Syasuoka req.pr_session_id = pppoe->session_id; 10090fbf3537Syasuoka req.pr_peer_session_id = 0; 10100fbf3537Syasuoka strlcpy(req.pr_proto.pppoe.over_ifname, 10110fbf3537Syasuoka pppoe_session_listen_ifname(pppoe), 10120fbf3537Syasuoka sizeof(req.pr_proto.pppoe.over_ifname)); 1013886d2b78Syasuoka 1014886d2b78Syasuoka sa = (struct sockaddr *)&req.peer_address; 1015886d2b78Syasuoka sa->sa_family = AF_UNSPEC; 1016886d2b78Syasuoka sa->sa_len = sizeof(struct sockaddr); 1017886d2b78Syasuoka 1018886d2b78Syasuoka eh = (struct ether_header *)sa->sa_data; 1019886d2b78Syasuoka eh->ether_type = htons(ETHERTYPE_PPPOE); 1020886d2b78Syasuoka memcpy(eh->ether_dhost, pppoe->ether_addr, ETHER_ADDR_LEN); 1021886d2b78Syasuoka memset(eh->ether_shost, 0, ETHER_ADDR_LEN); 10220fbf3537Syasuoka 10230fbf3537Syasuoka break; 1024886d2b78Syasuoka } 10250fbf3537Syasuoka #endif 10260fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 10270fbf3537Syasuoka case PPP_TUNNEL_PPTP: 10280fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 10290fbf3537Syasuoka 1030f0a4e295Syasuoka /* PPTP specific informations */ 10310fbf3537Syasuoka req.pr_session_id = call->id; 10320fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPTP; 10330fbf3537Syasuoka 10340fbf3537Syasuoka req.pr_peer_session_id = call->peers_call_id; 10350fbf3537Syasuoka req.pr_proto.pptp.snd_nxt = call->snd_nxt; 10360fbf3537Syasuoka req.pr_proto.pptp.snd_una = call->snd_una; 10370fbf3537Syasuoka req.pr_proto.pptp.rcv_nxt = call->rcv_nxt; 10380fbf3537Syasuoka req.pr_proto.pptp.rcv_acked = call->rcv_acked; 10390fbf3537Syasuoka req.pr_proto.pptp.winsz = call->winsz; 10400fbf3537Syasuoka req.pr_proto.pptp.maxwinsz = call->maxwinsz; 10410fbf3537Syasuoka req.pr_proto.pptp.peer_maxwinsz = call->peers_maxwinsz; 10420fbf3537Syasuoka 10430fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->peer.ss_family == AF_INET); 10440fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->our.ss_family == AF_INET); 1045886d2b78Syasuoka 1046886d2b78Syasuoka memcpy(&req.peer_address, &call->ctrl->peer, 1047886d2b78Syasuoka call->ctrl->peer.ss_len); 1048886d2b78Syasuoka memcpy(&req.local_address, &call->ctrl->our, 1049886d2b78Syasuoka call->ctrl->our.ss_len); 1050886d2b78Syasuoka break; 1051886d2b78Syasuoka #endif 1052886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1053886d2b78Syasuoka case PPP_TUNNEL_L2TP: 1054886d2b78Syasuoka l2tp = (l2tp_call *)ppp->phy_context; 1055886d2b78Syasuoka l2tpctrl = l2tp->ctrl; 1056886d2b78Syasuoka 1057886d2b78Syasuoka /* L2TPv2 specific context */ 1058886d2b78Syasuoka /* Session KEYS */ 1059886d2b78Syasuoka req.pr_protocol = PIPEX_PROTO_L2TP; 1060886d2b78Syasuoka req.pr_proto.l2tp.tunnel_id = l2tpctrl->tunnel_id; 1061886d2b78Syasuoka req.pr_proto.l2tp.peer_tunnel_id = l2tpctrl->peer_tunnel_id; 1062886d2b78Syasuoka req.pr_session_id = l2tp->session_id; 1063886d2b78Syasuoka req.pr_peer_session_id = l2tp->peer_session_id; 1064886d2b78Syasuoka 1065886d2b78Syasuoka /* options: XXX: needs other? */ 1066886d2b78Syasuoka if (l2tpctrl->data_use_seq) 1067886d2b78Syasuoka req.pr_proto.l2tp.option_flags |= 1068886d2b78Syasuoka PIPEX_L2TP_USE_SEQUENCING; 1069886d2b78Syasuoka 1070886d2b78Syasuoka /* transmission control contexts */ 1071886d2b78Syasuoka req.pr_proto.l2tp.ns_nxt = l2tp->snd_nxt; 1072886d2b78Syasuoka req.pr_proto.l2tp.nr_nxt = l2tp->rcv_nxt; 1073886d2b78Syasuoka 1074886d2b78Syasuoka NPPPD_ASSERT(l2tpctrl->peer.ss_family == AF_INET); 1075886d2b78Syasuoka 1076886d2b78Syasuoka memcpy(&req.peer_address, &l2tpctrl->peer, 1077886d2b78Syasuoka l2tpctrl->peer.ss_len); 1078886d2b78Syasuoka memcpy(&req.local_address, &l2tpctrl->sock, 1079886d2b78Syasuoka l2tpctrl->sock.ss_len); 1080886d2b78Syasuoka #ifdef IP_IPSEC_SA_COOKIE 1081886d2b78Syasuoka if (l2tpctrl->sa_cookie != NULL) 1082886d2b78Syasuoka req.pr_proto.l2tp.ipsec_sa_cookie = 1083886d2b78Syasuoka *(struct in_ipsec_sa_cookie *)l2tpctrl->sa_cookie; 1084886d2b78Syasuoka #endif 10850fbf3537Syasuoka break; 10860fbf3537Syasuoka #endif 10870fbf3537Syasuoka default: 10880fbf3537Syasuoka return 1; 10890fbf3537Syasuoka } 10900fbf3537Syasuoka 10910fbf3537Syasuoka if ((error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXASESSION, &req)) 10920fbf3537Syasuoka != 0) { 10930fbf3537Syasuoka if (errno == ENXIO) /* pipex is disabled on runtime */ 10940fbf3537Syasuoka error = 0; 10950fbf3537Syasuoka ppp->pipex_enabled = 0; 10960fbf3537Syasuoka return error; 10970fbf3537Syasuoka } 10980fbf3537Syasuoka 1099cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx) { 1100cd8e09b9Sdlg struct pipex_session_descr_req descr_req; 1101cd8e09b9Sdlg 1102cd8e09b9Sdlg descr_req.pdr_protocol = req.pr_protocol; 1103cd8e09b9Sdlg descr_req.pdr_session_id = req.pr_session_id; 1104cd8e09b9Sdlg memset(descr_req.pdr_descr, 0, sizeof(descr_req.pdr_descr)); 1105cd8e09b9Sdlg strlcpy(descr_req.pdr_descr, ppp->username, sizeof(descr_req.pdr_descr)); 1106cd8e09b9Sdlg error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXSIFDESCR, &descr_req); 1107cd8e09b9Sdlg if (error != 0) { 1108cd8e09b9Sdlg log_printf(LOG_WARNING, "PIPEXSIFDESCR(%s) failed: %d\n", ppp->username, error); 1109cd8e09b9Sdlg } 1110cd8e09b9Sdlg } 1111cd8e09b9Sdlg 11120fbf3537Syasuoka ppp->pipex_enabled = 1; 11130fbf3537Syasuoka if (ppp->timeout_sec > 0) { 1114f0a4e295Syasuoka /* Stop the npppd's idle-timer. We use pipex's idle-timer */ 11150fbf3537Syasuoka ppp->timeout_sec = 0; 11160fbf3537Syasuoka ppp_reset_idle_timeout(ppp); 11170fbf3537Syasuoka } 11180fbf3537Syasuoka 11190fbf3537Syasuoka return error; 11200fbf3537Syasuoka } 11210fbf3537Syasuoka 1122f0a4e295Syasuoka /** Disable PIPEX of the {@link npppd_ppp ppp} */ 11230fbf3537Syasuoka int 11240fbf3537Syasuoka npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) 11250fbf3537Syasuoka { 11260fbf3537Syasuoka struct pipex_session_close_req req; 11270fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 11280fbf3537Syasuoka pppoe_session *pppoe; 11290fbf3537Syasuoka #endif 11300fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 11310fbf3537Syasuoka pptp_call *call; 11320fbf3537Syasuoka #endif 1133886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1134886d2b78Syasuoka l2tp_call *l2tp; 1135886d2b78Syasuoka #endif 11360fbf3537Syasuoka int error; 11370fbf3537Syasuoka 11380fbf3537Syasuoka if (ppp->pipex_started == 0) 11390fbf3537Syasuoka return 0; /* not started */ 11400fbf3537Syasuoka 11410fbf3537Syasuoka bzero(&req, sizeof(req)); 11420fbf3537Syasuoka switch(ppp->tunnel_type) { 11430fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 11440fbf3537Syasuoka case PPP_TUNNEL_PPPOE: 11450fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 11460fbf3537Syasuoka 1147f0a4e295Syasuoka /* PPPoE specific informations */ 11480fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPPOE; 11490fbf3537Syasuoka req.pcr_session_id = pppoe->session_id; 11500fbf3537Syasuoka break; 11510fbf3537Syasuoka #endif 11520fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 11530fbf3537Syasuoka case PPP_TUNNEL_PPTP: 11540fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 11550fbf3537Syasuoka 1156f0a4e295Syasuoka /* PPTP specific informations */ 11570fbf3537Syasuoka req.pcr_session_id = call->id; 11580fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPTP; 11590fbf3537Syasuoka break; 11600fbf3537Syasuoka #endif 1161fd218b06Smarkus #ifdef USE_NPPPD_L2TP 1162fd218b06Smarkus case PPP_TUNNEL_L2TP: 1163fd218b06Smarkus l2tp = (l2tp_call *)ppp->phy_context; 1164fd218b06Smarkus 1165fd218b06Smarkus /* L2TP specific context */ 1166fd218b06Smarkus req.pcr_session_id = l2tp->session_id; 1167fd218b06Smarkus req.pcr_protocol = PIPEX_PROTO_L2TP; 1168fd218b06Smarkus break; 1169fd218b06Smarkus #endif 11700fbf3537Syasuoka default: 11710fbf3537Syasuoka return 1; 11720fbf3537Syasuoka } 11730fbf3537Syasuoka 11740fbf3537Syasuoka error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXDSESSION, &req); 11750fbf3537Syasuoka if (error == 0) { 11760fbf3537Syasuoka ppp->ipackets += req.pcr_stat.ipackets; 11770fbf3537Syasuoka ppp->opackets += req.pcr_stat.opackets; 11780fbf3537Syasuoka ppp->ierrors += req.pcr_stat.ierrors; 11790fbf3537Syasuoka ppp->oerrors += req.pcr_stat.oerrors; 11800fbf3537Syasuoka ppp->ibytes += req.pcr_stat.ibytes; 11810fbf3537Syasuoka ppp->obytes += req.pcr_stat.obytes; 11820fbf3537Syasuoka ppp->pipex_enabled = 0; 11830fbf3537Syasuoka } 11840fbf3537Syasuoka 11850fbf3537Syasuoka return error; 11860fbf3537Syasuoka } 11870fbf3537Syasuoka 1188f0a4e295Syasuoka /* XXX: s/npppd_ppp_pipex_ip_disable/npppd_ppp_pipex_stop/ ?? */ 1189f0a4e295Syasuoka 1190f0a4e295Syasuoka /** Stop PIPEX of the {@link npppd_ppp ppp} */ 11910fbf3537Syasuoka static int 11920fbf3537Syasuoka npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) 11930fbf3537Syasuoka { 11940fbf3537Syasuoka struct pipex_session_config_req req; 11950fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 11960fbf3537Syasuoka pppoe_session *pppoe; 11970fbf3537Syasuoka #endif 11980fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 11990fbf3537Syasuoka pptp_call *call; 12000fbf3537Syasuoka #endif 1201886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1202886d2b78Syasuoka l2tp_call *l2tp; 1203886d2b78Syasuoka #endif 12040fbf3537Syasuoka if (ppp->pipex_started == 0) 12050fbf3537Syasuoka return 0; /* not started */ 12060fbf3537Syasuoka 12070fbf3537Syasuoka bzero(&req, sizeof(req)); 12080fbf3537Syasuoka switch(ppp->tunnel_type) { 12090fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE 12100fbf3537Syasuoka case PPP_TUNNEL_PPPOE: 12110fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context; 12120fbf3537Syasuoka 1213f0a4e295Syasuoka /* PPPoE specific informations */ 12140fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPPOE; 12150fbf3537Syasuoka req.pcr_session_id = pppoe->session_id; 12160fbf3537Syasuoka break; 12170fbf3537Syasuoka #endif 12180fbf3537Syasuoka #ifdef USE_NPPPD_PPTP 12190fbf3537Syasuoka case PPP_TUNNEL_PPTP: 12200fbf3537Syasuoka call = (pptp_call *)ppp->phy_context; 12210fbf3537Syasuoka 1222f0a4e295Syasuoka /* PPTP specific informations */ 12230fbf3537Syasuoka req.pcr_session_id = call->id; 12240fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPTP; 12250fbf3537Syasuoka break; 12260fbf3537Syasuoka #endif 1227886d2b78Syasuoka #ifdef USE_NPPPD_L2TP 1228886d2b78Syasuoka case PPP_TUNNEL_L2TP: 1229886d2b78Syasuoka l2tp = (l2tp_call *)ppp->phy_context; 1230886d2b78Syasuoka 1231886d2b78Syasuoka /* L2TP specific context */ 1232886d2b78Syasuoka req.pcr_session_id = l2tp->session_id; 1233886d2b78Syasuoka req.pcr_protocol = PIPEX_PROTO_L2TP; 1234886d2b78Syasuoka break; 1235886d2b78Syasuoka #endif 12360fbf3537Syasuoka default: 12370fbf3537Syasuoka return 1; 12380fbf3537Syasuoka } 12390fbf3537Syasuoka req.pcr_ip_forward = 0; 12400fbf3537Syasuoka 12410fbf3537Syasuoka return ioctl(_this->iface[ppp->ifidx].devf, PIPEXCSESSION, &req); 12420fbf3537Syasuoka } 12430fbf3537Syasuoka 12440fbf3537Syasuoka static void 12450fbf3537Syasuoka pipex_periodic(npppd *_this) 12460fbf3537Syasuoka { 12470fbf3537Syasuoka struct pipex_session_list_req req; 12480fbf3537Syasuoka npppd_ppp *ppp; 1249*363e4d4bSyasuoka int i, error; 1250*363e4d4bSyasuoka u_int ppp_id; 12510fbf3537Syasuoka slist dlist, users; 12520fbf3537Syasuoka 12530fbf3537Syasuoka slist_init(&dlist); 12540fbf3537Syasuoka slist_init(&users); 12550fbf3537Syasuoka do { 12560fbf3537Syasuoka error = ioctl(_this->iface[0].devf, PIPEXGCLOSED, &req); 12570fbf3537Syasuoka if (error) { 12580fbf3537Syasuoka if (errno != ENXIO) 12590fbf3537Syasuoka log_printf(LOG_WARNING, 12600fbf3537Syasuoka "PIPEXGCLOSED failed: %m"); 12610fbf3537Syasuoka break; 12620fbf3537Syasuoka } 12630fbf3537Syasuoka for (i = 0; i < req.plr_ppp_id_count; i++) { 12640fbf3537Syasuoka ppp_id = req.plr_ppp_id[i]; 1265c46ae403Syasuoka slist_add(&dlist, (void *)(uintptr_t)ppp_id); 12660fbf3537Syasuoka } 12670fbf3537Syasuoka } while (req.plr_flags & PIPEX_LISTREQ_MORE); 12680fbf3537Syasuoka 12690fbf3537Syasuoka if (slist_length(&dlist) <= 0) 12700fbf3537Syasuoka goto pipex_done; 12710fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 12720fbf3537Syasuoka log_printf(LOG_WARNING, 12730fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__); 12740fbf3537Syasuoka slist_fini(&users); 12750fbf3537Syasuoka goto pipex_done; 12760fbf3537Syasuoka } 12770fbf3537Syasuoka 1278f0a4e295Syasuoka /* Disconnect request */ 12790fbf3537Syasuoka slist_itr_first(&dlist); 12800fbf3537Syasuoka while (slist_itr_has_next(&dlist)) { 1281f0a4e295Syasuoka /* FIXME: Linear search by PPP Id eats CPU */ 1282c46ae403Syasuoka ppp_id = (uintptr_t)slist_itr_next(&dlist); 12830fbf3537Syasuoka slist_itr_first(&users); 12840fbf3537Syasuoka ppp = NULL; 12850fbf3537Syasuoka while (slist_itr_has_next(&users)) { 12860fbf3537Syasuoka ppp = slist_itr_next(&users); 12870fbf3537Syasuoka if (ppp_id == ppp->id) { 12880fbf3537Syasuoka /* found */ 12890fbf3537Syasuoka slist_itr_remove(&users); 12900fbf3537Syasuoka break; 12910fbf3537Syasuoka } 12920fbf3537Syasuoka ppp = NULL; 12930fbf3537Syasuoka } 12940fbf3537Syasuoka if (ppp == NULL) { 12950fbf3537Syasuoka log_printf(LOG_WARNING, 12960fbf3537Syasuoka "kernel requested a ppp down, but it's not found. " 12970fbf3537Syasuoka "ppp=%d", ppp_id); 12980fbf3537Syasuoka continue; 12990fbf3537Syasuoka } 13000fbf3537Syasuoka ppp_log(ppp, LOG_INFO, "Stop requested by the kernel"); 13018daf7599Syasuoka /* TODO: PIPEX doesn't return the disconect reason */ 13028daf7599Syasuoka #ifdef USE_NPPPD_RADIUS 13038daf7599Syasuoka ppp_set_radius_terminate_cause(ppp, 13048daf7599Syasuoka RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT); 13058daf7599Syasuoka #endif 13060fbf3537Syasuoka ppp_stop(ppp, NULL); 13070fbf3537Syasuoka } 13080fbf3537Syasuoka pipex_done: 13090fbf3537Syasuoka slist_fini(&users); 13100fbf3537Syasuoka slist_fini(&dlist); 13110fbf3537Syasuoka } 13120fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 13130fbf3537Syasuoka 13140fbf3537Syasuoka /*********************************************************************** 1315f0a4e295Syasuoka * IP address assignment related functions 13160fbf3537Syasuoka ***********************************************************************/ 1317f0a4e295Syasuoka /** Prepare to use IP */ 13180fbf3537Syasuoka int 13190fbf3537Syasuoka npppd_prepare_ip(npppd *_this, npppd_ppp *ppp) 13200fbf3537Syasuoka { 13210fbf3537Syasuoka if (ppp_ipcp(ppp) == NULL) 13220fbf3537Syasuoka return 1; 13230fbf3537Syasuoka 13240fbf3537Syasuoka npppd_get_user_framed_ip_address(_this, ppp, ppp->username); 13250fbf3537Syasuoka 13260fbf3537Syasuoka if (npppd_iface_ip_is_ready(ppp_iface(ppp))) 13270fbf3537Syasuoka ppp->ipcp.ip4_our = ppp_iface(ppp)->ip4addr; 13280fbf3537Syasuoka else if (npppd_iface_ip_is_ready(&_this->iface[0])) 13290fbf3537Syasuoka ppp->ipcp.ip4_our = _this->iface[0].ip4addr; 13300fbf3537Syasuoka else 13310fbf3537Syasuoka return -1; 13320fbf3537Syasuoka if (ppp_ipcp(ppp)->dns_use_tunnel_end != 0) { 13330fbf3537Syasuoka ppp->ipcp.dns_pri = ppp->ipcp.ip4_our; 13340fbf3537Syasuoka ppp->ipcp.dns_sec.s_addr = INADDR_NONE; 13350fbf3537Syasuoka } else { 13360fbf3537Syasuoka ppp->ipcp.dns_pri = ppp_ipcp(ppp)->dns_pri; 13370fbf3537Syasuoka ppp->ipcp.dns_sec = ppp_ipcp(ppp)->dns_sec; 13380fbf3537Syasuoka } 13390fbf3537Syasuoka ppp->ipcp.nbns_pri = ppp_ipcp(ppp)->nbns_pri; 13400fbf3537Syasuoka ppp->ipcp.nbns_sec = ppp_ipcp(ppp)->nbns_sec; 13410fbf3537Syasuoka 13420fbf3537Syasuoka return 0; 13430fbf3537Syasuoka } 13440fbf3537Syasuoka 1345f0a4e295Syasuoka /** Notify stop using IP to npppd and release the resources. */ 13460fbf3537Syasuoka void 13470fbf3537Syasuoka npppd_release_ip(npppd *_this, npppd_ppp *ppp) 13480fbf3537Syasuoka { 13490fbf3537Syasuoka 13500fbf3537Syasuoka if (!ppp_ip_assigned(ppp)) 13510fbf3537Syasuoka return; 13520fbf3537Syasuoka 13530fbf3537Syasuoka npppd_set_ip_enabled(_this, ppp, 0); 13540fbf3537Syasuoka npppd_pool_release_ip(ppp->assigned_pool, ppp); 13550fbf3537Syasuoka ppp->assigned_pool = NULL; 13560fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = 0; 13570fbf3537Syasuoka } 13580fbf3537Syasuoka 1359f0a4e295Syasuoka /** 1360f0a4e295Syasuoka * Change IP enableness. When the enableness is change, npppd will operate 1361f0a4e295Syasuoka * the route entry. 1362f0a4e295Syasuoka */ 13630fbf3537Syasuoka void 13640fbf3537Syasuoka npppd_set_ip_enabled(npppd *_this, npppd_ppp *ppp, int enabled) 13650fbf3537Syasuoka { 13660fbf3537Syasuoka int was_enabled, found; 13670fbf3537Syasuoka slist *u; 13680fbf3537Syasuoka hash_link *hl; 13690fbf3537Syasuoka npppd_ppp *ppp1; 13700fbf3537Syasuoka 13710fbf3537Syasuoka NPPPD_ASSERT(ppp_ip_assigned(ppp)); 13720fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 13730fbf3537Syasuoka "npppd_set_ip_enabled(%s/%s, %s)", ppp->username, 13740fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address), 13750fbf3537Syasuoka (enabled)?"true" : "false")); 1376f0a4e295Syasuoka 13770fbf3537Syasuoka /* 1378f0a4e295Syasuoka * Don't do anything if the enableness is not change. Changing route 1379f0a4e295Syasuoka * makes many programs will wake up and do heavy operations, it causes 1380f0a4e295Syasuoka * system overload, so we refrain useless changing route. 13810fbf3537Syasuoka */ 13820fbf3537Syasuoka enabled = (enabled)? 1 : 0; 13830fbf3537Syasuoka was_enabled = (ppp->assigned_ip4_enabled != 0)? 1 : 0; 13840fbf3537Syasuoka if (enabled == was_enabled) 13850fbf3537Syasuoka return; 1386f0a4e295Syasuoka 13870fbf3537Syasuoka ppp->assigned_ip4_enabled = enabled; 13880fbf3537Syasuoka if (enabled) { 13890fbf3537Syasuoka if (ppp->username[0] != '\0') { 13900fbf3537Syasuoka if ((u = npppd_get_ppp_by_user(_this, ppp->username)) 13910fbf3537Syasuoka == NULL) { 13920fbf3537Syasuoka if ((u = malloc(sizeof(slist))) == NULL) { 13930fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 13940fbf3537Syasuoka "Out of memory on %s: %m", 13950fbf3537Syasuoka __func__); 13960fbf3537Syasuoka } else { 13970fbf3537Syasuoka slist_init(u); 13980fbf3537Syasuoka slist_set_size(u, 4); 13990fbf3537Syasuoka hash_insert(_this->map_user_ppp, 14000fbf3537Syasuoka ppp->username, u); 14010fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 14020fbf3537Syasuoka "hash_insert(user->ppp, %s)", 14030fbf3537Syasuoka ppp->username)); 14040fbf3537Syasuoka } 14050fbf3537Syasuoka } 1406f0a4e295Syasuoka if (u != NULL) /* above malloc() may failed */ 14070fbf3537Syasuoka slist_add(u, ppp); 14080fbf3537Syasuoka } 14090fbf3537Syasuoka 14100fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1411cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) { 14120fbf3537Syasuoka if (ppp->snp.snp_next != NULL) 1413f0a4e295Syasuoka /* 1414f0a4e295Syasuoka * There is a blackhole route that has same 1415f0a4e295Syasuoka * address/mask. 1416f0a4e295Syasuoka */ 14170fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address, 1418cd8e09b9Sdlg &ppp->ppp_framed_ip_netmask, &loop, 1419cd8e09b9Sdlg RTF_BLACKHOLE); 14200fbf3537Syasuoka /* See the comment for MRU_IPMTU() on ppp.h */ 14210fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) { 14220fbf3537Syasuoka in_host_route_add(&ppp->ppp_framed_ip_address, 1423cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr, 1424cd8e09b9Sdlg ppp_iface(ppp)->ifname, 14250fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 14260fbf3537Syasuoka } else { 14270fbf3537Syasuoka in_route_add(&ppp->ppp_framed_ip_address, 14280fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 1429cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr, 1430cd8e09b9Sdlg ppp_iface(ppp)->ifname, 0, 14310fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru)); 14320fbf3537Syasuoka } 1433cd8e09b9Sdlg } 14340fbf3537Syasuoka #endif 14350fbf3537Syasuoka } else { 14360fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1437cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) { 14380fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) { 14390fbf3537Syasuoka in_host_route_delete(&ppp->ppp_framed_ip_address, 14400fbf3537Syasuoka &ppp_iface(ppp)->ip4addr); 14410fbf3537Syasuoka } else { 14420fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address, 14430fbf3537Syasuoka &ppp->ppp_framed_ip_netmask, 14440fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 0); 14450fbf3537Syasuoka } 14460fbf3537Syasuoka if (ppp->snp.snp_next != NULL) 1447f0a4e295Syasuoka /* 1448f0a4e295Syasuoka * There is a blackhole route that has same 1449f0a4e295Syasuoka * address/mask. 1450f0a4e295Syasuoka */ 1451cd8e09b9Sdlg in_route_add(&ppp->snp.snp_addr, 1452cd8e09b9Sdlg &ppp->snp.snp_mask, &loop, LOOPBACK_IFNAME, 1453cd8e09b9Sdlg RTF_BLACKHOLE, 0); 1454cd8e09b9Sdlg } 14550fbf3537Syasuoka #endif 14560fbf3537Syasuoka if (ppp->username[0] != '\0') { 14570fbf3537Syasuoka hl = hash_lookup(_this->map_user_ppp, ppp->username); 14580fbf3537Syasuoka NPPPD_ASSERT(hl != NULL); 14590fbf3537Syasuoka if (hl == NULL) { 14600fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 14610fbf3537Syasuoka "Unexpected error: cannot find user(%s) " 14620fbf3537Syasuoka "from user database", ppp->username); 14630fbf3537Syasuoka return; 14640fbf3537Syasuoka } 14650fbf3537Syasuoka found = 0; 14660fbf3537Syasuoka u = hl->item; 14670fbf3537Syasuoka for (slist_itr_first(u); slist_itr_has_next(u);) { 14680fbf3537Syasuoka ppp1 = slist_itr_next(u); 14690fbf3537Syasuoka if (ppp1 == ppp) { 14700fbf3537Syasuoka slist_itr_remove(u); 14710fbf3537Syasuoka found++; 14720fbf3537Syasuoka break; 14730fbf3537Syasuoka } 14740fbf3537Syasuoka } 14750fbf3537Syasuoka if (found == 0) { 14760fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 14770fbf3537Syasuoka "Unexpected error: PPP instance is " 14780fbf3537Syasuoka "not found in the user's list."); 14790fbf3537Syasuoka } 14800fbf3537Syasuoka NPPPD_ASSERT(found != 0); 14810fbf3537Syasuoka if (slist_length(u) <= 0) { 1482f0a4e295Syasuoka /* The last PPP */ 14830fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, 14840fbf3537Syasuoka "hash_delete(user->ppp, %s)", 14850fbf3537Syasuoka ppp->username)); 14860fbf3537Syasuoka if (hash_delete(_this->map_user_ppp, 14870fbf3537Syasuoka ppp->username, 0) != 0) { 14880fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 14890fbf3537Syasuoka "Unexpected error: cannot delete " 14900fbf3537Syasuoka "user(%s) from user database", 14910fbf3537Syasuoka ppp->username); 14920fbf3537Syasuoka } 14930fbf3537Syasuoka slist_fini(u); 14940fbf3537Syasuoka free(u); 14950fbf3537Syasuoka } else { 1496f0a4e295Syasuoka /* Replace the reference. */ 14970fbf3537Syasuoka ppp1 = slist_get(u, 0); 14980fbf3537Syasuoka hl->key = ppp1->username; 14990fbf3537Syasuoka } 15000fbf3537Syasuoka } 15010fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX 15020fbf3537Syasuoka if (npppd_ppp_pipex_ip_disable(_this, ppp) != 0) 15030fbf3537Syasuoka ppp_log(ppp, LOG_ERR, 15040fbf3537Syasuoka "npppd_ppp_pipex_ip_disable() failed: %m"); 15050fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */ 15060fbf3537Syasuoka } 15070fbf3537Syasuoka } 15080fbf3537Syasuoka 15090fbf3537Syasuoka /** 1510f0a4e295Syasuoka * Assign the IP address. Returning "struct in_addr" is stored IP address 1511f0a4e295Syasuoka * in network byte order. 1512f0a4e295Syasuoka * @param req_ip4 IP address request to assign. If the address is used 1513f0a4e295Syasuoka * already, this function will return fail. 15140fbf3537Syasuoka */ 15150fbf3537Syasuoka int 15160fbf3537Syasuoka npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) 15170fbf3537Syasuoka { 15180fbf3537Syasuoka uint32_t ip4, ip4mask; 15190fbf3537Syasuoka int flag, dyna, rval, fallback_dyna; 15200fbf3537Syasuoka const char *reason = "out of the pool"; 15210fbf3537Syasuoka struct sockaddr_npppd *snp; 15220fbf3537Syasuoka npppd_pool *pool; 15230fbf3537Syasuoka npppd_auth_base *realm; 15240fbf3537Syasuoka 15250fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() assigned=%s", __func__, 15260fbf3537Syasuoka (ppp_ip_assigned(ppp))? "true" : "false")); 15270fbf3537Syasuoka if (ppp_ip_assigned(ppp)) 15280fbf3537Syasuoka return 0; 15290fbf3537Syasuoka 15300fbf3537Syasuoka ip4 = INADDR_ANY; 15310fbf3537Syasuoka ip4mask = 0xffffffffL; 15320fbf3537Syasuoka flag = ppp_ipcp(ppp)->ip_assign_flags; 15330fbf3537Syasuoka realm = ppp->realm; 15340fbf3537Syasuoka dyna = 0; 15350fbf3537Syasuoka fallback_dyna = 0; 15360fbf3537Syasuoka pool = NULL; 15370fbf3537Syasuoka 15380fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) { 15390fbf3537Syasuoka if (req_ip4 == INADDR_ANY) 15400fbf3537Syasuoka dyna = 1; 15410fbf3537Syasuoka } else if (ppp->realm_framed_ip_address.s_addr == INADDR_NAS_SELECT) { 15420fbf3537Syasuoka dyna = 1; 15430fbf3537Syasuoka } else { 15440fbf3537Syasuoka NPPPD_ASSERT(realm != NULL); 1545f0a4e295Syasuoka /* We cannot assign a fixed ip address without realm */ 15460fbf3537Syasuoka 15470fbf3537Syasuoka if ((npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_RADIUS && 15480fbf3537Syasuoka (flag & NPPPD_IP_ASSIGN_RADIUS) == 0 && 15490fbf3537Syasuoka (flag & NPPPD_IP_ASSIGN_FIXED) == 0) || 15500fbf3537Syasuoka (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL && 15510fbf3537Syasuoka (flag & NPPPD_IP_ASSIGN_FIXED) == 0)) 15520fbf3537Syasuoka dyna = 1; 15530fbf3537Syasuoka else { 15540fbf3537Syasuoka fallback_dyna = 1; 15550fbf3537Syasuoka req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr); 15560fbf3537Syasuoka ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr); 15570fbf3537Syasuoka } 15580fbf3537Syasuoka } 15590fbf3537Syasuoka if (!dyna) { 15600fbf3537Syasuoka /* 1561f0a4e295Syasuoka * Realm requires the fixed IP address, but the address 1562f0a4e295Syasuoka * doesn't belong any address pool. Fallback to dynamic 1563f0a4e295Syasuoka * assignment. 15640fbf3537Syasuoka */ 15650fbf3537Syasuoka for (slist_itr_first(ppp_pools(ppp)); 15660fbf3537Syasuoka slist_itr_has_next(ppp_pools(ppp));){ 15670fbf3537Syasuoka pool = slist_itr_next(ppp_pools(ppp)); 15680fbf3537Syasuoka rval = npppd_pool_get_assignability(pool, req_ip4, 15690fbf3537Syasuoka ip4mask, &snp); 15700fbf3537Syasuoka switch (rval) { 15710fbf3537Syasuoka case ADDRESS_OK: 15720fbf3537Syasuoka if (snp->snp_type == SNP_POOL) { 15730fbf3537Syasuoka /* 1574f0a4e295Syasuoka * Fixed address pool can be used 1575f0a4e295Syasuoka * only if the realm specified to use 1576f0a4e295Syasuoka * it. 15770fbf3537Syasuoka */ 15780fbf3537Syasuoka if (ppp->realm_framed_ip_address 15790fbf3537Syasuoka .s_addr != INADDR_USER_SELECT) 15800fbf3537Syasuoka ip4 = req_ip4; 15810fbf3537Syasuoka break; 15820fbf3537Syasuoka } 15830fbf3537Syasuoka ppp->assign_dynapool = 1; 15840fbf3537Syasuoka ip4 = req_ip4; 15850fbf3537Syasuoka break; 15860fbf3537Syasuoka case ADDRESS_RESERVED: 15870fbf3537Syasuoka reason = "reserved"; 15880fbf3537Syasuoka continue; 15890fbf3537Syasuoka case ADDRESS_OUT_OF_POOL: 15900fbf3537Syasuoka reason = "out of the pool"; 1591f0a4e295Syasuoka continue; /* try next */ 15920fbf3537Syasuoka case ADDRESS_BUSY: 15930fbf3537Syasuoka fallback_dyna = 0; 15940fbf3537Syasuoka reason = "busy"; 15950fbf3537Syasuoka break; 15960fbf3537Syasuoka default: 15970fbf3537Syasuoka case ADDRESS_INVALID: 15980fbf3537Syasuoka fallback_dyna = 0; 15990fbf3537Syasuoka reason = "invalid"; 16000fbf3537Syasuoka break; 16010fbf3537Syasuoka } 16020fbf3537Syasuoka break; 16030fbf3537Syasuoka } 16040fbf3537Syasuoka #define IP_4OCT(v) ((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16),\ 16050fbf3537Syasuoka ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v)) 16060fbf3537Syasuoka if (ip4 == 0) { 16070fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 16080fbf3537Syasuoka "Requested IP address (%d.%d.%d.%d)/%d " 16090fbf3537Syasuoka "is %s", IP_4OCT(req_ip4), 16100fbf3537Syasuoka netmask2prefixlen(htonl(ip4mask)), reason); 16110fbf3537Syasuoka if (fallback_dyna) 16120fbf3537Syasuoka goto dyna_assign; 16130fbf3537Syasuoka return 1; 16140fbf3537Syasuoka } 16150fbf3537Syasuoka ppp->assigned_pool = pool; 16160fbf3537Syasuoka 16170fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4); 16180fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(ip4mask); 16190fbf3537Syasuoka } else { 16200fbf3537Syasuoka dyna_assign: 16210fbf3537Syasuoka for (slist_itr_first(ppp_pools(ppp)); 16220fbf3537Syasuoka slist_itr_has_next(ppp_pools(ppp));){ 16230fbf3537Syasuoka pool = slist_itr_next(ppp_pools(ppp)); 16240fbf3537Syasuoka ip4 = npppd_pool_get_dynamic(pool, ppp); 16250fbf3537Syasuoka if (ip4 != 0) 16260fbf3537Syasuoka break; 16270fbf3537Syasuoka } 16280fbf3537Syasuoka if (ip4 == 0) { 16290fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 16300fbf3537Syasuoka "No free address in the pool."); 16310fbf3537Syasuoka return 1; 16320fbf3537Syasuoka } 16330fbf3537Syasuoka ppp->assigned_pool = pool; 16340fbf3537Syasuoka ppp->assign_dynapool = 1; 16350fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4); 16360fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(0xffffffffL); 16370fbf3537Syasuoka } 16380fbf3537Syasuoka 16390fbf3537Syasuoka return npppd_pool_assign_ip(ppp->assigned_pool, ppp); 16400fbf3537Syasuoka } 16410fbf3537Syasuoka 16420fbf3537Syasuoka static void * 16430fbf3537Syasuoka rtlist_remove(slist *prtlist, struct radish *radish) 16440fbf3537Syasuoka { 16450fbf3537Syasuoka struct radish *r; 16460fbf3537Syasuoka 16470fbf3537Syasuoka slist_itr_first(prtlist); 16480fbf3537Syasuoka while (slist_itr_has_next(prtlist)) { 16490fbf3537Syasuoka r = slist_itr_next(prtlist); 16500fbf3537Syasuoka if (!sockaddr_npppd_match(radish->rd_route, r->rd_route) || 16510fbf3537Syasuoka !sockaddr_npppd_match(radish->rd_mask, r->rd_mask)) 16520fbf3537Syasuoka continue; 16530fbf3537Syasuoka 16540fbf3537Syasuoka return slist_itr_remove(prtlist); 16550fbf3537Syasuoka } 16560fbf3537Syasuoka 16570fbf3537Syasuoka return NULL; 16580fbf3537Syasuoka } 16590fbf3537Syasuoka 1660f0a4e295Syasuoka /** Set {@link ::npppd#rd the only radish of npppd} */ 16610fbf3537Syasuoka int 16620fbf3537Syasuoka npppd_set_radish(npppd *_this, void *radish_head) 16630fbf3537Syasuoka { 16640fbf3537Syasuoka int rval, delppp0, count; 16650fbf3537Syasuoka struct sockaddr_npppd *snp; 16660fbf3537Syasuoka struct radish *radish, *r; 16670fbf3537Syasuoka slist rtlist0, rtlist1, delppp; 16680fbf3537Syasuoka npppd_ppp *ppp; 16690fbf3537Syasuoka void *dummy; 16700fbf3537Syasuoka 16710fbf3537Syasuoka slist_init(&rtlist0); 16720fbf3537Syasuoka slist_init(&rtlist1); 16730fbf3537Syasuoka slist_init(&delppp); 16740fbf3537Syasuoka 16750fbf3537Syasuoka if (radish_head != NULL) { 16760fbf3537Syasuoka if (rd2slist(radish_head, &rtlist1) != 0) { 16770fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m"); 1678f0a4e295Syasuoka goto fail; 16790fbf3537Syasuoka } 16800fbf3537Syasuoka } 16810fbf3537Syasuoka if (_this->rd != NULL) { 16820fbf3537Syasuoka if (rd2slist(_this->rd, &rtlist0) != 0) { 16830fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m"); 1684f0a4e295Syasuoka goto fail; 16850fbf3537Syasuoka } 16860fbf3537Syasuoka } 16870fbf3537Syasuoka if (_this->rd != NULL && radish_head != NULL) { 16880fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { 16890fbf3537Syasuoka radish = slist_itr_next(&rtlist0); 16900fbf3537Syasuoka snp = radish->rd_rtent; 16910fbf3537Syasuoka /* 1692f0a4e295Syasuoka * replace the pool address 16930fbf3537Syasuoka */ 16940fbf3537Syasuoka if (snp->snp_type == SNP_POOL || 16950fbf3537Syasuoka snp->snp_type == SNP_DYN_POOL) { 16960fbf3537Syasuoka if (rd_lookup(radish->rd_route, radish->rd_mask, 16970fbf3537Syasuoka radish_head) == NULL) 16980fbf3537Syasuoka continue; 1699f0a4e295Syasuoka /* don't add */ 17000fbf3537Syasuoka rtlist_remove(&rtlist1, radish); 1701f0a4e295Syasuoka /* don't delete */ 17020fbf3537Syasuoka slist_itr_remove(&rtlist0); 17030fbf3537Syasuoka continue; 17040fbf3537Syasuoka } 17050fbf3537Syasuoka /* 1706f0a4e295Syasuoka * handle the active PPP sessions. 17070fbf3537Syasuoka */ 17080fbf3537Syasuoka NPPPD_ASSERT(snp->snp_type == SNP_PPP); 17090fbf3537Syasuoka ppp = snp->snp_data_ptr; 17100fbf3537Syasuoka 1711f0a4e295Syasuoka /* Don't delete the route of active PPP session */ 17120fbf3537Syasuoka slist_itr_remove(&rtlist0); 17130fbf3537Syasuoka 1714f0a4e295Syasuoka /* clear informations about old pool configuration */ 17150fbf3537Syasuoka ppp->assigned_pool = NULL; 17160fbf3537Syasuoka snp->snp_next = NULL; 17170fbf3537Syasuoka 17180fbf3537Syasuoka delppp0 = 0; 17190fbf3537Syasuoka if (!rd_match((struct sockaddr *)snp, radish_head, &r)){ 17200fbf3537Syasuoka /* 1721f0a4e295Syasuoka * If the address doesn't belong the new pools, 1722f0a4e295Syasuoka * add the PPP session to the deletion list. 17230fbf3537Syasuoka */ 17240fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr); 17250fbf3537Syasuoka delppp0 = 1; 17260fbf3537Syasuoka } else { 17270fbf3537Syasuoka NPPPD_ASSERT( 17280fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent) 17290fbf3537Syasuoka ->snp_type == SNP_POOL || 17300fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent) 17310fbf3537Syasuoka ->snp_type == SNP_DYN_POOL); 17320fbf3537Syasuoka /* 1733f0a4e295Syasuoka * If there is a pool entry that has same 1734f0a4e295Syasuoka * address/mask, then make the RADISH entry a 1735f0a4e295Syasuoka * list. Set SNP_PPP as the first in the list, 1736f0a4e295Syasuoka * set current entry in snp->snp_next and 1737f0a4e295Syasuoka * delete it. 17380fbf3537Syasuoka */ 17390fbf3537Syasuoka if (sockaddr_npppd_match( 17400fbf3537Syasuoka radish->rd_route, r->rd_route) && 17410fbf3537Syasuoka sockaddr_npppd_match( 17420fbf3537Syasuoka radish->rd_mask, r->rd_mask)) { 1743f0a4e295Syasuoka /* 1744f0a4e295Syasuoka * Releasing it, so remove it from the 1745f0a4e295Syasuoka * new routing list. 1746f0a4e295Syasuoka */ 17470fbf3537Syasuoka rtlist_remove(&rtlist1, radish); 1748f0a4e295Syasuoka /* set as snp_snp_next */ 17490fbf3537Syasuoka snp->snp_next = r->rd_rtent; 17500fbf3537Syasuoka rval = rd_delete(r->rd_route, 17510fbf3537Syasuoka r->rd_mask, radish_head, &dummy); 17520fbf3537Syasuoka NPPPD_ASSERT(rval == 0); 17530fbf3537Syasuoka } 17540fbf3537Syasuoka } 1755f0a4e295Syasuoka /* Register to the new radish */ 17560fbf3537Syasuoka rval = rd_insert(radish->rd_route, radish->rd_mask, 17570fbf3537Syasuoka radish_head, snp); 17580fbf3537Syasuoka if (rval != 0) { 17590fbf3537Syasuoka errno = rval; 17600fbf3537Syasuoka ppp_log(((npppd_ppp *)snp->snp_data_ptr), 17610fbf3537Syasuoka LOG_ERR, 17620fbf3537Syasuoka "Fatal error on %s, cannot continue " 17630fbf3537Syasuoka "this ppp session: %m", __func__); 17640fbf3537Syasuoka if (!delppp0) 17650fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr); 17660fbf3537Syasuoka } 17670fbf3537Syasuoka } 17680fbf3537Syasuoka } 17690fbf3537Syasuoka count = 0; 17700fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS 1771cd8e09b9Sdlg if (_this->iface[0].using_pppx == 0) { 17720fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { 17730fbf3537Syasuoka radish = slist_itr_next(&rtlist0); 17740fbf3537Syasuoka in_route_delete(&SIN(radish->rd_route)->sin_addr, 1775cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop, 1776cd8e09b9Sdlg RTF_BLACKHOLE); 17770fbf3537Syasuoka count++; 17780fbf3537Syasuoka } 17790fbf3537Syasuoka if (count > 0) 17800fbf3537Syasuoka log_printf(LOG_INFO, 17810fbf3537Syasuoka "Deleted %d routes for old pool addresses", count); 17820fbf3537Syasuoka 17830fbf3537Syasuoka count = 0; 17840fbf3537Syasuoka for (slist_itr_first(&rtlist1); slist_itr_has_next(&rtlist1);) { 17850fbf3537Syasuoka radish = slist_itr_next(&rtlist1); 17860fbf3537Syasuoka in_route_add(&(SIN(radish->rd_route)->sin_addr), 1787cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop, 1788cd8e09b9Sdlg LOOPBACK_IFNAME, RTF_BLACKHOLE, 0); 17890fbf3537Syasuoka count++; 17900fbf3537Syasuoka } 17910fbf3537Syasuoka if (count > 0) 17920fbf3537Syasuoka log_printf(LOG_INFO, 1793cd8e09b9Sdlg "Added %d routes for new pool addresses", 1794cd8e09b9Sdlg count); 1795cd8e09b9Sdlg } 17960fbf3537Syasuoka #endif 17970fbf3537Syasuoka slist_fini(&rtlist0); 17980fbf3537Syasuoka slist_fini(&rtlist1); 17990fbf3537Syasuoka 18000fbf3537Syasuoka if (_this->rd != NULL) 18010fbf3537Syasuoka npppd_rd_walktree_delete(_this->rd); 18020fbf3537Syasuoka _this->rd = radish_head; 18030fbf3537Syasuoka 18040fbf3537Syasuoka for (slist_itr_first(&delppp); slist_itr_has_next(&delppp);) { 18050fbf3537Syasuoka ppp = slist_itr_next(&delppp); 18060fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE, 18070fbf3537Syasuoka "stop. IP address of this ppp is out of the pool.: %s", 18080fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address)); 18090fbf3537Syasuoka ppp_stop(ppp, NULL); 18100fbf3537Syasuoka } 18110fbf3537Syasuoka slist_fini(&delppp); 18120fbf3537Syasuoka 18130fbf3537Syasuoka return 0; 1814f0a4e295Syasuoka fail: 18150fbf3537Syasuoka slist_fini(&rtlist0); 18160fbf3537Syasuoka slist_fini(&rtlist1); 18170fbf3537Syasuoka slist_fini(&delppp); 18180fbf3537Syasuoka 18190fbf3537Syasuoka return 1; 18200fbf3537Syasuoka } 18210fbf3537Syasuoka 18220fbf3537Syasuoka /** 1823f0a4e295Syasuoka * This function stores all users to {@link slist} and returns them. 1824f0a4e295Syasuoka * References to {@link ::npppd_ppp} will be stored in users. 18250fbf3537Syasuoka */ 18260fbf3537Syasuoka int 18270fbf3537Syasuoka npppd_get_all_users(npppd *_this, slist *users) 18280fbf3537Syasuoka { 18290fbf3537Syasuoka int rval; 18300fbf3537Syasuoka struct radish *rd; 18310fbf3537Syasuoka struct sockaddr_npppd *snp; 18320fbf3537Syasuoka slist list; 18330fbf3537Syasuoka 18340fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 18350fbf3537Syasuoka 18360fbf3537Syasuoka slist_init(&list); 18370fbf3537Syasuoka rval = rd2slist(_this->rd, &list); 18380fbf3537Syasuoka if (rval != 0) 18390fbf3537Syasuoka return rval; 18400fbf3537Syasuoka 18410fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) { 18420fbf3537Syasuoka rd = slist_itr_next(&list); 18430fbf3537Syasuoka snp = rd->rd_rtent; 18440fbf3537Syasuoka if (snp->snp_type == SNP_PPP) { 18450fbf3537Syasuoka if (slist_add(users, snp->snp_data_ptr) == NULL) { 18460fbf3537Syasuoka log_printf(LOG_ERR, 18470fbf3537Syasuoka "slist_add() failed in %s: %m", __func__); 1848f0a4e295Syasuoka goto fail; 18490fbf3537Syasuoka } 18500fbf3537Syasuoka } 18510fbf3537Syasuoka } 18520fbf3537Syasuoka slist_fini(&list); 18530fbf3537Syasuoka 18540fbf3537Syasuoka return 0; 1855f0a4e295Syasuoka fail: 18560fbf3537Syasuoka slist_fini(&list); 18570fbf3537Syasuoka 18580fbf3537Syasuoka return 1; 18590fbf3537Syasuoka } 18600fbf3537Syasuoka 18610fbf3537Syasuoka static int 18620fbf3537Syasuoka rd2slist_walk(struct radish *rd, void *list0) 18630fbf3537Syasuoka { 18640fbf3537Syasuoka slist *list = list0; 18650fbf3537Syasuoka void *r; 18660fbf3537Syasuoka 18670fbf3537Syasuoka r = slist_add(list, rd); 18680fbf3537Syasuoka if (r == NULL) 18690fbf3537Syasuoka return -1; 18700fbf3537Syasuoka return 0; 18710fbf3537Syasuoka } 18720fbf3537Syasuoka static int 18730fbf3537Syasuoka rd2slist(struct radish_head *h, slist *list) 18740fbf3537Syasuoka { 18750fbf3537Syasuoka return rd_walktree(h, rd2slist_walk, list); 18760fbf3537Syasuoka } 18770fbf3537Syasuoka 18780fbf3537Syasuoka static void 18790fbf3537Syasuoka npppd_reload0(npppd *_this) 18800fbf3537Syasuoka { 18810fbf3537Syasuoka npppd_reload_config(_this); 18820fbf3537Syasuoka #ifdef USE_NPPPD_ARP 18830fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); 18840fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) 18850fbf3537Syasuoka arp_sock_init(); 18860fbf3537Syasuoka else 18870fbf3537Syasuoka arp_sock_fini(); 18880fbf3537Syasuoka #endif 18890fbf3537Syasuoka npppd_modules_reload(_this); 18900fbf3537Syasuoka npppd_ifaces_load_config(_this); 18910fbf3537Syasuoka #ifdef NPPPD_RESET_IP_ADDRESS 18920fbf3537Syasuoka { 18930fbf3537Syasuoka int i; 18940fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) { 18950fbf3537Syasuoka if (_this->iface[i].initialized != 0) 18960fbf3537Syasuoka npppd_iface_reinit(&_this->iface[i]); 18970fbf3537Syasuoka } 18980fbf3537Syasuoka } 18990fbf3537Syasuoka #endif 19000fbf3537Syasuoka npppd_auth_finalizer_periodic(_this); 19010fbf3537Syasuoka } 19020fbf3537Syasuoka 19030fbf3537Syasuoka /*********************************************************************** 1904f0a4e295Syasuoka * Signal handlers 19050fbf3537Syasuoka ***********************************************************************/ 19060fbf3537Syasuoka static void 19070fbf3537Syasuoka npppd_on_sighup(int fd, short ev_type, void *ctx) 19080fbf3537Syasuoka { 19090fbf3537Syasuoka npppd *_this; 19100fbf3537Syasuoka 19110fbf3537Syasuoka _this = ctx; 19120fbf3537Syasuoka #ifndef NO_DELAYED_RELOAD 19130fbf3537Syasuoka if (_this->delayed_reload > 0) 19140fbf3537Syasuoka _this->reloading_count = _this->delayed_reload; 19150fbf3537Syasuoka else 19160fbf3537Syasuoka #endif 19170fbf3537Syasuoka npppd_reload0(_this); 19180fbf3537Syasuoka } 19190fbf3537Syasuoka 19200fbf3537Syasuoka static void 19210fbf3537Syasuoka npppd_on_sigterm(int fd, short ev_type, void *ctx) 19220fbf3537Syasuoka { 19230fbf3537Syasuoka npppd *_this; 19240fbf3537Syasuoka 19250fbf3537Syasuoka _this = ctx; 19260fbf3537Syasuoka npppd_stop(_this); 19270fbf3537Syasuoka } 19280fbf3537Syasuoka 19290fbf3537Syasuoka static void 19300fbf3537Syasuoka npppd_on_sigint(int fd, short ev_type, void *ctx) 19310fbf3537Syasuoka { 19320fbf3537Syasuoka npppd *_this; 19330fbf3537Syasuoka 19340fbf3537Syasuoka _this = ctx; 19350fbf3537Syasuoka npppd_stop(_this); 19360fbf3537Syasuoka } 19370fbf3537Syasuoka 19385fefcc09Syasuoka static void 19395fefcc09Syasuoka npppd_on_sigchld(int fd, short ev_type, void *ctx) 19405fefcc09Syasuoka { 19415fefcc09Syasuoka int status; 19425fefcc09Syasuoka pid_t wpid; 19435fefcc09Syasuoka npppd *_this; 19445fefcc09Syasuoka 19455fefcc09Syasuoka _this = ctx; 19465fefcc09Syasuoka wpid = privsep_priv_pid(); 19475fefcc09Syasuoka if (wait4(wpid, &status, WNOHANG, NULL) == wpid) { 19485fefcc09Syasuoka if (WIFSIGNALED(status)) 19495fefcc09Syasuoka log_printf(LOG_WARNING, 19505fefcc09Syasuoka "priviledged process exits abnormaly. signal=%d", 19515fefcc09Syasuoka WTERMSIG(status)); 19525fefcc09Syasuoka else 19535fefcc09Syasuoka log_printf(LOG_WARNING, 19545fefcc09Syasuoka "priviledged process exits abnormaly. status=%d", 19555fefcc09Syasuoka WEXITSTATUS(status)); 19565fefcc09Syasuoka _this->stop_by_error = 1; 19575fefcc09Syasuoka npppd_stop(_this); 19585fefcc09Syasuoka } 19595fefcc09Syasuoka } 19600fbf3537Syasuoka /*********************************************************************** 1961f0a4e295Syasuoka * Miscellaneous functions 19620fbf3537Syasuoka ***********************************************************************/ 19630fbf3537Syasuoka static uint32_t 19640fbf3537Syasuoka str_hash(const void *ptr, int sz) 19650fbf3537Syasuoka { 19660fbf3537Syasuoka uint32_t hash = 0; 19670fbf3537Syasuoka int i, len; 19680fbf3537Syasuoka const char *str; 19690fbf3537Syasuoka 19700fbf3537Syasuoka str = ptr; 19710fbf3537Syasuoka len = strlen(str); 19720fbf3537Syasuoka for (i = 0; i < len; i++) 19730fbf3537Syasuoka hash = hash*0x1F + str[i]; 19740fbf3537Syasuoka hash = (hash << 16) ^ (hash & 0xffff); 19750fbf3537Syasuoka 19760fbf3537Syasuoka return hash % sz; 19770fbf3537Syasuoka } 19780fbf3537Syasuoka 19790fbf3537Syasuoka /** 1980f0a4e295Syasuoka * Select a authentication realm that is for given {@link ::npppd_ppp PPP}. 1981f0a4e295Syasuoka * Return 0 on success. 19820fbf3537Syasuoka */ 19830fbf3537Syasuoka int 19840fbf3537Syasuoka npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int 19850fbf3537Syasuoka eap_required) 19860fbf3537Syasuoka { 19870fbf3537Syasuoka int lsuffix, lprefix, lusername, lmax; 19880fbf3537Syasuoka const char *val; 19890fbf3537Syasuoka char *tok, *buf0, buf[NPPPD_CONFIG_BUFSIZ], buf1[MAX_USERNAME_LENGTH]; 19900fbf3537Syasuoka npppd_auth_base *realm = NULL, *realm0 = NULL, *realm1 = NULL; 19910fbf3537Syasuoka 19920fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 19930fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 19940fbf3537Syasuoka NPPPD_ASSERT(username != NULL); 19950fbf3537Syasuoka 19960fbf3537Syasuoka /* 1997f0a4e295Syasuoka * If the PPP suffix is the longest, and the length of the suffix is 1998f0a4e295Syasuoka * same, select the first one. 19990fbf3537Syasuoka */ 20000fbf3537Syasuoka lusername = strlen(username); 20010fbf3537Syasuoka lmax = -1; 20020fbf3537Syasuoka realm = NULL; 20030fbf3537Syasuoka 20040fbf3537Syasuoka if ((val = ppp_config_str(ppp, "realm_list")) == NULL) { 20050fbf3537Syasuoka #ifndef NO_DEFAULT_REALM 20060fbf3537Syasuoka /* 2007f0a4e295Syasuoka * If the realm is not a list, because of compatibility for 2008f0a4e295Syasuoka * past versions, we try fallback from LOCAL to RADIUS. 20090fbf3537Syasuoka */ 20100fbf3537Syasuoka realm0 = NULL; 20110fbf3537Syasuoka slist_itr_first(&_this->realms); 20120fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) { 20130fbf3537Syasuoka realm1 = slist_itr_next(&_this->realms); 20140fbf3537Syasuoka if (!npppd_auth_is_usable(realm1)) 20150fbf3537Syasuoka continue; 20160fbf3537Syasuoka switch (npppd_auth_get_type(realm1)) { 20170fbf3537Syasuoka case NPPPD_AUTH_TYPE_LOCAL: 20180fbf3537Syasuoka if (npppd_auth_get_user_password( 20190fbf3537Syasuoka realm1, npppd_auth_username_for_auth( 20200fbf3537Syasuoka realm1, username, buf1), 20210fbf3537Syasuoka NULL, NULL) == 0) { 20220fbf3537Syasuoka realm = realm1; 20230fbf3537Syasuoka goto found; 20240fbf3537Syasuoka } 20250fbf3537Syasuoka break; 20260fbf3537Syasuoka 20270fbf3537Syasuoka case NPPPD_AUTH_TYPE_RADIUS: 20280fbf3537Syasuoka realm = realm1; 20290fbf3537Syasuoka goto found; 20300fbf3537Syasuoka } 20310fbf3537Syasuoka } 20320fbf3537Syasuoka #else 20330fbf3537Syasuoka /* Nothing to do */ 20340fbf3537Syasuoka #endif 20350fbf3537Syasuoka } else { 20360fbf3537Syasuoka strlcpy(buf, val, sizeof(buf)); 20370fbf3537Syasuoka buf0 = buf; 20380fbf3537Syasuoka while ((tok = strsep(&buf0, " ,\t\r\n")) != NULL) { 20390fbf3537Syasuoka if (tok[0] == '\0') 20400fbf3537Syasuoka continue; 20410fbf3537Syasuoka realm0 = NULL; 20420fbf3537Syasuoka slist_itr_first(&_this->realms); 20430fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) { 20440fbf3537Syasuoka realm1 = slist_itr_next(&_this->realms); 20450fbf3537Syasuoka if (!npppd_auth_is_usable(realm1)) 20460fbf3537Syasuoka continue; 20470fbf3537Syasuoka if (eap_required && 20480fbf3537Syasuoka !npppd_auth_is_eap_capable(realm1)) 20490fbf3537Syasuoka continue; 20500fbf3537Syasuoka if (strcmp(npppd_auth_get_label(realm1), tok) 20510fbf3537Syasuoka == 0) { 20520fbf3537Syasuoka realm0 = realm1; 20530fbf3537Syasuoka break; 20540fbf3537Syasuoka } 20550fbf3537Syasuoka } 20560fbf3537Syasuoka if (realm0 == NULL) 20570fbf3537Syasuoka continue; 20580fbf3537Syasuoka lsuffix = strlen(npppd_auth_get_suffix(realm0)); 20590fbf3537Syasuoka if (lsuffix > lmax && 20600fbf3537Syasuoka (lsuffix == 0 || (lsuffix < lusername && 20610fbf3537Syasuoka strcmp(username + lusername - lsuffix, 20620fbf3537Syasuoka npppd_auth_get_suffix(realm0)) == 0))) { 20630fbf3537Syasuoka /* check prefix */ 20648daf7599Syasuoka lprefix = strlen(npppd_auth_get_prefix(realm0)); 20650fbf3537Syasuoka if (lprefix > 0 && 20660fbf3537Syasuoka strncmp(username, 20678daf7599Syasuoka npppd_auth_get_prefix(realm0), 20680fbf3537Syasuoka lprefix) != 0) 20690fbf3537Syasuoka continue; 20700fbf3537Syasuoka 20710fbf3537Syasuoka lmax = lsuffix; 20720fbf3537Syasuoka realm = realm0; 20730fbf3537Syasuoka } 20740fbf3537Syasuoka } 20750fbf3537Syasuoka } 20760fbf3537Syasuoka if (realm == NULL) { 20770fbf3537Syasuoka log_printf(LOG_INFO, "user='%s' could not bind any realms", 20780fbf3537Syasuoka username); 20790fbf3537Syasuoka return 1; 20800fbf3537Syasuoka } 20810fbf3537Syasuoka #ifndef NO_DEFAULT_REALM 20820fbf3537Syasuoka found: 20830fbf3537Syasuoka #endif 20840fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s bind realm %s(%s)", 20850fbf3537Syasuoka username, npppd_auth_get_label(realm), npppd_auth_get_name(realm))); 20860fbf3537Syasuoka 20870fbf3537Syasuoka if (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL) 20880fbf3537Syasuoka /* hook the auto reload */ 20890fbf3537Syasuoka npppd_auth_get_user_password(realm, 20900fbf3537Syasuoka npppd_auth_username_for_auth(realm1, username, buf1), NULL, 20910fbf3537Syasuoka NULL); 20920fbf3537Syasuoka ppp->realm = realm; 20930fbf3537Syasuoka 20940fbf3537Syasuoka return 0; 20950fbf3537Syasuoka } 20960fbf3537Syasuoka 2097f0a4e295Syasuoka /** Is assigned realm a LOCAL authentication? */ 20980fbf3537Syasuoka int 20990fbf3537Syasuoka npppd_ppp_is_realm_local(npppd *_this, npppd_ppp *ppp) 21000fbf3537Syasuoka { 21010fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 21020fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 21030fbf3537Syasuoka 21040fbf3537Syasuoka if (ppp->realm == NULL) 21050fbf3537Syasuoka return 0; 21060fbf3537Syasuoka 21070fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_LOCAL) 21080fbf3537Syasuoka ? 1 : 0; 21090fbf3537Syasuoka } 21100fbf3537Syasuoka 2111f0a4e295Syasuoka /** Is assigned realm a RADIUS authentication? */ 21120fbf3537Syasuoka int 21130fbf3537Syasuoka npppd_ppp_is_realm_radius(npppd *_this, npppd_ppp *ppp) 21140fbf3537Syasuoka { 21150fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 21160fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 21170fbf3537Syasuoka 21180fbf3537Syasuoka if (ppp->realm == NULL) 21190fbf3537Syasuoka return 0; 21200fbf3537Syasuoka 21210fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_RADIUS) 21220fbf3537Syasuoka ? 1 : 0; 21230fbf3537Syasuoka } 21240fbf3537Syasuoka 2125f0a4e295Syasuoka /** Is assigned realm usable? */ 21260fbf3537Syasuoka int 21270fbf3537Syasuoka npppd_ppp_is_realm_ready(npppd *_this, npppd_ppp *ppp) 21280fbf3537Syasuoka { 21290fbf3537Syasuoka if (ppp->realm == NULL) 21300fbf3537Syasuoka return 0; 21310fbf3537Syasuoka 21320fbf3537Syasuoka return npppd_auth_is_ready(ppp->realm); 21330fbf3537Syasuoka } 21340fbf3537Syasuoka 2135f0a4e295Syasuoka /** Return the name of assigned realm */ 21360fbf3537Syasuoka const char * 21370fbf3537Syasuoka npppd_ppp_get_realm_name(npppd *_this, npppd_ppp *ppp) 21380fbf3537Syasuoka { 21390fbf3537Syasuoka if (ppp->realm == NULL) 21400fbf3537Syasuoka return "(none)"; 21410fbf3537Syasuoka return npppd_auth_get_name(ppp->realm); 21420fbf3537Syasuoka } 21430fbf3537Syasuoka 2144f0a4e295Syasuoka /** Return the interface name that bound given {@link ::npppd_ppp PPP} */ 21450fbf3537Syasuoka const char * 21460fbf3537Syasuoka npppd_ppp_get_iface_name(npppd *_this, npppd_ppp *ppp) 21470fbf3537Syasuoka { 21480fbf3537Syasuoka if (ppp == NULL || ppp->ifidx < 0) 21490fbf3537Syasuoka return "(not binding)"; 21500fbf3537Syasuoka return ppp_iface(ppp)->ifname; 21510fbf3537Syasuoka } 21520fbf3537Syasuoka 2153f0a4e295Syasuoka /** Is the interface usable? */ 21540fbf3537Syasuoka int 21550fbf3537Syasuoka npppd_ppp_iface_is_ready(npppd *_this, npppd_ppp *ppp) 21560fbf3537Syasuoka { 21570fbf3537Syasuoka return (npppd_iface_ip_is_ready(ppp_iface(ppp)) && 21580fbf3537Syasuoka ppp_ipcp(ppp) != NULL)? 1 : 0; 21590fbf3537Syasuoka } 21600fbf3537Syasuoka 2161f0a4e295Syasuoka /** Select a suitable interface for {@link :npppd_ppp PPP} and bind them */ 21620fbf3537Syasuoka int 21630fbf3537Syasuoka npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp) 21640fbf3537Syasuoka { 21650fbf3537Syasuoka int i, ifidx, ntotal_session; 21660fbf3537Syasuoka const char *ifname, *label; 21670fbf3537Syasuoka char buf[BUFSIZ]; 21680fbf3537Syasuoka npppd_auth_base *realm; 21690fbf3537Syasuoka 21700fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 21710fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 21720fbf3537Syasuoka 21730fbf3537Syasuoka if (ppp->ifidx >= 0) 21740fbf3537Syasuoka return 0; 21750fbf3537Syasuoka if (ppp->peer_auth == 0) { 21760fbf3537Syasuoka strlcpy(buf, "no_auth.concentrate", sizeof(buf)); 21770fbf3537Syasuoka } else { 21780fbf3537Syasuoka realm = (npppd_auth_base *)ppp->realm; 21790fbf3537Syasuoka strlcpy(buf, "realm.", sizeof(buf)); 21800fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 21810fbf3537Syasuoka label = npppd_auth_get_label(realm); 21820fbf3537Syasuoka if (label[0] != '\0') { 21830fbf3537Syasuoka strlcat(buf, label, sizeof(buf)); 21840fbf3537Syasuoka strlcat(buf, ".concentrate", sizeof(buf)); 21850fbf3537Syasuoka } else 21860fbf3537Syasuoka strlcat(buf, "concentrate", sizeof(buf)); 21870fbf3537Syasuoka } 21880fbf3537Syasuoka 21890fbf3537Syasuoka ifname = ppp_config_str(ppp, buf); 21900fbf3537Syasuoka if (ifname == NULL) 21910fbf3537Syasuoka return 1; 21920fbf3537Syasuoka 2193f0a4e295Syasuoka /* Search a interface */ 21940fbf3537Syasuoka ifidx = -1; 21950fbf3537Syasuoka ntotal_session = 0; 21960fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) { 21970fbf3537Syasuoka if (_this->iface[i].initialized == 0) 21980fbf3537Syasuoka continue; 21990fbf3537Syasuoka ntotal_session += _this->iface[i].nsession; 22000fbf3537Syasuoka if (strcmp(_this->iface[i].ifname, ifname) == 0) 22010fbf3537Syasuoka ifidx = i; 22020fbf3537Syasuoka } 22030fbf3537Syasuoka if (ifidx < 0) 22040fbf3537Syasuoka return 1; 22050fbf3537Syasuoka 22060fbf3537Syasuoka if (ntotal_session >= _this->max_session) { 22070fbf3537Syasuoka ppp_log(ppp, LOG_WARNING, 22080fbf3537Syasuoka "Number of sessions reaches out of the limit=%d", 22090fbf3537Syasuoka _this->max_session); 22100fbf3537Syasuoka return 1; 22110fbf3537Syasuoka } 22120fbf3537Syasuoka if (_this->iface[ifidx].nsession >= _this->iface[ifidx].max_session) { 22130fbf3537Syasuoka ppp_log(ppp, LOG_WARNING, 22140fbf3537Syasuoka "Number of sessions reaches out of the interface limit=%d", 22150fbf3537Syasuoka _this->iface[ifidx].max_session); 22160fbf3537Syasuoka return 1; 22170fbf3537Syasuoka } 22180fbf3537Syasuoka 22190fbf3537Syasuoka ppp->ifidx = ifidx; 22200fbf3537Syasuoka ppp_iface(ppp)->nsession++; 22210fbf3537Syasuoka 22220fbf3537Syasuoka return 0; 22230fbf3537Syasuoka } 22240fbf3537Syasuoka 2225f0a4e295Syasuoka /** Unbind the interface from the {@link ::npppd_ppp PPP} */ 22260fbf3537Syasuoka void 22270fbf3537Syasuoka npppd_ppp_unbind_iface(npppd *_this, npppd_ppp *ppp) 22280fbf3537Syasuoka { 22290fbf3537Syasuoka if (ppp->ifidx >= 0) 22300fbf3537Syasuoka ppp_iface(ppp)->nsession--; 22310fbf3537Syasuoka 22320fbf3537Syasuoka ppp->ifidx = -1; 22330fbf3537Syasuoka } 22340fbf3537Syasuoka 22350fbf3537Syasuoka static int 22360fbf3537Syasuoka npppd_rd_walktree_delete(struct radish_head *rh) 22370fbf3537Syasuoka { 22380fbf3537Syasuoka void *dummy; 22390fbf3537Syasuoka struct radish *rd; 22400fbf3537Syasuoka slist list; 22410fbf3537Syasuoka 22420fbf3537Syasuoka slist_init(&list); 22430fbf3537Syasuoka if (rd2slist(rh, &list) != 0) 22440fbf3537Syasuoka return 1; 22450fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) { 22460fbf3537Syasuoka rd = slist_itr_next(&list); 22470fbf3537Syasuoka rd_delete(rd->rd_route, rd->rd_mask, rh, &dummy); 22480fbf3537Syasuoka } 22490fbf3537Syasuoka slist_fini(&list); 22500fbf3537Syasuoka 22510fbf3537Syasuoka free(rh); 22520fbf3537Syasuoka 22530fbf3537Syasuoka return 0; 22540fbf3537Syasuoka } 22550fbf3537Syasuoka 22560fbf3537Syasuoka #ifdef USE_NPPPD_RADIUS 2257f0a4e295Syasuoka /** 2258f0a4e295Syasuoka * Return radius_req_setting for the given {@link ::npppd_ppp PPP}. 2259f0a4e295Syasuoka * @return return NULL if no usable RADIUS setting. 2260f0a4e295Syasuoka */ 22610fbf3537Syasuoka void * 22628daf7599Syasuoka npppd_get_radius_auth_setting(npppd *_this, npppd_ppp *ppp) 22630fbf3537Syasuoka { 22640fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 22650fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 22660fbf3537Syasuoka 22670fbf3537Syasuoka if (ppp->realm == NULL) 22680fbf3537Syasuoka return NULL; 22690fbf3537Syasuoka if (!npppd_ppp_is_realm_radius(_this, ppp)) 22700fbf3537Syasuoka return NULL; 22710fbf3537Syasuoka 22728daf7599Syasuoka return npppd_auth_radius_get_radius_auth_setting(ppp->realm); 22730fbf3537Syasuoka } 22740fbf3537Syasuoka #endif 22750fbf3537Syasuoka 2276f0a4e295Syasuoka /** Finalize authentication realm */ 22770fbf3537Syasuoka static void 22780fbf3537Syasuoka npppd_auth_finalizer_periodic(npppd *_this) 22790fbf3537Syasuoka { 22800fbf3537Syasuoka int ndisposing = 0, refcnt; 22810fbf3537Syasuoka slist users; 22820fbf3537Syasuoka npppd_auth_base *auth_base; 22830fbf3537Syasuoka npppd_ppp *ppp; 22840fbf3537Syasuoka 22850fbf3537Syasuoka /* 2286f0a4e295Syasuoka * For the realms with disposing flag, if the realm has assigned PPPs, 2287f0a4e295Syasuoka * disconnect them. If all PPPs are disconnected then free the realm. 22880fbf3537Syasuoka */ 22890fbf3537Syasuoka NPPPD_DBG((DEBUG_LEVEL_2, "%s() called", __func__)); 22900fbf3537Syasuoka slist_itr_first(&_this->realms); 22910fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) { 22920fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms); 22930fbf3537Syasuoka if (!npppd_auth_is_disposing(auth_base)) 22940fbf3537Syasuoka continue; 22950fbf3537Syasuoka refcnt = 0; 22960fbf3537Syasuoka if (ndisposing++ == 0) { 22970fbf3537Syasuoka slist_init(&users); 22980fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) { 22990fbf3537Syasuoka log_printf(LOG_WARNING, 23000fbf3537Syasuoka "npppd_get_all_users() failed in %s(): %m", 23010fbf3537Syasuoka __func__); 23020fbf3537Syasuoka break; 23030fbf3537Syasuoka } 23040fbf3537Syasuoka } 23050fbf3537Syasuoka slist_itr_first(&users); 23060fbf3537Syasuoka while (slist_itr_has_next(&users)) { 23070fbf3537Syasuoka ppp = slist_itr_next(&users); 23080fbf3537Syasuoka if (ppp->realm == auth_base) { 23090fbf3537Syasuoka refcnt++; 23100fbf3537Syasuoka ppp_stop(ppp, NULL); 23110fbf3537Syasuoka ppp_log(ppp, LOG_INFO, 23120fbf3537Syasuoka "Stop request by npppd. Binding " 23130fbf3537Syasuoka "authentication realm is disposing. " 23140fbf3537Syasuoka "realm=%s", npppd_auth_get_name(auth_base)); 23150fbf3537Syasuoka slist_itr_remove(&users); 23160fbf3537Syasuoka } 23170fbf3537Syasuoka } 23188daf7599Syasuoka if (refcnt == 0) { 23190fbf3537Syasuoka npppd_auth_destroy(auth_base); 23208daf7599Syasuoka slist_itr_remove(&_this->realms); 23218daf7599Syasuoka } 23220fbf3537Syasuoka } 23230fbf3537Syasuoka if (ndisposing > 0) 23240fbf3537Syasuoka slist_fini(&users); 23250fbf3537Syasuoka } 23260fbf3537Syasuoka 2327f0a4e295Syasuoka /** compare sockaddr_npppd. return 0 if matches */ 23280fbf3537Syasuoka int 23290fbf3537Syasuoka sockaddr_npppd_match(void *a0, void *b0) 23300fbf3537Syasuoka { 23310fbf3537Syasuoka struct sockaddr_npppd *a, *b; 23320fbf3537Syasuoka 23330fbf3537Syasuoka a = a0; 23340fbf3537Syasuoka b = b0; 23350fbf3537Syasuoka 23360fbf3537Syasuoka return (a->snp_addr.s_addr == b->snp_addr.s_addr)? 1 : 0; 23370fbf3537Syasuoka } 23380fbf3537Syasuoka 23390fbf3537Syasuoka /** 2340f0a4e295Syasuoka * This function stores the username for authentication to the space specified 2341f0a4e295Syasuoka * by username_buffer and returns it. username_buffer must have space more 2342f0a4e295Syasuoka * than MAX_USERNAME_LENGTH. 23430fbf3537Syasuoka */ 23440fbf3537Syasuoka const char * 23450fbf3537Syasuoka npppd_ppp_get_username_for_auth(npppd *_this, npppd_ppp *ppp, 23460fbf3537Syasuoka const char *username, char *username_buffer) 23470fbf3537Syasuoka { 23480fbf3537Syasuoka NPPPD_ASSERT(_this != NULL); 23490fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL); 23500fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL); 23510fbf3537Syasuoka 23520fbf3537Syasuoka return npppd_auth_username_for_auth(ppp->realm, username, 23530fbf3537Syasuoka username_buffer); 23540fbf3537Syasuoka } 23550fbf3537Syasuoka 23560fbf3537Syasuoka static inline void 23570fbf3537Syasuoka seed_random(long *seed) 23580fbf3537Syasuoka { 23590fbf3537Syasuoka struct timeval t; 23600fbf3537Syasuoka #ifdef KERN_URND 23610fbf3537Syasuoka size_t seedsiz; 23620fbf3537Syasuoka int mib[] = { CTL_KERN, KERN_URND }; 23630fbf3537Syasuoka 23640fbf3537Syasuoka seedsiz = sizeof(*seed); 23650fbf3537Syasuoka if (sysctl(mib, countof(mib), seed, &seedsiz, NULL, 0) == 0) { 23660fbf3537Syasuoka NPPPD_ASSERT(seedsiz == sizeof(long)); 23670fbf3537Syasuoka return; 23680fbf3537Syasuoka } 23690fbf3537Syasuoka log_printf(LOG_WARNING, "Could not set random seed from the system: %m"); 23700fbf3537Syasuoka #endif 23710fbf3537Syasuoka gettimeofday(&t, NULL); 23720fbf3537Syasuoka *seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid(); 23730fbf3537Syasuoka } 2374*363e4d4bSyasuoka 2375*363e4d4bSyasuoka const char * 2376*363e4d4bSyasuoka npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp) 2377*363e4d4bSyasuoka { 2378*363e4d4bSyasuoka switch (ppp->tunnel_type) { 2379*363e4d4bSyasuoka case PPP_TUNNEL_NONE: 2380*363e4d4bSyasuoka return "None"; 2381*363e4d4bSyasuoka case PPP_TUNNEL_L2TP: 2382*363e4d4bSyasuoka return "L2TP"; 2383*363e4d4bSyasuoka case PPP_TUNNEL_PPTP: 2384*363e4d4bSyasuoka return "PPTP"; 2385*363e4d4bSyasuoka case PPP_TUNNEL_PPPOE: 2386*363e4d4bSyasuoka return "PPPoE"; 2387*363e4d4bSyasuoka case PPP_TUNNEL_SSTP: 2388*363e4d4bSyasuoka return "SSTP"; 2389*363e4d4bSyasuoka } 2390*363e4d4bSyasuoka 2391*363e4d4bSyasuoka NPPPD_ASSERT(0); 2392*363e4d4bSyasuoka return "Error"; 2393*363e4d4bSyasuoka } 2394