File: | src/usr.sbin/npppd/npppd/npppd.c |
Warning: | line 723, column 8 Although the value stored to 'rval' is used in the enclosing expression, the value is never actually read from 'rval' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: npppd.c,v 1.52 2021/11/15 15:14:24 millert Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2005-2008,2009 Internet Initiative Japan Inc. |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. |
27 | */ |
28 | /**@file |
29 | * Next pppd(nppd). This file provides a npppd daemon process and operations |
30 | * for npppd instance. |
31 | * @author Yasuoka Masahiko |
32 | * $Id: npppd.c,v 1.52 2021/11/15 15:14:24 millert Exp $ |
33 | */ |
34 | #include "version.h" |
35 | #include <sys/param.h> /* ALIGNED_POINTER */ |
36 | #include <sys/types.h> |
37 | #include <sys/socket.h> |
38 | #include <sys/sysctl.h> |
39 | #include <sys/wait.h> |
40 | #include <netinet/in.h> |
41 | #include <netinet/ip.h> |
42 | #include <net/route.h> |
43 | #include <arpa/inet.h> |
44 | #include <net/if_dl.h> |
45 | #include <unistd.h> |
46 | #include <time.h> |
47 | #include <syslog.h> |
48 | #include <string.h> |
49 | #include <stdlib.h> |
50 | #include <stdio.h> |
51 | #include <signal.h> |
52 | #include <netdb.h> |
53 | #include <fcntl.h> |
54 | #include <event.h> |
55 | #include <errno(*__errno()).h> |
56 | #include <err.h> |
57 | #include <pwd.h> |
58 | |
59 | #include "pathnames.h" |
60 | #include "debugutil.h" |
61 | #include "addr_range.h" |
62 | #include "npppd_subr.h" |
63 | #include "npppd_local.h" |
64 | #include "npppd_auth.h" |
65 | #include "radish.h" |
66 | #include "net_utils.h" |
67 | #include "time_utils.h" |
68 | |
69 | #include "l2tp_local.h" /* XXX sa_cookie */ |
70 | |
71 | #ifdef USE_NPPPD_ARP |
72 | #include "npppd_arp.h" |
73 | #endif |
74 | |
75 | #ifdef USE_NPPPD_PIPEX1 |
76 | #ifdef USE_NPPPD_PPPOE1 |
77 | #include "pppoe_local.h" |
78 | #endif /* USE_NPPPD_PPPOE */ |
79 | #include "psm-opt.h" |
80 | #include <sys/ioctl.h> |
81 | #include <net/pipex.h> |
82 | #endif /* USE_NPPPD_PIPEX */ |
83 | |
84 | #include "accept.h" |
85 | #include "log.h" |
86 | |
87 | static npppd s_npppd; /* singleton */ |
88 | |
89 | static void npppd_reload0 (npppd *); |
90 | static void npppd_update_pool_reference (npppd *); |
91 | static int npppd_rd_walktree_delete(struct radish_head *); |
92 | static __dead__attribute__((__noreturn__)) void usage (void); |
93 | static void npppd_stop_really (npppd *); |
94 | static uint32_t str_hash(const void *, int); |
95 | static void npppd_on_sighup (int, short, void *); |
96 | static void npppd_on_sigterm (int, short, void *); |
97 | static void npppd_on_sigint (int, short, void *); |
98 | static void npppd_on_sigchld (int, short, void *); |
99 | static void npppd_reset_timer(npppd *); |
100 | static void npppd_timer(int, short, void *); |
101 | static void npppd_auth_finalizer_periodic(npppd *); |
102 | static int rd2slist_walk (struct radish *, void *); |
103 | static int rd2slist (struct radish_head *, slist *); |
104 | static slist *npppd_get_ppp_by_user (npppd *, const char *); |
105 | static int npppd_get_all_users (npppd *, slist *); |
106 | static struct ipcpstat |
107 | *npppd_get_ipcp_stat(struct ipcpstat_head *, const char *); |
108 | static void npppd_destroy_ipcp_stats(struct ipcpstat_head *); |
109 | static void npppd_ipcp_stats_reload(npppd *); |
110 | |
111 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
112 | static struct in_addr loop; /* initialize at npppd_init() */ |
113 | #endif |
114 | static uint32_t str_hash(const void *, int); |
115 | |
116 | #ifdef USE_NPPPD_PIPEX1 |
117 | static int npppd_ppp_pipex_ip_disable(npppd *, npppd_ppp *); |
118 | static void pipex_periodic(npppd *); |
119 | #endif /* USE_NPPPD_PIPEX */ |
120 | |
121 | #ifdef NPPPD_DEBUG |
122 | #define NPPPD_DBG(x) log_printf x |
123 | #define NPPPD_ASSERT(x) ASSERT(x)((void)0); |
124 | #else |
125 | #define NPPPD_DBG(x) |
126 | #define NPPPD_ASSERT(x) |
127 | #endif |
128 | |
129 | /*********************************************************************** |
130 | * Daemon process |
131 | ***********************************************************************/ |
132 | int main (int, char *[]); |
133 | int debugsyslog = 0; /* used by log.c */ |
134 | |
135 | int |
136 | main(int argc, char *argv[]) |
137 | { |
138 | int ch, stop_by_error, runasdaemon = 1, nflag = 0; |
139 | const char *npppd_conf0 = DEFAULT_NPPPD_CONF"/etc/npppd/npppd.conf"; |
140 | struct passwd *pw; |
141 | |
142 | while ((ch = getopt(argc, argv, "nf:d")) != -1) { |
143 | switch (ch) { |
144 | case 'n': |
145 | nflag = 1; |
146 | break; |
147 | case 'f': |
148 | npppd_conf0 = optarg; |
149 | break; |
150 | case 'd': |
151 | debuglevel++; |
152 | runasdaemon = 0; |
153 | break; |
154 | default: |
155 | usage(); |
156 | } |
157 | } |
158 | argc -= optind; |
159 | argv += optind; |
160 | if (argc != 0) |
161 | usage(); |
162 | if (nflag) { |
163 | debuglevel++; |
164 | runasdaemon = 0; |
165 | } |
166 | |
167 | /* for log.c */ |
168 | log_init(debuglevel); |
169 | if (debuglevel > 0) { |
170 | /* for ../common/debugutil.c */ |
171 | debug_set_debugfp(stderr(&__sF[2])); |
172 | debug_use_syslog(0); |
173 | } |
174 | if (runasdaemon) |
175 | daemon(0, 0); |
176 | |
177 | /* check for root privileges */ |
178 | if (geteuid()) |
179 | errx(1, "need root privileges"); |
180 | /* check for npppd user */ |
181 | if (getpwnam(NPPPD_USER"_ppp") == NULL((void *)0)) |
182 | errx(1, "unknown user %s", NPPPD_USER"_ppp"); |
183 | |
184 | if (privsep_init() != 0) |
185 | err(1, "cannot drop privileges"); |
186 | |
187 | if (nflag) { |
188 | if (npppd_config_check(npppd_conf0) == 0) { |
189 | fprintf(stderr(&__sF[2]), "configuration OK\n"); |
190 | exit(EXIT_SUCCESS0); |
191 | } |
192 | exit(EXIT_FAILURE1); |
193 | } |
194 | if (npppd_init(&s_npppd, npppd_conf0) != 0) |
195 | exit(EXIT_FAILURE1); |
196 | |
197 | if ((pw = getpwnam(NPPPD_USER"_ppp")) == NULL((void *)0)) |
198 | err(EXIT_FAILURE1, "gwpwnam"); |
199 | if (chroot(pw->pw_dir) == -1) |
200 | err(EXIT_FAILURE1, "chroot"); |
201 | if (chdir("/") == -1) |
202 | err(EXIT_FAILURE1, "chdir(\"/\")"); |
203 | if (setgroups(1, &pw->pw_gid) || |
204 | setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || |
205 | setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) |
206 | err(EXIT_FAILURE1, "cannot drop privileges"); |
207 | /* privileges is dropped */ |
208 | |
209 | npppd_start(&s_npppd); |
210 | stop_by_error = s_npppd.stop_by_error; |
211 | npppd_fini(&s_npppd); |
212 | privsep_fini(); |
213 | log_printf(LOG_NOTICE5, "Terminate npppd."); |
214 | |
215 | exit((!stop_by_error)? EXIT_SUCCESS0 : EXIT_FAILURE1); |
216 | } |
217 | |
218 | static __dead__attribute__((__noreturn__)) void |
219 | usage(void) |
220 | { |
221 | fprintf(stderr(&__sF[2]), "usage: npppd [-dn] [-f config_file]\n"); |
222 | exit(1); |
223 | } |
224 | |
225 | /** Returns the singleton npppd instance */ |
226 | npppd * |
227 | npppd_get_npppd() |
228 | { |
229 | return &s_npppd; |
230 | } |
231 | |
232 | /*********************************************************************** |
233 | * Operations to npppd itself (initialize/finalize/start/stop) |
234 | ***********************************************************************/ |
235 | /** Initialize the npppd */ |
236 | int |
237 | npppd_init(npppd *_this, const char *config_file) |
238 | { |
239 | int i, status = -1, value; |
240 | const char *pidpath0; |
241 | FILE *pidfp = NULL((void *)0); |
242 | struct tunnconf *tunn; |
243 | struct ipcpconf *ipcpconf; |
244 | struct ipcpstat *ipcpstat; |
245 | int mib[] = { CTL_NET4, PF_PIPEX35, PIPEXCTL_ENABLE1 }; |
246 | size_t size; |
247 | |
248 | memset(_this, 0, sizeof(npppd)); |
249 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
250 | loop.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ? (__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff ) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001)) ) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001 ))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)( 0x7f000001)))); |
251 | #endif |
252 | |
253 | NPPPD_ASSERT(config_file != NULL); |
254 | |
255 | pidpath0 = NULL((void *)0); |
256 | _this->pid = getpid(); |
257 | slist_init(&_this->realms); |
258 | npppd_conf_init(&_this->conf); |
259 | |
260 | log_printf(LOG_NOTICE5, "Starting npppd pid=%u version=%s", |
261 | _this->pid, VERSION"5.0.0"); |
262 | #if defined(BUILD_DATE) && defined(BUILD_TIME) |
263 | log_printf(LOG_INFO6, "Build %s %s ", BUILD_DATE, BUILD_TIME); |
264 | #endif |
265 | if (get_nanotime() == INT64_MIN(-0x7fffffffffffffffLL - 1)) { |
266 | log_printf(LOG_ERR3, "get_nanotime() failed: %m"); |
267 | return 1; |
268 | } |
269 | |
270 | if (realpath(config_file, _this->config_file) == NULL((void *)0)) { |
271 | log_printf(LOG_ERR3, "realpath(%s,) failed in %s(): %m", |
272 | config_file, __func__); |
273 | return 1; |
274 | } |
275 | /* we assume 4.4 compatible realpath(). See realpath(3) on BSD. */ |
276 | NPPPD_ASSERT(_this->config_file[0] == '/'); |
277 | |
278 | _this->boot_id = arc4random(); |
279 | |
280 | #ifdef USE_NPPPD_L2TP1 |
281 | if (l2tpd_init(&_this->l2tpd) != 0) |
282 | return (-1); |
283 | #endif |
284 | #ifdef USE_NPPPD_PPTP1 |
285 | if (pptpd_init(&_this->pptpd) != 0) |
286 | return (-1); |
287 | #endif |
288 | #ifdef USE_NPPPD_PPPOE1 |
289 | if (pppoed_init(&_this->pppoed) != 0) |
290 | return (-1); |
291 | #endif |
292 | LIST_INIT(&_this->ipcpstats)do { ((&_this->ipcpstats)->lh_first) = ((void *)0); } while (0); |
293 | |
294 | /* load configuration */ |
295 | if ((status = npppd_reload_config(_this)) != 0) |
296 | return status; |
297 | |
298 | TAILQ_FOREACH(tunn, &_this->conf.tunnconfs, entry)for((tunn) = ((&_this->conf.tunnconfs)->tqh_first); (tunn) != ((void *)0); (tunn) = ((tunn)->entry.tqe_next)) { |
299 | if (tunn->pipex) { |
300 | size = sizeof(value); |
301 | if (!sysctl(mib, nitems(mib)(sizeof((mib)) / sizeof((mib)[0])), &value, &size, NULL((void *)0), 0) |
302 | && value == 0) |
303 | log_printf(LOG_WARNING4, |
304 | "pipex(4) is disabled by sysctl"); |
305 | break; |
306 | } |
307 | } |
308 | |
309 | if ((_this->map_user_ppp = hash_create( |
310 | (int (*) (const void *, const void *))strcmp, str_hash, |
311 | NPPPD_USER_HASH_SIZ1777)) == NULL((void *)0)) { |
312 | log_printf(LOG_ERR3, "hash_create() failed in %s(): %m", |
313 | __func__); |
314 | return -1; |
315 | } |
316 | |
317 | if (npppd_ifaces_load_config(_this) != 0) { |
318 | return -1; |
319 | } |
320 | |
321 | TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry)for((ipcpconf) = ((&_this->conf.ipcpconfs)->tqh_first ); (ipcpconf) != ((void *)0); (ipcpconf) = ((ipcpconf)->entry .tqe_next)) { |
322 | ipcpstat = malloc(sizeof(*ipcpstat)); |
323 | if (ipcpstat == NULL((void *)0)) { |
324 | log_printf(LOG_ERR3, "initializing ipcp_stats failed : %m"); |
325 | npppd_destroy_ipcp_stats(&_this->ipcpstats); |
326 | return -1; |
327 | } |
328 | memset(ipcpstat, 0, sizeof(*ipcpstat)); |
329 | strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpstat->name)); |
330 | LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry)do { if (((ipcpstat)->entry.le_next = (&_this->ipcpstats )->lh_first) != ((void *)0)) (&_this->ipcpstats)-> lh_first->entry.le_prev = &(ipcpstat)->entry.le_next ; (&_this->ipcpstats)->lh_first = (ipcpstat); (ipcpstat )->entry.le_prev = &(&_this->ipcpstats)->lh_first ; } while (0); |
331 | } |
332 | |
333 | pidpath0 = DEFAULT_NPPPD_PIDFILE"/var/run/npppd.pid"; |
334 | |
335 | /* initialize event(3) */ |
336 | event_init(); |
337 | _this->ctl_sock.cs_name = NPPPD_SOCKET"/var/run/npppd.sock"; |
338 | _this->ctl_sock.cs_ctx = _this; |
339 | if (control_init(&_this->ctl_sock) == -1) { |
340 | log_printf(LOG_ERR3, "control_init() failed %s(): %m", |
341 | __func__); |
342 | return (-1); |
343 | } |
344 | if (control_listen(&_this->ctl_sock) == -1) { |
345 | log_printf(LOG_ERR3, "control_listen() failed %s(): %m", |
346 | __func__); |
347 | return (-1); |
348 | } |
349 | accept_init(); |
350 | |
351 | /* ignore signals */ |
352 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); |
353 | signal(SIGURG16, SIG_IGN(void (*)(int))1); |
354 | |
355 | /* set signal handlers */ |
356 | signal_set(&_this->ev_sigterm, SIGTERM, npppd_on_sigterm, _this)event_set(&_this->ev_sigterm, 15, 0x08|0x10, npppd_on_sigterm , _this); |
357 | signal_set(&_this->ev_sigint, SIGINT, npppd_on_sigint, _this)event_set(&_this->ev_sigint, 2, 0x08|0x10, npppd_on_sigint , _this); |
358 | signal_set(&_this->ev_sighup, SIGHUP, npppd_on_sighup, _this)event_set(&_this->ev_sighup, 1, 0x08|0x10, npppd_on_sighup , _this); |
359 | signal_set(&_this->ev_sigchld, SIGCHLD, npppd_on_sigchld, _this)event_set(&_this->ev_sigchld, 20, 0x08|0x10, npppd_on_sigchld , _this); |
360 | signal_add(&_this->ev_sigterm, NULL)event_add(&_this->ev_sigterm, ((void *)0)); |
361 | signal_add(&_this->ev_sigint, NULL)event_add(&_this->ev_sigint, ((void *)0)); |
362 | signal_add(&_this->ev_sighup, NULL)event_add(&_this->ev_sighup, ((void *)0)); |
363 | signal_add(&_this->ev_sigchld, NULL)event_add(&_this->ev_sigchld, ((void *)0)); |
364 | |
365 | evtimer_set(&_this->ev_timer, npppd_timer, _this)event_set(&_this->ev_timer, -1, 0, npppd_timer, _this); |
366 | |
367 | /* start tun(4) or pppac(4) */ |
368 | status = 0; |
369 | for (i = 0; i < countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])); i++) { |
370 | if (_this->iface[i].initialized != 0) |
371 | status |= npppd_iface_start(&_this->iface[i]); |
372 | } |
373 | if (status != 0) |
374 | return -1; |
375 | |
376 | /* |
377 | * If the npppd can start(open) interfaces successfully, it can |
378 | * act as only one npppd process on the system and overwrite the pid |
379 | * file. |
380 | */ |
381 | if ((pidfp = fopen(pidpath0, "w+")) == NULL((void *)0)) { |
382 | log_printf(LOG_ERR3, "fopen(%s,w+) failed in %s(): %m", |
383 | pidpath0, __func__); |
384 | return -1; |
385 | } |
386 | strlcpy(_this->pidpath, pidpath0, sizeof(_this->pidpath)); |
387 | fprintf(pidfp, "%u\n", _this->pid); |
388 | fclose(pidfp); |
389 | pidfp = NULL((void *)0); |
390 | #ifdef USE_NPPPD_ARP |
391 | arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); |
392 | if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) |
393 | arp_sock_init(); |
394 | #endif |
395 | if ((status = npppd_modules_reload(_this)) != 0) |
396 | return status; |
397 | |
398 | npppd_update_pool_reference(_this); |
399 | |
400 | return 0; |
401 | } |
402 | |
403 | /** start the npppd */ |
404 | void |
405 | npppd_start(npppd *_this) |
406 | { |
407 | int rval = 0; |
408 | |
409 | npppd_reset_timer(_this); |
410 | while ((rval = event_loop(EVLOOP_ONCE0x01)) == 0) { |
411 | if (_this->finalized != 0) |
412 | break; |
413 | } |
414 | if (rval != 0) { |
415 | log_printf(LOG_CRIT2, "event_loop() failed: %m"); |
416 | abort(); |
417 | } |
418 | } |
419 | |
420 | /** stop the npppd */ |
421 | void |
422 | npppd_stop(npppd *_this) |
423 | { |
424 | int i; |
425 | #ifdef USE_NPPPD_L2TP1 |
426 | l2tpd_stop(&_this->l2tpd); |
427 | #endif |
428 | #ifdef USE_NPPPD_PPTP1 |
429 | pptpd_stop(&_this->pptpd); |
430 | #endif |
431 | #ifdef USE_NPPPD_PPPOE1 |
432 | pppoed_stop(&_this->pppoed); |
433 | #endif |
434 | #ifdef USE_NPPPD_ARP |
435 | arp_sock_fini(); |
436 | #endif |
437 | close(_this->ctl_sock.cs_fd); |
438 | control_cleanup(&_this->ctl_sock); |
439 | |
440 | for (i = countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])) - 1; i >= 0; i--) { |
441 | if (_this->iface[i].initialized != 0) |
442 | npppd_iface_stop(&_this->iface[i]); |
443 | } |
444 | npppd_set_radish(_this, NULL((void *)0)); |
445 | |
446 | _this->finalizing = 1; |
447 | npppd_reset_timer(_this); |
448 | } |
449 | |
450 | static void |
451 | npppd_stop_really(npppd *_this) |
452 | { |
453 | int i; |
454 | #if defined(USE_NPPPD_L2TP1) || defined(USE_NPPPD_PPTP1) |
455 | int wait_again; |
456 | |
457 | wait_again = 0; |
458 | |
459 | #ifdef USE_NPPPD_L2TP1 |
460 | if (!l2tpd_is_stopped(&_this->l2tpd)(((&_this->l2tpd)->state != 2 && (&_this ->l2tpd)->state != 1)? 1 : 0)) |
461 | wait_again |= 1; |
462 | #endif |
463 | #ifdef USE_NPPPD_PPTP1 |
464 | if (!pptpd_is_stopped(&_this->pptpd)(((&_this->pptpd)->state != 2 && (&_this ->pptpd)->state != 1)? 1 : 0)) |
465 | wait_again |= 1; |
466 | #endif |
467 | if (wait_again != 0) { |
468 | npppd_reset_timer(_this); |
469 | return; |
470 | } |
471 | #endif |
472 | for (i = countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])) - 1; i >= 0; i--) { |
473 | npppd_iface_fini(&_this->iface[i]); |
474 | } |
475 | _this->finalized = 1; |
476 | } |
477 | |
478 | /** finalize the npppd */ |
479 | void |
480 | npppd_fini(npppd *_this) |
481 | { |
482 | int i; |
483 | npppd_auth_base *auth_base; |
484 | |
485 | #ifdef USE_NPPPD_L2TP1 |
486 | l2tpd_uninit(&_this->l2tpd); |
487 | #endif |
488 | #ifdef USE_NPPPD_PPTP1 |
489 | pptpd_uninit(&_this->pptpd); |
490 | #endif |
491 | #ifdef USE_NPPPD_PPPOE1 |
492 | pppoed_uninit(&_this->pppoed); |
493 | #endif |
494 | for (slist_itr_first(&_this->realms); |
495 | slist_itr_has_next(&_this->realms);) { |
496 | auth_base = slist_itr_next(&_this->realms); |
497 | npppd_auth_destroy(auth_base); |
498 | } |
499 | for (i = countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])) - 1; i >= 0; i--) { |
500 | if (_this->iface[i].initialized != 0) |
501 | npppd_iface_fini(&_this->iface[i]); |
502 | } |
503 | |
504 | for (i = countof(_this->pool)(sizeof(_this->pool) / sizeof((_this->pool)[0])) - 1; i >= 0; i--) { |
505 | if (_this->pool[i].initialized != 0) |
506 | npppd_pool_uninit(&_this->pool[i]); |
507 | } |
508 | |
509 | npppd_destroy_ipcp_stats(&_this->ipcpstats); |
510 | |
511 | signal_del(&_this->ev_sigterm)event_del(&_this->ev_sigterm); |
512 | signal_del(&_this->ev_sigint)event_del(&_this->ev_sigint); |
513 | signal_del(&_this->ev_sighup)event_del(&_this->ev_sighup); |
514 | signal_del(&_this->ev_sigchld)event_del(&_this->ev_sigchld); |
515 | |
516 | npppd_conf_fini(&_this->conf); |
517 | |
518 | slist_fini(&_this->realms); |
519 | |
520 | if (_this->map_user_ppp != NULL((void *)0)) |
521 | hash_free(_this->map_user_ppp); |
522 | } |
523 | |
524 | /*********************************************************************** |
525 | * Timer related functions |
526 | ***********************************************************************/ |
527 | static void |
528 | npppd_reset_timer(npppd *_this) |
529 | { |
530 | struct timeval tv; |
531 | |
532 | if (_this->finalizing != 0) { |
533 | /* we can use the timer exclusively on finalizing */ |
534 | tv.tv_usec = 500000; |
535 | tv.tv_sec = 0; |
536 | evtimer_add(&_this->ev_timer, &tv)event_add(&_this->ev_timer, &tv); |
537 | } else { |
538 | tv.tv_usec = 0; |
539 | tv.tv_sec = NPPPD_TIMER_TICK_IVAL4; |
540 | evtimer_add(&_this->ev_timer, &tv)event_add(&_this->ev_timer, &tv); |
541 | } |
542 | } |
543 | |
544 | static void |
545 | npppd_timer(int fd, short evtype, void *ctx) |
546 | { |
547 | npppd *_this; |
548 | |
549 | _this = ctx; |
550 | if (_this->finalizing != 0) { |
551 | npppd_stop_really(_this); /* The timer has been reset */ |
552 | return; /* we can use the timer exclusively on finalizing */ |
553 | } |
554 | _this->secs += NPPPD_TIMER_TICK_IVAL4; |
555 | if (_this->reloading_count > 0) { |
556 | _this->reloading_count -= NPPPD_TIMER_TICK_IVAL4; |
557 | if (_this->reloading_count <= 0) { |
558 | npppd_reload0(_this); |
559 | _this->reloading_count = 0; |
560 | } |
561 | } else { |
562 | if ((_this->secs % TIMER_TICK_RUP(((((300) % 4) == 0) ? (300) : (300) + 4 - ((300) % 4)) |
563 | NPPPD_AUTH_REALM_FINALIZER_INTERVAL)((((300) % 4) == 0) ? (300) : (300) + 4 - ((300) % 4))) == 0) |
564 | npppd_auth_finalizer_periodic(_this); |
565 | } |
566 | |
567 | #ifdef USE_NPPPD_PPPOE1 |
568 | if (pppoed_need_polling(&_this->pppoed)(((&_this->pppoed)->listen_incomplete != 0)? 1 : 0)) |
569 | pppoed_reload_listeners(&_this->pppoed); |
570 | #endif |
571 | #ifdef USE_NPPPD_PIPEX1 |
572 | pipex_periodic(_this); |
573 | #endif |
574 | |
575 | npppd_reset_timer(_this); |
576 | } |
577 | |
578 | int |
579 | npppd_reset_routing_table(npppd *_this, int pool_only) |
580 | { |
581 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
582 | slist rtlist0; |
583 | |
584 | if (_this->iface[0].using_pppx) |
585 | return 0; |
586 | |
587 | slist_init(&rtlist0); |
588 | if (rd2slist(_this->rd, &rtlist0) != 0) |
589 | return 1; |
590 | |
591 | for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0); ) { |
592 | struct radish *rd; |
593 | struct sockaddr_npppd *snp; |
594 | npppd_ppp *ppp; |
595 | int is_first; |
596 | |
597 | rd = slist_itr_next(&rtlist0); |
598 | snp = rd->rd_rtent; |
599 | |
600 | is_first = 1; |
601 | for (snp = rd->rd_rtent; snp != NULL((void *)0); snp = snp->snp_next) { |
602 | switch (snp->snp_type) { |
603 | case SNP_POOL1: |
604 | case SNP_DYN_POOL2: |
605 | if (is_first) |
606 | in_route_add(&snp->snp_addrsin4.sin_addr, |
607 | &snp->snp_masksin4mask.sin_addr, &loop, |
608 | LOOPBACK_IFNAME"lo0", RTF_BLACKHOLE0x1000, 0); |
609 | break; |
610 | |
611 | case SNP_PPP3: |
612 | if (pool_only) |
613 | break; |
614 | ppp = snp->snp_data_ptr; |
615 | if (ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr |
616 | == 0xffffffffL) { |
617 | in_host_route_add(&ppp-> |
618 | ppp_framed_ip_addresssnp.sin4.sin_addr, |
619 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr, |
620 | ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ifname, |
621 | MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
622 | } else { |
623 | in_route_add(&ppp-> |
624 | ppp_framed_ip_addresssnp.sin4.sin_addr, |
625 | &ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr, |
626 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr, |
627 | ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ifname, 0, |
628 | MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
629 | } |
630 | break; |
631 | } |
632 | is_first = 0; |
633 | } |
634 | |
635 | } |
636 | |
637 | slist_fini(&rtlist0); |
638 | #endif |
639 | return 0; |
640 | } |
641 | |
642 | /*********************************************************************** |
643 | * Other npppd related functions. |
644 | ***********************************************************************/ |
645 | /** |
646 | * Get the user's password. Return 0 on success. |
647 | * |
648 | * @param username Username who acquires password |
649 | * @param password A pointer to a buffer space to store the password. |
650 | * Use NULL when you need to know only the length of |
651 | * the password. |
652 | * @param plpassword A pointer to the length of the password parameter. |
653 | * This function uses this parameter value and stores |
654 | * the required length value pointed to by this |
655 | * parameter. Use NULL when use don't need to know |
656 | * the password and its length. |
657 | * @return If the function succeeds, 0 is returned. The function returns |
658 | * 1 if the username is unknown, returns 2 if the password buffer |
659 | * length is not enough. It returns negative value for other |
660 | * errors. |
661 | */ |
662 | int |
663 | npppd_get_user_password(npppd *_this, npppd_ppp *ppp, |
664 | const char *username, char *password, int *plpassword) |
665 | { |
666 | char buf0[MAX_USERNAME_LENGTH256]; |
667 | |
668 | NPPPD_ASSERT(ppp->realm != NULL); |
669 | return npppd_auth_get_user_password(ppp->realm, |
670 | npppd_auth_username_for_auth(ppp->realm, username, buf0), password, |
671 | plpassword); |
672 | } |
673 | |
674 | /** Get the Framed-IP-Address attribute of the user */ |
675 | struct in_addr * |
676 | npppd_get_user_framed_ip_address(npppd *_this, npppd_ppp *ppp, |
677 | const char *username) |
678 | { |
679 | |
680 | if (ppp->peer_auth == 0) { |
681 | ppp->realm_framed_ip_address.s_addr = 0; |
682 | goto do_default; |
683 | } |
684 | NPPPD_ASSERT(ppp->realm != NULL); |
685 | |
686 | if (ppp->realm_framed_ip_address.s_addr != 0) |
687 | return &ppp->realm_framed_ip_address; |
688 | |
689 | /* assign by the authentication realm */ |
690 | if (npppd_auth_get_framed_ip(ppp->realm, username, |
691 | &ppp->realm_framed_ip_address, |
692 | &ppp->realm_framed_ip_netmask) != 0) |
693 | ppp->realm_framed_ip_address.s_addr = 0; |
694 | |
695 | do_default: |
696 | /* Use USER_SELECT if the realm doesn't specify the ip address */ |
697 | if (ppp->realm_framed_ip_address.s_addr == 0) |
698 | ppp->realm_framed_ip_address.s_addr = INADDR_USER_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFFL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFFL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFFL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFFL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFFL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFFL))); |
699 | |
700 | |
701 | if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFFL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFFL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFFL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFFL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFFL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFFL)))) { |
702 | /* Use NAS_SELECT if USER_SELECT is not allowed by the config */ |
703 | if (!ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->allow_user_select) |
704 | ppp->realm_framed_ip_address.s_addr = INADDR_NAS_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFEL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFEL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFEL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFEL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFEL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFEL))); |
705 | } |
706 | NPPPD_DBG((LOG_DEBUG, "%s() = %s", __func__, |
707 | inet_ntoa(ppp->realm_framed_ip_address))); |
708 | |
709 | return &ppp->realm_framed_ip_address; |
710 | } |
711 | |
712 | /** XXX */ |
713 | int |
714 | npppd_check_calling_number(npppd *_this, npppd_ppp *ppp) |
715 | { |
716 | struct tunnconf *conf; |
717 | int lnumber, rval; |
718 | char number[NPPPD_PHONE_NUMBER_LEN32 + 1]; |
719 | |
720 | conf = ppp_get_tunnconf(ppp); |
721 | if (conf->callnum_check != 0) { |
722 | lnumber = sizeof(number); |
723 | if ((rval = npppd_auth_get_calling_number(ppp->realm, |
Although the value stored to 'rval' is used in the enclosing expression, the value is never actually read from 'rval' | |
724 | ppp->username, number, &lnumber)) == 0) |
725 | return |
726 | (strcmp(number, ppp->calling_number) == 0)? 1 : 0; |
727 | if ((conf->callnum_check & NPPPD_CALLNUM_CHECK_STRICT1) != 0) |
728 | return 0; |
729 | } |
730 | |
731 | return 1; |
732 | } |
733 | |
734 | /** |
735 | * This function finds a {@link npppd_ppp} instance that is assigned the |
736 | * specified ip address and returns it |
737 | * @param ipaddr IP Address(Specify in network byte order) |
738 | */ |
739 | npppd_ppp * |
740 | npppd_get_ppp_by_ip(npppd *_this, struct in_addr ipaddr) |
741 | { |
742 | struct sockaddr_npppd *snp; |
743 | struct radish *rdp; |
744 | struct sockaddr_in npppd_get_ppp_by_ip_sin4; |
745 | |
746 | npppd_get_ppp_by_ip_sin4.sin_family = AF_INET2; |
747 | npppd_get_ppp_by_ip_sin4.sin_len = sizeof(struct sockaddr_in); |
748 | npppd_get_ppp_by_ip_sin4.sin_addr = ipaddr; |
749 | if (_this->rd == NULL((void *)0)) |
750 | return NULL((void *)0); /* no radix tree on startup */ |
751 | if (rd_match((struct sockaddr *)&npppd_get_ppp_by_ip_sin4, _this->rd, |
752 | &rdp)) { |
753 | snp = rdp->rd_rtent; |
754 | if (snp->snp_type == SNP_PPP3) |
755 | return snp->snp_data_ptr; |
756 | } |
757 | return NULL((void *)0); |
758 | } |
759 | |
760 | /** |
761 | * This function finds {@link npppd_ppp} instances that are authenticated |
762 | * as the specified username and returns them as a {@link slist} list. |
763 | * @param username PPP Username. |
764 | * @return {@link slist} that contains the {@link npppd_ppp} instances. |
765 | * NULL may be returned if no instance has been found. |
766 | */ |
767 | static slist * |
768 | npppd_get_ppp_by_user(npppd *_this, const char *username) |
769 | { |
770 | hash_link *hl; |
771 | |
772 | if ((hl = hash_lookup(_this->map_user_ppp, username)) != NULL((void *)0)) |
773 | return hl->item; |
774 | |
775 | return NULL((void *)0); |
776 | } |
777 | |
778 | /** |
779 | * This function finds a {@link npppd_ppp} instance that matches the specified |
780 | * ppp id and returns it. |
781 | * @param id {@link npppd_ppp#id ppp's id} |
782 | * @return This function returns the pointer if the instance which has |
783 | * specified ID is found, otherwise it returns NULL. |
784 | */ |
785 | npppd_ppp * |
786 | npppd_get_ppp_by_id(npppd *_this, u_int ppp_id) |
787 | { |
788 | slist users; |
789 | npppd_ppp *ppp0, *ppp; |
790 | |
791 | NPPPD_ASSERT(_this != NULL); |
792 | |
793 | ppp = NULL((void *)0); |
794 | slist_init(&users); |
795 | if (npppd_get_all_users(_this, &users) != 0) { |
796 | log_printf(LOG_WARNING4, |
797 | "npppd_get_all_users() failed in %s()", __func__); |
798 | } else { |
799 | /* FIXME: This linear search eats CPU. */ |
800 | for (slist_itr_first(&users); slist_itr_has_next(&users); ) { |
801 | ppp0 = slist_itr_next(&users); |
802 | if (ppp0->id == ppp_id) { |
803 | ppp = ppp0; |
804 | break; |
805 | } |
806 | } |
807 | } |
808 | slist_fini(&users); |
809 | |
810 | return ppp; |
811 | } |
812 | |
813 | static struct ipcpstat * |
814 | npppd_get_ipcp_stat(struct ipcpstat_head *head , const char *ipcp_name) |
815 | { |
816 | struct ipcpstat *ipcpstat = NULL((void *)0); |
817 | |
818 | LIST_FOREACH(ipcpstat, head, entry)for((ipcpstat) = ((head)->lh_first); (ipcpstat)!= ((void * )0); (ipcpstat) = ((ipcpstat)->entry.le_next)) { |
819 | if (strncmp(ipcpstat->name, ipcp_name, |
820 | sizeof(ipcpstat->name)) == 0) |
821 | return ipcpstat; |
822 | } |
823 | |
824 | return NULL((void *)0); |
825 | } |
826 | |
827 | static void |
828 | npppd_destroy_ipcp_stats(struct ipcpstat_head *head) |
829 | { |
830 | struct ipcpstat *ipcpstat, *tipcpstat; |
831 | npppd_ppp *ppp, *tppp; |
832 | |
833 | LIST_FOREACH_SAFE(ipcpstat, head, entry, tipcpstat)for ((ipcpstat) = ((head)->lh_first); (ipcpstat) && ((tipcpstat) = ((ipcpstat)->entry.le_next), 1); (ipcpstat ) = (tipcpstat)) { |
834 | LIST_FOREACH_SAFE(ppp, &ipcpstat->ppp, ipcpstat_entry, tppp)for ((ppp) = ((&ipcpstat->ppp)->lh_first); (ppp) && ((tppp) = ((ppp)->ipcpstat_entry.le_next), 1); (ppp) = (tppp )) { |
835 | ppp->ipcpstat = NULL((void *)0); |
836 | LIST_REMOVE(ppp, ipcpstat_entry)do { if ((ppp)->ipcpstat_entry.le_next != ((void *)0)) (ppp )->ipcpstat_entry.le_next->ipcpstat_entry.le_prev = (ppp )->ipcpstat_entry.le_prev; *(ppp)->ipcpstat_entry.le_prev = (ppp)->ipcpstat_entry.le_next; ; ; } while (0); |
837 | } |
838 | free(ipcpstat); |
839 | } |
840 | } |
841 | |
842 | static void |
843 | npppd_ipcp_stats_reload(npppd *_this) |
844 | { |
845 | struct ipcpstat *ipcpstat, *tipcpstat; |
846 | struct ipcpconf *ipcpconf; |
847 | struct ipcpstat_head destroy_list; |
848 | |
849 | LIST_INIT(&destroy_list)do { ((&destroy_list)->lh_first) = ((void *)0); } while (0); |
850 | LIST_FOREACH_SAFE(ipcpstat, &_this->ipcpstats, entry, tipcpstat)for ((ipcpstat) = ((&_this->ipcpstats)->lh_first); ( ipcpstat) && ((tipcpstat) = ((ipcpstat)->entry.le_next ), 1); (ipcpstat) = (tipcpstat)) { |
851 | LIST_REMOVE(ipcpstat, entry)do { if ((ipcpstat)->entry.le_next != ((void *)0)) (ipcpstat )->entry.le_next->entry.le_prev = (ipcpstat)->entry. le_prev; *(ipcpstat)->entry.le_prev = (ipcpstat)->entry .le_next; ; ; } while (0); |
852 | LIST_INSERT_HEAD(&destroy_list, ipcpstat, entry)do { if (((ipcpstat)->entry.le_next = (&destroy_list)-> lh_first) != ((void *)0)) (&destroy_list)->lh_first-> entry.le_prev = &(ipcpstat)->entry.le_next; (&destroy_list )->lh_first = (ipcpstat); (ipcpstat)->entry.le_prev = & (&destroy_list)->lh_first; } while (0); |
853 | } |
854 | |
855 | TAILQ_FOREACH(ipcpconf, &_this->conf.ipcpconfs, entry)for((ipcpconf) = ((&_this->conf.ipcpconfs)->tqh_first ); (ipcpconf) != ((void *)0); (ipcpconf) = ((ipcpconf)->entry .tqe_next)) { |
856 | ipcpstat = npppd_get_ipcp_stat(&destroy_list, ipcpconf->name); |
857 | if (ipcpstat != NULL((void *)0)) { |
858 | LIST_REMOVE(ipcpstat, entry)do { if ((ipcpstat)->entry.le_next != ((void *)0)) (ipcpstat )->entry.le_next->entry.le_prev = (ipcpstat)->entry. le_prev; *(ipcpstat)->entry.le_prev = (ipcpstat)->entry .le_next; ; ; } while (0); |
859 | LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry)do { if (((ipcpstat)->entry.le_next = (&_this->ipcpstats )->lh_first) != ((void *)0)) (&_this->ipcpstats)-> lh_first->entry.le_prev = &(ipcpstat)->entry.le_next ; (&_this->ipcpstats)->lh_first = (ipcpstat); (ipcpstat )->entry.le_prev = &(&_this->ipcpstats)->lh_first ; } while (0); |
860 | continue; |
861 | } |
862 | |
863 | ipcpstat = malloc(sizeof(*ipcpstat)); |
864 | if (ipcpstat == NULL((void *)0)) { |
865 | log_printf(LOG_ERR3, "initializing ipcp_stats failed : %m"); |
866 | continue; |
867 | } |
868 | memset(ipcpstat, 0, sizeof(*ipcpstat)); |
869 | strlcpy(ipcpstat->name, ipcpconf->name, sizeof(ipcpconf->name)); |
870 | LIST_INSERT_HEAD(&_this->ipcpstats, ipcpstat, entry)do { if (((ipcpstat)->entry.le_next = (&_this->ipcpstats )->lh_first) != ((void *)0)) (&_this->ipcpstats)-> lh_first->entry.le_prev = &(ipcpstat)->entry.le_next ; (&_this->ipcpstats)->lh_first = (ipcpstat); (ipcpstat )->entry.le_prev = &(&_this->ipcpstats)->lh_first ; } while (0); |
871 | } |
872 | npppd_destroy_ipcp_stats(&destroy_list); |
873 | } |
874 | |
875 | /** |
876 | * Checks whether the user reaches the maximum session limit |
877 | * (user_max_serssion). |
878 | * @return This function returns 1(true) if the user does not reach the |
879 | * limit, otherwise it returns 0(false). |
880 | */ |
881 | int |
882 | npppd_check_user_max_session(npppd *_this, npppd_ppp *ppp) |
883 | { |
884 | int global_count, realm_count; |
885 | npppd_ppp *ppp1; |
886 | slist *uppp; |
887 | |
888 | /* user_max_session == 0 means unlimit */ |
889 | if (_this->conf.user_max_session == 0 && |
890 | npppd_auth_user_session_unlimited(ppp->realm)) |
891 | return 1; |
892 | |
893 | global_count = realm_count = 0; |
894 | if ((uppp = npppd_get_ppp_by_user(_this, ppp->username)) != NULL((void *)0)) { |
895 | for (slist_itr_first(uppp); slist_itr_has_next(uppp); ) { |
896 | ppp1 = slist_itr_next(uppp); |
897 | if (ppp->realm == ppp1->realm) |
898 | realm_count++; |
899 | global_count++; |
900 | } |
901 | } |
902 | |
903 | if (npppd_check_auth_user_max_session(ppp->realm, realm_count)) { |
904 | ppp_log(ppp, LOG_WARNING4, |
905 | "user %s exceeds user-max-session limit per auth", |
906 | ppp->username); |
907 | return 0; |
908 | } else if (_this->conf.user_max_session != 0 && |
909 | _this->conf.user_max_session <= global_count) { |
910 | ppp_log(ppp, LOG_WARNING4, |
911 | "user %s exceeds user-max-session limit", ppp->username); |
912 | return 0; |
913 | } else |
914 | return 1; |
915 | } |
916 | |
917 | /*********************************************************************** |
918 | * Network I/O ralated functions. |
919 | ***********************************************************************/ |
920 | /** |
921 | * Call this function to output packets to the network(tun). This function |
922 | * currently assumes the packet is a IPv4 datagram. |
923 | */ |
924 | void |
925 | npppd_network_output(npppd *_this, npppd_ppp *ppp, int proto, u_char *pktp, |
926 | int lpktp) |
927 | { |
928 | struct ip *pip; |
929 | int lbuf; |
930 | u_char buf[256]; /* enough size for TCP/IP header */ |
931 | |
932 | NPPPD_ASSERT(ppp != NULL); |
933 | |
934 | if (!ppp_ip_assigned(ppp)(ppp->snp.sin4.sin_addr.s_addr != 0)) |
935 | return; |
936 | |
937 | if (lpktp < sizeof(struct ip)) { |
938 | ppp_log(ppp, LOG_DEBUG7, "Received IP packet is too small"); |
939 | return; |
940 | } |
941 | lbuf = MINIMUM(lpktp, sizeof(buf))(((lpktp) < (sizeof(buf))) ? (lpktp) : (sizeof(buf))); |
942 | if (!ALIGNED_POINTER(pktp, struct ip)1) { |
943 | memcpy(buf, pktp, lbuf); |
944 | pip = (struct ip *)buf; |
945 | } else { |
946 | pip = (struct ip *)pktp; |
947 | } |
948 | |
949 | if (ppp->ingress_filter != 0 && |
950 | (pip->ip_src.s_addr & ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr) |
951 | != (ppp->ppp_framed_ip_addresssnp.sin4.sin_addr.s_addr & |
952 | ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr)) { |
953 | char logbuf[80]; |
954 | strlcpy(logbuf, inet_ntoa(pip->ip_dst), sizeof(logbuf)); |
955 | ppp_log(ppp, LOG_INFO6, |
956 | "Drop packet by ingress filter. %s => %s", |
957 | inet_ntoa(pip->ip_src), logbuf); |
958 | |
959 | return; |
960 | } |
961 | if (ppp->timeout_sec > 0 && !ip_is_idle_packet(pip, lbuf)) |
962 | ppp_reset_idle_timeout(ppp); |
963 | |
964 | #ifndef NO_ADJUST_MSS |
965 | if (ppp->adjust_mss) { |
966 | if (lpktp == lbuf) { |
967 | /* |
968 | * We can assume the packet length is less than |
969 | * sizeof(buf). |
970 | */ |
971 | if (!ALIGNED_POINTER(pktp, struct ip)1) |
972 | pktp = buf; |
973 | adjust_tcp_mss(pktp, lpktp, MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
974 | } |
975 | } |
976 | #endif |
977 | npppd_iface_write(ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx]), ppp, proto, pktp, lpktp); |
978 | } |
979 | |
980 | #ifdef USE_NPPPD_PIPEX1 |
981 | /*********************************************************************** |
982 | * PIPEX related functions |
983 | ***********************************************************************/ |
984 | static void |
985 | pipex_setup_common(npppd_ppp *ppp, struct pipex_session_req *req) |
986 | { |
987 | memset(req, 0, sizeof(*req)); |
988 | if (psm_opt_is_accepted(&ppp->lcp, acfc)(((&ppp->lcp)->opt.acfc & 0x02) != 0)) |
989 | req->pr_ppp_flags |= PIPEX_PPP_ACFC_ENABLED0x0004; |
990 | if (psm_peer_opt_is_accepted(&ppp->lcp, acfc)(((&ppp->lcp)->opt.acfc & 0x20) != 0)) |
991 | req->pr_ppp_flags |= PIPEX_PPP_ACFC_ACCEPTED0x0001; |
992 | |
993 | if (psm_peer_opt_is_accepted(&ppp->lcp, pfc)(((&ppp->lcp)->opt.pfc & 0x20) != 0)) |
994 | req->pr_ppp_flags |= PIPEX_PPP_PFC_ACCEPTED0x0002; |
995 | if (psm_opt_is_accepted(&ppp->lcp, pfc)(((&ppp->lcp)->opt.pfc & 0x02) != 0)) |
996 | req->pr_ppp_flags |= PIPEX_PPP_PFC_ENABLED0x0008; |
997 | |
998 | if (ppp->has_acf != 0) |
999 | req->pr_ppp_flags |= PIPEX_PPP_HAS_ACF0x0080; |
1000 | |
1001 | if (ppp->adjust_mss != 0) |
1002 | req->pr_ppp_flags |= PIPEX_PPP_ADJUST_TCPMSS0x0100; |
1003 | if (ppp->ingress_filter != 0) |
1004 | req->pr_ppp_flags |= PIPEX_PPP_INGRESS_FILTER0x0200; |
1005 | |
1006 | req->pr_ip_srcaddr = ppp->pppd->iface[0].ip4addr; |
1007 | req->pr_ip_address = ppp->ppp_framed_ip_addresssnp.sin4.sin_addr; |
1008 | req->pr_ip_netmask = ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr; |
1009 | req->pr_peer_mru = ppp->peer_mru; |
1010 | req->pr_ppp_id = ppp->id; |
1011 | |
1012 | req->pr_timeout_sec = ppp->timeout_sec; |
1013 | |
1014 | #ifdef USE_NPPPD_MPPE1 |
1015 | req->pr_ccp_id = ppp->ccp.fsm.id; |
1016 | if (ppp->mppe.send.keybits > 0) { |
1017 | memcpy(req->pr_mppe_send.master_key, |
1018 | ppp->mppe.send.master_key, |
1019 | sizeof(req->pr_mppe_send.master_key)); |
1020 | req->pr_mppe_send.stateless = ppp->mppe.send.stateless; |
1021 | req->pr_mppe_send.keylenbits = ppp->mppe.send.keybits; |
1022 | req->pr_ppp_flags |= PIPEX_PPP_MPPE_ENABLED0x0020; |
1023 | } |
1024 | if (ppp->mppe.recv.keybits > 0) { |
1025 | memcpy(req->pr_mppe_recv.master_key, |
1026 | ppp->mppe.recv.master_key, |
1027 | sizeof(req->pr_mppe_recv.master_key)); |
1028 | req->pr_mppe_recv.stateless = ppp->mppe.recv.stateless; |
1029 | req->pr_mppe_recv.keylenbits = ppp->mppe.recv.keybits; |
1030 | req->pr_ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED0x0010; |
1031 | } |
1032 | if (ppp->mppe.required) |
1033 | req->pr_ppp_flags |= PIPEX_PPP_MPPE_REQUIRED0x0040; |
1034 | #endif /* USE_NPPPD_MPPE */ |
1035 | } |
1036 | |
1037 | /** Enable PIPEX of the {@link npppd_ppp ppp} */ |
1038 | int |
1039 | npppd_ppp_pipex_enable(npppd *_this, npppd_ppp *ppp) |
1040 | { |
1041 | struct pipex_session_req req; |
1042 | #ifdef USE_NPPPD_PPPOE1 |
1043 | pppoe_session *pppoe; |
1044 | #endif |
1045 | #ifdef USE_NPPPD_PPTP1 |
1046 | pptp_call *call; |
1047 | #endif |
1048 | #ifdef USE_NPPPD_L2TP1 |
1049 | l2tp_call *l2tp; |
1050 | l2tp_ctrl *l2tpctrl; |
1051 | #endif |
1052 | int error; |
1053 | |
1054 | NPPPD_ASSERT(ppp != NULL); |
1055 | NPPPD_ASSERT(ppp->phy_context != NULL); |
1056 | NPPPD_ASSERT(ppp->use_pipex != 0); |
1057 | |
1058 | pipex_setup_common(ppp, &req); |
1059 | |
1060 | switch (ppp->tunnel_type) { |
1061 | #ifdef USE_NPPPD_PPPOE1 |
1062 | case NPPPD_TUNNEL_PPPOE3: |
1063 | { |
1064 | struct sockaddr *sa; |
1065 | struct ether_header *eh; |
1066 | pppoe = (pppoe_session *)ppp->phy_context; |
1067 | |
1068 | /* PPPoE specific information */ |
1069 | req.pr_protocol = PIPEX_PROTO_PPPOE3; |
1070 | req.pr_session_id = pppoe->session_id; |
1071 | req.pr_peer_session_id = 0; |
1072 | strlcpy(req.pr_proto.pppoe.over_ifname, |
1073 | pppoe_session_listen_ifname(pppoe)((pppoed_listener *)slist_get(&(pppoe)->pppoed->listener , (pppoe)->listener_index))->listen_ifname, |
1074 | sizeof(req.pr_proto.pppoe.over_ifname)); |
1075 | |
1076 | sa = (struct sockaddr *)&req.pr_peer_address; |
1077 | sa->sa_family = AF_UNSPEC0; |
1078 | sa->sa_len = sizeof(struct sockaddr); |
1079 | |
1080 | eh = (struct ether_header *)sa->sa_data; |
1081 | eh->ether_type = htons(ETHERTYPE_PPPOE)(__uint16_t)(__builtin_constant_p(0x8864) ? (__uint16_t)(((__uint16_t )(0x8864) & 0xffU) << 8 | ((__uint16_t)(0x8864) & 0xff00U) >> 8) : __swap16md(0x8864)); |
1082 | memcpy(eh->ether_dhost, pppoe->ether_addr, ETHER_ADDR_LEN6); |
1083 | memset(eh->ether_shost, 0, ETHER_ADDR_LEN6); |
1084 | |
1085 | break; |
1086 | } |
1087 | #endif |
1088 | #ifdef USE_NPPPD_PPTP1 |
1089 | case NPPPD_TUNNEL_PPTP2: |
1090 | call = (pptp_call *)ppp->phy_context; |
1091 | |
1092 | /* PPTP specific information */ |
1093 | req.pr_session_id = call->id; |
1094 | req.pr_protocol = PIPEX_PROTO_PPTP2; |
1095 | |
1096 | req.pr_peer_session_id = call->peers_call_id; |
1097 | req.pr_proto.pptp.snd_nxt = call->snd_nxt; |
1098 | req.pr_proto.pptp.snd_una = call->snd_una; |
1099 | req.pr_proto.pptp.rcv_nxt = call->rcv_nxt; |
1100 | req.pr_proto.pptp.rcv_acked = call->rcv_acked; |
1101 | req.pr_proto.pptp.winsz = call->winsz; |
1102 | req.pr_proto.pptp.maxwinsz = call->maxwinsz; |
1103 | req.pr_proto.pptp.peer_maxwinsz = call->peers_maxwinsz; |
1104 | |
1105 | NPPPD_ASSERT(call->ctrl->peer.ss_family == AF_INET); |
1106 | NPPPD_ASSERT(call->ctrl->our.ss_family == AF_INET); |
1107 | |
1108 | memcpy(&req.pr_peer_address, &call->ctrl->peer, |
1109 | call->ctrl->peer.ss_len); |
1110 | memcpy(&req.pr_local_address, &call->ctrl->our, |
1111 | call->ctrl->our.ss_len); |
1112 | break; |
1113 | #endif |
1114 | #ifdef USE_NPPPD_L2TP1 |
1115 | case NPPPD_TUNNEL_L2TP1: |
1116 | l2tp = (l2tp_call *)ppp->phy_context; |
1117 | l2tpctrl = l2tp->ctrl; |
1118 | |
1119 | /* L2TPv2 specific context */ |
1120 | /* Session KEYS */ |
1121 | req.pr_protocol = PIPEX_PROTO_L2TP1; |
1122 | req.pr_proto.l2tp.tunnel_id = l2tpctrl->tunnel_id; |
1123 | req.pr_proto.l2tp.peer_tunnel_id = l2tpctrl->peer_tunnel_id; |
1124 | req.pr_session_id = l2tp->session_id; |
1125 | req.pr_peer_session_id = l2tp->peer_session_id; |
1126 | |
1127 | if (l2tpctrl->data_use_seq) |
1128 | req.pr_proto.l2tp.option_flags |= |
1129 | PIPEX_L2TP_USE_SEQUENCING0x00000001; |
1130 | |
1131 | /* transmission control contexts */ |
1132 | req.pr_proto.l2tp.ns_nxt = l2tp->snd_nxt; |
1133 | req.pr_proto.l2tp.nr_nxt = l2tp->rcv_nxt; |
1134 | |
1135 | memcpy(&req.pr_peer_address, &l2tpctrl->peer, |
1136 | l2tpctrl->peer.ss_len); |
1137 | memcpy(&req.pr_local_address, &l2tpctrl->sock, |
1138 | l2tpctrl->sock.ss_len); |
1139 | #ifdef USE_SA_COOKIE1 |
1140 | if (l2tpctrl->sa_cookie != NULL((void *)0)) { |
1141 | req.pr_proto.l2tp.ipsecflowinfo = |
1142 | ((struct in_ipsec_sa_cookie *)l2tpctrl->sa_cookie) |
1143 | ->ipsecflow; |
1144 | } |
1145 | #endif |
1146 | break; |
1147 | #endif |
1148 | default: |
1149 | return 1; |
1150 | } |
1151 | |
1152 | if ((error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXASESSION((unsigned long)0x80000000 | ((sizeof(struct pipex_session_req ) & 0x1fff) << 16) | ((('p')) << 8) | ((3))), &req)) |
1153 | != 0) { |
1154 | if (errno(*__errno()) == ENXIO6) /* pipex is disabled on runtime */ |
1155 | error = 0; |
1156 | ppp->pipex_enabled = 0; |
1157 | return error; |
1158 | } |
1159 | |
1160 | if (_this->iface[ppp->ifidx].using_pppx) { |
1161 | struct pipex_session_descr_req descr_req; |
1162 | |
1163 | descr_req.pdr_protocol = req.pr_protocol; |
1164 | descr_req.pdr_session_id = req.pr_session_id; |
1165 | memset(descr_req.pdr_descr, 0, sizeof(descr_req.pdr_descr)); |
1166 | strlcpy(descr_req.pdr_descr, ppp->username, sizeof(descr_req.pdr_descr)); |
1167 | error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXSIFDESCR((unsigned long)0x80000000 | ((sizeof(struct pipex_session_descr_req ) & 0x1fff) << 16) | ((('p')) << 8) | ((8))), &descr_req); |
1168 | if (error != 0) { |
1169 | log_printf(LOG_WARNING4, "PIPEXSIFDESCR(%s) failed: %d\n", ppp->username, error); |
1170 | } |
1171 | } |
1172 | |
1173 | ppp->pipex_enabled = 1; |
1174 | if (ppp->timeout_sec > 0) { |
1175 | /* Stop the npppd's idle-timer. We use pipex's idle-timer */ |
1176 | ppp->timeout_sec = 0; |
1177 | ppp_reset_idle_timeout(ppp); |
1178 | } |
1179 | |
1180 | return error; |
1181 | } |
1182 | |
1183 | /** Disable PIPEX of the {@link npppd_ppp ppp} */ |
1184 | int |
1185 | npppd_ppp_pipex_disable(npppd *_this, npppd_ppp *ppp) |
1186 | { |
1187 | struct pipex_session_close_req req; |
1188 | #ifdef USE_NPPPD_PPPOE1 |
1189 | pppoe_session *pppoe; |
1190 | #endif |
1191 | #ifdef USE_NPPPD_PPTP1 |
1192 | pptp_call *call; |
1193 | #endif |
1194 | #ifdef USE_NPPPD_L2TP1 |
1195 | l2tp_call *l2tp; |
1196 | #endif |
1197 | int error; |
1198 | |
1199 | if (ppp->pipex_started == 0) |
1200 | return 0; /* not started */ |
1201 | |
1202 | bzero(&req, sizeof(req)); |
1203 | switch(ppp->tunnel_type) { |
1204 | #ifdef USE_NPPPD_PPPOE1 |
1205 | case NPPPD_TUNNEL_PPPOE3: |
1206 | pppoe = (pppoe_session *)ppp->phy_context; |
1207 | |
1208 | /* PPPoE specific information */ |
1209 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_PPPOE3; |
1210 | req.pcr_session_idpsr_session_id = pppoe->session_id; |
1211 | break; |
1212 | #endif |
1213 | #ifdef USE_NPPPD_PPTP1 |
1214 | case NPPPD_TUNNEL_PPTP2: |
1215 | call = (pptp_call *)ppp->phy_context; |
1216 | |
1217 | /* PPTP specific information */ |
1218 | req.pcr_session_idpsr_session_id = call->id; |
1219 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_PPTP2; |
1220 | break; |
1221 | #endif |
1222 | #ifdef USE_NPPPD_L2TP1 |
1223 | case NPPPD_TUNNEL_L2TP1: |
1224 | l2tp = (l2tp_call *)ppp->phy_context; |
1225 | |
1226 | /* L2TP specific context */ |
1227 | req.pcr_session_idpsr_session_id = l2tp->session_id; |
1228 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_L2TP1; |
1229 | break; |
1230 | #endif |
1231 | default: |
1232 | return 1; |
1233 | } |
1234 | |
1235 | error = ioctl(_this->iface[ppp->ifidx].devf, PIPEXDSESSION(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct pipex_session_close_req) & 0x1fff) << 16) | ((('p')) << 8) | ((4))), &req); |
1236 | if (error == 0) { |
1237 | ppp->ipackets += req.pcr_statpsr_stat.ipackets; |
1238 | ppp->opackets += req.pcr_statpsr_stat.opackets; |
1239 | ppp->ierrors += req.pcr_statpsr_stat.ierrors; |
1240 | ppp->oerrors += req.pcr_statpsr_stat.oerrors; |
1241 | ppp->ibytes += req.pcr_statpsr_stat.ibytes; |
1242 | ppp->obytes += req.pcr_statpsr_stat.obytes; |
1243 | ppp->pipex_enabled = 0; |
1244 | } |
1245 | |
1246 | return error; |
1247 | } |
1248 | |
1249 | /* XXX: s/npppd_ppp_pipex_ip_disable/npppd_ppp_pipex_stop/ ?? */ |
1250 | |
1251 | /** Stop PIPEX of the {@link npppd_ppp ppp} */ |
1252 | static int |
1253 | npppd_ppp_pipex_ip_disable(npppd *_this, npppd_ppp *ppp) |
1254 | { |
1255 | struct pipex_session_config_req req; |
1256 | #ifdef USE_NPPPD_PPPOE1 |
1257 | pppoe_session *pppoe; |
1258 | #endif |
1259 | #ifdef USE_NPPPD_PPTP1 |
1260 | pptp_call *call; |
1261 | #endif |
1262 | #ifdef USE_NPPPD_L2TP1 |
1263 | l2tp_call *l2tp; |
1264 | #endif |
1265 | if (ppp->pipex_started == 0) |
1266 | return 0; /* not started */ |
1267 | |
1268 | bzero(&req, sizeof(req)); |
1269 | switch(ppp->tunnel_type) { |
1270 | #ifdef USE_NPPPD_PPPOE1 |
1271 | case NPPPD_TUNNEL_PPPOE3: |
1272 | pppoe = (pppoe_session *)ppp->phy_context; |
1273 | |
1274 | /* PPPoE specific information */ |
1275 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_PPPOE3; |
1276 | req.pcr_session_idpsr_session_id = pppoe->session_id; |
1277 | break; |
1278 | #endif |
1279 | #ifdef USE_NPPPD_PPTP1 |
1280 | case NPPPD_TUNNEL_PPTP2: |
1281 | call = (pptp_call *)ppp->phy_context; |
1282 | |
1283 | /* PPTP specific information */ |
1284 | req.pcr_session_idpsr_session_id = call->id; |
1285 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_PPTP2; |
1286 | break; |
1287 | #endif |
1288 | #ifdef USE_NPPPD_L2TP1 |
1289 | case NPPPD_TUNNEL_L2TP1: |
1290 | l2tp = (l2tp_call *)ppp->phy_context; |
1291 | |
1292 | /* L2TP specific context */ |
1293 | req.pcr_session_idpsr_session_id = l2tp->session_id; |
1294 | req.pcr_protocolpsr_protocol = PIPEX_PROTO_L2TP1; |
1295 | break; |
1296 | #endif |
1297 | default: |
1298 | return 1; |
1299 | } |
1300 | req.pcr_ip_forward = 0; |
1301 | |
1302 | return ioctl(_this->iface[ppp->ifidx].devf, PIPEXCSESSION((unsigned long)0x80000000 | ((sizeof(struct pipex_session_config_req ) & 0x1fff) << 16) | ((('p')) << 8) | ((5))), &req); |
1303 | } |
1304 | |
1305 | static void |
1306 | pipex_periodic(npppd *_this) |
1307 | { |
1308 | struct pipex_session_list_req req; |
1309 | npppd_ppp *ppp; |
1310 | int i, devf, error; |
1311 | u_int ppp_id; |
1312 | slist dlist, users; |
1313 | |
1314 | slist_init(&dlist); |
1315 | slist_init(&users); |
1316 | |
1317 | devf = -1; |
1318 | for (i = 0; i < nitems(_this->iface)(sizeof((_this->iface)) / sizeof((_this->iface)[0])); i++) { |
1319 | if (_this->iface[i].initialized != 0) { |
1320 | devf = _this->iface[i].devf; |
1321 | break; |
1322 | } |
1323 | } |
1324 | if (devf >= 0) { |
1325 | do { |
1326 | error = ioctl(devf, PIPEXGCLOSED((unsigned long)0x40000000 | ((sizeof(struct pipex_session_list_req ) & 0x1fff) << 16) | ((('p')) << 8) | ((7))), &req); |
1327 | if (error) { |
1328 | if (errno(*__errno()) != ENXIO6) |
1329 | log_printf(LOG_WARNING4, |
1330 | "PIPEXGCLOSED failed: %m"); |
1331 | break; |
1332 | } |
1333 | for (i = 0; i < req.plr_ppp_id_count; i++) { |
1334 | ppp_id = req.plr_ppp_id[i]; |
1335 | slist_add(&dlist, (void *)(uintptr_t)ppp_id); |
1336 | } |
1337 | } while (req.plr_flags & PIPEX_LISTREQ_MORE0x01); |
1338 | } |
1339 | |
1340 | if (slist_length(&dlist) <= 0) |
1341 | goto pipex_done; |
1342 | if (npppd_get_all_users(_this, &users) != 0) { |
1343 | log_printf(LOG_WARNING4, |
1344 | "npppd_get_all_users() failed in %s()", __func__); |
1345 | slist_fini(&users); |
1346 | goto pipex_done; |
1347 | } |
1348 | |
1349 | /* Disconnect request */ |
1350 | slist_itr_first(&dlist); |
1351 | while (slist_itr_has_next(&dlist)) { |
1352 | /* FIXME: Linear search by PPP Id eats CPU */ |
1353 | ppp_id = (uintptr_t)slist_itr_next(&dlist); |
1354 | slist_itr_first(&users); |
1355 | ppp = NULL((void *)0); |
1356 | while (slist_itr_has_next(&users)) { |
1357 | ppp = slist_itr_next(&users); |
1358 | if (ppp_id == ppp->id) { |
1359 | /* found */ |
1360 | slist_itr_remove(&users); |
1361 | break; |
1362 | } |
1363 | ppp = NULL((void *)0); |
1364 | } |
1365 | if (ppp == NULL((void *)0)) { |
1366 | log_printf(LOG_WARNING4, |
1367 | "kernel requested a ppp down, but it's not found. " |
1368 | "ppp=%d", ppp_id); |
1369 | continue; |
1370 | } |
1371 | ppp_log(ppp, LOG_INFO6, "Stop requested by the kernel"); |
1372 | /* TODO: PIPEX doesn't return the disconnect reason */ |
1373 | #ifdef USE_NPPPD_RADIUS1 |
1374 | ppp_set_radius_terminate_cause(ppp, |
1375 | RADIUS_TERMNATE_CAUSE_IDLE_TIMEOUT4); |
1376 | #endif |
1377 | ppp_stop(ppp, NULL((void *)0)); |
1378 | } |
1379 | pipex_done: |
1380 | slist_fini(&users); |
1381 | slist_fini(&dlist); |
1382 | } |
1383 | #endif /* USE_NPPPD_PIPEX */ |
1384 | |
1385 | /*********************************************************************** |
1386 | * IP address assignment related functions |
1387 | ***********************************************************************/ |
1388 | /** Prepare to use IP */ |
1389 | int |
1390 | npppd_prepare_ip(npppd *_this, npppd_ppp *ppp) |
1391 | { |
1392 | |
1393 | if (ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf) == NULL((void *)0)) |
1394 | return 1; |
1395 | |
1396 | npppd_get_user_framed_ip_address(_this, ppp, ppp->username); |
1397 | |
1398 | if (npppd_iface_ip_is_ready(ppp_iface(ppp))(((&(ppp)->pppd->iface[(ppp)->ifidx]))->initialized != 0 && ((&(ppp)->pppd->iface[(ppp)->ifidx ]))->ip4addr.s_addr != ((u_int32_t)(0x00000000)))) |
1399 | ppp->ipcp.ip4_our = ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr; |
1400 | else if (npppd_iface_ip_is_ready(&_this->iface[0])((&_this->iface[0])->initialized != 0 && (& _this->iface[0])->ip4addr.s_addr != ((u_int32_t)(0x00000000 )))) |
1401 | ppp->ipcp.ip4_our = _this->iface[0].ip4addr; |
1402 | else |
1403 | return -1; |
1404 | ppp->ipcp.dns_pri = ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->dns_servers[0]; |
1405 | ppp->ipcp.dns_sec = ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->dns_servers[1]; |
1406 | ppp->ipcp.nbns_pri = ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->nbns_servers[0]; |
1407 | ppp->ipcp.nbns_sec = ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->nbns_servers[1]; |
1408 | |
1409 | return 0; |
1410 | } |
1411 | |
1412 | /** Notify stop using IP to npppd and release the resources. */ |
1413 | void |
1414 | npppd_release_ip(npppd *_this, npppd_ppp *ppp) |
1415 | { |
1416 | |
1417 | if (!ppp_ip_assigned(ppp)(ppp->snp.sin4.sin_addr.s_addr != 0)) |
1418 | return; |
1419 | |
1420 | npppd_set_ip_enabled(_this, ppp, 0); |
1421 | npppd_pool_release_ip(ppp->assigned_pool, ppp); |
1422 | ppp->assigned_pool = NULL((void *)0); |
1423 | ppp->ppp_framed_ip_addresssnp.sin4.sin_addr.s_addr = 0; |
1424 | } |
1425 | |
1426 | /** |
1427 | * Change IP enableness. When the enableness is change, npppd will operate |
1428 | * the route entry. |
1429 | */ |
1430 | void |
1431 | npppd_set_ip_enabled(npppd *_this, npppd_ppp *ppp, int enabled) |
1432 | { |
1433 | int was_enabled, found; |
1434 | slist *u; |
1435 | hash_link *hl; |
1436 | npppd_ppp *ppp1; |
1437 | |
1438 | NPPPD_ASSERT(ppp_ip_assigned(ppp)); |
1439 | NPPPD_DBG((LOG_DEBUG, |
1440 | "npppd_set_ip_enabled(%s/%s, %s)", ppp->username, |
1441 | inet_ntoa(ppp->ppp_framed_ip_address), |
1442 | (enabled)?"true" : "false")); |
1443 | |
1444 | /* |
1445 | * Don't do anything if the enableness is not change. Changing route |
1446 | * makes many programs will wake up and do heavy operations, it causes |
1447 | * system overload, so we refrain useless changing route. |
1448 | */ |
1449 | enabled = (enabled)? 1 : 0; |
1450 | was_enabled = (ppp->assigned_ip4_enabled != 0)? 1 : 0; |
1451 | if (enabled == was_enabled) |
1452 | return; |
1453 | |
1454 | ppp->assigned_ip4_enabled = enabled; |
1455 | if (enabled) { |
1456 | if (ppp->username[0] != '\0') { |
1457 | if ((u = npppd_get_ppp_by_user(_this, ppp->username)) |
1458 | == NULL((void *)0)) { |
1459 | if ((u = malloc(sizeof(slist))) == NULL((void *)0)) { |
1460 | ppp_log(ppp, LOG_ERR3, |
1461 | "Out of memory on %s: %m", |
1462 | __func__); |
1463 | } else { |
1464 | slist_init(u); |
1465 | slist_set_size(u, 4); |
1466 | hash_insert(_this->map_user_ppp, |
1467 | ppp->username, u); |
1468 | NPPPD_DBG((LOG_DEBUG, |
1469 | "hash_insert(user->ppp, %s)", |
1470 | ppp->username)); |
1471 | } |
1472 | } |
1473 | if (u != NULL((void *)0)) /* above malloc() may failed */ |
1474 | slist_add(u, ppp); |
1475 | } |
1476 | |
1477 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
1478 | if (_this->iface[ppp->ifidx].using_pppx == 0) { |
1479 | if (ppp->snp.snp_next != NULL((void *)0)) |
1480 | /* |
1481 | * There is a blackhole route that has same |
1482 | * address/mask. |
1483 | */ |
1484 | in_route_delete(&ppp->ppp_framed_ip_addresssnp.sin4.sin_addr, |
1485 | &ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr, &loop, |
1486 | RTF_BLACKHOLE0x1000); |
1487 | /* See the comment for MRU_IPMTU() on ppp.h */ |
1488 | if (ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr == 0xffffffffL) { |
1489 | in_host_route_add(&ppp->ppp_framed_ip_addresssnp.sin4.sin_addr, |
1490 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr, |
1491 | ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ifname, |
1492 | MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
1493 | } else { |
1494 | in_route_add(&ppp->ppp_framed_ip_addresssnp.sin4.sin_addr, |
1495 | &ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr, |
1496 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr, |
1497 | ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ifname, 0, |
1498 | MRU_IPMTU(ppp->peer_mru)(ppp->peer_mru)); |
1499 | } |
1500 | } |
1501 | #endif |
1502 | } else { |
1503 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
1504 | if (_this->iface[ppp->ifidx].using_pppx == 0) { |
1505 | if (ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr == 0xffffffffL) { |
1506 | in_host_route_delete(&ppp->ppp_framed_ip_addresssnp.sin4.sin_addr, |
1507 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr); |
1508 | } else { |
1509 | in_route_delete(&ppp->ppp_framed_ip_addresssnp.sin4.sin_addr, |
1510 | &ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr, |
1511 | &ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ip4addr, 0); |
1512 | } |
1513 | if (ppp->snp.snp_next != NULL((void *)0)) |
1514 | /* |
1515 | * There is a blackhole route that has same |
1516 | * address/mask. |
1517 | */ |
1518 | in_route_add(&ppp->snp.snp_addrsin4.sin_addr, |
1519 | &ppp->snp.snp_masksin4mask.sin_addr, &loop, LOOPBACK_IFNAME"lo0", |
1520 | RTF_BLACKHOLE0x1000, 0); |
1521 | } |
1522 | #endif |
1523 | if (ppp->username[0] != '\0') { |
1524 | hl = hash_lookup(_this->map_user_ppp, ppp->username); |
1525 | NPPPD_ASSERT(hl != NULL); |
1526 | if (hl == NULL((void *)0)) { |
1527 | ppp_log(ppp, LOG_ERR3, |
1528 | "Unexpected error: cannot find user(%s) " |
1529 | "from user database", ppp->username); |
1530 | return; |
1531 | } |
1532 | found = 0; |
1533 | u = hl->item; |
1534 | for (slist_itr_first(u); slist_itr_has_next(u);) { |
1535 | ppp1 = slist_itr_next(u); |
1536 | if (ppp1 == ppp) { |
1537 | slist_itr_remove(u); |
1538 | found++; |
1539 | break; |
1540 | } |
1541 | } |
1542 | if (found == 0) { |
1543 | ppp_log(ppp, LOG_ERR3, |
1544 | "Unexpected error: PPP instance is " |
1545 | "not found in the user's list."); |
1546 | } |
1547 | NPPPD_ASSERT(found != 0); |
1548 | if (slist_length(u) <= 0) { |
1549 | /* The last PPP */ |
1550 | NPPPD_DBG((LOG_DEBUG, |
1551 | "hash_delete(user->ppp, %s)", |
1552 | ppp->username)); |
1553 | if (hash_delete(_this->map_user_ppp, |
1554 | ppp->username, 0) != 0) { |
1555 | ppp_log(ppp, LOG_ERR3, |
1556 | "Unexpected error: cannot delete " |
1557 | "user(%s) from user database", |
1558 | ppp->username); |
1559 | } |
1560 | slist_fini(u); |
1561 | free(u); |
1562 | } else { |
1563 | /* Replace the reference. */ |
1564 | ppp1 = slist_get(u, 0); |
1565 | hl->key = ppp1->username; |
1566 | } |
1567 | } |
1568 | #ifdef USE_NPPPD_PIPEX1 |
1569 | if (npppd_ppp_pipex_ip_disable(_this, ppp) != 0) |
1570 | ppp_log(ppp, LOG_ERR3, |
1571 | "npppd_ppp_pipex_ip_disable() failed: %m"); |
1572 | #endif /* USE_NPPPD_PIPEX */ |
1573 | } |
1574 | } |
1575 | |
1576 | /** |
1577 | * Assign the IP address. Returning "struct in_addr" is stored IP address |
1578 | * in network byte order. |
1579 | * @param req_ip4 IP address request to assign. If the address is used |
1580 | * already, this function will return fail. |
1581 | */ |
1582 | int |
1583 | npppd_assign_ip_addr(npppd *_this, npppd_ppp *ppp, uint32_t req_ip4) |
1584 | { |
1585 | uint32_t ip4, ip4mask; |
1586 | int dyna, rval, fallback_dyna; |
1587 | const char *reason = "out of the pool"; |
1588 | struct sockaddr_npppd *snp; |
1589 | npppd_pool *pool; |
1590 | npppd_auth_base *realm; |
1591 | |
1592 | NPPPD_DBG((LOG_DEBUG, "%s() assigned=%s", __func__, |
1593 | (ppp_ip_assigned(ppp))? "true" : "false")); |
1594 | if (ppp_ip_assigned(ppp)(ppp->snp.sin4.sin_addr.s_addr != 0)) |
1595 | return 0; |
1596 | |
1597 | ip4 = INADDR_ANY((u_int32_t)(0x00000000)); |
1598 | ip4mask = 0xffffffffL; |
1599 | realm = ppp->realm; |
1600 | dyna = 0; |
1601 | fallback_dyna = 0; |
1602 | pool = NULL((void *)0); |
1603 | |
1604 | if (ppp->realm_framed_ip_address.s_addr == INADDR_USER_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFFL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFFL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFFL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFFL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFFL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFFL)))) { |
1605 | if (req_ip4 == INADDR_ANY((u_int32_t)(0x00000000))) |
1606 | dyna = 1; |
1607 | } else if (ppp->realm_framed_ip_address.s_addr == INADDR_NAS_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFEL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFEL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFEL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFEL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFEL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFEL)))) { |
1608 | dyna = 1; |
1609 | } else { |
1610 | NPPPD_ASSERT(realm != NULL); |
1611 | fallback_dyna = 1; |
1612 | req_ip4 = ntohl(ppp->realm_framed_ip_address.s_addr)(__uint32_t)(__builtin_constant_p(ppp->realm_framed_ip_address .s_addr) ? (__uint32_t)(((__uint32_t)(ppp->realm_framed_ip_address .s_addr) & 0xff) << 24 | ((__uint32_t)(ppp->realm_framed_ip_address .s_addr) & 0xff00) << 8 | ((__uint32_t)(ppp->realm_framed_ip_address .s_addr) & 0xff0000) >> 8 | ((__uint32_t)(ppp->realm_framed_ip_address .s_addr) & 0xff000000) >> 24) : __swap32md(ppp-> realm_framed_ip_address.s_addr)); |
1613 | ip4mask = ntohl(ppp->realm_framed_ip_netmask.s_addr)(__uint32_t)(__builtin_constant_p(ppp->realm_framed_ip_netmask .s_addr) ? (__uint32_t)(((__uint32_t)(ppp->realm_framed_ip_netmask .s_addr) & 0xff) << 24 | ((__uint32_t)(ppp->realm_framed_ip_netmask .s_addr) & 0xff00) << 8 | ((__uint32_t)(ppp->realm_framed_ip_netmask .s_addr) & 0xff0000) >> 8 | ((__uint32_t)(ppp->realm_framed_ip_netmask .s_addr) & 0xff000000) >> 24) : __swap32md(ppp-> realm_framed_ip_netmask.s_addr)); |
1614 | } |
1615 | if (!dyna) { |
1616 | /* |
1617 | * Realm requires the fixed IP address, but the address |
1618 | * doesn't belong any address pool. Fallback to dynamic |
1619 | * assignment. |
1620 | */ |
1621 | pool = ppp_pool(ppp)((ppp)->pppd->iface_pool[(ppp)->ifidx]); |
1622 | rval = npppd_pool_get_assignability(pool, req_ip4, ip4mask, |
1623 | &snp); |
1624 | switch (rval) { |
1625 | case ADDRESS_OK0: |
1626 | if (snp->snp_type == SNP_POOL1) { |
1627 | /* |
1628 | * Fixed address pool can be used only if the |
1629 | * realm specified to use it. |
1630 | */ |
1631 | if (ppp->realm_framed_ip_address |
1632 | .s_addr != INADDR_USER_SELECT((__uint32_t)(__builtin_constant_p(0xFFFFFFFFL) ? (__uint32_t )(((__uint32_t)(0xFFFFFFFFL) & 0xff) << 24 | ((__uint32_t )(0xFFFFFFFFL) & 0xff00) << 8 | ((__uint32_t)(0xFFFFFFFFL ) & 0xff0000) >> 8 | ((__uint32_t)(0xFFFFFFFFL) & 0xff000000) >> 24) : __swap32md(0xFFFFFFFFL)))) |
1633 | ip4 = req_ip4; |
1634 | break; |
1635 | } |
1636 | ppp->assign_dynapool = 1; |
1637 | ip4 = req_ip4; |
1638 | break; |
1639 | case ADDRESS_RESERVED1: |
1640 | reason = "reserved"; |
1641 | break; |
1642 | case ADDRESS_OUT_OF_POOL4: |
1643 | reason = "out of the pool"; |
1644 | break; |
1645 | case ADDRESS_BUSY2: |
1646 | fallback_dyna = 0; |
1647 | reason = "busy"; |
1648 | break; |
1649 | default: |
1650 | case ADDRESS_INVALID3: |
1651 | fallback_dyna = 0; |
1652 | reason = "invalid"; |
1653 | break; |
1654 | } |
1655 | #define IP_4OCT(v)((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16), ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v)) ((0xff000000 & (v)) >> 24), ((0x00ff0000 & (v)) >> 16),\ |
1656 | ((0x0000ff00 & (v)) >> 8), (0x000000ff & (v)) |
1657 | if (ip4 == 0) { |
1658 | ppp_log(ppp, LOG_NOTICE5, |
1659 | "Requested IP address (%d.%d.%d.%d)/%d " |
1660 | "is %s", IP_4OCT(req_ip4)((0xff000000 & (req_ip4)) >> 24), ((0x00ff0000 & (req_ip4)) >> 16), ((0x0000ff00 & (req_ip4)) >> 8), (0x000000ff & (req_ip4)), |
1661 | netmask2prefixlen(ip4mask), reason); |
1662 | if (fallback_dyna) |
1663 | goto dyna_assign; |
1664 | return 1; |
1665 | } |
1666 | ppp->assigned_pool = pool; |
1667 | |
1668 | ppp->ppp_framed_ip_addresssnp.sin4.sin_addr.s_addr = htonl(ip4)(__uint32_t)(__builtin_constant_p(ip4) ? (__uint32_t)(((__uint32_t )(ip4) & 0xff) << 24 | ((__uint32_t)(ip4) & 0xff00 ) << 8 | ((__uint32_t)(ip4) & 0xff0000) >> 8 | ((__uint32_t)(ip4) & 0xff000000) >> 24) : __swap32md (ip4)); |
1669 | ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr = htonl(ip4mask)(__uint32_t)(__builtin_constant_p(ip4mask) ? (__uint32_t)(((__uint32_t )(ip4mask) & 0xff) << 24 | ((__uint32_t)(ip4mask) & 0xff00) << 8 | ((__uint32_t)(ip4mask) & 0xff0000) >> 8 | ((__uint32_t)(ip4mask) & 0xff000000) >> 24) : __swap32md (ip4mask)); |
1670 | ppp->acct_framed_ip_address = ppp->ppp_framed_ip_addresssnp.sin4.sin_addr; |
1671 | } else { |
1672 | dyna_assign: |
1673 | pool = ppp_pool(ppp)((ppp)->pppd->iface_pool[(ppp)->ifidx]); |
1674 | ip4 = npppd_pool_get_dynamic(pool, ppp); |
1675 | if (ip4 == 0) { |
1676 | ppp_log(ppp, LOG_NOTICE5, |
1677 | "No free address in the pool."); |
1678 | return 1; |
1679 | } |
1680 | ppp->assigned_pool = pool; |
1681 | ppp->assign_dynapool = 1; |
1682 | ppp->ppp_framed_ip_addresssnp.sin4.sin_addr.s_addr = htonl(ip4)(__uint32_t)(__builtin_constant_p(ip4) ? (__uint32_t)(((__uint32_t )(ip4) & 0xff) << 24 | ((__uint32_t)(ip4) & 0xff00 ) << 8 | ((__uint32_t)(ip4) & 0xff0000) >> 8 | ((__uint32_t)(ip4) & 0xff000000) >> 24) : __swap32md (ip4)); |
1683 | ppp->ppp_framed_ip_netmasksnp.sin4mask.sin_addr.s_addr = htonl(0xffffffffL)(__uint32_t)(__builtin_constant_p(0xffffffffL) ? (__uint32_t) (((__uint32_t)(0xffffffffL) & 0xff) << 24 | ((__uint32_t )(0xffffffffL) & 0xff00) << 8 | ((__uint32_t)(0xffffffffL ) & 0xff0000) >> 8 | ((__uint32_t)(0xffffffffL) & 0xff000000) >> 24) : __swap32md(0xffffffffL)); |
1684 | ppp->acct_framed_ip_address = ppp->ppp_framed_ip_addresssnp.sin4.sin_addr; |
1685 | } |
1686 | |
1687 | return npppd_pool_assign_ip(ppp->assigned_pool, ppp); |
1688 | } |
1689 | |
1690 | static void * |
1691 | rtlist_remove(slist *prtlist, struct radish *radish) |
1692 | { |
1693 | struct radish *r; |
1694 | |
1695 | slist_itr_first(prtlist); |
1696 | while (slist_itr_has_next(prtlist)) { |
1697 | r = slist_itr_next(prtlist); |
1698 | if (!sockaddr_npppd_match(radish->rd_route, r->rd_route) || |
1699 | !sockaddr_npppd_match(radish->rd_mask, r->rd_mask)) |
1700 | continue; |
1701 | |
1702 | return slist_itr_remove(prtlist); |
1703 | } |
1704 | |
1705 | return NULL((void *)0); |
1706 | } |
1707 | |
1708 | /** Set {@link ::npppd#rd the only radish of npppd} */ |
1709 | int |
1710 | npppd_set_radish(npppd *_this, void *radish_head) |
1711 | { |
1712 | int rval, delppp0, count; |
1713 | struct sockaddr_npppd *snp; |
1714 | struct radish *radish, *r; |
1715 | slist rtlist0, rtlist1, delppp; |
1716 | npppd_ppp *ppp; |
1717 | void *dummy; |
1718 | |
1719 | slist_init(&rtlist0); |
1720 | slist_init(&rtlist1); |
1721 | slist_init(&delppp); |
1722 | |
1723 | if (radish_head != NULL((void *)0)) { |
1724 | if (rd2slist(radish_head, &rtlist1) != 0) { |
1725 | log_printf(LOG_WARNING4, "rd2slist failed: %m"); |
1726 | goto fail; |
1727 | } |
1728 | } |
1729 | if (_this->rd != NULL((void *)0)) { |
1730 | if (rd2slist(_this->rd, &rtlist0) != 0) { |
1731 | log_printf(LOG_WARNING4, "rd2slist failed: %m"); |
1732 | goto fail; |
1733 | } |
1734 | } |
1735 | if (_this->rd != NULL((void *)0) && radish_head != NULL((void *)0)) { |
1736 | for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { |
1737 | radish = slist_itr_next(&rtlist0); |
1738 | snp = radish->rd_rtent; |
1739 | /* |
1740 | * replace the pool address |
1741 | */ |
1742 | if (snp->snp_type == SNP_POOL1 || |
1743 | snp->snp_type == SNP_DYN_POOL2) { |
1744 | if (rd_lookup(radish->rd_route, radish->rd_mask, |
1745 | radish_head) == NULL((void *)0)) |
1746 | continue; |
1747 | /* don't add */ |
1748 | rtlist_remove(&rtlist1, radish); |
1749 | /* don't delete */ |
1750 | slist_itr_remove(&rtlist0); |
1751 | continue; |
1752 | } |
1753 | /* |
1754 | * handle the active PPP sessions. |
1755 | */ |
1756 | NPPPD_ASSERT(snp->snp_type == SNP_PPP); |
1757 | ppp = snp->snp_data_ptr; |
1758 | |
1759 | /* Don't delete the route of active PPP session */ |
1760 | slist_itr_remove(&rtlist0); |
1761 | |
1762 | /* clear information about old pool configuration */ |
1763 | snp->snp_next = NULL((void *)0); |
1764 | |
1765 | delppp0 = 0; |
1766 | if (!rd_match((struct sockaddr *)snp, radish_head, &r)){ |
1767 | /* |
1768 | * If the address doesn't belong the new pools, |
1769 | * add the PPP session to the deletion list. |
1770 | */ |
1771 | slist_add(&delppp, snp->snp_data_ptr); |
1772 | delppp0 = 1; |
1773 | } else { |
1774 | NPPPD_ASSERT( |
1775 | ((struct sockaddr_npppd *)r->rd_rtent) |
1776 | ->snp_type == SNP_POOL || |
1777 | ((struct sockaddr_npppd *)r->rd_rtent) |
1778 | ->snp_type == SNP_DYN_POOL); |
1779 | /* |
1780 | * If there is a pool entry that has same |
1781 | * address/mask, then make the RADISH entry a |
1782 | * list. Set SNP_PPP as the first in the list, |
1783 | * set current entry in snp->snp_next and |
1784 | * delete it. |
1785 | */ |
1786 | if (sockaddr_npppd_match( |
1787 | radish->rd_route, r->rd_route) && |
1788 | sockaddr_npppd_match( |
1789 | radish->rd_mask, r->rd_mask)) { |
1790 | /* |
1791 | * Releasing it, so remove it from the |
1792 | * new routing list. |
1793 | */ |
1794 | rtlist_remove(&rtlist1, radish); |
1795 | /* set as snp_snp_next */ |
1796 | snp->snp_next = r->rd_rtent; |
1797 | rval = rd_delete(r->rd_route, |
1798 | r->rd_mask, radish_head, &dummy); |
1799 | NPPPD_ASSERT(rval == 0); |
1800 | } |
1801 | } |
1802 | /* Register to the new radish */ |
1803 | rval = rd_insert(radish->rd_route, radish->rd_mask, |
1804 | radish_head, snp); |
1805 | if (rval != 0) { |
1806 | errno(*__errno()) = rval; |
1807 | ppp_log(((npppd_ppp *)snp->snp_data_ptr), |
1808 | LOG_ERR3, |
1809 | "Fatal error on %s, cannot continue " |
1810 | "this ppp session: %m", __func__); |
1811 | if (!delppp0) |
1812 | slist_add(&delppp, snp->snp_data_ptr); |
1813 | } |
1814 | } |
1815 | } |
1816 | count = 0; |
1817 | #ifndef NO_ROUTE_FOR_POOLED_ADDRESS |
1818 | if (_this->iface[0].using_pppx == 0) { |
1819 | for (slist_itr_first(&rtlist0); slist_itr_has_next(&rtlist0);) { |
1820 | radish = slist_itr_next(&rtlist0); |
1821 | in_route_delete(&SIN(radish->rd_route)((struct sockaddr_in *)(radish->rd_route))->sin_addr, |
1822 | &SIN(radish->rd_mask)((struct sockaddr_in *)(radish->rd_mask))->sin_addr, &loop, |
1823 | RTF_BLACKHOLE0x1000); |
1824 | count++; |
1825 | } |
1826 | if (count > 0) |
1827 | log_printf(LOG_INFO6, |
1828 | "Deleted %d routes for old pool addresses", count); |
1829 | |
1830 | count = 0; |
1831 | for (slist_itr_first(&rtlist1); slist_itr_has_next(&rtlist1);) { |
1832 | radish = slist_itr_next(&rtlist1); |
1833 | in_route_add(&(SIN(radish->rd_route)((struct sockaddr_in *)(radish->rd_route))->sin_addr), |
1834 | &SIN(radish->rd_mask)((struct sockaddr_in *)(radish->rd_mask))->sin_addr, &loop, |
1835 | LOOPBACK_IFNAME"lo0", RTF_BLACKHOLE0x1000, 0); |
1836 | count++; |
1837 | } |
1838 | if (count > 0) |
1839 | log_printf(LOG_INFO6, |
1840 | "Added %d routes for new pool addresses", |
1841 | count); |
1842 | } |
1843 | #endif |
1844 | slist_fini(&rtlist0); |
1845 | slist_fini(&rtlist1); |
1846 | |
1847 | if (_this->rd != NULL((void *)0)) { |
1848 | npppd_rd_walktree_delete(_this->rd); |
1849 | _this->rd = NULL((void *)0); |
1850 | } |
1851 | if (radish_head == NULL((void *)0)) |
1852 | npppd_get_all_users(_this, &delppp); |
1853 | _this->rd = radish_head; |
1854 | |
1855 | for (slist_itr_first(&delppp); slist_itr_has_next(&delppp);) { |
1856 | ppp = slist_itr_next(&delppp); |
1857 | ppp_log(ppp, LOG_NOTICE5, |
1858 | "stop. IP address of this ppp is out of the pool.: %s", |
1859 | inet_ntoa(ppp->ppp_framed_ip_addresssnp.sin4.sin_addr)); |
1860 | ppp_stop(ppp, NULL((void *)0)); |
1861 | } |
1862 | slist_fini(&delppp); |
1863 | |
1864 | return 0; |
1865 | fail: |
1866 | slist_fini(&rtlist0); |
1867 | slist_fini(&rtlist1); |
1868 | slist_fini(&delppp); |
1869 | |
1870 | return 1; |
1871 | } |
1872 | |
1873 | /** |
1874 | * This function stores all users to {@link slist} and returns them. |
1875 | * References to {@link ::npppd_ppp} will be stored in users. |
1876 | */ |
1877 | static int |
1878 | npppd_get_all_users(npppd *_this, slist *users) |
1879 | { |
1880 | int rval; |
1881 | struct radish *rd; |
1882 | struct sockaddr_npppd *snp; |
1883 | slist list; |
1884 | |
1885 | NPPPD_ASSERT(_this != NULL); |
1886 | |
1887 | slist_init(&list); |
1888 | if (_this->rd == NULL((void *)0)) |
1889 | return 0; |
1890 | rval = rd2slist(_this->rd, &list); |
1891 | if (rval != 0) |
1892 | return rval; |
1893 | |
1894 | for (slist_itr_first(&list); slist_itr_has_next(&list);) { |
1895 | rd = slist_itr_next(&list); |
1896 | snp = rd->rd_rtent; |
1897 | if (snp->snp_type == SNP_PPP3) { |
1898 | if (slist_add(users, snp->snp_data_ptr) == NULL((void *)0)) { |
1899 | log_printf(LOG_ERR3, |
1900 | "slist_add() failed in %s: %m", __func__); |
1901 | goto fail; |
1902 | } |
1903 | } |
1904 | } |
1905 | slist_fini(&list); |
1906 | |
1907 | return 0; |
1908 | fail: |
1909 | slist_fini(&list); |
1910 | |
1911 | return 1; |
1912 | } |
1913 | |
1914 | static int |
1915 | rd2slist_walk(struct radish *rd, void *list0) |
1916 | { |
1917 | slist *list = list0; |
1918 | void *r; |
1919 | |
1920 | r = slist_add(list, rd); |
1921 | if (r == NULL((void *)0)) |
1922 | return -1; |
1923 | return 0; |
1924 | } |
1925 | static int |
1926 | rd2slist(struct radish_head *h, slist *list) |
1927 | { |
1928 | return rd_walktree(h, rd2slist_walk, list); |
1929 | } |
1930 | |
1931 | static void |
1932 | npppd_reload0(npppd *_this) |
1933 | { |
1934 | int i; |
1935 | |
1936 | npppd_reload_config(_this); |
1937 | #ifdef USE_NPPPD_ARP |
1938 | arp_set_strictintfnetwork(npppd_config_str_equali(_this, "arpd.strictintfnetwork", "true", ARPD_STRICTINTFNETWORK_DEFAULT)); |
1939 | if (npppd_config_str_equali(_this, "arpd.enabled", "true", ARPD_DEFAULT) == 1) |
1940 | arp_sock_init(); |
1941 | else |
1942 | arp_sock_fini(); |
1943 | #endif |
1944 | npppd_modules_reload(_this); |
1945 | npppd_ifaces_load_config(_this); |
1946 | npppd_update_pool_reference(_this); |
1947 | npppd_auth_finalizer_periodic(_this); |
1948 | npppd_ipcp_stats_reload(_this); |
1949 | |
1950 | for (i = 0; i < countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])); i++) { |
1951 | if (_this->iface[i].initialized != 0 && |
1952 | _this->iface[i].started == 0) |
1953 | npppd_iface_start(&_this->iface[i]); |
1954 | } |
1955 | } |
1956 | |
1957 | static void |
1958 | npppd_update_pool_reference(npppd *_this) |
1959 | { |
1960 | int i, j; |
1961 | /* update iface to pool reference */ |
1962 | for (i = 0; i < countof(_this->iface_pool)(sizeof(_this->iface_pool) / sizeof((_this->iface_pool) [0])); i++) { |
1963 | _this->iface_pool[i] = NULL((void *)0); |
1964 | if (_this->iface[i].initialized == 0) |
1965 | continue; |
1966 | if (_this->iface[i].ipcpconf == NULL((void *)0)) |
1967 | continue; /* no IPCP for this interface */ |
1968 | |
1969 | for (j = 0; j < countof(_this->pool)(sizeof(_this->pool) / sizeof((_this->pool)[0])); j++) { |
1970 | if (_this->pool[j].initialized == 0) |
1971 | continue; |
1972 | if (strcmp(_this->iface[i].ipcpconf->name, |
1973 | _this->pool[j].ipcp_name) == 0) { |
1974 | /* found the ipcp that has the pool */ |
1975 | _this->iface_pool[i] = &_this->pool[j]; |
1976 | break; |
1977 | } |
1978 | } |
1979 | } |
1980 | } |
1981 | |
1982 | /*********************************************************************** |
1983 | * Signal handlers |
1984 | ***********************************************************************/ |
1985 | static void |
1986 | npppd_on_sighup(int fd, short ev_type, void *ctx) |
1987 | { |
1988 | npppd *_this; |
1989 | |
1990 | _this = ctx; |
1991 | #ifndef NO_DELAYED_RELOAD |
1992 | if (_this->delayed_reload > 0) |
1993 | _this->reloading_count = _this->delayed_reload; |
1994 | else |
1995 | #endif |
1996 | npppd_reload0(_this); |
1997 | } |
1998 | |
1999 | static void |
2000 | npppd_on_sigterm(int fd, short ev_type, void *ctx) |
2001 | { |
2002 | npppd *_this; |
2003 | |
2004 | _this = ctx; |
2005 | npppd_stop(_this); |
2006 | } |
2007 | |
2008 | static void |
2009 | npppd_on_sigint(int fd, short ev_type, void *ctx) |
2010 | { |
2011 | npppd *_this; |
2012 | |
2013 | _this = ctx; |
2014 | npppd_stop(_this); |
2015 | } |
2016 | |
2017 | static void |
2018 | npppd_on_sigchld(int fd, short ev_type, void *ctx) |
2019 | { |
2020 | int status; |
2021 | pid_t wpid; |
2022 | npppd *_this; |
2023 | |
2024 | _this = ctx; |
2025 | wpid = privsep_priv_pid(); |
2026 | if (wait4(wpid, &status, WNOHANG1, NULL((void *)0)) == wpid) { |
2027 | if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177 ) != 0)) |
2028 | log_printf(LOG_WARNING4, |
2029 | "privileged process exits abnormally. signal=%d", |
2030 | WTERMSIG(status)(((status) & 0177))); |
2031 | else |
2032 | log_printf(LOG_WARNING4, |
2033 | "privileged process exits abnormally. status=%d", |
2034 | WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff)); |
2035 | _this->stop_by_error = 1; |
2036 | npppd_stop(_this); |
2037 | } |
2038 | } |
2039 | /*********************************************************************** |
2040 | * Miscellaneous functions |
2041 | ***********************************************************************/ |
2042 | static uint32_t |
2043 | str_hash(const void *ptr, int sz) |
2044 | { |
2045 | uint32_t hash = 0; |
2046 | int i, len; |
2047 | const char *str; |
2048 | |
2049 | str = ptr; |
2050 | len = strlen(str); |
2051 | for (i = 0; i < len; i++) |
2052 | hash = hash*0x1F + str[i]; |
2053 | hash = (hash << 16) ^ (hash & 0xffff); |
2054 | |
2055 | return hash % sz; |
2056 | } |
2057 | |
2058 | /** |
2059 | * Select a authentication realm that is for given {@link ::npppd_ppp PPP}. |
2060 | * Return 0 on success. |
2061 | */ |
2062 | int |
2063 | npppd_ppp_bind_realm(npppd *_this, npppd_ppp *ppp, const char *username, int |
2064 | eap_required) |
2065 | { |
2066 | struct confbind *bind; |
2067 | npppd_auth_base *realm = NULL((void *)0), *realm0 = NULL((void *)0), *realm1 = NULL((void *)0); |
2068 | char buf1[MAX_USERNAME_LENGTH256]; |
2069 | int lsuffix, lusername, lmax; |
2070 | |
2071 | NPPPD_ASSERT(_this != NULL); |
2072 | NPPPD_ASSERT(ppp != NULL); |
2073 | NPPPD_ASSERT(username != NULL); |
2074 | |
2075 | /* |
2076 | * If the PPP suffix is the longest, and the length of the suffix is |
2077 | * same, select the first one. |
2078 | */ |
2079 | lusername = strlen(username); |
2080 | lmax = -1; |
2081 | realm = NULL((void *)0); |
2082 | |
2083 | TAILQ_FOREACH(bind, &_this->conf.confbinds, entry)for((bind) = ((&_this->conf.confbinds)->tqh_first); (bind) != ((void *)0); (bind) = ((bind)->entry.tqe_next)) { |
2084 | if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) |
2085 | continue; |
2086 | |
2087 | realm0 = NULL((void *)0); |
2088 | slist_itr_first(&_this->realms); |
2089 | while (slist_itr_has_next(&_this->realms)) { |
2090 | realm1 = slist_itr_next(&_this->realms); |
2091 | if (!npppd_auth_is_usable(realm1)) |
2092 | continue; |
2093 | if (eap_required && !npppd_auth_is_eap_capable(realm1)) |
2094 | continue; |
2095 | if (strcmp(npppd_auth_get_name(realm1), |
2096 | bind->authconf->name) == 0) { |
2097 | realm0 = realm1; |
2098 | break; |
2099 | } |
2100 | } |
2101 | if (realm0 == NULL((void *)0)) |
2102 | continue; |
2103 | |
2104 | lsuffix = strlen(npppd_auth_get_suffix(realm0)); |
2105 | if (lsuffix > lmax && |
2106 | (lsuffix == 0 || |
2107 | (lsuffix < lusername && strcmp(username + lusername |
2108 | - lsuffix, npppd_auth_get_suffix(realm0)) |
2109 | == 0))) { |
2110 | lmax = lsuffix; |
2111 | realm = realm0; |
2112 | } |
2113 | } |
2114 | |
2115 | if (realm == NULL((void *)0)) { |
2116 | log_printf(LOG_INFO6, "user='%s' could not bind any realms", |
2117 | username); |
2118 | return 1; |
2119 | } |
2120 | NPPPD_DBG((LOG_DEBUG, "bind realm %s", npppd_auth_get_name(realm))); |
2121 | |
2122 | if (npppd_auth_get_type(realm) == NPPPD_AUTH_TYPE_LOCAL1) |
2123 | /* hook the auto reload */ |
2124 | npppd_auth_get_user_password(realm, |
2125 | npppd_auth_username_for_auth(realm1, username, buf1), NULL((void *)0), |
2126 | NULL((void *)0)); |
2127 | ppp->realm = realm; |
2128 | |
2129 | return 0; |
2130 | } |
2131 | |
2132 | /** Is assigned realm a LOCAL authentication? */ |
2133 | int |
2134 | npppd_ppp_is_realm_local(npppd *_this, npppd_ppp *ppp) |
2135 | { |
2136 | NPPPD_ASSERT(_this != NULL); |
2137 | NPPPD_ASSERT(ppp != NULL); |
2138 | |
2139 | if (ppp->realm == NULL((void *)0)) |
2140 | return 0; |
2141 | |
2142 | return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_LOCAL1) |
2143 | ? 1 : 0; |
2144 | } |
2145 | |
2146 | /** Is assigned realm a RADIUS authentication? */ |
2147 | int |
2148 | npppd_ppp_is_realm_radius(npppd *_this, npppd_ppp *ppp) |
2149 | { |
2150 | NPPPD_ASSERT(_this != NULL); |
2151 | NPPPD_ASSERT(ppp != NULL); |
2152 | |
2153 | if (ppp->realm == NULL((void *)0)) |
2154 | return 0; |
2155 | |
2156 | return (npppd_auth_get_type(ppp->realm) == NPPPD_AUTH_TYPE_RADIUS2) |
2157 | ? 1 : 0; |
2158 | } |
2159 | |
2160 | /** Is assigned realm usable? */ |
2161 | int |
2162 | npppd_ppp_is_realm_ready(npppd *_this, npppd_ppp *ppp) |
2163 | { |
2164 | if (ppp->realm == NULL((void *)0)) |
2165 | return 0; |
2166 | |
2167 | return npppd_auth_is_ready(ppp->realm); |
2168 | } |
2169 | |
2170 | /** Return the name of assigned realm */ |
2171 | const char * |
2172 | npppd_ppp_get_realm_name(npppd *_this, npppd_ppp *ppp) |
2173 | { |
2174 | if (ppp->realm == NULL((void *)0)) |
2175 | return "(none)"; |
2176 | return npppd_auth_get_name(ppp->realm); |
2177 | } |
2178 | |
2179 | /** Return the interface name that bound given {@link ::npppd_ppp PPP} */ |
2180 | const char * |
2181 | npppd_ppp_get_iface_name(npppd *_this, npppd_ppp *ppp) |
2182 | { |
2183 | if (ppp == NULL((void *)0) || ppp->ifidx < 0) |
2184 | return "(not binding)"; |
2185 | return ppp_iface(ppp)(&(ppp)->pppd->iface[(ppp)->ifidx])->ifname; |
2186 | } |
2187 | |
2188 | /** Is the interface usable? */ |
2189 | int |
2190 | npppd_ppp_iface_is_ready(npppd *_this, npppd_ppp *ppp) |
2191 | { |
2192 | return (npppd_iface_ip_is_ready(ppp_iface(ppp))(((&(ppp)->pppd->iface[(ppp)->ifidx]))->initialized != 0 && ((&(ppp)->pppd->iface[(ppp)->ifidx ]))->ip4addr.s_addr != ((u_int32_t)(0x00000000))) && |
2193 | ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf) != NULL((void *)0))? 1 : 0; |
2194 | } |
2195 | |
2196 | /** Select a suitable interface for {@link :npppd_ppp PPP} and bind them */ |
2197 | int |
2198 | npppd_ppp_bind_iface(npppd *_this, npppd_ppp *ppp) |
2199 | { |
2200 | int i, ifidx; |
2201 | struct confbind *bind; |
2202 | struct ipcpstat *ipcpstat; |
2203 | |
2204 | NPPPD_ASSERT(_this != NULL); |
2205 | NPPPD_ASSERT(ppp != NULL); |
2206 | |
2207 | if (ppp->ifidx >= 0) |
2208 | return 0; |
2209 | |
2210 | TAILQ_FOREACH(bind, &_this->conf.confbinds, entry)for((bind) = ((&_this->conf.confbinds)->tqh_first); (bind) != ((void *)0); (bind) = ((bind)->entry.tqe_next)) { |
2211 | if (strcmp(bind->tunnconf->name, ppp->phy_label) != 0) |
2212 | continue; |
2213 | if (ppp->realm == NULL((void *)0)) { |
2214 | if (bind->authconf == NULL((void *)0)) |
2215 | break; |
2216 | } else if (strcmp(bind->authconf->name, |
2217 | npppd_auth_get_name(ppp->realm)) == 0) |
2218 | break; |
2219 | } |
2220 | if (bind == NULL((void *)0)) |
2221 | return 1; |
2222 | |
2223 | /* Search a interface */ |
2224 | ifidx = -1; |
2225 | for (i = 0; i < countof(_this->iface)(sizeof(_this->iface) / sizeof((_this->iface)[0])); i++) { |
2226 | if (_this->iface[i].initialized == 0) |
2227 | continue; |
2228 | if (strcmp(_this->iface[i].ifname, bind->iface->name) == 0) |
2229 | ifidx = i; |
2230 | } |
2231 | if (ifidx < 0) |
2232 | return 1; |
2233 | |
2234 | ppp->ifidx = ifidx; |
2235 | NPPPD_ASSERT(ppp_ipcp(ppp) != NULL); |
2236 | ipcpstat = npppd_get_ipcp_stat(&_this->ipcpstats, ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->name); |
2237 | if (ipcpstat == NULL((void *)0)) { |
2238 | ppp_log(ppp, LOG_WARNING4, "Unknown IPCP %s", |
2239 | ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->name); |
2240 | ppp->ifidx = -1; /* unbind interface */ |
2241 | return 1; |
2242 | } |
2243 | if (ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->max_session > 0 && |
2244 | ipcpstat->nsession >= ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->max_session) { |
2245 | ppp_log(ppp, LOG_WARNING4, |
2246 | "Number of sessions per IPCP reaches out of the limit=%d", |
2247 | ppp_ipcp(ppp)((ppp)->pppd->iface[(ppp)->ifidx].ipcpconf)->max_session); |
2248 | ppp->ifidx = -1; /* unbind interface */ |
2249 | return 1; |
2250 | } |
2251 | |
2252 | if (_this->conf.max_session > 0 && |
2253 | _this->nsession >= _this->conf.max_session) { |
2254 | ppp_log(ppp, LOG_WARNING4, |
2255 | "Number of sessions reaches out of the limit=%d", |
2256 | _this->conf.max_session); |
2257 | ppp->ifidx = -1; /* unbind interface */ |
2258 | return 1; |
2259 | } |
2260 | _this->nsession++; |
2261 | |
2262 | LIST_INSERT_HEAD(&ipcpstat->ppp, ppp, ipcpstat_entry)do { if (((ppp)->ipcpstat_entry.le_next = (&ipcpstat-> ppp)->lh_first) != ((void *)0)) (&ipcpstat->ppp)-> lh_first->ipcpstat_entry.le_prev = &(ppp)->ipcpstat_entry .le_next; (&ipcpstat->ppp)->lh_first = (ppp); (ppp) ->ipcpstat_entry.le_prev = &(&ipcpstat->ppp)-> lh_first; } while (0); |
2263 | ppp->ipcpstat = ipcpstat; |
2264 | ipcpstat->nsession++; |
2265 | |
2266 | return 0; |
2267 | } |
2268 | |
2269 | /** Unbind the interface from the {@link ::npppd_ppp PPP} */ |
2270 | void |
2271 | npppd_ppp_unbind_iface(npppd *_this, npppd_ppp *ppp) |
2272 | { |
2273 | if (ppp->ifidx >= 0) { |
2274 | _this->nsession--; |
2275 | if (ppp->ipcpstat!= NULL((void *)0)) { |
2276 | ppp->ipcpstat->nsession--; |
2277 | LIST_REMOVE(ppp, ipcpstat_entry)do { if ((ppp)->ipcpstat_entry.le_next != ((void *)0)) (ppp )->ipcpstat_entry.le_next->ipcpstat_entry.le_prev = (ppp )->ipcpstat_entry.le_prev; *(ppp)->ipcpstat_entry.le_prev = (ppp)->ipcpstat_entry.le_next; ; ; } while (0); |
2278 | } |
2279 | } |
2280 | ppp->ifidx = -1; |
2281 | } |
2282 | |
2283 | static int |
2284 | npppd_rd_walktree_delete(struct radish_head *rh) |
2285 | { |
2286 | void *dummy; |
2287 | struct radish *rd; |
2288 | slist list; |
2289 | |
2290 | slist_init(&list); |
2291 | if (rd2slist(rh, &list) != 0) |
2292 | return 1; |
2293 | for (slist_itr_first(&list); slist_itr_has_next(&list);) { |
2294 | rd = slist_itr_next(&list); |
2295 | rd_delete(rd->rd_route, rd->rd_mask, rh, &dummy); |
2296 | } |
2297 | slist_fini(&list); |
2298 | |
2299 | free(rh); |
2300 | |
2301 | return 0; |
2302 | } |
2303 | |
2304 | #ifdef USE_NPPPD_RADIUS1 |
2305 | /** |
2306 | * Return radius_req_setting for the given {@link ::npppd_ppp PPP}. |
2307 | * @return return NULL if no usable RADIUS setting. |
2308 | */ |
2309 | void * |
2310 | npppd_get_radius_auth_setting(npppd *_this, npppd_ppp *ppp) |
2311 | { |
2312 | NPPPD_ASSERT(_this != NULL); |
2313 | NPPPD_ASSERT(ppp != NULL); |
2314 | |
2315 | if (ppp->realm == NULL((void *)0)) |
2316 | return NULL((void *)0); |
2317 | if (!npppd_ppp_is_realm_radius(_this, ppp)) |
2318 | return NULL((void *)0); |
2319 | |
2320 | return npppd_auth_radius_get_radius_auth_setting(ppp->realm); |
2321 | } |
2322 | #endif |
2323 | |
2324 | /** Finalize authentication realm */ |
2325 | static void |
2326 | npppd_auth_finalizer_periodic(npppd *_this) |
2327 | { |
2328 | int ndisposing = 0, refcnt; |
2329 | slist users; |
2330 | npppd_auth_base *auth_base; |
2331 | npppd_ppp *ppp; |
2332 | |
2333 | /* |
2334 | * For the realms with disposing flag, if the realm has assigned PPPs, |
2335 | * disconnect them. If all PPPs are disconnected then free the realm. |
2336 | */ |
2337 | NPPPD_DBG((DEBUG_LEVEL_2, "%s() called", __func__)); |
2338 | slist_itr_first(&_this->realms); |
2339 | while (slist_itr_has_next(&_this->realms)) { |
2340 | auth_base = slist_itr_next(&_this->realms); |
2341 | if (!npppd_auth_is_disposing(auth_base)) |
2342 | continue; |
2343 | refcnt = 0; |
2344 | if (ndisposing++ == 0) { |
2345 | slist_init(&users); |
2346 | if (npppd_get_all_users(_this, &users) != 0) { |
2347 | log_printf(LOG_WARNING4, |
2348 | "npppd_get_all_users() failed in %s(): %m", |
2349 | __func__); |
2350 | break; |
2351 | } |
2352 | } |
2353 | slist_itr_first(&users); |
2354 | while (slist_itr_has_next(&users)) { |
2355 | ppp = slist_itr_next(&users); |
2356 | if (ppp->realm == auth_base) { |
2357 | refcnt++; |
2358 | ppp_stop(ppp, NULL((void *)0)); |
2359 | ppp_log(ppp, LOG_INFO6, |
2360 | "Stop request by npppd. Binding " |
2361 | "authentication realm is disposing. " |
2362 | "realm=%s", npppd_auth_get_name(auth_base)); |
2363 | slist_itr_remove(&users); |
2364 | } |
2365 | } |
2366 | if (refcnt == 0) { |
2367 | npppd_auth_destroy(auth_base); |
2368 | slist_itr_remove(&_this->realms); |
2369 | } |
2370 | } |
2371 | if (ndisposing > 0) |
2372 | slist_fini(&users); |
2373 | } |
2374 | |
2375 | /** compare sockaddr_npppd. return 0 if matches */ |
2376 | int |
2377 | sockaddr_npppd_match(void *a0, void *b0) |
2378 | { |
2379 | struct sockaddr_npppd *a, *b; |
2380 | |
2381 | a = a0; |
2382 | b = b0; |
2383 | |
2384 | return (a->snp_addrsin4.sin_addr.s_addr == b->snp_addrsin4.sin_addr.s_addr)? 1 : 0; |
2385 | } |
2386 | |
2387 | /** |
2388 | * This function stores the username for authentication to the space specified |
2389 | * by username_buffer and returns it. username_buffer must have space more |
2390 | * than MAX_USERNAME_LENGTH. |
2391 | */ |
2392 | const char * |
2393 | npppd_ppp_get_username_for_auth(npppd *_this, npppd_ppp *ppp, |
2394 | const char *username, char *username_buffer) |
2395 | { |
2396 | NPPPD_ASSERT(_this != NULL); |
2397 | NPPPD_ASSERT(ppp != NULL); |
2398 | NPPPD_ASSERT(ppp->realm != NULL); |
2399 | |
2400 | return npppd_auth_username_for_auth(ppp->realm, username, |
2401 | username_buffer); |
2402 | } |
2403 | |
2404 | const char * |
2405 | npppd_tunnel_protocol_name(int tunn_protocol) |
2406 | { |
2407 | switch (tunn_protocol) { |
2408 | case NPPPD_TUNNEL_NONE0: |
2409 | return "None"; |
2410 | case NPPPD_TUNNEL_L2TP1: |
2411 | return "L2TP"; |
2412 | case NPPPD_TUNNEL_PPTP2: |
2413 | return "PPTP"; |
2414 | case NPPPD_TUNNEL_PPPOE3: |
2415 | return "PPPoE"; |
2416 | case NPPPD_TUNNEL_SSTP4: |
2417 | return "SSTP"; |
2418 | } |
2419 | |
2420 | return "Error"; |
2421 | } |
2422 | |
2423 | const char * |
2424 | npppd_ppp_tunnel_protocol_name(npppd *_this, npppd_ppp *ppp) |
2425 | { |
2426 | return npppd_tunnel_protocol_name(ppp->tunnel_type); |
2427 | } |
2428 | |
2429 | struct tunnconf * |
2430 | npppd_get_tunnconf(npppd *_this, const char *name) |
2431 | { |
2432 | struct tunnconf *conf; |
2433 | |
2434 | TAILQ_FOREACH(conf, &_this->conf.tunnconfs, entry)for((conf) = ((&_this->conf.tunnconfs)->tqh_first); (conf) != ((void *)0); (conf) = ((conf)->entry.tqe_next)) { |
2435 | if (strcmp(conf->name, name) == 0) |
2436 | return conf; |
2437 | } |
2438 | |
2439 | return NULL((void *)0); |
2440 | } |
2441 | |
2442 | void |
2443 | npppd_on_ppp_start(npppd *_this, npppd_ppp *ppp) |
2444 | { |
2445 | struct ctl_conn *c; |
2446 | |
2447 | TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void *)0 ); (c) = ((c)->entry.tqe_next)) { |
2448 | if (npppd_ctl_add_started_ppp_id(c->ctx, ppp->id) == 0) { |
2449 | npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); |
2450 | imsg_event_add(&c->iev); |
2451 | } |
2452 | } |
2453 | } |
2454 | |
2455 | void |
2456 | npppd_on_ppp_stop(npppd *_this, npppd_ppp *ppp) |
2457 | { |
2458 | struct ctl_conn *c; |
2459 | |
2460 | TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void *)0 ); (c) = ((c)->entry.tqe_next)) { |
2461 | if (npppd_ctl_add_stopped_ppp(c->ctx, ppp) == 0) { |
2462 | npppd_ctl_imsg_compose(c->ctx, &c->iev.ibuf); |
2463 | imsg_event_add(&c->iev); |
2464 | } |
2465 | } |
2466 | } |
2467 | |
2468 | void |
2469 | imsg_event_add(struct imsgev *iev) |
2470 | { |
2471 | iev->events = EV_READ0x02; |
2472 | if (iev->ibuf.w.queued) |
2473 | iev->events |= EV_WRITE0x04; |
2474 | |
2475 | event_del(&iev->ev); |
2476 | event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); |
2477 | event_add(&iev->ev, NULL((void *)0)); |
2478 | } |