1*a4a82b86Smvs /* $OpenBSD: npppd.c,v 1.53 2022/07/01 09:57:24 mvs Exp $ */
2e109dc18Syasuoka
30fbf3537Syasuoka /*-
44a39ccd0Sderaadt * Copyright (c) 2005-2008,2009 Internet Initiative Japan Inc.
50fbf3537Syasuoka * All rights reserved.
60fbf3537Syasuoka *
70fbf3537Syasuoka * Redistribution and use in source and binary forms, with or without
80fbf3537Syasuoka * modification, are permitted provided that the following conditions
90fbf3537Syasuoka * are met:
100fbf3537Syasuoka * 1. Redistributions of source code must retain the above copyright
110fbf3537Syasuoka * notice, this list of conditions and the following disclaimer.
120fbf3537Syasuoka * 2. Redistributions in binary form must reproduce the above copyright
130fbf3537Syasuoka * notice, this list of conditions and the following disclaimer in the
140fbf3537Syasuoka * documentation and/or other materials provided with the distribution.
150fbf3537Syasuoka *
160fbf3537Syasuoka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170fbf3537Syasuoka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180fbf3537Syasuoka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190fbf3537Syasuoka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200fbf3537Syasuoka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210fbf3537Syasuoka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220fbf3537Syasuoka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230fbf3537Syasuoka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240fbf3537Syasuoka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250fbf3537Syasuoka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260fbf3537Syasuoka * SUCH DAMAGE.
270fbf3537Syasuoka */
280fbf3537Syasuoka /**@file
29f0a4e295Syasuoka * Next pppd(nppd). This file provides a npppd daemon process and operations
30f0a4e295Syasuoka * for npppd instance.
310fbf3537Syasuoka * @author Yasuoka Masahiko
32*a4a82b86Smvs * $Id: npppd.c,v 1.53 2022/07/01 09:57:24 mvs Exp $
330fbf3537Syasuoka */
340fbf3537Syasuoka #include "version.h"
35dbad4650Sderaadt #include <sys/param.h> /* ALIGNED_POINTER */
360fbf3537Syasuoka #include <sys/types.h>
370fbf3537Syasuoka #include <sys/socket.h>
380fbf3537Syasuoka #include <sys/sysctl.h>
395fefcc09Syasuoka #include <sys/wait.h>
400fbf3537Syasuoka #include <netinet/in.h>
410fbf3537Syasuoka #include <netinet/ip.h>
420fbf3537Syasuoka #include <net/route.h>
430fbf3537Syasuoka #include <arpa/inet.h>
440fbf3537Syasuoka #include <net/if_dl.h>
450fbf3537Syasuoka #include <unistd.h>
460fbf3537Syasuoka #include <time.h>
470fbf3537Syasuoka #include <syslog.h>
480fbf3537Syasuoka #include <string.h>
490fbf3537Syasuoka #include <stdlib.h>
500fbf3537Syasuoka #include <stdio.h>
510fbf3537Syasuoka #include <signal.h>
520fbf3537Syasuoka #include <netdb.h>
530fbf3537Syasuoka #include <fcntl.h>
540fbf3537Syasuoka #include <event.h>
550fbf3537Syasuoka #include <errno.h>
564a78f66bSyasuoka #include <err.h>
574a78f66bSyasuoka #include <pwd.h>
580fbf3537Syasuoka
590fbf3537Syasuoka #include "pathnames.h"
600fbf3537Syasuoka #include "debugutil.h"
610fbf3537Syasuoka #include "addr_range.h"
620fbf3537Syasuoka #include "npppd_subr.h"
630fbf3537Syasuoka #include "npppd_local.h"
640fbf3537Syasuoka #include "npppd_auth.h"
650fbf3537Syasuoka #include "radish.h"
660fbf3537Syasuoka #include "net_utils.h"
670fbf3537Syasuoka #include "time_utils.h"
680fbf3537Syasuoka
69b56612b6Smarkus #include "l2tp_local.h" /* XXX sa_cookie */
70b56612b6Smarkus
710fbf3537Syasuoka #ifdef USE_NPPPD_ARP
720fbf3537Syasuoka #include "npppd_arp.h"
730fbf3537Syasuoka #endif
740fbf3537Syasuoka
750fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
760fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
770fbf3537Syasuoka #include "pppoe_local.h"
780fbf3537Syasuoka #endif /* USE_NPPPD_PPPOE */
790fbf3537Syasuoka #include "psm-opt.h"
800fbf3537Syasuoka #include <sys/ioctl.h>
810fbf3537Syasuoka #include <net/pipex.h>
820fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */
830fbf3537Syasuoka
8459408346Syasuoka #include "accept.h"
8559408346Syasuoka #include "log.h"
8659408346Syasuoka
870fbf3537Syasuoka static npppd s_npppd; /* singleton */
880fbf3537Syasuoka
890fbf3537Syasuoka static void npppd_reload0 (npppd *);
90821f7c56Syasuoka static void npppd_update_pool_reference (npppd *);
910fbf3537Syasuoka static int npppd_rd_walktree_delete(struct radish_head *);
920cd27c4aSyasuoka static __dead void usage (void);
930fbf3537Syasuoka static void npppd_stop_really (npppd *);
940fbf3537Syasuoka static uint32_t str_hash(const void *, int);
950fbf3537Syasuoka static void npppd_on_sighup (int, short, void *);
960fbf3537Syasuoka static void npppd_on_sigterm (int, short, void *);
970fbf3537Syasuoka static void npppd_on_sigint (int, short, void *);
985fefcc09Syasuoka static void npppd_on_sigchld (int, short, void *);
990fbf3537Syasuoka static void npppd_reset_timer(npppd *);
1000fbf3537Syasuoka static void npppd_timer(int, short, void *);
1010fbf3537Syasuoka static void npppd_auth_finalizer_periodic(npppd *);
1020fbf3537Syasuoka static int rd2slist_walk (struct radish *, void *);
1030fbf3537Syasuoka static int rd2slist (struct radish_head *, slist *);
10434682664Syasuoka static slist *npppd_get_ppp_by_user (npppd *, const char *);
10534682664Syasuoka static int npppd_get_all_users (npppd *, slist *);
1062a5607d2Sgoda static struct ipcpstat
1072a5607d2Sgoda *npppd_get_ipcp_stat(struct ipcpstat_head *, const char *);
1082a5607d2Sgoda static void npppd_destroy_ipcp_stats(struct ipcpstat_head *);
1092a5607d2Sgoda static void npppd_ipcp_stats_reload(npppd *);
1100fbf3537Syasuoka
1110fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS
1120fbf3537Syasuoka static struct in_addr loop; /* initialize at npppd_init() */
1130fbf3537Syasuoka #endif
1140fbf3537Syasuoka static uint32_t str_hash(const void *, int);
1150fbf3537Syasuoka
1160fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
1170fbf3537Syasuoka static void pipex_periodic(npppd *);
1180fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */
1190fbf3537Syasuoka
1200fbf3537Syasuoka #ifdef NPPPD_DEBUG
1210fbf3537Syasuoka #define NPPPD_DBG(x) log_printf x
1220fbf3537Syasuoka #define NPPPD_ASSERT(x) ASSERT(x)
1230fbf3537Syasuoka #else
1240fbf3537Syasuoka #define NPPPD_DBG(x)
1250fbf3537Syasuoka #define NPPPD_ASSERT(x)
1260fbf3537Syasuoka #endif
1270fbf3537Syasuoka
1280fbf3537Syasuoka /***********************************************************************
129f0a4e295Syasuoka * Daemon process
1300fbf3537Syasuoka ***********************************************************************/
1310fbf3537Syasuoka int main (int, char *[]);
132821f7c56Syasuoka int debugsyslog = 0; /* used by log.c */
1330fbf3537Syasuoka
1340fbf3537Syasuoka int
main(int argc,char * argv[])1350fbf3537Syasuoka main(int argc, char *argv[])
1360fbf3537Syasuoka {
137821f7c56Syasuoka int ch, stop_by_error, runasdaemon = 1, nflag = 0;
1380fbf3537Syasuoka const char *npppd_conf0 = DEFAULT_NPPPD_CONF;
1394a78f66bSyasuoka struct passwd *pw;
1400fbf3537Syasuoka
1410cd27c4aSyasuoka while ((ch = getopt(argc, argv, "nf:d")) != -1) {
1420fbf3537Syasuoka switch (ch) {
143821f7c56Syasuoka case 'n':
144821f7c56Syasuoka nflag = 1;
1450fbf3537Syasuoka break;
146821f7c56Syasuoka case 'f':
1470fbf3537Syasuoka npppd_conf0 = optarg;
1480fbf3537Syasuoka break;
1490fbf3537Syasuoka case 'd':
1500fbf3537Syasuoka debuglevel++;
151821f7c56Syasuoka runasdaemon = 0;
1520fbf3537Syasuoka break;
1530cd27c4aSyasuoka default:
1540fbf3537Syasuoka usage();
1550fbf3537Syasuoka }
1560fbf3537Syasuoka }
157821f7c56Syasuoka argc -= optind;
158821f7c56Syasuoka argv += optind;
1590cd27c4aSyasuoka if (argc != 0)
160821f7c56Syasuoka usage();
161821f7c56Syasuoka if (nflag) {
162821f7c56Syasuoka debuglevel++;
163821f7c56Syasuoka runasdaemon = 0;
164821f7c56Syasuoka }
165821f7c56Syasuoka
166821f7c56Syasuoka /* for log.c */
167821f7c56Syasuoka log_init(debuglevel);
1680fbf3537Syasuoka if (debuglevel > 0) {
169821f7c56Syasuoka /* for ../common/debugutil.c */
1700fbf3537Syasuoka debug_set_debugfp(stderr);
1710fbf3537Syasuoka debug_use_syslog(0);
172821f7c56Syasuoka }
1730fbf3537Syasuoka if (runasdaemon)
1740fbf3537Syasuoka daemon(0, 0);
1750fbf3537Syasuoka
1764a78f66bSyasuoka /* check for root privileges */
1774a78f66bSyasuoka if (geteuid())
1784a78f66bSyasuoka errx(1, "need root privileges");
1794a78f66bSyasuoka /* check for npppd user */
1804a78f66bSyasuoka if (getpwnam(NPPPD_USER) == NULL)
1814a78f66bSyasuoka errx(1, "unknown user %s", NPPPD_USER);
1824a78f66bSyasuoka
1834a78f66bSyasuoka if (privsep_init() != 0)
1844a78f66bSyasuoka err(1, "cannot drop privileges");
1854a78f66bSyasuoka
186821f7c56Syasuoka if (nflag) {
187821f7c56Syasuoka if (npppd_config_check(npppd_conf0) == 0) {
188821f7c56Syasuoka fprintf(stderr, "configuration OK\n");
189821f7c56Syasuoka exit(EXIT_SUCCESS);
190821f7c56Syasuoka }
191821f7c56Syasuoka exit(EXIT_FAILURE);
192821f7c56Syasuoka }
1939a200ddfSyasuoka if (npppd_init(&s_npppd, npppd_conf0) != 0)
1949a200ddfSyasuoka exit(EXIT_FAILURE);
1954a78f66bSyasuoka
1964a78f66bSyasuoka if ((pw = getpwnam(NPPPD_USER)) == NULL)
1979a200ddfSyasuoka err(EXIT_FAILURE, "gwpwnam");
1984a78f66bSyasuoka if (chroot(pw->pw_dir) == -1)
1999a200ddfSyasuoka err(EXIT_FAILURE, "chroot");
2004a78f66bSyasuoka if (chdir("/") == -1)
2019a200ddfSyasuoka err(EXIT_FAILURE, "chdir(\"/\")");
2024a78f66bSyasuoka if (setgroups(1, &pw->pw_gid) ||
2034a78f66bSyasuoka setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
2044a78f66bSyasuoka setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
2059a200ddfSyasuoka err(EXIT_FAILURE, "cannot drop privileges");
2064a78f66bSyasuoka /* privileges is dropped */
2074a78f66bSyasuoka
2080fbf3537Syasuoka npppd_start(&s_npppd);
2099a200ddfSyasuoka stop_by_error = s_npppd.stop_by_error;
2100fbf3537Syasuoka npppd_fini(&s_npppd);
2114a78f66bSyasuoka privsep_fini();
2120fbf3537Syasuoka log_printf(LOG_NOTICE, "Terminate npppd.");
2130fbf3537Syasuoka
2149a200ddfSyasuoka exit((!stop_by_error)? EXIT_SUCCESS : EXIT_FAILURE);
2150fbf3537Syasuoka }
2160fbf3537Syasuoka
2170cd27c4aSyasuoka static __dead void
usage(void)2180cd27c4aSyasuoka usage(void)
2190fbf3537Syasuoka {
2200cd27c4aSyasuoka fprintf(stderr, "usage: npppd [-dn] [-f config_file]\n");
2210cd27c4aSyasuoka exit(1);
2220fbf3537Syasuoka }
2230fbf3537Syasuoka
224f0a4e295Syasuoka /** Returns the singleton npppd instance */
2250fbf3537Syasuoka npppd *
npppd_get_npppd()2260fbf3537Syasuoka npppd_get_npppd()
2270fbf3537Syasuoka {
2280fbf3537Syasuoka return &s_npppd;
2290fbf3537Syasuoka }
2300fbf3537Syasuoka
2310fbf3537Syasuoka /***********************************************************************
232f0a4e295Syasuoka * Operations to npppd itself (initialize/finalize/start/stop)
2330fbf3537Syasuoka ***********************************************************************/
234f0a4e295Syasuoka /** Initialize the npppd */
2350fbf3537Syasuoka int
npppd_init(npppd * _this,const char * config_file)2360fbf3537Syasuoka npppd_init(npppd *_this, const char *config_file)
2370fbf3537Syasuoka {
2384c9b8a40Syasuoka int i, status = -1, value;
2390fbf3537Syasuoka const char *pidpath0;
2400fbf3537Syasuoka FILE *pidfp = NULL;
2414c9b8a40Syasuoka struct tunnconf *tunn;
2422a5607d2Sgoda struct ipcpconf *ipcpconf;
2432a5607d2Sgoda struct ipcpstat *ipcpstat;
2444c9b8a40Syasuoka int mib[] = { CTL_NET, PF_PIPEX, PIPEXCTL_ENABLE };
2454c9b8a40Syasuoka size_t size;
2460fbf3537Syasuoka
2470fbf3537Syasuoka memset(_this, 0, sizeof(npppd));
248cd8e09b9Sdlg #ifndef NO_ROUTE_FOR_POOLED_ADDRESS
2490fbf3537Syasuoka loop.s_addr = htonl(INADDR_LOOPBACK);
250cd8e09b9Sdlg #endif
2510fbf3537Syasuoka
2520fbf3537Syasuoka NPPPD_ASSERT(config_file != NULL);
2530fbf3537Syasuoka
2540fbf3537Syasuoka pidpath0 = NULL;
2550fbf3537Syasuoka _this->pid = getpid();
2560fbf3537Syasuoka slist_init(&_this->realms);
257821f7c56Syasuoka npppd_conf_init(&_this->conf);
2580fbf3537Syasuoka
2590fbf3537Syasuoka log_printf(LOG_NOTICE, "Starting npppd pid=%u version=%s",
2600fbf3537Syasuoka _this->pid, VERSION);
2610fbf3537Syasuoka #if defined(BUILD_DATE) && defined(BUILD_TIME)
2620fbf3537Syasuoka log_printf(LOG_INFO, "Build %s %s ", BUILD_DATE, BUILD_TIME);
2630fbf3537Syasuoka #endif
2640fbf3537Syasuoka if (get_nanotime() == INT64_MIN) {
2650fbf3537Syasuoka log_printf(LOG_ERR, "get_nanotime() failed: %m");
2660fbf3537Syasuoka return 1;
2670fbf3537Syasuoka }
2680fbf3537Syasuoka
2690fbf3537Syasuoka if (realpath(config_file, _this->config_file) == NULL) {
2700fbf3537Syasuoka log_printf(LOG_ERR, "realpath(%s,) failed in %s(): %m",
2710fbf3537Syasuoka config_file, __func__);
2720fbf3537Syasuoka return 1;
2730fbf3537Syasuoka }
274f0a4e295Syasuoka /* we assume 4.4 compatible realpath(). See realpath(3) on BSD. */
2750fbf3537Syasuoka NPPPD_ASSERT(_this->config_file[0] == '/');
2760fbf3537Syasuoka
277c2307f15Syasuoka _this->boot_id = arc4random();
2788daf7599Syasuoka
27906adecbeSyasuoka #ifdef USE_NPPPD_L2TP
28006adecbeSyasuoka if (l2tpd_init(&_this->l2tpd) != 0)
28106adecbeSyasuoka return (-1);
28206adecbeSyasuoka #endif
28306adecbeSyasuoka #ifdef USE_NPPPD_PPTP
28406adecbeSyasuoka if (pptpd_init(&_this->pptpd) != 0)
28506adecbeSyasuoka return (-1);
28606adecbeSyasuoka #endif
28706adecbeSyasuoka #ifdef USE_NPPPD_PPPOE
28806adecbeSyasuoka if (pppoed_init(&_this->pppoed) != 0)
28906adecbeSyasuoka return (-1);
29006adecbeSyasuoka #endif
2912a5607d2Sgoda LIST_INIT(&_this->ipcpstats);
2922a5607d2Sgoda
293f0a4e295Syasuoka /* load configuration */
2940fbf3537Syasuoka if ((status = npppd_reload_config(_this)) != 0)
2950fbf3537Syasuoka return status;
2960fbf3537Syasuoka
2974c9b8a40Syasuoka TAILQ_FOREACH(tunn, &_this->conf.tunnconfs, entry) {
2984c9b8a40Syasuoka if (tunn->pipex) {
2994c9b8a40Syasuoka size = sizeof(value);
3004c9b8a40Syasuoka if (!sysctl(mib, nitems(mib), &value, &size, NULL, 0)
3014c9b8a40Syasuoka && value == 0)
3024c9b8a40Syasuoka log_printf(LOG_WARNING,
3034c9b8a40Syasuoka "pipex(4) is disabled by sysctl");
3044c9b8a40Syasuoka break;
3054c9b8a40Syasuoka }
3064c9b8a40Syasuoka }
3074c9b8a40Syasuoka
3080fbf3537Syasuoka if ((_this->map_user_ppp = hash_create(
3090fbf3537Syasuoka (int (*) (const void *, const void *))strcmp, str_hash,
3100fbf3537Syasuoka NPPPD_USER_HASH_SIZ)) == NULL) {
3110fbf3537Syasuoka log_printf(LOG_ERR, "hash_create() failed in %s(): %m",
3120fbf3537Syasuoka __func__);
3130fbf3537Syasuoka return -1;
3140fbf3537Syasuoka }
3150fbf3537Syasuoka
3160fbf3537Syasuoka if (npppd_ifaces_load_config(_this) != 0) {
3170fbf3537Syasuoka return -1;
3180fbf3537Syasuoka }
3190fbf3537Syasuoka
3202a5607d2Sgoda TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry) {
3212a5607d2Sgoda ipcpstat = malloc(sizeof(*ipcpstat));
3222a5607d2Sgoda if (ipcpstat == NULL) {
3232a5607d2Sgoda log_printf(LOG_ERR, "initializing ipcp_stats failed : %m");
3242a5607d2Sgoda npppd_destroy_ipcp_stats(&_this->ipcpstats);
3252a5607d2Sgoda return -1;
3262a5607d2Sgoda }
3272a5607d2Sgoda memset(ipcpstat, 0, sizeof(*ipcpstat));
3282a5607d2Sgoda strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpstat->name));
3292a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry);
3302a5607d2Sgoda }
3312a5607d2Sgoda
3320fbf3537Syasuoka pidpath0 = DEFAULT_NPPPD_PIDFILE;
3330fbf3537Syasuoka
334f0a4e295Syasuoka /* initialize event(3) */
3350fbf3537Syasuoka event_init();
33634682664Syasuoka _this->ctl_sock.cs_name = NPPPD_SOCKET;
33734682664Syasuoka _this->ctl_sock.cs_ctx = _this;
33834682664Syasuoka if (control_init(&_this->ctl_sock) == -1) {
33934682664Syasuoka log_printf(LOG_ERR, "control_init() failed %s(): %m",
34034682664Syasuoka __func__);
34134682664Syasuoka return (-1);
34234682664Syasuoka }
34334682664Syasuoka if (control_listen(&_this->ctl_sock) == -1) {
34434682664Syasuoka log_printf(LOG_ERR, "control_listen() failed %s(): %m",
34534682664Syasuoka __func__);
34634682664Syasuoka return (-1);
34734682664Syasuoka }
34859408346Syasuoka accept_init();
34959408346Syasuoka
350f0a4e295Syasuoka /* ignore signals */
3510fbf3537Syasuoka signal(SIGPIPE, SIG_IGN);
3520fbf3537Syasuoka signal(SIGURG, SIG_IGN);
353f0a4e295Syasuoka
354f0a4e295Syasuoka /* set signal handlers */
3550fbf3537Syasuoka signal_set(&_this->ev_sigterm, SIGTERM, npppd_on_sigterm, _this);
3560fbf3537Syasuoka signal_set(&_this->ev_sigint, SIGINT, npppd_on_sigint, _this);
3570fbf3537Syasuoka signal_set(&_this->ev_sighup, SIGHUP, npppd_on_sighup, _this);
3585fefcc09Syasuoka signal_set(&_this->ev_sigchld, SIGCHLD, npppd_on_sigchld, _this);
3590fbf3537Syasuoka signal_add(&_this->ev_sigterm, NULL);
3600fbf3537Syasuoka signal_add(&_this->ev_sigint, NULL);
3610fbf3537Syasuoka signal_add(&_this->ev_sighup, NULL);
3625fefcc09Syasuoka signal_add(&_this->ev_sigchld, NULL);
3630fbf3537Syasuoka
3640fbf3537Syasuoka evtimer_set(&_this->ev_timer, npppd_timer, _this);
3650fbf3537Syasuoka
366f0a4e295Syasuoka /* start tun(4) or pppac(4) */
3670fbf3537Syasuoka status = 0;
3680fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) {
3690fbf3537Syasuoka if (_this->iface[i].initialized != 0)
3700fbf3537Syasuoka status |= npppd_iface_start(&_this->iface[i]);
3710fbf3537Syasuoka }
3720fbf3537Syasuoka if (status != 0)
3730fbf3537Syasuoka return -1;
3740fbf3537Syasuoka
3750fbf3537Syasuoka /*
376f0a4e295Syasuoka * If the npppd can start(open) interfaces successfully, it can
377f0a4e295Syasuoka * act as only one npppd process on the system and overwrite the pid
378f0a4e295Syasuoka * file.
3790fbf3537Syasuoka */
3800fbf3537Syasuoka if ((pidfp = fopen(pidpath0, "w+")) == NULL) {
3810fbf3537Syasuoka log_printf(LOG_ERR, "fopen(%s,w+) failed in %s(): %m",
3820fbf3537Syasuoka pidpath0, __func__);
3830fbf3537Syasuoka return -1;
3840fbf3537Syasuoka }
3850fbf3537Syasuoka strlcpy(_this->pidpath, pidpath0, sizeof(_this->pidpath));
3860fbf3537Syasuoka fprintf(pidfp, "%u\n", _this->pid);
3870fbf3537Syasuoka fclose(pidfp);
3880fbf3537Syasuoka pidfp = NULL;
3890fbf3537Syasuoka #ifdef USE_NPPPD_ARP
3900fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT));
3910fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1)
3920fbf3537Syasuoka arp_sock_init();
3930fbf3537Syasuoka #endif
394821f7c56Syasuoka if ((status = npppd_modules_reload(_this)) != 0)
395821f7c56Syasuoka return status;
396821f7c56Syasuoka
397821f7c56Syasuoka npppd_update_pool_reference(_this);
398821f7c56Syasuoka
399821f7c56Syasuoka return 0;
4000fbf3537Syasuoka }
4010fbf3537Syasuoka
402f0a4e295Syasuoka /** start the npppd */
4030fbf3537Syasuoka void
npppd_start(npppd * _this)4040fbf3537Syasuoka npppd_start(npppd *_this)
4050fbf3537Syasuoka {
4060fbf3537Syasuoka int rval = 0;
4070fbf3537Syasuoka
4080fbf3537Syasuoka npppd_reset_timer(_this);
409f65d56a4Syasuoka while ((rval = event_loop(EVLOOP_ONCE)) == 0) {
4100fbf3537Syasuoka if (_this->finalized != 0)
4110fbf3537Syasuoka break;
4120fbf3537Syasuoka }
413f65d56a4Syasuoka if (rval != 0) {
4140fbf3537Syasuoka log_printf(LOG_CRIT, "event_loop() failed: %m");
415f65d56a4Syasuoka abort();
416f65d56a4Syasuoka }
4170fbf3537Syasuoka }
4180fbf3537Syasuoka
419f0a4e295Syasuoka /** stop the npppd */
4200fbf3537Syasuoka void
npppd_stop(npppd * _this)4210fbf3537Syasuoka npppd_stop(npppd *_this)
4220fbf3537Syasuoka {
4230fbf3537Syasuoka int i;
4240fbf3537Syasuoka #ifdef USE_NPPPD_L2TP
4250fbf3537Syasuoka l2tpd_stop(&_this->l2tpd);
4260fbf3537Syasuoka #endif
4270fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
4280fbf3537Syasuoka pptpd_stop(&_this->pptpd);
4290fbf3537Syasuoka #endif
4300fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
4310fbf3537Syasuoka pppoed_stop(&_this->pppoed);
4320fbf3537Syasuoka #endif
4330fbf3537Syasuoka #ifdef USE_NPPPD_ARP
4340fbf3537Syasuoka arp_sock_fini();
4350fbf3537Syasuoka #endif
43634682664Syasuoka close(_this->ctl_sock.cs_fd);
43734682664Syasuoka control_cleanup(&_this->ctl_sock);
43834682664Syasuoka
4390fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) {
4400fbf3537Syasuoka if (_this->iface[i].initialized != 0)
4410fbf3537Syasuoka npppd_iface_stop(&_this->iface[i]);
4420fbf3537Syasuoka }
4430fbf3537Syasuoka npppd_set_radish(_this, NULL);
4440fbf3537Syasuoka
4450fbf3537Syasuoka _this->finalizing = 1;
4460fbf3537Syasuoka npppd_reset_timer(_this);
4470fbf3537Syasuoka }
4480fbf3537Syasuoka
4490fbf3537Syasuoka static void
npppd_stop_really(npppd * _this)4500fbf3537Syasuoka npppd_stop_really(npppd *_this)
4510fbf3537Syasuoka {
4520fbf3537Syasuoka int i;
4530fbf3537Syasuoka #if defined(USE_NPPPD_L2TP) || defined(USE_NPPPD_PPTP)
4540fbf3537Syasuoka int wait_again;
4550fbf3537Syasuoka
4560fbf3537Syasuoka wait_again = 0;
4570fbf3537Syasuoka
4580fbf3537Syasuoka #ifdef USE_NPPPD_L2TP
4590fbf3537Syasuoka if (!l2tpd_is_stopped(&_this->l2tpd))
4600fbf3537Syasuoka wait_again |= 1;
4610fbf3537Syasuoka #endif
4620fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
4630fbf3537Syasuoka if (!pptpd_is_stopped(&_this->pptpd))
4640fbf3537Syasuoka wait_again |= 1;
4650fbf3537Syasuoka #endif
4660fbf3537Syasuoka if (wait_again != 0) {
4670fbf3537Syasuoka npppd_reset_timer(_this);
4680fbf3537Syasuoka return;
4690fbf3537Syasuoka }
4700fbf3537Syasuoka #endif
4710fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) {
4720fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]);
4730fbf3537Syasuoka }
4740fbf3537Syasuoka _this->finalized = 1;
4750fbf3537Syasuoka }
4760fbf3537Syasuoka
477f0a4e295Syasuoka /** finalize the npppd */
4780fbf3537Syasuoka void
npppd_fini(npppd * _this)4790fbf3537Syasuoka npppd_fini(npppd *_this)
4800fbf3537Syasuoka {
4810fbf3537Syasuoka int i;
4820fbf3537Syasuoka npppd_auth_base *auth_base;
4830fbf3537Syasuoka
4840fbf3537Syasuoka #ifdef USE_NPPPD_L2TP
4850fbf3537Syasuoka l2tpd_uninit(&_this->l2tpd);
4860fbf3537Syasuoka #endif
4870fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
4880fbf3537Syasuoka pptpd_uninit(&_this->pptpd);
4890fbf3537Syasuoka #endif
4900fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
4910fbf3537Syasuoka pppoed_uninit(&_this->pppoed);
4920fbf3537Syasuoka #endif
4930fbf3537Syasuoka for (slist_itr_first(&_this->realms);
4940fbf3537Syasuoka slist_itr_has_next(&_this->realms);) {
4950fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms);
4960fbf3537Syasuoka npppd_auth_destroy(auth_base);
4970fbf3537Syasuoka }
4980fbf3537Syasuoka for (i = countof(_this->iface) - 1; i >= 0; i--) {
4990fbf3537Syasuoka if (_this->iface[i].initialized != 0)
5000fbf3537Syasuoka npppd_iface_fini(&_this->iface[i]);
5010fbf3537Syasuoka }
5020fbf3537Syasuoka
5030fbf3537Syasuoka for (i = countof(_this->pool) - 1; i >= 0; i--) {
5040fbf3537Syasuoka if (_this->pool[i].initialized != 0)
5050fbf3537Syasuoka npppd_pool_uninit(&_this->pool[i]);
5060fbf3537Syasuoka }
5070fbf3537Syasuoka
5082a5607d2Sgoda npppd_destroy_ipcp_stats(&_this->ipcpstats);
5092a5607d2Sgoda
5100fbf3537Syasuoka signal_del(&_this->ev_sigterm);
5110fbf3537Syasuoka signal_del(&_this->ev_sigint);
5120fbf3537Syasuoka signal_del(&_this->ev_sighup);
5135fefcc09Syasuoka signal_del(&_this->ev_sigchld);
5140fbf3537Syasuoka
515821f7c56Syasuoka npppd_conf_fini(&_this->conf);
5160fbf3537Syasuoka
5170fbf3537Syasuoka slist_fini(&_this->realms);
5180fbf3537Syasuoka
5190fbf3537Syasuoka if (_this->map_user_ppp != NULL)
5200fbf3537Syasuoka hash_free(_this->map_user_ppp);
5210fbf3537Syasuoka }
5220fbf3537Syasuoka
5230fbf3537Syasuoka /***********************************************************************
524f0a4e295Syasuoka * Timer related functions
5250fbf3537Syasuoka ***********************************************************************/
5260fbf3537Syasuoka static void
npppd_reset_timer(npppd * _this)5270fbf3537Syasuoka npppd_reset_timer(npppd *_this)
5280fbf3537Syasuoka {
5290fbf3537Syasuoka struct timeval tv;
5300fbf3537Syasuoka
5310fbf3537Syasuoka if (_this->finalizing != 0) {
532f0a4e295Syasuoka /* we can use the timer exclusively on finalizing */
5330fbf3537Syasuoka tv.tv_usec = 500000;
5340fbf3537Syasuoka tv.tv_sec = 0;
5350fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv);
5360fbf3537Syasuoka } else {
5370fbf3537Syasuoka tv.tv_usec = 0;
5380fbf3537Syasuoka tv.tv_sec = NPPPD_TIMER_TICK_IVAL;
5390fbf3537Syasuoka evtimer_add(&_this->ev_timer, &tv);
5400fbf3537Syasuoka }
5410fbf3537Syasuoka }
5420fbf3537Syasuoka
5430fbf3537Syasuoka static void
npppd_timer(int fd,short evtype,void * ctx)5440fbf3537Syasuoka npppd_timer(int fd, short evtype, void *ctx)
5450fbf3537Syasuoka {
5460fbf3537Syasuoka npppd *_this;
5470fbf3537Syasuoka
5480fbf3537Syasuoka _this = ctx;
5490fbf3537Syasuoka if (_this->finalizing != 0) {
550f0a4e295Syasuoka npppd_stop_really(_this); /* The timer has been reset */
551f0a4e295Syasuoka return; /* we can use the timer exclusively on finalizing */
5520fbf3537Syasuoka }
5530fbf3537Syasuoka _this->secs += NPPPD_TIMER_TICK_IVAL;
5540fbf3537Syasuoka if (_this->reloading_count > 0) {
5550fbf3537Syasuoka _this->reloading_count -= NPPPD_TIMER_TICK_IVAL;
5560fbf3537Syasuoka if (_this->reloading_count <= 0) {
5570fbf3537Syasuoka npppd_reload0(_this);
5580fbf3537Syasuoka _this->reloading_count = 0;
5590fbf3537Syasuoka }
5600fbf3537Syasuoka } else {
5610fbf3537Syasuoka if ((_this->secs % TIMER_TICK_RUP(
5620fbf3537Syasuoka NPPPD_AUTH_REALM_FINALIZER_INTERVAL)) == 0)
5630fbf3537Syasuoka npppd_auth_finalizer_periodic(_this);
5640fbf3537Syasuoka }
5650fbf3537Syasuoka
5660fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
5670fbf3537Syasuoka if (pppoed_need_polling(&_this->pppoed))
5680fbf3537Syasuoka pppoed_reload_listeners(&_this->pppoed);
5690fbf3537Syasuoka #endif
5700fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
5710fbf3537Syasuoka pipex_periodic(_this);
5720fbf3537Syasuoka #endif
5730fbf3537Syasuoka
5740fbf3537Syasuoka npppd_reset_timer(_this);
5750fbf3537Syasuoka }
5760fbf3537Syasuoka
5770fbf3537Syasuoka int
npppd_reset_routing_table(npppd * _this,int pool_only)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
npppd_get_user_password(npppd * _this,npppd_ppp * ppp,const char * username,char * password,int * plpassword)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 *
npppd_get_user_framed_ip_address(npppd * _this,npppd_ppp * ppp,const char * username)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
685821f7c56Syasuoka if (ppp->realm_framed_ip_address.s_addr != 0)
6860fbf3537Syasuoka return &ppp->realm_framed_ip_address;
6870fbf3537Syasuoka
688f0a4e295Syasuoka /* assign by the authentication realm */
6890fbf3537Syasuoka if (npppd_auth_get_framed_ip(ppp->realm, username,
6900fbf3537Syasuoka &ppp->realm_framed_ip_address,
6910fbf3537Syasuoka &ppp->realm_framed_ip_netmask) != 0)
6920fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = 0;
6930fbf3537Syasuoka
6940fbf3537Syasuoka do_default:
695f0a4e295Syasuoka /* Use USER_SELECT if the realm doesn't specify the ip address */
6960fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == 0)
6970fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_USER_SELECT;
698821f7c56Syasuoka
699821f7c56Syasuoka
7000fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) {
701f0a4e295Syasuoka /* Use NAS_SELECT if USER_SELECT is not allowed by the config */
702821f7c56Syasuoka if (!ppp_ipcp(ppp)->allow_user_select)
7030fbf3537Syasuoka ppp->realm_framed_ip_address.s_addr = INADDR_NAS_SELECT;
7040fbf3537Syasuoka }
7050fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() = %s", __func__,
7060fbf3537Syasuoka inet_ntoa(ppp->realm_framed_ip_address)));
7070fbf3537Syasuoka
7080fbf3537Syasuoka return &ppp->realm_framed_ip_address;
7090fbf3537Syasuoka }
7100fbf3537Syasuoka
7110fbf3537Syasuoka /** XXX */
7120fbf3537Syasuoka int
npppd_check_calling_number(npppd * _this,npppd_ppp * ppp)7130fbf3537Syasuoka npppd_check_calling_number(npppd *_this, npppd_ppp *ppp)
7140fbf3537Syasuoka {
715821f7c56Syasuoka struct tunnconf *conf;
716821f7c56Syasuoka int lnumber, rval;
7170fbf3537Syasuoka char number[NPPPD_PHONE_NUMBER_LEN + 1];
7180fbf3537Syasuoka
719821f7c56Syasuoka conf = ppp_get_tunnconf(ppp);
720821f7c56Syasuoka if (conf->callnum_check != 0) {
7210fbf3537Syasuoka lnumber = sizeof(number);
7220fbf3537Syasuoka if ((rval = npppd_auth_get_calling_number(ppp->realm,
723821f7c56Syasuoka ppp->username, number, &lnumber)) == 0)
7240fbf3537Syasuoka return
7250fbf3537Syasuoka (strcmp(number, ppp->calling_number) == 0)? 1 : 0;
726821f7c56Syasuoka if ((conf->callnum_check & NPPPD_CALLNUM_CHECK_STRICT) != 0)
7270fbf3537Syasuoka return 0;
7280fbf3537Syasuoka }
7290fbf3537Syasuoka
7300fbf3537Syasuoka return 1;
7310fbf3537Syasuoka }
7320fbf3537Syasuoka
7330fbf3537Syasuoka /**
734f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that is assigned the
735f0a4e295Syasuoka * specified ip address and returns it
736f0a4e295Syasuoka * @param ipaddr IP Address(Specify in network byte order)
7370fbf3537Syasuoka */
7380fbf3537Syasuoka npppd_ppp *
npppd_get_ppp_by_ip(npppd * _this,struct in_addr ipaddr)7390fbf3537Syasuoka npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr)
7400fbf3537Syasuoka {
7410fbf3537Syasuoka struct sockaddr_npppd *snp;
7420fbf3537Syasuoka struct radish *rdp;
743f0a4e295Syasuoka struct sockaddr_in npppd_get_ppp_by_ip_sin4;
7440fbf3537Syasuoka
745f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_family = AF_INET;
746f0a4e295Syasuoka npppd_get_ppp_by_ip_sin4.sin_len = sizeof(struct sockaddr_in);
7470fbf3537Syasuoka npppd_get_ppp_by_ip_sin4.sin_addr = ipaddr;
7480fbf3537Syasuoka if (_this->rd == NULL)
749f0a4e295Syasuoka return NULL; /* no radix tree on startup */
7500fbf3537Syasuoka if (rd_match((struct sockaddr *)&npppd_get_ppp_by_ip_sin4, _this->rd,
7510fbf3537Syasuoka &rdp)) {
7520fbf3537Syasuoka snp = rdp->rd_rtent;
7530fbf3537Syasuoka if (snp->snp_type == SNP_PPP)
7540fbf3537Syasuoka return snp->snp_data_ptr;
7550fbf3537Syasuoka }
7560fbf3537Syasuoka return NULL;
7570fbf3537Syasuoka }
7580fbf3537Syasuoka
7590fbf3537Syasuoka /**
760f0a4e295Syasuoka * This function finds {@link npppd_ppp} instances that are authenticated
761f0a4e295Syasuoka * as the specified username and returns them as a {@link slist} list.
762f0a4e295Syasuoka * @param username PPP Username.
763f5c2ff87Syasuoka * @return {@link slist} that contains the {@link npppd_ppp} instances.
764f0a4e295Syasuoka * NULL may be returned if no instance has been found.
7650fbf3537Syasuoka */
76634682664Syasuoka static slist *
npppd_get_ppp_by_user(npppd * _this,const char * username)7670fbf3537Syasuoka npppd_get_ppp_by_user(npppd *_this, const char *username)
7680fbf3537Syasuoka {
7690fbf3537Syasuoka hash_link *hl;
7700fbf3537Syasuoka
7710fbf3537Syasuoka if ((hl = hash_lookup(_this->map_user_ppp, username)) != NULL)
7720fbf3537Syasuoka return hl->item;
7730fbf3537Syasuoka
7740fbf3537Syasuoka return NULL;
7750fbf3537Syasuoka }
7760fbf3537Syasuoka
7770fbf3537Syasuoka /**
778f0a4e295Syasuoka * This function finds a {@link npppd_ppp} instance that matches the specified
779f0a4e295Syasuoka * ppp id and returns it.
780f0a4e295Syasuoka * @param id {@link npppd_ppp#id ppp's id}
781f0a4e295Syasuoka * @return This function returns the pointer if the instance which has
782f0a4e295Syasuoka * specified ID is found, otherwise it returns NULL.
7830fbf3537Syasuoka */
7840fbf3537Syasuoka npppd_ppp *
npppd_get_ppp_by_id(npppd * _this,u_int ppp_id)785363e4d4bSyasuoka npppd_get_ppp_by_id(npppd *_this, u_int ppp_id)
7860fbf3537Syasuoka {
7870fbf3537Syasuoka slist users;
7880fbf3537Syasuoka npppd_ppp *ppp0, *ppp;
7890fbf3537Syasuoka
7900fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
7910fbf3537Syasuoka
7920fbf3537Syasuoka ppp = NULL;
7930fbf3537Syasuoka slist_init(&users);
7940fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) {
7950fbf3537Syasuoka log_printf(LOG_WARNING,
7960fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__);
7970fbf3537Syasuoka } else {
798f0a4e295Syasuoka /* FIXME: This linear search eats CPU. */
7990fbf3537Syasuoka for (slist_itr_first(&users); slist_itr_has_next(&users); ) {
8000fbf3537Syasuoka ppp0 = slist_itr_next(&users);
8010fbf3537Syasuoka if (ppp0->id == ppp_id) {
8020fbf3537Syasuoka ppp = ppp0;
8030fbf3537Syasuoka break;
8040fbf3537Syasuoka }
8050fbf3537Syasuoka }
8060fbf3537Syasuoka }
8070fbf3537Syasuoka slist_fini(&users);
8080fbf3537Syasuoka
8090fbf3537Syasuoka return ppp;
8100fbf3537Syasuoka }
8110fbf3537Syasuoka
8122a5607d2Sgoda static struct ipcpstat *
npppd_get_ipcp_stat(struct ipcpstat_head * head,const char * ipcp_name)8132a5607d2Sgoda npppd_get_ipcp_stat(struct ipcpstat_head *head , const char *ipcp_name)
8142a5607d2Sgoda {
8152a5607d2Sgoda struct ipcpstat *ipcpstat = NULL;
8162a5607d2Sgoda
8172a5607d2Sgoda LIST_FOREACH(ipcpstat, head, entry) {
8182a5607d2Sgoda if (strncmp(ipcpstat->name, ipcp_name,
8192a5607d2Sgoda sizeof(ipcpstat->name)) == 0)
8202a5607d2Sgoda return ipcpstat;
8212a5607d2Sgoda }
8222a5607d2Sgoda
8232a5607d2Sgoda return NULL;
8242a5607d2Sgoda }
8252a5607d2Sgoda
8262a5607d2Sgoda static void
npppd_destroy_ipcp_stats(struct ipcpstat_head * head)8272a5607d2Sgoda npppd_destroy_ipcp_stats(struct ipcpstat_head *head)
8282a5607d2Sgoda {
8292a5607d2Sgoda struct ipcpstat *ipcpstat, *tipcpstat;
8302a5607d2Sgoda npppd_ppp *ppp, *tppp;
8312a5607d2Sgoda
8322a5607d2Sgoda LIST_FOREACH_SAFE(ipcpstat, head, entry, tipcpstat) {
8332a5607d2Sgoda LIST_FOREACH_SAFE(ppp, &ipcpstat->ppp, ipcpstat_entry, tppp) {
8342a5607d2Sgoda ppp->ipcpstat = NULL;
8352a5607d2Sgoda LIST_REMOVE(ppp, ipcpstat_entry);
8362a5607d2Sgoda }
8372a5607d2Sgoda free(ipcpstat);
8382a5607d2Sgoda }
8392a5607d2Sgoda }
8402a5607d2Sgoda
8412a5607d2Sgoda static void
npppd_ipcp_stats_reload(npppd * _this)8422a5607d2Sgoda npppd_ipcp_stats_reload(npppd *_this)
8432a5607d2Sgoda {
8442a5607d2Sgoda struct ipcpstat *ipcpstat, *tipcpstat;
8452a5607d2Sgoda struct ipcpconf *ipcpconf;
8462a5607d2Sgoda struct ipcpstat_head destroy_list;
8472a5607d2Sgoda
8482a5607d2Sgoda LIST_INIT(&destroy_list);
8492a5607d2Sgoda LIST_FOREACH_SAFE(ipcpstat, &_this->ipcpstats, entry, tipcpstat) {
8502a5607d2Sgoda LIST_REMOVE(ipcpstat, entry);
8512a5607d2Sgoda LIST_INSERT_HEAD(&destroy_list, ipcpstat, entry);
8522a5607d2Sgoda }
8532a5607d2Sgoda
8542a5607d2Sgoda TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry) {
8552a5607d2Sgoda ipcpstat = npppd_get_ipcp_stat(&destroy_list, ipcpconf->name);
8562a5607d2Sgoda if (ipcpstat != NULL) {
8572a5607d2Sgoda LIST_REMOVE(ipcpstat, entry);
8582a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry);
8592a5607d2Sgoda continue;
8602a5607d2Sgoda }
8612a5607d2Sgoda
8622a5607d2Sgoda ipcpstat = malloc(sizeof(*ipcpstat));
8632a5607d2Sgoda if (ipcpstat == NULL) {
8642a5607d2Sgoda log_printf(LOG_ERR, "initializing ipcp_stats failed : %m");
8652a5607d2Sgoda continue;
8662a5607d2Sgoda }
8672a5607d2Sgoda memset(ipcpstat, 0, sizeof(*ipcpstat));
8682a5607d2Sgoda strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpconf->name));
8692a5607d2Sgoda LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry);
8702a5607d2Sgoda }
8712a5607d2Sgoda npppd_destroy_ipcp_stats(&destroy_list);
8722a5607d2Sgoda }
8732a5607d2Sgoda
8740fbf3537Syasuoka /**
875f0a4e295Syasuoka * Checks whether the user reaches the maximum session limit
876f0a4e295Syasuoka * (user_max_serssion).
877f0a4e295Syasuoka * @return This function returns 1(true) if the user does not reach the
878f0a4e295Syasuoka * limit, otherwise it returns 0(false).
8790fbf3537Syasuoka */
8800fbf3537Syasuoka int
npppd_check_user_max_session(npppd * _this,npppd_ppp * ppp)8810fbf3537Syasuoka npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp)
8820fbf3537Syasuoka {
883d50b169aSgoda int global_count, realm_count;
8840fbf3537Syasuoka npppd_ppp *ppp1;
8850fbf3537Syasuoka slist *uppp;
8860fbf3537Syasuoka
887f0a4e295Syasuoka /* user_max_session == 0 means unlimit */
888d50b169aSgoda if (_this->conf.user_max_session == 0 &&
889d50b169aSgoda npppd_auth_user_session_unlimited(ppp->realm))
8900fbf3537Syasuoka return 1;
8910fbf3537Syasuoka
892d50b169aSgoda global_count = realm_count = 0;
8930fbf3537Syasuoka if ((uppp = npppd_get_ppp_by_user(_this, ppp->username)) != NULL) {
8940fbf3537Syasuoka for (slist_itr_first(uppp); slist_itr_has_next(uppp); ) {
8950fbf3537Syasuoka ppp1 = slist_itr_next(uppp);
896d50b169aSgoda if (ppp->realm == ppp1->realm)
897d50b169aSgoda realm_count++;
898d50b169aSgoda global_count++;
8990fbf3537Syasuoka }
9000fbf3537Syasuoka }
9010fbf3537Syasuoka
902d50b169aSgoda if (npppd_check_auth_user_max_session(ppp->realm, realm_count)) {
903d50b169aSgoda ppp_log(ppp, LOG_WARNING,
904d50b169aSgoda "user %s exceeds user-max-session limit per auth",
905d50b169aSgoda ppp->username);
906d50b169aSgoda return 0;
907d50b169aSgoda } else if (_this->conf.user_max_session != 0 &&
908d50b169aSgoda _this->conf.user_max_session <= global_count) {
909d50b169aSgoda ppp_log(ppp, LOG_WARNING,
910d50b169aSgoda "user %s exceeds user-max-session limit", ppp->username);
911d50b169aSgoda return 0;
912d50b169aSgoda } else
913d50b169aSgoda return 1;
9140fbf3537Syasuoka }
9150fbf3537Syasuoka
9160fbf3537Syasuoka /***********************************************************************
917f0a4e295Syasuoka * Network I/O ralated functions.
9180fbf3537Syasuoka ***********************************************************************/
9190fbf3537Syasuoka /**
920f0a4e295Syasuoka * Call this function to output packets to the network(tun). This function
921f0a4e295Syasuoka * currently assumes the packet is a IPv4 datagram.
9220fbf3537Syasuoka */
9230fbf3537Syasuoka void
npppd_network_output(npppd * _this,npppd_ppp * ppp,int proto,u_char * pktp,int lpktp)9240fbf3537Syasuoka npppd_network_output(npppd *_this, npppd_ppp *ppp, int proto, u_char *pktp,
9250fbf3537Syasuoka int lpktp)
9260fbf3537Syasuoka {
9270fbf3537Syasuoka struct ip *pip;
9280fbf3537Syasuoka int lbuf;
929f0a4e295Syasuoka u_char buf[256]; /* enough size for TCP/IP header */
9300fbf3537Syasuoka
9310fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
9320fbf3537Syasuoka
9330fbf3537Syasuoka if (!ppp_ip_assigned(ppp))
9340fbf3537Syasuoka return;
9350fbf3537Syasuoka
9360fbf3537Syasuoka if (lpktp < sizeof(struct ip)) {
9370fbf3537Syasuoka ppp_log(ppp, LOG_DEBUG, "Received IP packet is too small");
9380fbf3537Syasuoka return;
9390fbf3537Syasuoka }
940dbad4650Sderaadt lbuf = MINIMUM(lpktp, sizeof(buf));
9410fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip)) {
9420fbf3537Syasuoka memcpy(buf, pktp, lbuf);
9430fbf3537Syasuoka pip = (struct ip *)buf;
9440fbf3537Syasuoka } else {
9450fbf3537Syasuoka pip = (struct ip *)pktp;
9460fbf3537Syasuoka }
9470fbf3537Syasuoka
9483b5b2d97Syasuoka if (ppp->ingress_filter != 0 &&
9493b5b2d97Syasuoka (pip->ip_src.s_addr & ppp->ppp_framed_ip_netmask.s_addr)
9503b5b2d97Syasuoka != (ppp->ppp_framed_ip_address.s_addr &
9510fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr)) {
9520fbf3537Syasuoka char logbuf[80];
9530fbf3537Syasuoka strlcpy(logbuf, inet_ntoa(pip->ip_dst), sizeof(logbuf));
9540fbf3537Syasuoka ppp_log(ppp, LOG_INFO,
9550fbf3537Syasuoka "Drop packet by ingress filter. %s => %s",
9560fbf3537Syasuoka inet_ntoa(pip->ip_src), logbuf);
9570fbf3537Syasuoka
9580fbf3537Syasuoka return;
9590fbf3537Syasuoka }
9600fbf3537Syasuoka if (ppp->timeout_sec > 0 && !ip_is_idle_packet(pip, lbuf))
9610fbf3537Syasuoka ppp_reset_idle_timeout(ppp);
9620fbf3537Syasuoka
9630fbf3537Syasuoka #ifndef NO_ADJUST_MSS
9640fbf3537Syasuoka if (ppp->adjust_mss) {
9650fbf3537Syasuoka if (lpktp == lbuf) {
9660fbf3537Syasuoka /*
967f0a4e295Syasuoka * We can assume the packet length is less than
968f0a4e295Syasuoka * sizeof(buf).
9690fbf3537Syasuoka */
9700fbf3537Syasuoka if (!ALIGNED_POINTER(pktp, struct ip))
9710fbf3537Syasuoka pktp = buf;
9720fbf3537Syasuoka adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru));
9730fbf3537Syasuoka }
9740fbf3537Syasuoka }
9750fbf3537Syasuoka #endif
97641d69f6eSyasuoka npppd_iface_write(ppp_iface(ppp), ppp, proto, pktp, lpktp);
9770fbf3537Syasuoka }
9780fbf3537Syasuoka
9790fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
980f0a4e295Syasuoka /***********************************************************************
981f0a4e295Syasuoka * PIPEX related functions
982f0a4e295Syasuoka ***********************************************************************/
9830fbf3537Syasuoka static void
pipex_setup_common(npppd_ppp * ppp,struct pipex_session_req * req)9840fbf3537Syasuoka pipex_setup_common(npppd_ppp *ppp, struct pipex_session_req *req)
9850fbf3537Syasuoka {
9860fbf3537Syasuoka memset(req, 0, sizeof(*req));
9870fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, acfc))
9880fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ENABLED;
9890fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, acfc))
9900fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ACFC_ACCEPTED;
9910fbf3537Syasuoka
9920fbf3537Syasuoka if (psm_peer_opt_is_accepted(&ppp->lcp, pfc))
9930fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ACCEPTED;
9940fbf3537Syasuoka if (psm_opt_is_accepted(&ppp->lcp, pfc))
9950fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_PFC_ENABLED;
9960fbf3537Syasuoka
9970fbf3537Syasuoka if (ppp->has_acf != 0)
9980fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_HAS_ACF;
9990fbf3537Syasuoka
10000fbf3537Syasuoka if (ppp->adjust_mss != 0)
10010fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_ADJUST_TCPMSS;
10023b5b2d97Syasuoka if (ppp->ingress_filter != 0)
10033b5b2d97Syasuoka req->pr_ppp_flags |= PIPEX_PPP_INGRESS_FILTER;
10040fbf3537Syasuoka
1005cd8e09b9Sdlg req->pr_ip_srcaddr = ppp->pppd->iface[0].ip4addr;
10060fbf3537Syasuoka req->pr_ip_address = ppp->ppp_framed_ip_address;
10070fbf3537Syasuoka req->pr_ip_netmask = ppp->ppp_framed_ip_netmask;
10080fbf3537Syasuoka req->pr_peer_mru = ppp->peer_mru;
10090fbf3537Syasuoka req->pr_ppp_id = ppp->id;
10100fbf3537Syasuoka
10110fbf3537Syasuoka req->pr_timeout_sec = ppp->timeout_sec;
10120fbf3537Syasuoka
10130fbf3537Syasuoka #ifdef USE_NPPPD_MPPE
10140fbf3537Syasuoka req->pr_ccp_id = ppp->ccp.fsm.id;
1015de0a2dd6Syasuoka if (ppp->mppe.send.keybits > 0) {
10160fbf3537Syasuoka memcpy(req->pr_mppe_send.master_key,
1017de0a2dd6Syasuoka ppp->mppe.send.master_key,
1018de0a2dd6Syasuoka sizeof(req->pr_mppe_send.master_key));
10190fbf3537Syasuoka req->pr_mppe_send.stateless = ppp->mppe.send.stateless;
10200fbf3537Syasuoka req->pr_mppe_send.keylenbits = ppp->mppe.send.keybits;
1021de0a2dd6Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
1022de0a2dd6Syasuoka }
1023de0a2dd6Syasuoka if (ppp->mppe.recv.keybits > 0) {
10240fbf3537Syasuoka memcpy(req->pr_mppe_recv.master_key,
1025de0a2dd6Syasuoka ppp->mppe.recv.master_key,
1026de0a2dd6Syasuoka sizeof(req->pr_mppe_recv.master_key));
10270fbf3537Syasuoka req->pr_mppe_recv.stateless = ppp->mppe.recv.stateless;
10280fbf3537Syasuoka req->pr_mppe_recv.keylenbits = ppp->mppe.recv.keybits;
10290fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
10300fbf3537Syasuoka }
10310fbf3537Syasuoka if (ppp->mppe.required)
10320fbf3537Syasuoka req->pr_ppp_flags |= PIPEX_PPP_MPPE_REQUIRED;
10330fbf3537Syasuoka #endif /* USE_NPPPD_MPPE */
10340fbf3537Syasuoka }
10350fbf3537Syasuoka
1036f0a4e295Syasuoka /** Enable PIPEX of the {@link npppd_ppp ppp} */
10370fbf3537Syasuoka int
npppd_ppp_pipex_enable(npppd * _this,npppd_ppp * ppp)10380fbf3537Syasuoka npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp)
10390fbf3537Syasuoka {
10400fbf3537Syasuoka struct pipex_session_req req;
10410fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
10420fbf3537Syasuoka pppoe_session *pppoe;
10430fbf3537Syasuoka #endif
10440fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
10450fbf3537Syasuoka pptp_call *call;
10460fbf3537Syasuoka #endif
1047886d2b78Syasuoka #ifdef USE_NPPPD_L2TP
1048886d2b78Syasuoka l2tp_call *l2tp;
1049886d2b78Syasuoka l2tp_ctrl *l2tpctrl;
1050886d2b78Syasuoka #endif
10510fbf3537Syasuoka int error;
10520fbf3537Syasuoka
10530fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
10540fbf3537Syasuoka NPPPD_ASSERT(ppp->phy_context != NULL);
10550fbf3537Syasuoka NPPPD_ASSERT(ppp->use_pipex != 0);
10560fbf3537Syasuoka
10570fbf3537Syasuoka pipex_setup_common(ppp, &req);
10580fbf3537Syasuoka
10590fbf3537Syasuoka switch (ppp->tunnel_type) {
10600fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
1061821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE:
1062886d2b78Syasuoka {
1063886d2b78Syasuoka struct sockaddr *sa;
1064886d2b78Syasuoka struct ether_header *eh;
10650fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context;
10660fbf3537Syasuoka
1067f5c2ff87Syasuoka /* PPPoE specific information */
10680fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPPOE;
10690fbf3537Syasuoka req.pr_session_id = pppoe->session_id;
10700fbf3537Syasuoka req.pr_peer_session_id = 0;
10710fbf3537Syasuoka strlcpy(req.pr_proto.pppoe.over_ifname,
10720fbf3537Syasuoka pppoe_session_listen_ifname(pppoe),
10730fbf3537Syasuoka sizeof(req.pr_proto.pppoe.over_ifname));
1074886d2b78Syasuoka
1075bdfe8fd0Syasuoka sa = (struct sockaddr *)&req.pr_peer_address;
1076886d2b78Syasuoka sa->sa_family = AF_UNSPEC;
1077886d2b78Syasuoka sa->sa_len = sizeof(struct sockaddr);
1078886d2b78Syasuoka
1079886d2b78Syasuoka eh = (struct ether_header *)sa->sa_data;
1080886d2b78Syasuoka eh->ether_type = htons(ETHERTYPE_PPPOE);
1081886d2b78Syasuoka memcpy(eh->ether_dhost, pppoe->ether_addr, ETHER_ADDR_LEN);
1082886d2b78Syasuoka memset(eh->ether_shost, 0, ETHER_ADDR_LEN);
10830fbf3537Syasuoka
10840fbf3537Syasuoka break;
1085886d2b78Syasuoka }
10860fbf3537Syasuoka #endif
10870fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
1088821f7c56Syasuoka case NPPPD_TUNNEL_PPTP:
10890fbf3537Syasuoka call = (pptp_call *)ppp->phy_context;
10900fbf3537Syasuoka
1091f5c2ff87Syasuoka /* PPTP specific information */
10920fbf3537Syasuoka req.pr_session_id = call->id;
10930fbf3537Syasuoka req.pr_protocol = PIPEX_PROTO_PPTP;
10940fbf3537Syasuoka
10950fbf3537Syasuoka req.pr_peer_session_id = call->peers_call_id;
10960fbf3537Syasuoka req.pr_proto.pptp.snd_nxt = call->snd_nxt;
10970fbf3537Syasuoka req.pr_proto.pptp.snd_una = call->snd_una;
10980fbf3537Syasuoka req.pr_proto.pptp.rcv_nxt = call->rcv_nxt;
10990fbf3537Syasuoka req.pr_proto.pptp.rcv_acked = call->rcv_acked;
11000fbf3537Syasuoka req.pr_proto.pptp.winsz = call->winsz;
11010fbf3537Syasuoka req.pr_proto.pptp.maxwinsz = call->maxwinsz;
11020fbf3537Syasuoka req.pr_proto.pptp.peer_maxwinsz = call->peers_maxwinsz;
11030fbf3537Syasuoka
11040fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->peer.ss_family == AF_INET);
11050fbf3537Syasuoka NPPPD_ASSERT(call->ctrl->our.ss_family == AF_INET);
1106886d2b78Syasuoka
1107bdfe8fd0Syasuoka memcpy(&req.pr_peer_address, &call->ctrl->peer,
1108886d2b78Syasuoka call->ctrl->peer.ss_len);
1109bdfe8fd0Syasuoka memcpy(&req.pr_local_address, &call->ctrl->our,
1110886d2b78Syasuoka call->ctrl->our.ss_len);
1111886d2b78Syasuoka break;
1112886d2b78Syasuoka #endif
1113886d2b78Syasuoka #ifdef USE_NPPPD_L2TP
1114821f7c56Syasuoka case NPPPD_TUNNEL_L2TP:
1115886d2b78Syasuoka l2tp = (l2tp_call *)ppp->phy_context;
1116886d2b78Syasuoka l2tpctrl = l2tp->ctrl;
1117886d2b78Syasuoka
1118886d2b78Syasuoka /* L2TPv2 specific context */
1119886d2b78Syasuoka /* Session KEYS */
1120886d2b78Syasuoka req.pr_protocol = PIPEX_PROTO_L2TP;
1121886d2b78Syasuoka req.pr_proto.l2tp.tunnel_id = l2tpctrl->tunnel_id;
1122886d2b78Syasuoka req.pr_proto.l2tp.peer_tunnel_id = l2tpctrl->peer_tunnel_id;
1123886d2b78Syasuoka req.pr_session_id = l2tp->session_id;
1124886d2b78Syasuoka req.pr_peer_session_id = l2tp->peer_session_id;
1125886d2b78Syasuoka
1126886d2b78Syasuoka if (l2tpctrl->data_use_seq)
1127886d2b78Syasuoka req.pr_proto.l2tp.option_flags |=
1128886d2b78Syasuoka PIPEX_L2TP_USE_SEQUENCING;
1129886d2b78Syasuoka
1130886d2b78Syasuoka /* transmission control contexts */
1131886d2b78Syasuoka req.pr_proto.l2tp.ns_nxt = l2tp->snd_nxt;
1132886d2b78Syasuoka req.pr_proto.l2tp.nr_nxt = l2tp->rcv_nxt;
1133886d2b78Syasuoka
1134bdfe8fd0Syasuoka memcpy(&req.pr_peer_address, &l2tpctrl->peer,
1135886d2b78Syasuoka l2tpctrl->peer.ss_len);
1136bdfe8fd0Syasuoka memcpy(&req.pr_local_address, &l2tpctrl->sock,
1137886d2b78Syasuoka l2tpctrl->sock.ss_len);
1138a5018c90Syasuoka #ifdef USE_SA_COOKIE
1139a5018c90Syasuoka if (l2tpctrl->sa_cookie != NULL) {
1140a5018c90Syasuoka req.pr_proto.l2tp.ipsecflowinfo =
1141a5018c90Syasuoka ((struct in_ipsec_sa_cookie *)l2tpctrl->sa_cookie)
1142a5018c90Syasuoka ->ipsecflow;
1143a5018c90Syasuoka }
1144886d2b78Syasuoka #endif
11450fbf3537Syasuoka break;
11460fbf3537Syasuoka #endif
11470fbf3537Syasuoka default:
11480fbf3537Syasuoka return 1;
11490fbf3537Syasuoka }
11500fbf3537Syasuoka
11510fbf3537Syasuoka if ((error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXASESSION, &req))
11520fbf3537Syasuoka != 0) {
11530fbf3537Syasuoka if (errno == ENXIO) /* pipex is disabled on runtime */
11540fbf3537Syasuoka error = 0;
11550fbf3537Syasuoka ppp->pipex_enabled = 0;
11560fbf3537Syasuoka return error;
11570fbf3537Syasuoka }
11580fbf3537Syasuoka
1159cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx) {
1160cd8e09b9Sdlg struct pipex_session_descr_req descr_req;
1161cd8e09b9Sdlg
1162cd8e09b9Sdlg descr_req.pdr_protocol = req.pr_protocol;
1163cd8e09b9Sdlg descr_req.pdr_session_id = req.pr_session_id;
1164cd8e09b9Sdlg memset(descr_req.pdr_descr, 0, sizeof(descr_req.pdr_descr));
1165cd8e09b9Sdlg strlcpy(descr_req.pdr_descr, ppp->username, sizeof(descr_req.pdr_descr));
1166cd8e09b9Sdlg error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXSIFDESCR, &descr_req);
1167cd8e09b9Sdlg if (error != 0) {
1168cd8e09b9Sdlg log_printf(LOG_WARNING, "PIPEXSIFDESCR(%s) failed: %d\n", ppp->username, error);
1169cd8e09b9Sdlg }
1170cd8e09b9Sdlg }
1171cd8e09b9Sdlg
11720fbf3537Syasuoka ppp->pipex_enabled = 1;
11730fbf3537Syasuoka if (ppp->timeout_sec > 0) {
1174f0a4e295Syasuoka /* Stop the npppd's idle-timer. We use pipex's idle-timer */
11750fbf3537Syasuoka ppp->timeout_sec = 0;
11760fbf3537Syasuoka ppp_reset_idle_timeout(ppp);
11770fbf3537Syasuoka }
11780fbf3537Syasuoka
11790fbf3537Syasuoka return error;
11800fbf3537Syasuoka }
11810fbf3537Syasuoka
1182f0a4e295Syasuoka /** Disable PIPEX of the {@link npppd_ppp ppp} */
11830fbf3537Syasuoka int
npppd_ppp_pipex_disable(npppd * _this,npppd_ppp * ppp)11840fbf3537Syasuoka npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp)
11850fbf3537Syasuoka {
11860fbf3537Syasuoka struct pipex_session_close_req req;
11870fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
11880fbf3537Syasuoka pppoe_session *pppoe;
11890fbf3537Syasuoka #endif
11900fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
11910fbf3537Syasuoka pptp_call *call;
11920fbf3537Syasuoka #endif
1193886d2b78Syasuoka #ifdef USE_NPPPD_L2TP
1194886d2b78Syasuoka l2tp_call *l2tp;
1195886d2b78Syasuoka #endif
11960fbf3537Syasuoka int error;
11970fbf3537Syasuoka
11980fbf3537Syasuoka if (ppp->pipex_started == 0)
11990fbf3537Syasuoka return 0; /* not started */
12000fbf3537Syasuoka
12010fbf3537Syasuoka bzero(&req, sizeof(req));
12020fbf3537Syasuoka switch(ppp->tunnel_type) {
12030fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
1204821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE:
12050fbf3537Syasuoka pppoe = (pppoe_session *)ppp->phy_context;
12060fbf3537Syasuoka
1207f5c2ff87Syasuoka /* PPPoE specific information */
12080fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPPOE;
12090fbf3537Syasuoka req.pcr_session_id = pppoe->session_id;
12100fbf3537Syasuoka break;
12110fbf3537Syasuoka #endif
12120fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
1213821f7c56Syasuoka case NPPPD_TUNNEL_PPTP:
12140fbf3537Syasuoka call = (pptp_call *)ppp->phy_context;
12150fbf3537Syasuoka
1216f5c2ff87Syasuoka /* PPTP specific information */
12170fbf3537Syasuoka req.pcr_session_id = call->id;
12180fbf3537Syasuoka req.pcr_protocol = PIPEX_PROTO_PPTP;
12190fbf3537Syasuoka break;
12200fbf3537Syasuoka #endif
1221fd218b06Smarkus #ifdef USE_NPPPD_L2TP
1222821f7c56Syasuoka case NPPPD_TUNNEL_L2TP:
1223fd218b06Smarkus l2tp = (l2tp_call *)ppp->phy_context;
1224fd218b06Smarkus
1225fd218b06Smarkus /* L2TP specific context */
1226fd218b06Smarkus req.pcr_session_id = l2tp->session_id;
1227fd218b06Smarkus req.pcr_protocol = PIPEX_PROTO_L2TP;
1228fd218b06Smarkus break;
1229fd218b06Smarkus #endif
12300fbf3537Syasuoka default:
12310fbf3537Syasuoka return 1;
12320fbf3537Syasuoka }
12330fbf3537Syasuoka
12340fbf3537Syasuoka error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXDSESSION, &req);
12350fbf3537Syasuoka if (error == 0) {
12360fbf3537Syasuoka ppp->ipackets += req.pcr_stat.ipackets;
12370fbf3537Syasuoka ppp->opackets += req.pcr_stat.opackets;
12380fbf3537Syasuoka ppp->ierrors += req.pcr_stat.ierrors;
12390fbf3537Syasuoka ppp->oerrors += req.pcr_stat.oerrors;
12400fbf3537Syasuoka ppp->ibytes += req.pcr_stat.ibytes;
12410fbf3537Syasuoka ppp->obytes += req.pcr_stat.obytes;
12420fbf3537Syasuoka ppp->pipex_enabled = 0;
12430fbf3537Syasuoka }
12440fbf3537Syasuoka
12450fbf3537Syasuoka return error;
12460fbf3537Syasuoka }
12470fbf3537Syasuoka
12480fbf3537Syasuoka static void
pipex_periodic(npppd * _this)12490fbf3537Syasuoka pipex_periodic(npppd *_this)
12500fbf3537Syasuoka {
12510fbf3537Syasuoka struct pipex_session_list_req req;
12520fbf3537Syasuoka npppd_ppp *ppp;
1253ec8bab80Syasuoka int i, devf, error;
1254363e4d4bSyasuoka u_int ppp_id;
12550fbf3537Syasuoka slist dlist, users;
12560fbf3537Syasuoka
12570fbf3537Syasuoka slist_init(&dlist);
12580fbf3537Syasuoka slist_init(&users);
1259ec8bab80Syasuoka
1260ec8bab80Syasuoka devf = -1;
1261ec8bab80Syasuoka for (i = 0; i < nitems(_this->iface); i++) {
1262ec8bab80Syasuoka if (_this->iface[i].initialized != 0) {
1263ec8bab80Syasuoka devf = _this->iface[i].devf;
1264ec8bab80Syasuoka break;
1265ec8bab80Syasuoka }
1266ec8bab80Syasuoka }
1267ec8bab80Syasuoka if (devf >= 0) {
12680fbf3537Syasuoka do {
1269ec8bab80Syasuoka error = ioctl(devf, PIPEXGCLOSED, &req);
12700fbf3537Syasuoka if (error) {
12710fbf3537Syasuoka if (errno != ENXIO)
12720fbf3537Syasuoka log_printf(LOG_WARNING,
12730fbf3537Syasuoka "PIPEXGCLOSED failed: %m");
12740fbf3537Syasuoka break;
12750fbf3537Syasuoka }
12760fbf3537Syasuoka for (i = 0; i < req.plr_ppp_id_count; i++) {
12770fbf3537Syasuoka ppp_id = req.plr_ppp_id[i];
1278c46ae403Syasuoka slist_add(&dlist, (void *)(uintptr_t)ppp_id);
12790fbf3537Syasuoka }
12800fbf3537Syasuoka } while (req.plr_flags & PIPEX_LISTREQ_MORE);
1281ec8bab80Syasuoka }
12820fbf3537Syasuoka
12830fbf3537Syasuoka if (slist_length(&dlist) <= 0)
12840fbf3537Syasuoka goto pipex_done;
12850fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) {
12860fbf3537Syasuoka log_printf(LOG_WARNING,
12870fbf3537Syasuoka "npppd_get_all_users() failed in %s()", __func__);
12880fbf3537Syasuoka slist_fini(&users);
12890fbf3537Syasuoka goto pipex_done;
12900fbf3537Syasuoka }
12910fbf3537Syasuoka
1292f0a4e295Syasuoka /* Disconnect request */
12930fbf3537Syasuoka slist_itr_first(&dlist);
12940fbf3537Syasuoka while (slist_itr_has_next(&dlist)) {
1295f0a4e295Syasuoka /* FIXME: Linear search by PPP Id eats CPU */
1296c46ae403Syasuoka ppp_id = (uintptr_t)slist_itr_next(&dlist);
12970fbf3537Syasuoka slist_itr_first(&users);
12980fbf3537Syasuoka ppp = NULL;
12990fbf3537Syasuoka while (slist_itr_has_next(&users)) {
13000fbf3537Syasuoka ppp = slist_itr_next(&users);
13010fbf3537Syasuoka if (ppp_id == ppp->id) {
13020fbf3537Syasuoka /* found */
13030fbf3537Syasuoka slist_itr_remove(&users);
13040fbf3537Syasuoka break;
13050fbf3537Syasuoka }
13060fbf3537Syasuoka ppp = NULL;
13070fbf3537Syasuoka }
13080fbf3537Syasuoka if (ppp == NULL) {
13090fbf3537Syasuoka log_printf(LOG_WARNING,
13100fbf3537Syasuoka "kernel requested a ppp down, but it's not found. "
13110fbf3537Syasuoka "ppp=%d", ppp_id);
13120fbf3537Syasuoka continue;
13130fbf3537Syasuoka }
13140fbf3537Syasuoka ppp_log(ppp, LOG_INFO, "Stop requested by the kernel");
1315f5c2ff87Syasuoka /* TODO: PIPEX doesn't return the disconnect reason */
13168daf7599Syasuoka #ifdef USE_NPPPD_RADIUS
13178daf7599Syasuoka ppp_set_radius_terminate_cause(ppp,
13188daf7599Syasuoka RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT);
13198daf7599Syasuoka #endif
13200fbf3537Syasuoka ppp_stop(ppp, NULL);
13210fbf3537Syasuoka }
13220fbf3537Syasuoka pipex_done:
13230fbf3537Syasuoka slist_fini(&users);
13240fbf3537Syasuoka slist_fini(&dlist);
13250fbf3537Syasuoka }
13260fbf3537Syasuoka #endif /* USE_NPPPD_PIPEX */
13270fbf3537Syasuoka
13280fbf3537Syasuoka /***********************************************************************
1329f0a4e295Syasuoka * IP address assignment related functions
13300fbf3537Syasuoka ***********************************************************************/
1331f0a4e295Syasuoka /** Prepare to use IP */
13320fbf3537Syasuoka int
npppd_prepare_ip(npppd * _this,npppd_ppp * ppp)13330fbf3537Syasuoka npppd_prepare_ip(npppd *_this, npppd_ppp *ppp)
13340fbf3537Syasuoka {
1335821f7c56Syasuoka
13360fbf3537Syasuoka if (ppp_ipcp(ppp) == NULL)
13370fbf3537Syasuoka return 1;
13380fbf3537Syasuoka
13390fbf3537Syasuoka npppd_get_user_framed_ip_address(_this, ppp, ppp->username);
13400fbf3537Syasuoka
13410fbf3537Syasuoka if (npppd_iface_ip_is_ready(ppp_iface(ppp)))
13420fbf3537Syasuoka ppp->ipcp.ip4_our = ppp_iface(ppp)->ip4addr;
13430fbf3537Syasuoka else if (npppd_iface_ip_is_ready(&_this->iface[0]))
13440fbf3537Syasuoka ppp->ipcp.ip4_our = _this->iface[0].ip4addr;
13450fbf3537Syasuoka else
13460fbf3537Syasuoka return -1;
1347821f7c56Syasuoka ppp->ipcp.dns_pri = ppp_ipcp(ppp)->dns_servers[0];
1348821f7c56Syasuoka ppp->ipcp.dns_sec = ppp_ipcp(ppp)->dns_servers[1];
1349821f7c56Syasuoka ppp->ipcp.nbns_pri = ppp_ipcp(ppp)->nbns_servers[0];
1350821f7c56Syasuoka ppp->ipcp.nbns_sec = ppp_ipcp(ppp)->nbns_servers[1];
13510fbf3537Syasuoka
13520fbf3537Syasuoka return 0;
13530fbf3537Syasuoka }
13540fbf3537Syasuoka
1355f0a4e295Syasuoka /** Notify stop using IP to npppd and release the resources. */
13560fbf3537Syasuoka void
npppd_release_ip(npppd * _this,npppd_ppp * ppp)13570fbf3537Syasuoka npppd_release_ip(npppd *_this, npppd_ppp *ppp)
13580fbf3537Syasuoka {
13590fbf3537Syasuoka
13600fbf3537Syasuoka if (!ppp_ip_assigned(ppp))
13610fbf3537Syasuoka return;
13620fbf3537Syasuoka
13630fbf3537Syasuoka npppd_set_ip_enabled(_this, ppp, 0);
13640fbf3537Syasuoka npppd_pool_release_ip(ppp->assigned_pool, ppp);
13650fbf3537Syasuoka ppp->assigned_pool = NULL;
13660fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = 0;
13670fbf3537Syasuoka }
13680fbf3537Syasuoka
1369f0a4e295Syasuoka /**
1370f0a4e295Syasuoka * Change IP enableness. When the enableness is change, npppd will operate
1371f0a4e295Syasuoka * the route entry.
1372f0a4e295Syasuoka */
13730fbf3537Syasuoka void
npppd_set_ip_enabled(npppd * _this,npppd_ppp * ppp,int enabled)13740fbf3537Syasuoka npppd_set_ip_enabled(npppd *_this, npppd_ppp *ppp, int enabled)
13750fbf3537Syasuoka {
13760fbf3537Syasuoka int was_enabled, found;
13770fbf3537Syasuoka slist *u;
13780fbf3537Syasuoka hash_link *hl;
13790fbf3537Syasuoka npppd_ppp *ppp1;
13800fbf3537Syasuoka
13810fbf3537Syasuoka NPPPD_ASSERT(ppp_ip_assigned(ppp));
13820fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG,
13830fbf3537Syasuoka "npppd_set_ip_enabled(%s/%s, %s)", ppp->username,
13840fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address),
13850fbf3537Syasuoka (enabled)?"true" : "false"));
1386f0a4e295Syasuoka
13870fbf3537Syasuoka /*
1388f0a4e295Syasuoka * Don't do anything if the enableness is not change. Changing route
1389f0a4e295Syasuoka * makes many programs will wake up and do heavy operations, it causes
1390f0a4e295Syasuoka * system overload, so we refrain useless changing route.
13910fbf3537Syasuoka */
13920fbf3537Syasuoka enabled = (enabled)? 1 : 0;
13930fbf3537Syasuoka was_enabled = (ppp->assigned_ip4_enabled != 0)? 1 : 0;
13940fbf3537Syasuoka if (enabled == was_enabled)
13950fbf3537Syasuoka return;
1396f0a4e295Syasuoka
13970fbf3537Syasuoka ppp->assigned_ip4_enabled = enabled;
13980fbf3537Syasuoka if (enabled) {
13990fbf3537Syasuoka if (ppp->username[0] != '\0') {
14000fbf3537Syasuoka if ((u = npppd_get_ppp_by_user(_this, ppp->username))
14010fbf3537Syasuoka == NULL) {
14020fbf3537Syasuoka if ((u = malloc(sizeof(slist))) == NULL) {
14030fbf3537Syasuoka ppp_log(ppp, LOG_ERR,
14040fbf3537Syasuoka "Out of memory on %s: %m",
14050fbf3537Syasuoka __func__);
14060fbf3537Syasuoka } else {
14070fbf3537Syasuoka slist_init(u);
14080fbf3537Syasuoka slist_set_size(u, 4);
14090fbf3537Syasuoka hash_insert(_this->map_user_ppp,
14100fbf3537Syasuoka ppp->username, u);
14110fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG,
14120fbf3537Syasuoka "hash_insert(user->ppp, %s)",
14130fbf3537Syasuoka ppp->username));
14140fbf3537Syasuoka }
14150fbf3537Syasuoka }
1416f0a4e295Syasuoka if (u != NULL) /* above malloc() may failed */
14170fbf3537Syasuoka slist_add(u, ppp);
14180fbf3537Syasuoka }
14190fbf3537Syasuoka
14200fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS
1421cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) {
14220fbf3537Syasuoka if (ppp->snp.snp_next != NULL)
1423f0a4e295Syasuoka /*
1424f0a4e295Syasuoka * There is a blackhole route that has same
1425f0a4e295Syasuoka * address/mask.
1426f0a4e295Syasuoka */
14270fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address,
1428cd8e09b9Sdlg &ppp->ppp_framed_ip_netmask, &loop,
1429cd8e09b9Sdlg RTF_BLACKHOLE);
14300fbf3537Syasuoka /* See the comment for MRU_IPMTU() on ppp.h */
14310fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) {
14320fbf3537Syasuoka in_host_route_add(&ppp->ppp_framed_ip_address,
1433cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr,
1434cd8e09b9Sdlg ppp_iface(ppp)->ifname,
14350fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru));
14360fbf3537Syasuoka } else {
14370fbf3537Syasuoka in_route_add(&ppp->ppp_framed_ip_address,
14380fbf3537Syasuoka &ppp->ppp_framed_ip_netmask,
1439cd8e09b9Sdlg &ppp_iface(ppp)->ip4addr,
1440cd8e09b9Sdlg ppp_iface(ppp)->ifname, 0,
14410fbf3537Syasuoka MRU_IPMTU(ppp->peer_mru));
14420fbf3537Syasuoka }
1443cd8e09b9Sdlg }
14440fbf3537Syasuoka #endif
14450fbf3537Syasuoka } else {
14460fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS
1447cd8e09b9Sdlg if (_this->iface[ppp->ifidx].using_pppx == 0) {
14480fbf3537Syasuoka if (ppp->ppp_framed_ip_netmask.s_addr == 0xffffffffL) {
14490fbf3537Syasuoka in_host_route_delete(&ppp->ppp_framed_ip_address,
14500fbf3537Syasuoka &ppp_iface(ppp)->ip4addr);
14510fbf3537Syasuoka } else {
14520fbf3537Syasuoka in_route_delete(&ppp->ppp_framed_ip_address,
14530fbf3537Syasuoka &ppp->ppp_framed_ip_netmask,
14540fbf3537Syasuoka &ppp_iface(ppp)->ip4addr, 0);
14550fbf3537Syasuoka }
14560fbf3537Syasuoka if (ppp->snp.snp_next != NULL)
1457f0a4e295Syasuoka /*
1458f0a4e295Syasuoka * There is a blackhole route that has same
1459f0a4e295Syasuoka * address/mask.
1460f0a4e295Syasuoka */
1461cd8e09b9Sdlg in_route_add(&ppp->snp.snp_addr,
1462cd8e09b9Sdlg &ppp->snp.snp_mask, &loop, LOOPBACK_IFNAME,
1463cd8e09b9Sdlg RTF_BLACKHOLE, 0);
1464cd8e09b9Sdlg }
14650fbf3537Syasuoka #endif
14660fbf3537Syasuoka if (ppp->username[0] != '\0') {
14670fbf3537Syasuoka hl = hash_lookup(_this->map_user_ppp, ppp->username);
14680fbf3537Syasuoka NPPPD_ASSERT(hl != NULL);
14690fbf3537Syasuoka if (hl == NULL) {
14700fbf3537Syasuoka ppp_log(ppp, LOG_ERR,
14710fbf3537Syasuoka "Unexpected error: cannot find user(%s) "
14720fbf3537Syasuoka "from user database", ppp->username);
14730fbf3537Syasuoka return;
14740fbf3537Syasuoka }
14750fbf3537Syasuoka found = 0;
14760fbf3537Syasuoka u = hl->item;
14770fbf3537Syasuoka for (slist_itr_first(u); slist_itr_has_next(u);) {
14780fbf3537Syasuoka ppp1 = slist_itr_next(u);
14790fbf3537Syasuoka if (ppp1 == ppp) {
14800fbf3537Syasuoka slist_itr_remove(u);
14810fbf3537Syasuoka found++;
14820fbf3537Syasuoka break;
14830fbf3537Syasuoka }
14840fbf3537Syasuoka }
14850fbf3537Syasuoka if (found == 0) {
14860fbf3537Syasuoka ppp_log(ppp, LOG_ERR,
14870fbf3537Syasuoka "Unexpected error: PPP instance is "
14880fbf3537Syasuoka "not found in the user's list.");
14890fbf3537Syasuoka }
14900fbf3537Syasuoka NPPPD_ASSERT(found != 0);
14910fbf3537Syasuoka if (slist_length(u) <= 0) {
1492f0a4e295Syasuoka /* The last PPP */
14930fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG,
14940fbf3537Syasuoka "hash_delete(user->ppp, %s)",
14950fbf3537Syasuoka ppp->username));
14960fbf3537Syasuoka if (hash_delete(_this->map_user_ppp,
14970fbf3537Syasuoka ppp->username, 0) != 0) {
14980fbf3537Syasuoka ppp_log(ppp, LOG_ERR,
14990fbf3537Syasuoka "Unexpected error: cannot delete "
15000fbf3537Syasuoka "user(%s) from user database",
15010fbf3537Syasuoka ppp->username);
15020fbf3537Syasuoka }
15030fbf3537Syasuoka slist_fini(u);
15040fbf3537Syasuoka free(u);
15050fbf3537Syasuoka } else {
1506f0a4e295Syasuoka /* Replace the reference. */
15070fbf3537Syasuoka ppp1 = slist_get(u, 0);
15080fbf3537Syasuoka hl->key = ppp1->username;
15090fbf3537Syasuoka }
15100fbf3537Syasuoka }
15110fbf3537Syasuoka }
15120fbf3537Syasuoka }
15130fbf3537Syasuoka
15140fbf3537Syasuoka /**
1515f0a4e295Syasuoka * Assign the IP address. Returning "struct in_addr" is stored IP address
1516f0a4e295Syasuoka * in network byte order.
1517f0a4e295Syasuoka * @param req_ip4 IP address request to assign. If the address is used
1518f0a4e295Syasuoka * already, this function will return fail.
15190fbf3537Syasuoka */
15200fbf3537Syasuoka int
npppd_assign_ip_addr(npppd * _this,npppd_ppp * ppp,uint32_t req_ip4)15210fbf3537Syasuoka npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4)
15220fbf3537Syasuoka {
15230fbf3537Syasuoka uint32_t ip4, ip4mask;
1524821f7c56Syasuoka int dyna, rval, fallback_dyna;
15250fbf3537Syasuoka const char *reason = "out of the pool";
15260fbf3537Syasuoka struct sockaddr_npppd *snp;
15270fbf3537Syasuoka npppd_pool *pool;
15280fbf3537Syasuoka npppd_auth_base *realm;
15290fbf3537Syasuoka
15300fbf3537Syasuoka NPPPD_DBG((LOG_DEBUG, "%s() assigned=%s", __func__,
15310fbf3537Syasuoka (ppp_ip_assigned(ppp))? "true" : "false"));
15320fbf3537Syasuoka if (ppp_ip_assigned(ppp))
15330fbf3537Syasuoka return 0;
15340fbf3537Syasuoka
15350fbf3537Syasuoka ip4 = INADDR_ANY;
15360fbf3537Syasuoka ip4mask = 0xffffffffL;
15370fbf3537Syasuoka realm = ppp->realm;
15380fbf3537Syasuoka dyna = 0;
15390fbf3537Syasuoka fallback_dyna = 0;
15400fbf3537Syasuoka pool = NULL;
15410fbf3537Syasuoka
15420fbf3537Syasuoka if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT) {
15430fbf3537Syasuoka if (req_ip4 == INADDR_ANY)
15440fbf3537Syasuoka dyna = 1;
15450fbf3537Syasuoka } else if (ppp->realm_framed_ip_address.s_addr == INADDR_NAS_SELECT) {
15460fbf3537Syasuoka dyna = 1;
15470fbf3537Syasuoka } else {
15480fbf3537Syasuoka NPPPD_ASSERT(realm != NULL);
15490fbf3537Syasuoka fallback_dyna = 1;
15500fbf3537Syasuoka req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr);
15510fbf3537Syasuoka ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr);
15520fbf3537Syasuoka }
15530fbf3537Syasuoka if (!dyna) {
15540fbf3537Syasuoka /*
1555f0a4e295Syasuoka * Realm requires the fixed IP address, but the address
1556f0a4e295Syasuoka * doesn't belong any address pool. Fallback to dynamic
1557f0a4e295Syasuoka * assignment.
15580fbf3537Syasuoka */
1559821f7c56Syasuoka pool = ppp_pool(ppp);
1560821f7c56Syasuoka rval = npppd_pool_get_assignability(pool, req_ip4, ip4mask,
1561821f7c56Syasuoka &snp);
15620fbf3537Syasuoka switch (rval) {
15630fbf3537Syasuoka case ADDRESS_OK:
15640fbf3537Syasuoka if (snp->snp_type == SNP_POOL) {
15650fbf3537Syasuoka /*
1566821f7c56Syasuoka * Fixed address pool can be used only if the
1567821f7c56Syasuoka * realm specified to use it.
15680fbf3537Syasuoka */
15690fbf3537Syasuoka if (ppp->realm_framed_ip_address
15700fbf3537Syasuoka .s_addr != INADDR_USER_SELECT)
15710fbf3537Syasuoka ip4 = req_ip4;
15720fbf3537Syasuoka break;
15730fbf3537Syasuoka }
15740fbf3537Syasuoka ppp->assign_dynapool = 1;
15750fbf3537Syasuoka ip4 = req_ip4;
15760fbf3537Syasuoka break;
15770fbf3537Syasuoka case ADDRESS_RESERVED:
15780fbf3537Syasuoka reason = "reserved";
1579821f7c56Syasuoka break;
15800fbf3537Syasuoka case ADDRESS_OUT_OF_POOL:
15810fbf3537Syasuoka reason = "out of the pool";
1582821f7c56Syasuoka break;
15830fbf3537Syasuoka case ADDRESS_BUSY:
15840fbf3537Syasuoka fallback_dyna = 0;
15850fbf3537Syasuoka reason = "busy";
15860fbf3537Syasuoka break;
15870fbf3537Syasuoka default:
15880fbf3537Syasuoka case ADDRESS_INVALID:
15890fbf3537Syasuoka fallback_dyna = 0;
15900fbf3537Syasuoka reason = "invalid";
15910fbf3537Syasuoka break;
15920fbf3537Syasuoka }
15930fbf3537Syasuoka #define IP_4OCT(v) ((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16),\
15940fbf3537Syasuoka ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v))
15950fbf3537Syasuoka if (ip4 == 0) {
15960fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE,
15970fbf3537Syasuoka "Requested IP address (%d.%d.%d.%d)/%d "
15980fbf3537Syasuoka "is %s", IP_4OCT(req_ip4),
1599baaa6b9aSyasuoka netmask2prefixlen(ip4mask), reason);
16000fbf3537Syasuoka if (fallback_dyna)
16010fbf3537Syasuoka goto dyna_assign;
16020fbf3537Syasuoka return 1;
16030fbf3537Syasuoka }
160432012184Syasuoka ppp->assigned_pool = pool;
16050fbf3537Syasuoka
16060fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4);
16070fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(ip4mask);
1608b0b96f97Syasuoka ppp->acct_framed_ip_address = ppp->ppp_framed_ip_address;
16090fbf3537Syasuoka } else {
16100fbf3537Syasuoka dyna_assign:
1611821f7c56Syasuoka pool = ppp_pool(ppp);
16120fbf3537Syasuoka ip4 = npppd_pool_get_dynamic(pool, ppp);
16130fbf3537Syasuoka if (ip4 == 0) {
16140fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE,
16150fbf3537Syasuoka "No free address in the pool.");
16160fbf3537Syasuoka return 1;
16170fbf3537Syasuoka }
16180fbf3537Syasuoka ppp->assigned_pool = pool;
16190fbf3537Syasuoka ppp->assign_dynapool = 1;
16200fbf3537Syasuoka ppp->ppp_framed_ip_address.s_addr = htonl(ip4);
16210fbf3537Syasuoka ppp->ppp_framed_ip_netmask.s_addr = htonl(0xffffffffL);
1622b0b96f97Syasuoka ppp->acct_framed_ip_address = ppp->ppp_framed_ip_address;
16230fbf3537Syasuoka }
16240fbf3537Syasuoka
16250fbf3537Syasuoka return npppd_pool_assign_ip(ppp->assigned_pool, ppp);
16260fbf3537Syasuoka }
16270fbf3537Syasuoka
16280fbf3537Syasuoka static void *
rtlist_remove(slist * prtlist,struct radish * radish)16290fbf3537Syasuoka rtlist_remove(slist *prtlist, struct radish *radish)
16300fbf3537Syasuoka {
16310fbf3537Syasuoka struct radish *r;
16320fbf3537Syasuoka
16330fbf3537Syasuoka slist_itr_first(prtlist);
16340fbf3537Syasuoka while (slist_itr_has_next(prtlist)) {
16350fbf3537Syasuoka r = slist_itr_next(prtlist);
16360fbf3537Syasuoka if (!sockaddr_npppd_match(radish->rd_route, r->rd_route) ||
16370fbf3537Syasuoka !sockaddr_npppd_match(radish->rd_mask, r->rd_mask))
16380fbf3537Syasuoka continue;
16390fbf3537Syasuoka
16400fbf3537Syasuoka return slist_itr_remove(prtlist);
16410fbf3537Syasuoka }
16420fbf3537Syasuoka
16430fbf3537Syasuoka return NULL;
16440fbf3537Syasuoka }
16450fbf3537Syasuoka
1646f0a4e295Syasuoka /** Set {@link ::npppd#rd the only radish of npppd} */
16470fbf3537Syasuoka int
npppd_set_radish(npppd * _this,void * radish_head)16480fbf3537Syasuoka npppd_set_radish(npppd *_this, void *radish_head)
16490fbf3537Syasuoka {
16500fbf3537Syasuoka int rval, delppp0, count;
16510fbf3537Syasuoka struct sockaddr_npppd *snp;
16520fbf3537Syasuoka struct radish *radish, *r;
16530fbf3537Syasuoka slist rtlist0, rtlist1, delppp;
16540fbf3537Syasuoka npppd_ppp *ppp;
16550fbf3537Syasuoka void *dummy;
16560fbf3537Syasuoka
16570fbf3537Syasuoka slist_init(&rtlist0);
16580fbf3537Syasuoka slist_init(&rtlist1);
16590fbf3537Syasuoka slist_init(&delppp);
16600fbf3537Syasuoka
16610fbf3537Syasuoka if (radish_head != NULL) {
16620fbf3537Syasuoka if (rd2slist(radish_head, &rtlist1) != 0) {
16630fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m");
1664f0a4e295Syasuoka goto fail;
16650fbf3537Syasuoka }
16660fbf3537Syasuoka }
16670fbf3537Syasuoka if (_this->rd != NULL) {
16680fbf3537Syasuoka if (rd2slist(_this->rd, &rtlist0) != 0) {
16690fbf3537Syasuoka log_printf(LOG_WARNING, "rd2slist failed: %m");
1670f0a4e295Syasuoka goto fail;
16710fbf3537Syasuoka }
16720fbf3537Syasuoka }
16730fbf3537Syasuoka if (_this->rd != NULL && radish_head != NULL) {
16740fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) {
16750fbf3537Syasuoka radish = slist_itr_next(&rtlist0);
16760fbf3537Syasuoka snp = radish->rd_rtent;
16770fbf3537Syasuoka /*
1678f0a4e295Syasuoka * replace the pool address
16790fbf3537Syasuoka */
16800fbf3537Syasuoka if (snp->snp_type == SNP_POOL ||
16810fbf3537Syasuoka snp->snp_type == SNP_DYN_POOL) {
16820fbf3537Syasuoka if (rd_lookup(radish->rd_route, radish->rd_mask,
16830fbf3537Syasuoka radish_head) == NULL)
16840fbf3537Syasuoka continue;
1685f0a4e295Syasuoka /* don't add */
16860fbf3537Syasuoka rtlist_remove(&rtlist1, radish);
1687f0a4e295Syasuoka /* don't delete */
16880fbf3537Syasuoka slist_itr_remove(&rtlist0);
16890fbf3537Syasuoka continue;
16900fbf3537Syasuoka }
16910fbf3537Syasuoka /*
1692f0a4e295Syasuoka * handle the active PPP sessions.
16930fbf3537Syasuoka */
16940fbf3537Syasuoka NPPPD_ASSERT(snp->snp_type == SNP_PPP);
16950fbf3537Syasuoka ppp = snp->snp_data_ptr;
16960fbf3537Syasuoka
1697f0a4e295Syasuoka /* Don't delete the route of active PPP session */
16980fbf3537Syasuoka slist_itr_remove(&rtlist0);
16990fbf3537Syasuoka
1700f5c2ff87Syasuoka /* clear information about old pool configuration */
17010fbf3537Syasuoka snp->snp_next = NULL;
17020fbf3537Syasuoka
17030fbf3537Syasuoka delppp0 = 0;
17040fbf3537Syasuoka if (!rd_match((struct sockaddr *)snp, radish_head, &r)){
17050fbf3537Syasuoka /*
1706f0a4e295Syasuoka * If the address doesn't belong the new pools,
1707f0a4e295Syasuoka * add the PPP session to the deletion list.
17080fbf3537Syasuoka */
17090fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr);
17100fbf3537Syasuoka delppp0 = 1;
17110fbf3537Syasuoka } else {
17120fbf3537Syasuoka NPPPD_ASSERT(
17130fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent)
17140fbf3537Syasuoka ->snp_type == SNP_POOL ||
17150fbf3537Syasuoka ((struct sockaddr_npppd *)r->rd_rtent)
17160fbf3537Syasuoka ->snp_type == SNP_DYN_POOL);
17170fbf3537Syasuoka /*
1718f0a4e295Syasuoka * If there is a pool entry that has same
1719f0a4e295Syasuoka * address/mask, then make the RADISH entry a
1720f0a4e295Syasuoka * list. Set SNP_PPP as the first in the list,
1721f0a4e295Syasuoka * set current entry in snp->snp_next and
1722f0a4e295Syasuoka * delete it.
17230fbf3537Syasuoka */
17240fbf3537Syasuoka if (sockaddr_npppd_match(
17250fbf3537Syasuoka radish->rd_route, r->rd_route) &&
17260fbf3537Syasuoka sockaddr_npppd_match(
17270fbf3537Syasuoka radish->rd_mask, r->rd_mask)) {
1728f0a4e295Syasuoka /*
1729f0a4e295Syasuoka * Releasing it, so remove it from the
1730f0a4e295Syasuoka * new routing list.
1731f0a4e295Syasuoka */
17320fbf3537Syasuoka rtlist_remove(&rtlist1, radish);
1733f0a4e295Syasuoka /* set as snp_snp_next */
17340fbf3537Syasuoka snp->snp_next = r->rd_rtent;
17350fbf3537Syasuoka rval = rd_delete(r->rd_route,
17360fbf3537Syasuoka r->rd_mask, radish_head, &dummy);
17370fbf3537Syasuoka NPPPD_ASSERT(rval == 0);
17380fbf3537Syasuoka }
17390fbf3537Syasuoka }
1740f0a4e295Syasuoka /* Register to the new radish */
17410fbf3537Syasuoka rval = rd_insert(radish->rd_route, radish->rd_mask,
17420fbf3537Syasuoka radish_head, snp);
17430fbf3537Syasuoka if (rval != 0) {
17440fbf3537Syasuoka errno = rval;
17450fbf3537Syasuoka ppp_log(((npppd_ppp *)snp->snp_data_ptr),
17460fbf3537Syasuoka LOG_ERR,
17470fbf3537Syasuoka "Fatal error on %s, cannot continue "
17480fbf3537Syasuoka "this ppp session: %m", __func__);
17490fbf3537Syasuoka if (!delppp0)
17500fbf3537Syasuoka slist_add(&delppp, snp->snp_data_ptr);
17510fbf3537Syasuoka }
17520fbf3537Syasuoka }
17530fbf3537Syasuoka }
17540fbf3537Syasuoka count = 0;
17550fbf3537Syasuoka #ifndef NO_ROUTE_FOR_POOLED_ADDRESS
1756cd8e09b9Sdlg if (_this->iface[0].using_pppx == 0) {
17570fbf3537Syasuoka for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) {
17580fbf3537Syasuoka radish = slist_itr_next(&rtlist0);
17590fbf3537Syasuoka in_route_delete(&SIN(radish->rd_route)->sin_addr,
1760cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop,
1761cd8e09b9Sdlg RTF_BLACKHOLE);
17620fbf3537Syasuoka count++;
17630fbf3537Syasuoka }
17640fbf3537Syasuoka if (count > 0)
17650fbf3537Syasuoka log_printf(LOG_INFO,
17660fbf3537Syasuoka "Deleted %d routes for old pool addresses", count);
17670fbf3537Syasuoka
17680fbf3537Syasuoka count = 0;
17690fbf3537Syasuoka for (slist_itr_first(&rtlist1); slist_itr_has_next(&rtlist1);) {
17700fbf3537Syasuoka radish = slist_itr_next(&rtlist1);
17710fbf3537Syasuoka in_route_add(&(SIN(radish->rd_route)->sin_addr),
1772cd8e09b9Sdlg &SIN(radish->rd_mask)->sin_addr, &loop,
1773cd8e09b9Sdlg LOOPBACK_IFNAME, RTF_BLACKHOLE, 0);
17740fbf3537Syasuoka count++;
17750fbf3537Syasuoka }
17760fbf3537Syasuoka if (count > 0)
17770fbf3537Syasuoka log_printf(LOG_INFO,
1778cd8e09b9Sdlg "Added %d routes for new pool addresses",
1779cd8e09b9Sdlg count);
1780cd8e09b9Sdlg }
17810fbf3537Syasuoka #endif
17820fbf3537Syasuoka slist_fini(&rtlist0);
17830fbf3537Syasuoka slist_fini(&rtlist1);
17840fbf3537Syasuoka
1785230b2897Syasuoka if (_this->rd != NULL) {
17860fbf3537Syasuoka npppd_rd_walktree_delete(_this->rd);
1787230b2897Syasuoka _this->rd = NULL;
1788230b2897Syasuoka }
178984c9ec02Syasuoka if (radish_head == NULL)
179084c9ec02Syasuoka npppd_get_all_users(_this, &delppp);
17913089d6fcSyasuoka _this->rd = radish_head;
17920fbf3537Syasuoka
17930fbf3537Syasuoka for (slist_itr_first(&delppp); slist_itr_has_next(&delppp);) {
17940fbf3537Syasuoka ppp = slist_itr_next(&delppp);
17950fbf3537Syasuoka ppp_log(ppp, LOG_NOTICE,
17960fbf3537Syasuoka "stop. IP address of this ppp is out of the pool.: %s",
17970fbf3537Syasuoka inet_ntoa(ppp->ppp_framed_ip_address));
17980fbf3537Syasuoka ppp_stop(ppp, NULL);
17990fbf3537Syasuoka }
18000fbf3537Syasuoka slist_fini(&delppp);
18010fbf3537Syasuoka
18020fbf3537Syasuoka return 0;
1803f0a4e295Syasuoka fail:
18040fbf3537Syasuoka slist_fini(&rtlist0);
18050fbf3537Syasuoka slist_fini(&rtlist1);
18060fbf3537Syasuoka slist_fini(&delppp);
18070fbf3537Syasuoka
18080fbf3537Syasuoka return 1;
18090fbf3537Syasuoka }
18100fbf3537Syasuoka
18110fbf3537Syasuoka /**
1812f0a4e295Syasuoka * This function stores all users to {@link slist} and returns them.
1813f0a4e295Syasuoka * References to {@link ::npppd_ppp} will be stored in users.
18140fbf3537Syasuoka */
181534682664Syasuoka static int
npppd_get_all_users(npppd * _this,slist * users)18160fbf3537Syasuoka npppd_get_all_users(npppd *_this, slist *users)
18170fbf3537Syasuoka {
18180fbf3537Syasuoka int rval;
18190fbf3537Syasuoka struct radish *rd;
18200fbf3537Syasuoka struct sockaddr_npppd *snp;
18210fbf3537Syasuoka slist list;
18220fbf3537Syasuoka
18230fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
18240fbf3537Syasuoka
18250fbf3537Syasuoka slist_init(&list);
182684c9ec02Syasuoka if (_this->rd == NULL)
182784c9ec02Syasuoka return 0;
18280fbf3537Syasuoka rval = rd2slist(_this->rd, &list);
18290fbf3537Syasuoka if (rval != 0)
18300fbf3537Syasuoka return rval;
18310fbf3537Syasuoka
18320fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) {
18330fbf3537Syasuoka rd = slist_itr_next(&list);
18340fbf3537Syasuoka snp = rd->rd_rtent;
18350fbf3537Syasuoka if (snp->snp_type == SNP_PPP) {
18360fbf3537Syasuoka if (slist_add(users, snp->snp_data_ptr) == NULL) {
18370fbf3537Syasuoka log_printf(LOG_ERR,
18380fbf3537Syasuoka "slist_add() failed in %s: %m", __func__);
1839f0a4e295Syasuoka goto fail;
18400fbf3537Syasuoka }
18410fbf3537Syasuoka }
18420fbf3537Syasuoka }
18430fbf3537Syasuoka slist_fini(&list);
18440fbf3537Syasuoka
18450fbf3537Syasuoka return 0;
1846f0a4e295Syasuoka fail:
18470fbf3537Syasuoka slist_fini(&list);
18480fbf3537Syasuoka
18490fbf3537Syasuoka return 1;
18500fbf3537Syasuoka }
18510fbf3537Syasuoka
18520fbf3537Syasuoka static int
rd2slist_walk(struct radish * rd,void * list0)18530fbf3537Syasuoka rd2slist_walk(struct radish *rd, void *list0)
18540fbf3537Syasuoka {
18550fbf3537Syasuoka slist *list = list0;
18560fbf3537Syasuoka void *r;
18570fbf3537Syasuoka
18580fbf3537Syasuoka r = slist_add(list, rd);
18590fbf3537Syasuoka if (r == NULL)
18600fbf3537Syasuoka return -1;
18610fbf3537Syasuoka return 0;
18620fbf3537Syasuoka }
18630fbf3537Syasuoka static int
rd2slist(struct radish_head * h,slist * list)18640fbf3537Syasuoka rd2slist(struct radish_head *h, slist *list)
18650fbf3537Syasuoka {
18660fbf3537Syasuoka return rd_walktree(h, rd2slist_walk, list);
18670fbf3537Syasuoka }
18680fbf3537Syasuoka
18690fbf3537Syasuoka static void
npppd_reload0(npppd * _this)18700fbf3537Syasuoka npppd_reload0(npppd *_this)
18710fbf3537Syasuoka {
1872821f7c56Syasuoka int i;
1873821f7c56Syasuoka
18740fbf3537Syasuoka npppd_reload_config(_this);
18750fbf3537Syasuoka #ifdef USE_NPPPD_ARP
18760fbf3537Syasuoka arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT));
18770fbf3537Syasuoka if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1)
18780fbf3537Syasuoka arp_sock_init();
18790fbf3537Syasuoka else
18800fbf3537Syasuoka arp_sock_fini();
18810fbf3537Syasuoka #endif
18820fbf3537Syasuoka npppd_modules_reload(_this);
18830fbf3537Syasuoka npppd_ifaces_load_config(_this);
1884821f7c56Syasuoka npppd_update_pool_reference(_this);
18850fbf3537Syasuoka npppd_auth_finalizer_periodic(_this);
18862a5607d2Sgoda npppd_ipcp_stats_reload(_this);
1887821f7c56Syasuoka
1888821f7c56Syasuoka for (i = 0; i < countof(_this->iface); i++) {
1889821f7c56Syasuoka if (_this->iface[i].initialized != 0 &&
1890821f7c56Syasuoka _this->iface[i].started == 0)
1891821f7c56Syasuoka npppd_iface_start(&_this->iface[i]);
1892821f7c56Syasuoka }
1893821f7c56Syasuoka }
1894821f7c56Syasuoka
1895821f7c56Syasuoka static void
npppd_update_pool_reference(npppd * _this)1896821f7c56Syasuoka npppd_update_pool_reference(npppd *_this)
1897821f7c56Syasuoka {
1898821f7c56Syasuoka int i, j;
1899821f7c56Syasuoka /* update iface to pool reference */
1900821f7c56Syasuoka for (i = 0; i < countof(_this->iface_pool); i++) {
1901821f7c56Syasuoka _this->iface_pool[i] = NULL;
1902821f7c56Syasuoka if (_this->iface[i].initialized == 0)
1903821f7c56Syasuoka continue;
1904821f7c56Syasuoka if (_this->iface[i].ipcpconf == NULL)
1905821f7c56Syasuoka continue; /* no IPCP for this interface */
1906821f7c56Syasuoka
1907821f7c56Syasuoka for (j = 0; j < countof(_this->pool); j++) {
1908821f7c56Syasuoka if (_this->pool[j].initialized == 0)
1909821f7c56Syasuoka continue;
1910821f7c56Syasuoka if (strcmp(_this->iface[i].ipcpconf->name,
1911821f7c56Syasuoka _this->pool[j].ipcp_name) == 0) {
1912821f7c56Syasuoka /* found the ipcp that has the pool */
1913821f7c56Syasuoka _this->iface_pool[i] = &_this->pool[j];
1914821f7c56Syasuoka break;
1915821f7c56Syasuoka }
1916821f7c56Syasuoka }
1917821f7c56Syasuoka }
19180fbf3537Syasuoka }
19190fbf3537Syasuoka
19200fbf3537Syasuoka /***********************************************************************
1921f0a4e295Syasuoka * Signal handlers
19220fbf3537Syasuoka ***********************************************************************/
19230fbf3537Syasuoka static void
npppd_on_sighup(int fd,short ev_type,void * ctx)19240fbf3537Syasuoka npppd_on_sighup(int fd, short ev_type, void *ctx)
19250fbf3537Syasuoka {
19260fbf3537Syasuoka npppd *_this;
19270fbf3537Syasuoka
19280fbf3537Syasuoka _this = ctx;
19290fbf3537Syasuoka #ifndef NO_DELAYED_RELOAD
19300fbf3537Syasuoka if (_this->delayed_reload > 0)
19310fbf3537Syasuoka _this->reloading_count = _this->delayed_reload;
19320fbf3537Syasuoka else
19330fbf3537Syasuoka #endif
19340fbf3537Syasuoka npppd_reload0(_this);
19350fbf3537Syasuoka }
19360fbf3537Syasuoka
19370fbf3537Syasuoka static void
npppd_on_sigterm(int fd,short ev_type,void * ctx)19380fbf3537Syasuoka npppd_on_sigterm(int fd, short ev_type, void *ctx)
19390fbf3537Syasuoka {
19400fbf3537Syasuoka npppd *_this;
19410fbf3537Syasuoka
19420fbf3537Syasuoka _this = ctx;
19430fbf3537Syasuoka npppd_stop(_this);
19440fbf3537Syasuoka }
19450fbf3537Syasuoka
19460fbf3537Syasuoka static void
npppd_on_sigint(int fd,short ev_type,void * ctx)19470fbf3537Syasuoka npppd_on_sigint(int fd, short ev_type, void *ctx)
19480fbf3537Syasuoka {
19490fbf3537Syasuoka npppd *_this;
19500fbf3537Syasuoka
19510fbf3537Syasuoka _this = ctx;
19520fbf3537Syasuoka npppd_stop(_this);
19530fbf3537Syasuoka }
19540fbf3537Syasuoka
19555fefcc09Syasuoka static void
npppd_on_sigchld(int fd,short ev_type,void * ctx)19565fefcc09Syasuoka npppd_on_sigchld(int fd, short ev_type, void *ctx)
19575fefcc09Syasuoka {
19585fefcc09Syasuoka int status;
19595fefcc09Syasuoka pid_t wpid;
19605fefcc09Syasuoka npppd *_this;
19615fefcc09Syasuoka
19625fefcc09Syasuoka _this = ctx;
19635fefcc09Syasuoka wpid = privsep_priv_pid();
19645fefcc09Syasuoka if (wait4(wpid, &status, WNOHANG, NULL) == wpid) {
19655fefcc09Syasuoka if (WIFSIGNALED(status))
19665fefcc09Syasuoka log_printf(LOG_WARNING,
1967f5c2ff87Syasuoka "privileged process exits abnormally. signal=%d",
19685fefcc09Syasuoka WTERMSIG(status));
19695fefcc09Syasuoka else
19705fefcc09Syasuoka log_printf(LOG_WARNING,
1971f5c2ff87Syasuoka "privileged process exits abnormally. status=%d",
19725fefcc09Syasuoka WEXITSTATUS(status));
19735fefcc09Syasuoka _this->stop_by_error = 1;
19745fefcc09Syasuoka npppd_stop(_this);
19755fefcc09Syasuoka }
19765fefcc09Syasuoka }
19770fbf3537Syasuoka /***********************************************************************
1978f0a4e295Syasuoka * Miscellaneous functions
19790fbf3537Syasuoka ***********************************************************************/
19800fbf3537Syasuoka static uint32_t
str_hash(const void * ptr,int sz)19810fbf3537Syasuoka str_hash(const void *ptr, int sz)
19820fbf3537Syasuoka {
19830fbf3537Syasuoka uint32_t hash = 0;
19840fbf3537Syasuoka int i, len;
19850fbf3537Syasuoka const char *str;
19860fbf3537Syasuoka
19870fbf3537Syasuoka str = ptr;
19880fbf3537Syasuoka len = strlen(str);
19890fbf3537Syasuoka for (i = 0; i < len; i++)
19900fbf3537Syasuoka hash = hash*0x1F + str[i];
19910fbf3537Syasuoka hash = (hash << 16) ^ (hash & 0xffff);
19920fbf3537Syasuoka
19930fbf3537Syasuoka return hash % sz;
19940fbf3537Syasuoka }
19950fbf3537Syasuoka
19960fbf3537Syasuoka /**
1997f0a4e295Syasuoka * Select a authentication realm that is for given {@link ::npppd_ppp PPP}.
1998f0a4e295Syasuoka * Return 0 on success.
19990fbf3537Syasuoka */
20000fbf3537Syasuoka int
npppd_ppp_bind_realm(npppd * _this,npppd_ppp * ppp,const char * username,int eap_required)20010fbf3537Syasuoka npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int
20020fbf3537Syasuoka eap_required)
20030fbf3537Syasuoka {
2004821f7c56Syasuoka struct confbind *bind;
20050fbf3537Syasuoka npppd_auth_base *realm = NULL, *realm0 = NULL, *realm1 = NULL;
2006821f7c56Syasuoka char buf1[MAX_USERNAME_LENGTH];
200734379bfeSyasuoka int lsuffix, lusername, lmax;
20080fbf3537Syasuoka
20090fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
20100fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
20110fbf3537Syasuoka NPPPD_ASSERT(username != NULL);
20120fbf3537Syasuoka
20130fbf3537Syasuoka /*
2014f0a4e295Syasuoka * If the PPP suffix is the longest, and the length of the suffix is
2015f0a4e295Syasuoka * same, select the first one.
20160fbf3537Syasuoka */
20170fbf3537Syasuoka lusername = strlen(username);
20180fbf3537Syasuoka lmax = -1;
20190fbf3537Syasuoka realm = NULL;
20200fbf3537Syasuoka
2021821f7c56Syasuoka TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) {
2022821f7c56Syasuoka if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0)
20230fbf3537Syasuoka continue;
20240fbf3537Syasuoka
20250fbf3537Syasuoka realm0 = NULL;
20260fbf3537Syasuoka slist_itr_first(&_this->realms);
20270fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) {
20280fbf3537Syasuoka realm1 = slist_itr_next(&_this->realms);
20290fbf3537Syasuoka if (!npppd_auth_is_usable(realm1))
20300fbf3537Syasuoka continue;
2031821f7c56Syasuoka if (eap_required && !npppd_auth_is_eap_capable(realm1))
20320fbf3537Syasuoka continue;
2033821f7c56Syasuoka if (strcmp(npppd_auth_get_name(realm1),
2034821f7c56Syasuoka bind->authconf->name) == 0) {
20350fbf3537Syasuoka realm0 = realm1;
20360fbf3537Syasuoka break;
20370fbf3537Syasuoka }
20380fbf3537Syasuoka }
20390fbf3537Syasuoka if (realm0 == NULL)
20400fbf3537Syasuoka continue;
2041821f7c56Syasuoka
20420fbf3537Syasuoka lsuffix = strlen(npppd_auth_get_suffix(realm0));
20430fbf3537Syasuoka if (lsuffix > lmax &&
2044821f7c56Syasuoka (lsuffix == 0 ||
2045821f7c56Syasuoka (lsuffix < lusername && strcmp(username + lusername
2046821f7c56Syasuoka - lsuffix, npppd_auth_get_suffix(realm0))
2047821f7c56Syasuoka == 0))) {
20480fbf3537Syasuoka lmax = lsuffix;
20490fbf3537Syasuoka realm = realm0;
20500fbf3537Syasuoka }
20510fbf3537Syasuoka }
2052821f7c56Syasuoka
20530fbf3537Syasuoka if (realm == NULL) {
20540fbf3537Syasuoka log_printf(LOG_INFO, "user='%s' could not bind any realms",
20550fbf3537Syasuoka username);
20560fbf3537Syasuoka return 1;
20570fbf3537Syasuoka }
2058821f7c56Syasuoka NPPPD_DBG((LOG_DEBUG, "bind realm %s", npppd_auth_get_name(realm)));
20590fbf3537Syasuoka
20600fbf3537Syasuoka if (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL)
20610fbf3537Syasuoka /* hook the auto reload */
20620fbf3537Syasuoka npppd_auth_get_user_password(realm,
20630fbf3537Syasuoka npppd_auth_username_for_auth(realm1, username, buf1), NULL,
20640fbf3537Syasuoka NULL);
20650fbf3537Syasuoka ppp->realm = realm;
20660fbf3537Syasuoka
20670fbf3537Syasuoka return 0;
20680fbf3537Syasuoka }
20690fbf3537Syasuoka
2070f0a4e295Syasuoka /** Is assigned realm a LOCAL authentication? */
20710fbf3537Syasuoka int
npppd_ppp_is_realm_local(npppd * _this,npppd_ppp * ppp)20720fbf3537Syasuoka npppd_ppp_is_realm_local(npppd *_this, npppd_ppp *ppp)
20730fbf3537Syasuoka {
20740fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
20750fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
20760fbf3537Syasuoka
20770fbf3537Syasuoka if (ppp->realm == NULL)
20780fbf3537Syasuoka return 0;
20790fbf3537Syasuoka
20800fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_LOCAL)
20810fbf3537Syasuoka ? 1 : 0;
20820fbf3537Syasuoka }
20830fbf3537Syasuoka
2084f0a4e295Syasuoka /** Is assigned realm a RADIUS authentication? */
20850fbf3537Syasuoka int
npppd_ppp_is_realm_radius(npppd * _this,npppd_ppp * ppp)20860fbf3537Syasuoka npppd_ppp_is_realm_radius(npppd *_this, npppd_ppp *ppp)
20870fbf3537Syasuoka {
20880fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
20890fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
20900fbf3537Syasuoka
20910fbf3537Syasuoka if (ppp->realm == NULL)
20920fbf3537Syasuoka return 0;
20930fbf3537Syasuoka
20940fbf3537Syasuoka return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_RADIUS)
20950fbf3537Syasuoka ? 1 : 0;
20960fbf3537Syasuoka }
20970fbf3537Syasuoka
2098f0a4e295Syasuoka /** Is assigned realm usable? */
20990fbf3537Syasuoka int
npppd_ppp_is_realm_ready(npppd * _this,npppd_ppp * ppp)21000fbf3537Syasuoka npppd_ppp_is_realm_ready(npppd *_this, npppd_ppp *ppp)
21010fbf3537Syasuoka {
21020fbf3537Syasuoka if (ppp->realm == NULL)
21030fbf3537Syasuoka return 0;
21040fbf3537Syasuoka
21050fbf3537Syasuoka return npppd_auth_is_ready(ppp->realm);
21060fbf3537Syasuoka }
21070fbf3537Syasuoka
2108f0a4e295Syasuoka /** Return the name of assigned realm */
21090fbf3537Syasuoka const char *
npppd_ppp_get_realm_name(npppd * _this,npppd_ppp * ppp)21100fbf3537Syasuoka npppd_ppp_get_realm_name(npppd *_this, npppd_ppp *ppp)
21110fbf3537Syasuoka {
21120fbf3537Syasuoka if (ppp->realm == NULL)
21130fbf3537Syasuoka return "(none)";
21140fbf3537Syasuoka return npppd_auth_get_name(ppp->realm);
21150fbf3537Syasuoka }
21160fbf3537Syasuoka
2117f0a4e295Syasuoka /** Return the interface name that bound given {@link ::npppd_ppp PPP} */
21180fbf3537Syasuoka const char *
npppd_ppp_get_iface_name(npppd * _this,npppd_ppp * ppp)21190fbf3537Syasuoka npppd_ppp_get_iface_name(npppd *_this, npppd_ppp *ppp)
21200fbf3537Syasuoka {
21210fbf3537Syasuoka if (ppp == NULL || ppp->ifidx < 0)
21220fbf3537Syasuoka return "(not binding)";
21230fbf3537Syasuoka return ppp_iface(ppp)->ifname;
21240fbf3537Syasuoka }
21250fbf3537Syasuoka
2126f0a4e295Syasuoka /** Is the interface usable? */
21270fbf3537Syasuoka int
npppd_ppp_iface_is_ready(npppd * _this,npppd_ppp * ppp)21280fbf3537Syasuoka npppd_ppp_iface_is_ready(npppd *_this, npppd_ppp *ppp)
21290fbf3537Syasuoka {
21300fbf3537Syasuoka return (npppd_iface_ip_is_ready(ppp_iface(ppp)) &&
21310fbf3537Syasuoka ppp_ipcp(ppp) != NULL)? 1 : 0;
21320fbf3537Syasuoka }
21330fbf3537Syasuoka
2134f0a4e295Syasuoka /** Select a suitable interface for {@link :npppd_ppp PPP} and bind them */
21350fbf3537Syasuoka int
npppd_ppp_bind_iface(npppd * _this,npppd_ppp * ppp)21360fbf3537Syasuoka npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp)
21370fbf3537Syasuoka {
2138821f7c56Syasuoka int i, ifidx;
2139821f7c56Syasuoka struct confbind *bind;
21402a5607d2Sgoda struct ipcpstat *ipcpstat;
21410fbf3537Syasuoka
21420fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
21430fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
21440fbf3537Syasuoka
21450fbf3537Syasuoka if (ppp->ifidx >= 0)
21460fbf3537Syasuoka return 0;
21470fbf3537Syasuoka
2148821f7c56Syasuoka TAILQ_FOREACH(bind, &_this->conf.confbinds, entry) {
2149821f7c56Syasuoka if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0)
2150821f7c56Syasuoka continue;
2151821f7c56Syasuoka if (ppp->realm == NULL) {
2152821f7c56Syasuoka if (bind->authconf == NULL)
2153821f7c56Syasuoka break;
2154821f7c56Syasuoka } else if (strcmp(bind->authconf->name,
2155821f7c56Syasuoka npppd_auth_get_name(ppp->realm)) == 0)
2156821f7c56Syasuoka break;
2157821f7c56Syasuoka }
2158821f7c56Syasuoka if (bind == NULL)
21590fbf3537Syasuoka return 1;
21600fbf3537Syasuoka
2161f0a4e295Syasuoka /* Search a interface */
21620fbf3537Syasuoka ifidx = -1;
21630fbf3537Syasuoka for (i = 0; i < countof(_this->iface); i++) {
21640fbf3537Syasuoka if (_this->iface[i].initialized == 0)
21650fbf3537Syasuoka continue;
2166821f7c56Syasuoka if (strcmp(_this->iface[i].ifname, bind->iface->name) == 0)
21670fbf3537Syasuoka ifidx = i;
21680fbf3537Syasuoka }
21690fbf3537Syasuoka if (ifidx < 0)
21700fbf3537Syasuoka return 1;
21710fbf3537Syasuoka
21722a5607d2Sgoda ppp->ifidx = ifidx;
21732a5607d2Sgoda NPPPD_ASSERT(ppp_ipcp(ppp) != NULL);
21742a5607d2Sgoda ipcpstat = npppd_get_ipcp_stat(&_this->ipcpstats, ppp_ipcp(ppp)->name);
21752a5607d2Sgoda if (ipcpstat == NULL) {
21762a5607d2Sgoda ppp_log(ppp, LOG_WARNING, "Unknown IPCP %s",
21772a5607d2Sgoda ppp_ipcp(ppp)->name);
2178f5c2ff87Syasuoka ppp->ifidx = -1; /* unbind interface */
21792a5607d2Sgoda return 1;
21802a5607d2Sgoda }
21812a5607d2Sgoda if (ppp_ipcp(ppp)->max_session > 0 &&
21822a5607d2Sgoda ipcpstat->nsession >= ppp_ipcp(ppp)->max_session) {
21832a5607d2Sgoda ppp_log(ppp, LOG_WARNING,
21842a5607d2Sgoda "Number of sessions per IPCP reaches out of the limit=%d",
21852a5607d2Sgoda ppp_ipcp(ppp)->max_session);
2186f5c2ff87Syasuoka ppp->ifidx = -1; /* unbind interface */
21872a5607d2Sgoda return 1;
21882a5607d2Sgoda }
21892a5607d2Sgoda
2190e43db91eSyasuoka if (_this->conf.max_session > 0 &&
21914080edd5Syasuoka _this->nsession >= _this->conf.max_session) {
21920fbf3537Syasuoka ppp_log(ppp, LOG_WARNING,
21930fbf3537Syasuoka "Number of sessions reaches out of the limit=%d",
2194e43db91eSyasuoka _this->conf.max_session);
2195f5c2ff87Syasuoka ppp->ifidx = -1; /* unbind interface */
21960fbf3537Syasuoka return 1;
21970fbf3537Syasuoka }
21984080edd5Syasuoka _this->nsession++;
21990fbf3537Syasuoka
22002a5607d2Sgoda LIST_INSERT_HEAD(&ipcpstat->ppp, ppp, ipcpstat_entry);
22012a5607d2Sgoda ppp->ipcpstat = ipcpstat;
22022a5607d2Sgoda ipcpstat->nsession++;
22032a5607d2Sgoda
22040fbf3537Syasuoka return 0;
22050fbf3537Syasuoka }
22060fbf3537Syasuoka
2207f0a4e295Syasuoka /** Unbind the interface from the {@link ::npppd_ppp PPP} */
22080fbf3537Syasuoka void
npppd_ppp_unbind_iface(npppd * _this,npppd_ppp * ppp)22090fbf3537Syasuoka npppd_ppp_unbind_iface(npppd *_this, npppd_ppp *ppp)
22100fbf3537Syasuoka {
22112a5607d2Sgoda if (ppp->ifidx >= 0) {
2212821f7c56Syasuoka _this->nsession--;
22132a5607d2Sgoda if (ppp->ipcpstat!= NULL) {
22142a5607d2Sgoda ppp->ipcpstat->nsession--;
22152a5607d2Sgoda LIST_REMOVE(ppp, ipcpstat_entry);
22162a5607d2Sgoda }
22172a5607d2Sgoda }
22180fbf3537Syasuoka ppp->ifidx = -1;
22190fbf3537Syasuoka }
22200fbf3537Syasuoka
22210fbf3537Syasuoka static int
npppd_rd_walktree_delete(struct radish_head * rh)22220fbf3537Syasuoka npppd_rd_walktree_delete(struct radish_head *rh)
22230fbf3537Syasuoka {
22240fbf3537Syasuoka void *dummy;
22250fbf3537Syasuoka struct radish *rd;
22260fbf3537Syasuoka slist list;
22270fbf3537Syasuoka
22280fbf3537Syasuoka slist_init(&list);
22290fbf3537Syasuoka if (rd2slist(rh, &list) != 0)
22300fbf3537Syasuoka return 1;
22310fbf3537Syasuoka for (slist_itr_first(&list); slist_itr_has_next(&list);) {
22320fbf3537Syasuoka rd = slist_itr_next(&list);
22330fbf3537Syasuoka rd_delete(rd->rd_route, rd->rd_mask, rh, &dummy);
22340fbf3537Syasuoka }
22350fbf3537Syasuoka slist_fini(&list);
22360fbf3537Syasuoka
22370fbf3537Syasuoka free(rh);
22380fbf3537Syasuoka
22390fbf3537Syasuoka return 0;
22400fbf3537Syasuoka }
22410fbf3537Syasuoka
22420fbf3537Syasuoka #ifdef USE_NPPPD_RADIUS
2243f0a4e295Syasuoka /**
2244f0a4e295Syasuoka * Return radius_req_setting for the given {@link ::npppd_ppp PPP}.
2245f0a4e295Syasuoka * @return return NULL if no usable RADIUS setting.
2246f0a4e295Syasuoka */
22470fbf3537Syasuoka void *
npppd_get_radius_auth_setting(npppd * _this,npppd_ppp * ppp)22488daf7599Syasuoka npppd_get_radius_auth_setting(npppd *_this, npppd_ppp *ppp)
22490fbf3537Syasuoka {
22500fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
22510fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
22520fbf3537Syasuoka
22530fbf3537Syasuoka if (ppp->realm == NULL)
22540fbf3537Syasuoka return NULL;
22550fbf3537Syasuoka if (!npppd_ppp_is_realm_radius(_this, ppp))
22560fbf3537Syasuoka return NULL;
22570fbf3537Syasuoka
22588daf7599Syasuoka return npppd_auth_radius_get_radius_auth_setting(ppp->realm);
22590fbf3537Syasuoka }
22600fbf3537Syasuoka #endif
22610fbf3537Syasuoka
2262f0a4e295Syasuoka /** Finalize authentication realm */
22630fbf3537Syasuoka static void
npppd_auth_finalizer_periodic(npppd * _this)22640fbf3537Syasuoka npppd_auth_finalizer_periodic(npppd *_this)
22650fbf3537Syasuoka {
22660fbf3537Syasuoka int ndisposing = 0, refcnt;
22670fbf3537Syasuoka slist users;
22680fbf3537Syasuoka npppd_auth_base *auth_base;
22690fbf3537Syasuoka npppd_ppp *ppp;
22700fbf3537Syasuoka
22710fbf3537Syasuoka /*
2272f0a4e295Syasuoka * For the realms with disposing flag, if the realm has assigned PPPs,
2273f0a4e295Syasuoka * disconnect them. If all PPPs are disconnected then free the realm.
22740fbf3537Syasuoka */
22750fbf3537Syasuoka NPPPD_DBG((DEBUG_LEVEL_2, "%s() called", __func__));
22760fbf3537Syasuoka slist_itr_first(&_this->realms);
22770fbf3537Syasuoka while (slist_itr_has_next(&_this->realms)) {
22780fbf3537Syasuoka auth_base = slist_itr_next(&_this->realms);
22790fbf3537Syasuoka if (!npppd_auth_is_disposing(auth_base))
22800fbf3537Syasuoka continue;
22810fbf3537Syasuoka refcnt = 0;
22820fbf3537Syasuoka if (ndisposing++ == 0) {
22830fbf3537Syasuoka slist_init(&users);
22840fbf3537Syasuoka if (npppd_get_all_users(_this, &users) != 0) {
22850fbf3537Syasuoka log_printf(LOG_WARNING,
22860fbf3537Syasuoka "npppd_get_all_users() failed in %s(): %m",
22870fbf3537Syasuoka __func__);
22880fbf3537Syasuoka break;
22890fbf3537Syasuoka }
22900fbf3537Syasuoka }
22910fbf3537Syasuoka slist_itr_first(&users);
22920fbf3537Syasuoka while (slist_itr_has_next(&users)) {
22930fbf3537Syasuoka ppp = slist_itr_next(&users);
22940fbf3537Syasuoka if (ppp->realm == auth_base) {
22950fbf3537Syasuoka refcnt++;
22960fbf3537Syasuoka ppp_stop(ppp, NULL);
22970fbf3537Syasuoka ppp_log(ppp, LOG_INFO,
22980fbf3537Syasuoka "Stop request by npppd. Binding "
22990fbf3537Syasuoka "authentication realm is disposing. "
23000fbf3537Syasuoka "realm=%s", npppd_auth_get_name(auth_base));
23010fbf3537Syasuoka slist_itr_remove(&users);
23020fbf3537Syasuoka }
23030fbf3537Syasuoka }
23048daf7599Syasuoka if (refcnt == 0) {
23050fbf3537Syasuoka npppd_auth_destroy(auth_base);
23068daf7599Syasuoka slist_itr_remove(&_this->realms);
23078daf7599Syasuoka }
23080fbf3537Syasuoka }
23090fbf3537Syasuoka if (ndisposing > 0)
23100fbf3537Syasuoka slist_fini(&users);
23110fbf3537Syasuoka }
23120fbf3537Syasuoka
2313f0a4e295Syasuoka /** compare sockaddr_npppd. return 0 if matches */
23140fbf3537Syasuoka int
sockaddr_npppd_match(void * a0,void * b0)23150fbf3537Syasuoka sockaddr_npppd_match(void *a0, void *b0)
23160fbf3537Syasuoka {
23170fbf3537Syasuoka struct sockaddr_npppd *a, *b;
23180fbf3537Syasuoka
23190fbf3537Syasuoka a = a0;
23200fbf3537Syasuoka b = b0;
23210fbf3537Syasuoka
23220fbf3537Syasuoka return (a->snp_addr.s_addr == b->snp_addr.s_addr)? 1 : 0;
23230fbf3537Syasuoka }
23240fbf3537Syasuoka
23250fbf3537Syasuoka /**
2326f0a4e295Syasuoka * This function stores the username for authentication to the space specified
2327f0a4e295Syasuoka * by username_buffer and returns it. username_buffer must have space more
2328f0a4e295Syasuoka * than MAX_USERNAME_LENGTH.
23290fbf3537Syasuoka */
23300fbf3537Syasuoka const char *
npppd_ppp_get_username_for_auth(npppd * _this,npppd_ppp * ppp,const char * username,char * username_buffer)23310fbf3537Syasuoka npppd_ppp_get_username_for_auth(npppd *_this, npppd_ppp *ppp,
23320fbf3537Syasuoka const char *username, char *username_buffer)
23330fbf3537Syasuoka {
23340fbf3537Syasuoka NPPPD_ASSERT(_this != NULL);
23350fbf3537Syasuoka NPPPD_ASSERT(ppp != NULL);
23360fbf3537Syasuoka NPPPD_ASSERT(ppp->realm != NULL);
23370fbf3537Syasuoka
23380fbf3537Syasuoka return npppd_auth_username_for_auth(ppp->realm, username,
23390fbf3537Syasuoka username_buffer);
23400fbf3537Syasuoka }
23410fbf3537Syasuoka
2342363e4d4bSyasuoka const char *
npppd_tunnel_protocol_name(int tunn_protocol)2343821f7c56Syasuoka npppd_tunnel_protocol_name(int tunn_protocol)
2344363e4d4bSyasuoka {
2345821f7c56Syasuoka switch (tunn_protocol) {
2346821f7c56Syasuoka case NPPPD_TUNNEL_NONE:
2347363e4d4bSyasuoka return "None";
2348821f7c56Syasuoka case NPPPD_TUNNEL_L2TP:
2349363e4d4bSyasuoka return "L2TP";
2350821f7c56Syasuoka case NPPPD_TUNNEL_PPTP:
2351363e4d4bSyasuoka return "PPTP";
2352821f7c56Syasuoka case NPPPD_TUNNEL_PPPOE:
2353363e4d4bSyasuoka return "PPPoE";
2354821f7c56Syasuoka case NPPPD_TUNNEL_SSTP:
2355363e4d4bSyasuoka return "SSTP";
2356363e4d4bSyasuoka }
2357363e4d4bSyasuoka
2358363e4d4bSyasuoka return "Error";
2359363e4d4bSyasuoka }
2360821f7c56Syasuoka
2361821f7c56Syasuoka const char *
npppd_ppp_tunnel_protocol_name(npppd * _this,npppd_ppp * ppp)2362821f7c56Syasuoka npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp)
2363821f7c56Syasuoka {
2364821f7c56Syasuoka return npppd_tunnel_protocol_name(ppp->tunnel_type);
2365821f7c56Syasuoka }
2366821f7c56Syasuoka
2367821f7c56Syasuoka struct tunnconf *
npppd_get_tunnconf(npppd * _this,const char * name)2368821f7c56Syasuoka npppd_get_tunnconf(npppd *_this, const char *name)
2369821f7c56Syasuoka {
2370821f7c56Syasuoka struct tunnconf *conf;
2371821f7c56Syasuoka
2372821f7c56Syasuoka TAILQ_FOREACH(conf, &_this->conf.tunnconfs, entry) {
2373821f7c56Syasuoka if (strcmp(conf->name, name) == 0)
2374821f7c56Syasuoka return conf;
2375821f7c56Syasuoka }
2376821f7c56Syasuoka
2377821f7c56Syasuoka return NULL;
2378821f7c56Syasuoka }
2379821f7c56Syasuoka
238034682664Syasuoka void
npppd_on_ppp_start(npppd * _this,npppd_ppp * ppp)238134682664Syasuoka npppd_on_ppp_start(npppd *_this, npppd_ppp *ppp)
238234682664Syasuoka {
238334682664Syasuoka struct ctl_conn *c;
238434682664Syasuoka
238534682664Syasuoka TAILQ_FOREACH(c, &ctl_conns, entry) {
238634682664Syasuoka if (npppd_ctl_add_started_ppp_id(c->ctx, ppp->id) == 0) {
238734682664Syasuoka npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
238834682664Syasuoka imsg_event_add(&c->iev);
238934682664Syasuoka }
239034682664Syasuoka }
239134682664Syasuoka }
239234682664Syasuoka
239334682664Syasuoka void
npppd_on_ppp_stop(npppd * _this,npppd_ppp * ppp)239434682664Syasuoka npppd_on_ppp_stop(npppd *_this, npppd_ppp *ppp)
239534682664Syasuoka {
239634682664Syasuoka struct ctl_conn *c;
239734682664Syasuoka
239834682664Syasuoka TAILQ_FOREACH(c, &ctl_conns, entry) {
239934682664Syasuoka if (npppd_ctl_add_stopped_ppp(c->ctx, ppp) == 0) {
240034682664Syasuoka npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf);
240134682664Syasuoka imsg_event_add(&c->iev);
240234682664Syasuoka }
240334682664Syasuoka }
240434682664Syasuoka }
240534682664Syasuoka
240634682664Syasuoka void
imsg_event_add(struct imsgev * iev)240734682664Syasuoka imsg_event_add(struct imsgev *iev)
240834682664Syasuoka {
240934682664Syasuoka iev->events = EV_READ;
241034682664Syasuoka if (iev->ibuf.w.queued)
241134682664Syasuoka iev->events |= EV_WRITE;
241234682664Syasuoka
241334682664Syasuoka event_del(&iev->ev);
241434682664Syasuoka event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
241534682664Syasuoka event_add(&iev->ev, NULL);
241634682664Syasuoka }
2417