blob: b086a0da10c2d9670c817dfd791e0c94508ca4d2 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*
2 * main.c - Point-to-Point Protocol main module
3 *
4 * Copyright (c) 1989 Carnegie Mellon University.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#define RCSID "$Id: main.c,v 1.1 2008-08-04 06:11:52 winfred Exp $"
21
22#include <stdio.h>
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <signal.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <syslog.h>
31#include <netdb.h>
32#include <utmp.h>
33#include <pwd.h>
34#include <setjmp.h>
35#include <sys/param.h>
36#include <sys/types.h>
37#include <sys/wait.h>
38#include <sys/time.h>
39#include <sys/resource.h>
40#include <sys/stat.h>
41#include <sys/socket.h>
42#include <netinet/in.h>
43#include <arpa/inet.h>
44#include <sys/time.h>
45
46
47#include "pppd.h"
48#include "magic.h"
49#include "fsm.h"
50#include "lcp.h"
51#include "ipcp.h"
52#include "upap.h"
53#include "chap.h"
54#include "ccp.h"
55#include "pathnames.h"
56#include "../../include/netapi.h"
57
58#ifdef CBCP_SUPPORT
59#include "cbcp.h"
60#endif
61
62#ifdef IPX_CHANGE
63#include "ipxcp.h"
64#endif /* IPX_CHANGE */
65#ifdef AT_CHANGE
66#include "atcp.h"
67#endif
68
69static const char rcsid[] = RCSID;
70
71/* interface vars */
72char ifname[32]; /* Interface name */
73int ifunit; /* Interface unit number */
74
75struct channel *the_channel;
76
77char *progname; /* Name of this program */
78char hostname[MAXNAMELEN]; /* Our hostname */
79static char pidfilename[MAXPATHLEN]; /* name of pid file */
80static char linkpidfile[MAXPATHLEN]; /* name of linkname pid file */
81char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
82uid_t uid; /* Our real user-id */
83
84int hungup; /* terminal has been hung up */
85int privileged; /* we're running as real uid root */
86int need_holdoff; /* need holdoff period before restarting */
87int detached; /* have detached from terminal */
88volatile int status; /* exit status for pppd */
89int unsuccess; /* # unsuccessful connection attempts */
90int do_callback; /* != 0 if we should do callback next */
91int doing_callback; /* != 0 if we are doing callback */
92
93
94#define pppdb NULL
95
96int (*holdoff_hook) __P((void)) = NULL;
97int (*new_phase_hook) __P((int)) = NULL;
98
99static int conn_running; /* we have a [dis]connector running */
100static int devfd; /* fd of underlying device */
101static int fd_ppp = -1; /* fd for talking PPP */
102static int fd_loop; /* fd for getting demand-dial packets */
103
104int phase; /* where the link is at */
105int kill_link;
106int open_ccp_flag;
107int listen_time;
108int got_sigusr2;
109int got_sigterm;
110int got_sighup;
111
112static int waiting;
113static sigjmp_buf sigjmp;
114
115char **script_env; /* Env. variable values for scripts */
116int s_env_nalloc; /* # words avail at script_env */
117
118u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
119u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
120
121static int n_children; /* # child processes still running */
122static int got_sigchld; /* set if we have received a SIGCHLD */
123
124int privopen; /* don't lock, open device as root */
125
126char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
127
128GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
129int ngroups; /* How many groups valid in groups */
130
131static struct timeval start_time; /* Time when link was started. */
132
133struct pppd_stats link_stats;
134int link_connect_time;
135int link_stats_valid;
136
137/*
138 * We maintain a list of child process pids and
139 * functions to call when they exit.
140 */
141struct subprocess {
142 pid_t pid;
143 char *prog;
144 void (*done) __P((void *));
145 void *arg;
146 struct subprocess *next;
147};
148
149static struct subprocess *children;
150
151/* Prototypes for procedures local to this file. */
152
153static void setup_signals __P((void));
154static void create_pidfile __P((void));
155static void create_linkpidfile __P((void));
156static void cleanup __P((void));
157static void get_input __P((void));
158static void calltimeout __P((void));
159static struct timeval *timeleft __P((struct timeval *));
160static void kill_my_pg __P((int));
161static void hup __P((int));
162static void term __P((int));
163static void chld __P((int));
164static void toggle_debug __P((int));
165static void open_ccp __P((int));
166static void bad_signal __P((int));
167static void holdoff_end __P((void *));
168static int reap_kids __P((int waitfor));
169#define update_db_entry()
170#define add_db_key(a)
171#define delete_db_key(a)
172#define cleanup_db()
173static void handle_events __P((void));
174
175extern char *ttyname __P((int));
176extern char *getlogin __P((void));
177int main __P((int, char *[]));
178
179#ifdef ultrix
180#undef O_NONBLOCK
181#define O_NONBLOCK O_NDELAY
182#endif
183
184#ifdef ULTRIX
185#define setlogmask(x)
186#endif
187
188/*
189 * PPP Data Link Layer "protocol" table.
190 * One entry per supported protocol.
191 * The last entry must be NULL.
192 */
193struct protent *protocols[] = {
194 &lcp_protent,
195 &pap_protent,
196#ifdef CHAP_SUPPORT
197 &chap_protent,
198#endif
199 &ipcp_protent,
200#ifdef CCP_SUPPORT
201 &ccp_protent,
202#endif
203 NULL
204};
205
206/*
207 * If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
208 */
209#if !defined(PPP_DRV_NAME)
210#define PPP_DRV_NAME "ppp"
211#endif /* !defined(PPP_DRV_NAME) */
212
213
214/*
215ÄÚ²¿¶¨Ê±Æ÷:
216PPPOE/DHCP×ÔÊÊӦģʽÏ£¬ÓÅÏÈÖ´ÐÐPPPOE²¦ºÅ£¬
217³¬Ê±ÔòÆô¶¯DHCP
218*/
219void time_out_action(int signo)
220{
221 char pppoe_reply[8] = {0};
222 char path_sh[32] = {0};
223 char ethwan[32] = {0};
224 char cmd[100] = {0};
225 sc_cfg_get("pppoe_reply", pppoe_reply, sizeof(pppoe_reply));
226 if(0 == strcmp(pppoe_reply, "0"))
227 {
228 sc_cfg_get("path_sh", path_sh, sizeof(path_sh));
229 sc_cfg_get("ethwan", ethwan, sizeof(ethwan));
230 sprintf(cmd,"udhcpc -i %s -s %s/udhcpc.sh &",ethwan,path_sh);
231 system(cmd);
232 exit(1);
233 }
234
235}
236
237void init_sigaction()
238{
239 struct sigaction my_act;
240 my_act.sa_handler = time_out_action;
241 my_act.sa_flags = 0;
242 sigemptyset(&my_act.sa_mask);
243 sigaction(SIGALRM,&my_act,NULL);
244 //signal(SIGALRM,time_out_action);
245}
246
247void init_time()
248{
249 struct itimerval value;
250 value.it_value.tv_sec = 10;
251 value.it_value.tv_usec = 0;
252
253 value.it_interval.tv_sec = 0;
254 value.it_interval.tv_usec = 0;
255
256 sc_cfg_set("pppoe_reply", "0");
257
258 setitimer(ITIMER_REAL,&value,NULL);
259}
260
261
262
263
264
265
266
267int
268main(argc, argv)
269 int argc;
270 char *argv[];
271{
272 int i, t;
273 char *p;
274 struct passwd *pw;
275 struct protent *protp;
276 char numbuf[16];
277 char eth_mode[32] = {0};
278 sc_cfg_get("ethwan_mode", eth_mode, sizeof(eth_mode));
279
280 new_phase(PHASE_INITIALIZE);
281
282 //sc_cfg_set("ppp_status","ppp_connecting");//linxu
283
284 /*
285 * Ensure that fds 0, 1, 2 are open, to /dev/null if nowhere else.
286 * This way we can close 0, 1, 2 in detach() without clobbering
287 * a fd that we are using.
288 */
289 if ((i = open("/dev/null", O_RDWR)) >= 0) {
290 while (0 <= i && i <= 2)
291 i = dup(i);
292 if (i >= 0)
293 close(i);
294 }
295
296 script_env = NULL;
297
298 /* Initialize syslog facilities */
299 //reopen_log();
300
301 if (gethostname(hostname, MAXNAMELEN) < 0 ) {
302 option_error("Couldn't get hostname: %m");
303 exit(1);
304 }
305 hostname[MAXNAMELEN-1] = 0;
306
307 /* make sure we don't create world or group writable files. */
308 umask(umask(0777) | 022);
309
310 uid = getuid();
311 privileged = uid == 0;
312 slprintf(numbuf, sizeof(numbuf), "%d", uid);
313 script_setenv("ORIG_UID", numbuf, 0);
314
315 ngroups = getgroups(NGROUPS_MAX, groups);
316
317 /*
318 * Initialize magic number generator now so that protocols may
319 * use magic numbers in initialization.
320 */
321 magic_init();
322
323 /*
324 * Initialize each protocol.
325 */
326 for (i = 0; (protp = protocols[i]) != NULL; ++i)
327 (*protp->init)(0);
328
329 progname = *argv;
330
331 /*
332 * Parse, in order, the system options file, the user's options file,
333 * and the command line arguments.
334 */
335
336 if (!parse_args(argc, argv))
337 exit(EXIT_OPTION_ERROR);
338 devnam_fixed = 1; /* can no longer change device name */
339
340 reopen_log(); // According to ipparam value, decide log name
341
342 /*
343 * Work out the device name, if it hasn't already been specified,
344 * and parse the tty's options file.
345 */
346 if (the_channel->process_extra_options)
347 (*the_channel->process_extra_options)();
348
349 if (debug)
350 setlogmask(LOG_UPTO(LOG_DEBUG));
351
352 /*
353 * Check that we are running as root.
354 */
355 if (geteuid() != 0) {
356 option_error("must be root to run %s, since it is not setuid-root",
357 argv[0]);
358 exit(EXIT_NOT_ROOT);
359 }
360
361 if (!ppp_available()) {
362 option_error("%s", no_ppp_msg);
363 exit(EXIT_NO_KERNEL_SUPPORT);
364 }
365
366 /*
367 * Check that the options given are valid and consistent.
368 */
369 check_options();
370 if (!sys_check_options())
371 exit(EXIT_OPTION_ERROR);
372 auth_check_options();
373 for (i = 0; (protp = protocols[i]) != NULL; ++i)
374 if (protp->check_options != NULL)
375 (*protp->check_options)();
376 if (the_channel->check_options)
377 (*the_channel->check_options)();
378
379
380 if (dump_options || dryrun) {
381 init_pr_log(NULL, LOG_INFO);
382 print_options(pr_log, NULL);
383 end_pr_log();
384 if (dryrun)
385 die(0);
386 }
387
388 /*
389 * Initialize system-dependent stuff.
390 */
391 sys_init();
392
393 /*
394 * Detach ourselves from the terminal, if required,
395 * and identify who is running us.
396 */
397 if (!nodetach && !updetach)
398 detach();
399 p = getlogin();
400 if (p == NULL) {
401 pw = getpwuid(uid);
402 if (pw != NULL && pw->pw_name != NULL)
403 p = pw->pw_name;
404 else
405 p = "(unknown)";
406 }
407 syslog(LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid);
408 script_setenv("PPPLOGNAME", p, 0);
409
410 if (devnam[0])
411 script_setenv("DEVICE", devnam, 1);
412 slprintf(numbuf, sizeof(numbuf), "%d", getpid());
413 script_setenv("PPPD_PID", numbuf, 1);
414
415 setup_signals();
416
417 if (0 == strcmp(eth_mode, "auto") || 0 == strcmp(eth_mode, "ondemand"))
418 {
419 init_sigaction();
420 init_time();
421 }
422 waiting = 0;
423
424 create_linkpidfile();
425
426 /*
427 * If we're doing dial-on-demand, set up the interface now.
428 */
429 if (demand) {
430 /*
431 * Open the loopback channel and set it up to be the ppp interface.
432 */
433 fd_loop = open_ppp_loopback();
434 set_ifunit(1);
435
436 /*
437 * Configure the interface and mark it up, etc.
438 */
439 demand_conf();
440 }
441
442 do_callback = 0;
443 for (;;) {
444
445 listen_time = 0;
446 need_holdoff = 1;
447 devfd = -1;
448 status = EXIT_OK;
449 ++unsuccess;
450 doing_callback = do_callback;
451 do_callback = 0;
452
453 if (demand && !doing_callback) {
454 /*
455 * Don't do anything until we see some activity.
456 */
457 new_phase(PHASE_DORMANT);
458 demand_unblock();
459 add_fd(fd_loop);
460 for (;;) {
461 handle_events();
462 if (kill_link && !persist)
463 break;
464 if (get_loop_output())
465 break;
466 }
467 remove_fd(fd_loop);
468 if (kill_link && !persist)
469 break;
470
471 /*
472 * Now we want to bring up the link.
473 */
474 demand_block();
475 info("Starting link");
476 }
477
478 new_phase(PHASE_SERIALCONN);
479
480 devfd = the_channel->connect();
481 if (devfd < 0)
482 continue;
483
484 /* set up the serial device as a ppp interface */
485 fd_ppp = the_channel->establish_ppp(devfd);
486 if (fd_ppp < 0) {
487 status = EXIT_FATAL_ERROR;
488 goto disconnect;
489 }
490
491 if (!demand && ifunit >= 0)
492 set_ifunit(1);
493
494 /*
495 * Start opening the connection and wait for
496 * incoming events (reply, timeout, etc.).
497 */
498 notice("Connect: %s <--> %s", ifname, ppp_devnam);
499 my_gettimeofday(&start_time, NULL);
500 link_stats_valid = 0;
501 script_unsetenv("CONNECT_TIME");
502 script_unsetenv("BYTES_SENT");
503 script_unsetenv("BYTES_RCVD");
504 lcp_lowerup(0);
505
506 add_fd(fd_ppp);
507 lcp_open(0); /* Start protocol */
508 status = EXIT_NEGOTIATION_FAILED;
509 new_phase(PHASE_ESTABLISH);
510 while (phase != PHASE_DEAD) {
511 handle_events();
512 get_input();
513 if (kill_link)
514 lcp_close(0, "User request");
515#ifdef CCP_SUPPORT
516 if (open_ccp_flag) {
517 if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) {
518 ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
519 (*ccp_protent.open)(0);
520 }
521 }
522#endif
523 }
524
525 /*
526 * Print connect time and statistics.
527 */
528 if (link_stats_valid) {
529 int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */
530 info("Connect time %d.%d minutes.", t/10, t%10);
531 info("Sent %u bytes, received %u bytes.",
532 link_stats.bytes_out, link_stats.bytes_in);
533 }
534
535 /*
536 * Delete pid file before disestablishing ppp. Otherwise it
537 * can happen that another pppd gets the same unit and then
538 * we delete its pid file.
539 */
540 if (!demand) {
541 if (pidfilename[0] != 0
542 && unlink(pidfilename) < 0 && errno != ENOENT)
543 warn("unable to delete pid file %s: %m", pidfilename);
544 pidfilename[0] = 0;
545 }
546
547 /*
548 * If we may want to bring the link up again, transfer
549 * the ppp unit back to the loopback. Set the
550 * real serial device back to its normal mode of operation.
551 */
552 remove_fd(fd_ppp);
553 clean_check();
554 the_channel->disestablish_ppp(devfd);
555 fd_ppp = -1;
556 if (!hungup)
557 lcp_lowerdown(0);
558 if (!demand)
559 script_unsetenv("IFNAME");
560
561 disconnect:
562 new_phase(PHASE_DISCONNECT);
563 the_channel->disconnect();
564
565/* fail: */
566 /*add by maxl begin, 2010-12-16*/
567 /*for setting ppp status to disconnected when pppoe down*/
568 //sc_cfg_set("ppp_status","ppp_disconnected"); //linxu
569 /*add by maxl end,2010-12-16*/
570
571 if (the_channel->cleanup)
572 (*the_channel->cleanup)();
573
574 if (!demand) {
575 if (pidfilename[0] != 0
576 && unlink(pidfilename) < 0 && errno != ENOENT)
577 warn("unable to delete pid file %s: %m", pidfilename);
578 pidfilename[0] = 0;
579 }
580
581 if (!persist || (maxfail > 0 && unsuccess >= maxfail))
582 break;
583
584 if (demand)
585 demand_discard();
586 t = need_holdoff? holdoff: 0;
587 if (holdoff_hook)
588 t = (*holdoff_hook)();
589 if (t > 0) {
590 new_phase(PHASE_HOLDOFF);
591 TIMEOUT(holdoff_end, NULL, t);
592 do {
593 handle_events();
594 if (kill_link)
595 new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
596 } while (phase == PHASE_HOLDOFF);
597 if (!persist)
598 break;
599 }
600 }
601
602 /* Wait for scripts to finish */
603 while (n_children > 0) {
604 if (debug) {
605 struct subprocess *chp;
606 dbglog("Waiting for %d child processes...", n_children);
607 for (chp = children; chp != NULL; chp = chp->next)
608 dbglog(" script %s, pid %d", chp->prog, chp->pid);
609 }
610 if (reap_kids(1) < 0)
611 break;
612 }
613
614 die(status);
615 return 0;
616}
617
618/*
619 * handle_events - wait for something to happen and respond to it.
620 */
621static void
622handle_events()
623{
624 struct timeval timo;
625 sigset_t mask;
626
627 kill_link = open_ccp_flag = 0;
628 if (sigsetjmp(sigjmp, 1) == 0) {
629 sigprocmask(SIG_BLOCK, &mask, NULL);
630 if (got_sighup || got_sigterm || got_sigusr2 || got_sigchld) {
631 sigprocmask(SIG_UNBLOCK, &mask, NULL);
632 } else {
633 waiting = 1;
634 sigprocmask(SIG_UNBLOCK, &mask, NULL);
635 wait_input(timeleft(&timo));
636 }
637 }
638 waiting = 0;
639 calltimeout();
640 if (got_sighup) {
641 kill_link = 1;
642 got_sighup = 0;
643 if (status != EXIT_HANGUP)
644 status = EXIT_USER_REQUEST;
645 }
646 if (got_sigterm) {
647 kill_link = 1;
648 persist = 0;
649 status = EXIT_USER_REQUEST;
650 got_sigterm = 0;
651 }
652 if (got_sigchld) {
653 reap_kids(0); /* Don't leave dead kids lying around */
654 got_sigchld = 0;
655 }
656 if (got_sigusr2) {
657 open_ccp_flag = 1;
658 got_sigusr2 = 0;
659 }
660}
661
662/*
663 * setup_signals - initialize signal handling.
664 */
665static void
666setup_signals()
667{
668 struct sigaction sa;
669 sigset_t mask;
670
671 /*
672 * Compute mask of all interesting signals and install signal handlers
673 * for each. Only one signal handler may be active at a time. Therefore,
674 * all other signals should be masked when any handler is executing.
675 */
676 sigemptyset(&mask);
677 sigaddset(&mask, SIGHUP);
678 sigaddset(&mask, SIGINT);
679 sigaddset(&mask, SIGTERM);
680 sigaddset(&mask, SIGCHLD);
681 sigaddset(&mask, SIGUSR2);
682
683#define SIGNAL(s, handler) do { \
684 sa.sa_handler = handler; \
685 if (sigaction(s, &sa, NULL) < 0) \
686 fatal("Couldn't establish signal handler (%d): %m", s); \
687 } while (0)
688
689 sa.sa_mask = mask;
690 sa.sa_flags = 0;
691 SIGNAL(SIGHUP, hup); /* Hangup */
692 SIGNAL(SIGINT, term); /* Interrupt */
693 SIGNAL(SIGTERM, term); /* Terminate */
694 SIGNAL(SIGCHLD, chld);
695
696 SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */
697 SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */
698
699 /*
700 * Install a handler for other signals which would otherwise
701 * cause pppd to exit without cleaning up.
702 */
703 SIGNAL(SIGABRT, bad_signal);
704 //SIGNAL(SIGALRM, bad_signal);
705 SIGNAL(SIGFPE, bad_signal);
706 SIGNAL(SIGILL, bad_signal);
707 SIGNAL(SIGPIPE, bad_signal);
708 SIGNAL(SIGQUIT, bad_signal);
709 SIGNAL(SIGSEGV, bad_signal);
710#ifdef SIGBUS
711 SIGNAL(SIGBUS, bad_signal);
712#endif
713#ifdef SIGEMT
714 SIGNAL(SIGEMT, bad_signal);
715#endif
716#ifdef SIGPOLL
717 SIGNAL(SIGPOLL, bad_signal);
718#endif
719#ifdef SIGPROF
720 SIGNAL(SIGPROF, bad_signal);
721#endif
722#ifdef SIGSYS
723 SIGNAL(SIGSYS, bad_signal);
724#endif
725#ifdef SIGTRAP
726 SIGNAL(SIGTRAP, bad_signal);
727#endif
728#ifdef SIGVTALRM
729 SIGNAL(SIGVTALRM, bad_signal);
730#endif
731#ifdef SIGXCPU
732 SIGNAL(SIGXCPU, bad_signal);
733#endif
734#ifdef SIGXFSZ
735 SIGNAL(SIGXFSZ, bad_signal);
736#endif
737
738 /*
739 * Apparently we can get a SIGPIPE when we call syslog, if
740 * syslogd has died and been restarted. Ignoring it seems
741 * be sufficient.
742 */
743 signal(SIGPIPE, SIG_IGN);
744}
745
746/*
747 * set_ifunit - do things we need to do once we know which ppp
748 * unit we are using.
749 */
750void
751set_ifunit(iskey)
752 int iskey;
753{
754 info("Using interface %s%d", PPP_DRV_NAME, ifunit);
755 slprintf(ifname, sizeof(ifname), "%s%d", PPP_DRV_NAME, ifunit);
756 script_setenv("IFNAME", ifname, iskey);
757
758 char *arg[3]={_PATH_SETPPPOEPID, ipparam, NULL}; // tallest 1219
759 run_program(_PATH_SETPPPOEPID,arg,0,0,0);
760
761 if (iskey) {
762 create_pidfile(); /* write pid to file */
763 create_linkpidfile();
764 }
765}
766
767/*
768 * detach - detach us from the controlling terminal.
769 */
770void
771detach()
772{
773 int pid;
774 char numbuf[16];
775
776 if (detached)
777 return;
778 if ((pid = fork()) < 0) {
779 error("Couldn't detach (fork failed: %m)");
780 die(1); /* or just return? */
781 }
782 if (pid != 0) {
783 /* parent */
784 exit(0); /* parent dies */
785 }
786 setsid();
787 chdir("/");
788 close(0);
789 close(1);
790 close(2);
791 detached = 1;
792 if (log_default)
793 log_to_fd = -1;
794 /* update pid files if they have been written already */
795 if (pidfilename[0])
796 create_pidfile();
797 if (linkpidfile[0])
798 create_linkpidfile();
799 slprintf(numbuf, sizeof(numbuf), "%d", getpid());
800 script_setenv("PPPD_PID", numbuf, 1);
801}
802
803/*
804 * reopen_log - (re)open our connection to syslog.
805 */
806void
807reopen_log()
808{
809#ifdef ULTRIX
810 openlog("pppd", LOG_PID);
811#else
812#ifdef MPPPOE_SUPPORT
813 if(!strncmp(ipparam, "0", 1))
814 openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
815 else
816 openlog("pppd-1", LOG_PID | LOG_NDELAY, LOG_PPP);
817#else
818 openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
819#endif
820 setlogmask(LOG_UPTO(LOG_INFO));
821#endif
822}
823
824/*
825 * Create a file containing our process ID.
826 */
827static void
828create_pidfile()
829{
830 FILE *pidfile;
831
832 slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
833 _PATH_VARRUN, ifname);
834 if ((pidfile = fopen(pidfilename, "w")) != NULL) {
835 fprintf(pidfile, "%d\n", getpid());
836 (void) fclose(pidfile);
837 } else {
838 error("Failed to create pid file %s: %m", pidfilename);
839 pidfilename[0] = 0;
840 }
841}
842
843static void
844create_linkpidfile()
845{
846 FILE *pidfile;
847
848 if (linkname[0] == 0)
849 return;
850 script_setenv("LINKNAME", linkname, 1);
851 slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",
852 _PATH_VARRUN, linkname);
853 if ((pidfile = fopen(linkpidfile, "w")) != NULL) {
854 fprintf(pidfile, "%d\n", getpid());
855 if (ifname[0])
856 fprintf(pidfile, "%s\n", ifname);
857 (void) fclose(pidfile);
858 } else {
859 error("Failed to create pid file %s: %m", linkpidfile);
860 linkpidfile[0] = 0;
861 }
862}
863
864/*
865 * holdoff_end - called via a timeout when the holdoff period ends.
866 */
867static void
868holdoff_end(arg)
869 void *arg;
870{
871 new_phase(PHASE_DORMANT);
872}
873
874/*
875 * get_input - called when incoming data is available.
876 */
877static void
878get_input()
879{
880 int len, i;
881 u_char *p;
882 u_short protocol;
883 struct protent *protp;
884
885 p = inpacket_buf; /* point to beginning of packet buffer */
886
887 len = read_packet(inpacket_buf);
888 if (len < 0)
889 return;
890
891 if (len == 0) {
892 notice("Modem hangup");
893 hungup = 1;
894 status = EXIT_HANGUP;
895 lcp_lowerdown(0); /* serial link is no longer available */
896 link_terminated(0);
897 return;
898 }
899
900 if (debug /*&& (debugflags & DBG_INPACKET)*/)
901 dbglog("rcvd %P", p, len);
902
903 if (len < PPP_HDRLEN) {
904 MAINDEBUG(("io(): Received short packet."));
905 return;
906 }
907
908 p += 2; /* Skip address and control */
909 GETSHORT(protocol, p);
910 len -= PPP_HDRLEN;
911
912 /*
913 * Toss all non-LCP packets unless LCP is OPEN.
914 */
915 if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
916 MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
917 return;
918 }
919
920 /*
921 * Until we get past the authentication phase, toss all packets
922 * except LCP, LQR and authentication packets.
923 */
924 if (phase <= PHASE_AUTHENTICATE
925 && !(protocol == PPP_LCP || protocol == PPP_LQR
926 || protocol == PPP_PAP || protocol == PPP_CHAP)) {
927 MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
928 protocol, phase));
929 return;
930 }
931
932 /*
933 * Upcall the proper protocol input routine.
934 */
935 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
936 if (protp->protocol == protocol && protp->enabled_flag) {
937 (*protp->input)(0, p, len);
938 return;
939 }
940 if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
941 && protp->datainput != NULL) {
942 (*protp->datainput)(0, p, len);
943 return;
944 }
945 }
946
947 if (debug) {
948 warn("Unsupported protocol 0x%x received", protocol);
949 }
950 lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
951}
952
953/*
954 * new_phase - signal the start of a new phase of pppd's operation.
955 */
956void
957new_phase(p)
958 int p;
959{
960 phase = p;
961 if (new_phase_hook)
962 (*new_phase_hook)(p);
963}
964
965/*
966 * die - clean up state and exit with the specified status.
967 */
968void
969die(status)
970 int status;
971{
972 char pppoe_errno[128]={0};
973 cleanup();
974 syslog(LOG_INFO, "Exit.");
975 //sc_cfg_set("ppp_status","ppp_disconnected"); //linxu
976
977 sscanf(pppoe_errno, "%d", status);
978 sc_cfg_set("pppoe_errno",pppoe_errno);
979 exit(status);
980}
981
982/*
983 * cleanup - restore anything which needs to be restored before we exit
984 */
985/* ARGSUSED */
986static void
987cleanup()
988{
989 sys_cleanup();
990
991 if (fd_ppp >= 0)
992 the_channel->disestablish_ppp(devfd);
993 if (the_channel->cleanup)
994 (*the_channel->cleanup)();
995
996 if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
997 warn("unable to delete pid file %s: %m", pidfilename);
998 pidfilename[0] = 0;
999 if (linkpidfile[0] != 0 && unlink(linkpidfile) < 0 && errno != ENOENT)
1000 warn("unable to delete pid file %s: %m", linkpidfile);
1001 linkpidfile[0] = 0;
1002}
1003
1004/*
1005 * update_link_stats - get stats at link termination.
1006 */
1007void
1008update_link_stats(u)
1009 int u;
1010{
1011 struct timeval now;
1012 char numbuf[32];
1013
1014 if (!get_ppp_stats(u, &link_stats)
1015 || my_gettimeofday(&now, NULL) < 0)
1016 return;
1017 link_connect_time = now.tv_sec - start_time.tv_sec;
1018 link_stats_valid = 1;
1019
1020 slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time);
1021 script_setenv("CONNECT_TIME", numbuf, 0);
1022 slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out);
1023 script_setenv("BYTES_SENT", numbuf, 0);
1024 slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in);
1025 script_setenv("BYTES_RCVD", numbuf, 0);
1026}
1027
1028
1029struct callout {
1030 struct timeval c_time; /* time at which to call routine */
1031 void *c_arg; /* argument to routine */
1032 void (*c_func) __P((void *)); /* routine */
1033 struct callout *c_next;
1034};
1035
1036static struct callout *callout = NULL; /* Callout list */
1037static struct timeval timenow; /* Current time */
1038
1039/*
1040 * timeout - Schedule a timeout.
1041 *
1042 * Note that this timeout takes the number of milliseconds, NOT hz (as in
1043 * the kernel).
1044 */
1045void
1046timeout(func, arg, secs, usecs)
1047 void (*func) __P((void *));
1048 void *arg;
1049 int secs, usecs;
1050{
1051 struct callout *newp, *p, **pp;
1052
1053 // Compiler error
1054 //MAINDEBUG(("Timeout %p:%p in %d.%03d seconds.", func, arg,
1055 // time / 1000, time % 1000));
1056
1057 /*
1058 * Allocate timeout.
1059 */
1060 if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
1061 fatal("Out of memory in timeout()!");
1062 newp->c_arg = arg;
1063 newp->c_func = func;
1064 my_gettimeofday(&timenow, NULL);
1065 newp->c_time.tv_sec = timenow.tv_sec + secs;
1066 newp->c_time.tv_usec = timenow.tv_usec + usecs;
1067 if (newp->c_time.tv_usec >= 1000000) {
1068 newp->c_time.tv_sec += newp->c_time.tv_usec / 1000000;
1069 newp->c_time.tv_usec %= 1000000;
1070 }
1071
1072 /*
1073 * Find correct place and link it in.
1074 */
1075 for (pp = &callout; (p = *pp); pp = &p->c_next)
1076 if (newp->c_time.tv_sec < p->c_time.tv_sec
1077 || (newp->c_time.tv_sec == p->c_time.tv_sec
1078 && newp->c_time.tv_usec < p->c_time.tv_usec))
1079 break;
1080 newp->c_next = p;
1081 *pp = newp;
1082}
1083
1084
1085/*
1086 * untimeout - Unschedule a timeout.
1087 */
1088void
1089untimeout(func, arg)
1090 void (*func) __P((void *));
1091 void *arg;
1092{
1093 struct callout **copp, *freep;
1094
1095 MAINDEBUG(("Untimeout %p:%p.", func, arg));
1096
1097 /*
1098 * Find first matching timeout and remove it from the list.
1099 */
1100 for (copp = &callout; (freep = *copp); copp = &freep->c_next)
1101 if (freep->c_func == func && freep->c_arg == arg) {
1102 *copp = freep->c_next;
1103 free((char *) freep);
1104 break;
1105 }
1106}
1107
1108
1109/*
1110 * calltimeout - Call any timeout routines which are now due.
1111 */
1112static void
1113calltimeout()
1114{
1115 struct callout *p;
1116
1117 while (callout != NULL) {
1118 p = callout;
1119
1120 if (my_gettimeofday(&timenow, NULL) < 0)
1121 fatal("Failed to get time of day: %m");
1122 if (!(p->c_time.tv_sec < timenow.tv_sec
1123 || (p->c_time.tv_sec == timenow.tv_sec
1124 && p->c_time.tv_usec <= timenow.tv_usec)))
1125 break; /* no, it's not time yet */
1126
1127 callout = p->c_next;
1128 (*p->c_func)(p->c_arg);
1129
1130 free((char *) p);
1131 }
1132}
1133
1134
1135/*
1136 * timeleft - return the length of time until the next timeout is due.
1137 */
1138static struct timeval *
1139timeleft(tvp)
1140 struct timeval *tvp;
1141{
1142 if (callout == NULL)
1143 return NULL;
1144
1145 my_gettimeofday(&timenow, NULL);
1146 tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
1147 tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
1148 if (tvp->tv_usec < 0) {
1149 tvp->tv_usec += 1000000;
1150 tvp->tv_sec -= 1;
1151 }
1152 if (tvp->tv_sec < 0)
1153 tvp->tv_sec = tvp->tv_usec = 0;
1154
1155 return tvp;
1156}
1157
1158
1159/*
1160 * kill_my_pg - send a signal to our process group, and ignore it ourselves.
1161 */
1162static void
1163kill_my_pg(sig)
1164 int sig;
1165{
1166 struct sigaction act, oldact;
1167
1168 act.sa_handler = SIG_IGN;
1169 act.sa_flags = 0;
1170 kill(0, sig);
1171 sigaction(sig, &act, &oldact);
1172 sigaction(sig, &oldact, NULL);
1173}
1174
1175
1176/*
1177 * hup - Catch SIGHUP signal.
1178 *
1179 * Indicates that the physical layer has been disconnected.
1180 * We don't rely on this indication; if the user has sent this
1181 * signal, we just take the link down.
1182 */
1183static void
1184hup(sig)
1185 int sig;
1186{
1187 info("Hangup (SIGHUP)");
1188 got_sighup = 1;
1189 if (conn_running)
1190 /* Send the signal to the [dis]connector process(es) also */
1191 kill_my_pg(sig);
1192 if (waiting)
1193 siglongjmp(sigjmp, 1);
1194}
1195
1196
1197/*
1198 * term - Catch SIGTERM signal and SIGINT signal (^C/del).
1199 *
1200 * Indicates that we should initiate a graceful disconnect and exit.
1201 */
1202/*ARGSUSED*/
1203static void
1204term(sig)
1205 int sig;
1206{
1207 info("Terminating on signal %d.", sig);
1208 got_sigterm = 1;
1209 if (conn_running)
1210 /* Send the signal to the [dis]connector process(es) also */
1211 kill_my_pg(sig);
1212 if (waiting)
1213 siglongjmp(sigjmp, 1);
1214}
1215
1216
1217/*
1218 * chld - Catch SIGCHLD signal.
1219 * Sets a flag so we will call reap_kids in the mainline.
1220 */
1221static void
1222chld(sig)
1223 int sig;
1224{
1225 got_sigchld = 1;
1226 if (waiting)
1227 siglongjmp(sigjmp, 1);
1228}
1229
1230
1231/*
1232 * toggle_debug - Catch SIGUSR1 signal.
1233 *
1234 * Toggle debug flag.
1235 */
1236/*ARGSUSED*/
1237static void
1238toggle_debug(sig)
1239 int sig;
1240{
1241 debug = !debug;
1242 if (debug) {
1243 setlogmask(LOG_UPTO(LOG_DEBUG));
1244 } else {
1245 setlogmask(LOG_UPTO(LOG_WARNING));
1246 }
1247}
1248
1249
1250/*
1251 * open_ccp - Catch SIGUSR2 signal.
1252 *
1253 * Try to (re)negotiate compression.
1254 */
1255/*ARGSUSED*/
1256static void
1257open_ccp(sig)
1258 int sig;
1259{
1260 got_sigusr2 = 1;
1261 if (waiting)
1262 siglongjmp(sigjmp, 1);
1263}
1264
1265
1266/*
1267 * bad_signal - We've caught a fatal signal. Clean up state and exit.
1268 */
1269static void
1270bad_signal(sig)
1271 int sig;
1272{
1273 static int crashed = 0;
1274
1275 if (crashed)
1276 _exit(127);
1277 crashed = 1;
1278 error("Fatal signal %d", sig);
1279 if (conn_running)
1280 kill_my_pg(SIGTERM);
1281 die(127);
1282}
1283
1284/*
1285 * run-program - execute a program with given arguments,
1286 * but don't wait for it.
1287 * If the program can't be executed, logs an error unless
1288 * must_exist is 0 and the program file doesn't exist.
1289 * Returns -1 if it couldn't fork, 0 if the file doesn't exist
1290 * or isn't an executable plain file, or the process ID of the child.
1291 * If done != NULL, (*done)(arg) will be called later (within
1292 * reap_kids) iff the return value is > 0.
1293 */
1294pid_t
1295run_program(prog, args, must_exist, done, arg)
1296 char *prog;
1297 char **args;
1298 int must_exist;
1299 void (*done) __P((void *));
1300 void *arg;
1301{
1302 int pid;
1303 struct stat sbuf;
1304
1305 /*
1306 * First check if the file exists and is executable.
1307 * We don't use access() because that would use the
1308 * real user-id, which might not be root, and the script
1309 * might be accessible only to root.
1310 */
1311 errno = EINVAL;
1312 if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
1313 || (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
1314 if (must_exist || errno != ENOENT)
1315 warn("Can't execute %s: %m", prog);
1316 return 0;
1317 }
1318
1319 pid = fork();
1320 if (pid == -1) {
1321 error("Failed to create child process for %s: %m", prog);
1322 return -1;
1323 }
1324 if (pid == 0) {
1325 int new_fd;
1326
1327 /* Leave the current location */
1328 (void) setsid(); /* No controlling tty. */
1329 (void) umask (S_IRWXG|S_IRWXO);
1330 (void) chdir ("/"); /* no current directory. */
1331 setuid(0); /* set real UID = root */
1332 setgid(getegid());
1333
1334 /* Ensure that nothing of our device environment is inherited. */
1335 sys_close();
1336 closelog();
1337 close (0);
1338 close (1);
1339 close (2);
1340 if (the_channel->close)
1341 (*the_channel->close)();
1342
1343 /* Don't pass handles to the PPP device, even by accident. */
1344 new_fd = open (_PATH_DEVNULL, O_RDWR);
1345 if (new_fd >= 0) {
1346 if (new_fd != 0) {
1347 dup2 (new_fd, 0); /* stdin <- /dev/null */
1348 close (new_fd);
1349 }
1350 dup2 (0, 1); /* stdout -> /dev/null */
1351 dup2 (0, 2); /* stderr -> /dev/null */
1352 }
1353
1354#ifdef BSD
1355 /* Force the priority back to zero if pppd is running higher. */
1356 if (setpriority (PRIO_PROCESS, 0, 0) < 0)
1357 warn("can't reset priority to 0: %m");
1358#endif
1359
1360 /* SysV recommends a second fork at this point. */
1361
1362 /* run the program */
1363 execve(prog, args, script_env);
1364 if (must_exist || errno != ENOENT) {
1365 /* have to reopen the log, there's nowhere else
1366 for the message to go. */
1367 reopen_log();
1368 syslog(LOG_ERR, "Can't execute %s: %m", prog);
1369 closelog();
1370 }
1371 _exit(-1);
1372 }
1373
1374 if (debug)
1375 dbglog("Script %s started (pid %d)", prog, pid);
1376 record_child(pid, prog, done, arg);
1377
1378 return pid;
1379}
1380
1381
1382/*
1383 * record_child - add a child process to the list for reap_kids
1384 * to use.
1385 */
1386void
1387record_child(pid, prog, done, arg)
1388 int pid;
1389 char *prog;
1390 void (*done) __P((void *));
1391 void *arg;
1392{
1393 struct subprocess *chp;
1394
1395 ++n_children;
1396
1397 chp = (struct subprocess *) malloc(sizeof(struct subprocess));
1398 if (chp == NULL) {
1399 warn("losing track of %s process", prog);
1400 } else {
1401 chp->pid = pid;
1402 chp->prog = prog;
1403 chp->done = done;
1404 chp->arg = arg;
1405 chp->next = children;
1406 children = chp;
1407 }
1408}
1409
1410
1411/*
1412 * reap_kids - get status from any dead child processes,
1413 * and log a message for abnormal terminations.
1414 */
1415static int
1416reap_kids(waitfor)
1417 int waitfor;
1418{
1419 int pid, status;
1420 struct subprocess *chp, **prevp;
1421
1422 if (n_children == 0)
1423 return 0;
1424 while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
1425 && pid != 0) {
1426 for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) {
1427 if (chp->pid == pid) {
1428 --n_children;
1429 *prevp = chp->next;
1430 break;
1431 }
1432 }
1433 if (WIFSIGNALED(status)) {
1434 warn("Child process %s (pid %d) terminated with signal %d",
1435 (chp? chp->prog: "??"), pid, WTERMSIG(status));
1436 } else if (debug)
1437 dbglog("Script %s finished (pid %d), status = 0x%x",
1438 (chp? chp->prog: "??"), pid, status);
1439 if (chp && chp->done)
1440 (*chp->done)(chp->arg);
1441 if (chp)
1442 free(chp);
1443 }
1444 if (pid == -1) {
1445 if (errno == ECHILD)
1446 return -1;
1447 if (errno != EINTR)
1448 error("Error waiting for child process: %m");
1449 }
1450 return 0;
1451}
1452
1453/*
1454 * script_setenv - set an environment variable value to be used
1455 * for scripts that we run (e.g. ip-up, auth-up, etc.)
1456 */
1457void
1458script_setenv(var, value, iskey)
1459 char *var, *value;
1460 int iskey;
1461{
1462 size_t varl = strlen(var);
1463 size_t vl = varl + strlen(value) + 2;
1464 int i;
1465 char *p, *newstring;
1466
1467 newstring = (char *) malloc(vl+1);
1468 if (newstring == 0)
1469 return;
1470 *newstring++ = iskey;
1471 slprintf(newstring, vl, "%s=%s", var, value);
1472
1473 /* check if this variable is already set */
1474 if (script_env != 0) {
1475 for (i = 0; (p = script_env[i]) != 0; ++i) {
1476 if (strncmp(p, var, varl) == 0 && p[varl] == '=') {
1477 if (p[-1] && pppdb != NULL)
1478 delete_db_key(p);
1479 free(p-1);
1480 script_env[i] = newstring;
1481 if (iskey && pppdb != NULL)
1482 add_db_key(newstring);
1483 update_db_entry();
1484 return;
1485 }
1486 }
1487 } else {
1488 /* no space allocated for script env. ptrs. yet */
1489 i = 0;
1490 script_env = (char **) malloc(16 * sizeof(char *));
1491 if (script_env == 0)
1492 return;
1493 s_env_nalloc = 16;
1494 }
1495
1496 /* reallocate script_env with more space if needed */
1497 if (i + 1 >= s_env_nalloc) {
1498 int new_n = i + 17;
1499 char **newenv = (char **) realloc((void *)script_env,
1500 new_n * sizeof(char *));
1501 if (newenv == 0)
1502 return;
1503 script_env = newenv;
1504 s_env_nalloc = new_n;
1505 }
1506
1507 script_env[i] = newstring;
1508 script_env[i+1] = 0;
1509
1510 if (pppdb != NULL) {
1511 if (iskey)
1512 add_db_key(newstring);
1513 update_db_entry();
1514 }
1515}
1516
1517/*
1518 * script_unsetenv - remove a variable from the environment
1519 * for scripts.
1520 */
1521void
1522script_unsetenv(var)
1523 char *var;
1524{
1525 int vl = strlen(var);
1526 int i;
1527 char *p;
1528
1529 if (script_env == 0)
1530 return;
1531 for (i = 0; (p = script_env[i]) != 0; ++i) {
1532 if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
1533 if (p[-1] && pppdb != NULL)
1534 delete_db_key(p);
1535 free(p-1);
1536 while ((script_env[i] = script_env[i+1]) != 0)
1537 ++i;
1538 break;
1539 }
1540 }
1541 if (pppdb != NULL)
1542 update_db_entry();
1543}