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