tmp.c
来源:互联网 发布:python while循环终止 编辑:程序博客网 时间:2024/06/05 15:09
/*
* main.c - Point-to-Point Protocol main module
*
* Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The name "Carnegie Mellon University" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For permission or any legal
* details, please contact
* Office of Technology Transfer
* Carnegie Mellon University
* 5000 Forbes Avenue
* Pittsburgh, PA 15213-3890
* (412) 268-4387, fax: (412) 268-7395
* tech-transfer@andrew.cmu.edu
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Computing Services
* at Carnegie Mellon University (http://www.cmu.edu/computing/)."
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Copyright (c) 1999-2004 Paul Mackerras. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. The name(s) of the authors of this software must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 3. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by Paul Mackerras
* <paulus@samba.org>".
*
* THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RCSID "$Id: main.c,v 1.156 2008/06/23 11:47:18 paulus Exp $"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <syslog.h>
#include <netdb.h>
#include <utmp.h>
#include <pwd.h>
#include <setjmp.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "pppd.h"
#include "magic.h"
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
#ifdef INET6
#include "ipv6cp.h"
#endif
#include "upap.h"
#include "chap-new.h"
#include "eap.h"
#include "ccp.h"
#include "ecp.h"
#include "pathnames.h"
#ifdef USE_TDB
#include "tdb.h"
#endif
#ifdef CBCP_SUPPORT
#include "cbcp.h"
#endif
#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif /* IPX_CHANGE */
#ifdef AT_CHANGE
#include "atcp.h"
#endif
static const char rcsid[] = RCSID;
/* interface vars */
char ifname[32]; /* Interface name */
int ifunit; /* Interface unit number */
struct channel *the_channel;
char *progname; /* Name of this program */
char hostname[MAXNAMELEN]; /* Our hostname */
static char pidfilename[MAXPATHLEN]; /* name of pid file */
static char linkpidfile[MAXPATHLEN]; /* name of linkname pid file */
char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
uid_t uid; /* Our real user-id */
struct notifier *pidchange = NULL;
struct notifier *phasechange = NULL;
struct notifier *exitnotify = NULL;
struct notifier *sigreceived = NULL;
struct notifier *fork_notifier = NULL;
int hungup; /* terminal has been hung up */
int privileged; /* we're running as real uid root */
int need_holdoff; /* need holdoff period before restarting */
int detached; /* have detached from terminal */
volatile int status; /* exit status for pppd */
int unsuccess; /* # unsuccessful connection attempts */
int do_callback; /* != 0 if we should do callback next */
int doing_callback; /* != 0 if we are doing callback */
int ppp_session_number; /* Session number, for channels with such a
concept (eg PPPoE) */
int childwait_done; /* have timed out waiting for children */
#ifdef USE_TDB
TDB_CONTEXT *pppdb; /* database for storing status etc. */
#endif
char db_key[32];
int ( *holdoff_hook ) __P ( ( void ) ) = NULL;
int ( *new_phase_hook ) __P ( ( int ) ) = NULL;
void ( *snoop_recv_hook ) __P ( ( unsigned char *p, int len ) ) = NULL;
void ( *snoop_send_hook ) __P ( ( unsigned char *p, int len ) ) = NULL;
static int conn_running; /* we have a [dis]connector running */
static int fd_loop; /* fd for getting demand-dial packets */
int fd_devnull; /* fd for /dev/null */
int devfd = -1; /* fd of underlying device */
int fd_ppp = -1; /* fd for talking PPP */
int phase; /* where the link is at */
int kill_link;
int asked_to_quit;
int open_ccp_flag;
int listen_time;
int got_sigusr2;
int got_sigterm;
int got_sighup;
static sigset_t signals_handled;
static int waiting;
static sigjmp_buf sigjmp;
char **script_env; /* Env. variable values for scripts */
int s_env_nalloc; /* # words avail at script_env */
u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
static int n_children; /* # child processes still running */
static int got_sigchld; /* set if we have received a SIGCHLD */
int privopen; /* don't lock, open device as root */
char *no_ppp_msg = "Sorry - this system lacks PPP kernel support/n";
GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
int ngroups; /* How many groups valid in groups */
static struct timeval start_time; /* Time when link was started. */
static struct pppd_stats old_link_stats;
struct pppd_stats link_stats;
unsigned link_connect_time;
int link_stats_valid;
int error_count;
bool bundle_eof;
bool bundle_terminating;
/*
* We maintain a list of child process pids and
* functions to call when they exit.
*/
struct subprocess
{
pid_t pid;
char *prog;
void ( *done ) __P ( ( void * ) );
void *arg;
int killable;
struct subprocess *next;
};
static struct subprocess *children;
/* Prototypes for procedures local to this file. */
static void setup_signals __P ( ( void ) );
static void create_pidfile __P ( ( int pid ) );
static void create_linkpidfile __P ( ( int pid ) );
static void cleanup __P ( ( void ) );
static void get_input __P ( ( void ) );
static void calltimeout __P ( ( void ) );
static struct timeval *timeleft __P ( ( struct timeval * ) );
static void kill_my_pg __P ( ( int ) );
static void hup __P ( ( int ) );
static void term __P ( ( int ) );
static void chld __P ( ( int ) );
static void toggle_debug __P ( ( int ) );
static void open_ccp __P ( ( int ) );
static void bad_signal __P ( ( int ) );
static void holdoff_end __P ( ( void * ) );
static void forget_child __P ( ( int pid, int status ) );
static int reap_kids __P ( ( void ) );
static void childwait_end __P ( ( void * ) );
#ifdef USE_TDB
static void update_db_entry __P ( ( void ) );
static void add_db_key __P ( ( const char * ) );
static void delete_db_key __P ( ( const char * ) );
static void cleanup_db __P ( ( void ) );
#endif
static void handle_events __P ( ( void ) );
void print_link_stats __P ( ( void ) );
extern char *ttyname __P ( ( int ) );
extern char *getlogin __P ( ( void ) );
int main __P ( ( int, char *[] ) );
#ifdef ultrix
#undef O_NONBLOCK
#define O_NONBLOCK O_NDELAY
#endif
#ifdef ULTRIX
#define setlogmask(x)
#endif
/*
* PPP Data Link Layer "protocol" table.
* One entry per supported protocol.
* The last entry must be NULL.
*/
struct protent *protocols[] =
{
&lcp_protent,
&pap_protent,
&chap_protent,
#ifdef CBCP_SUPPORT
&cbcp_protent,
#endif
&ipcp_protent,
#ifdef INET6
&ipv6cp_protent,
#endif
&ccp_protent,
&ecp_protent,
#ifdef IPX_CHANGE
&ipxcp_protent,
#endif
#ifdef AT_CHANGE
&atcp_protent,
#endif
&eap_protent,
NULL
};
/*
* If PPP_DRV_NAME is not defined, use the default "ppp" as the device name.
*/
#if !defined(PPP_DRV_NAME)
#define PPP_DRV_NAME "ppp"
#endif /* !defined(PPP_DRV_NAME) */
int main ( int argc, char *argv[] )
{
int i, t;
char *p;
struct passwd *pw;
struct protent *protp;
char numbuf[16];
link_stats_valid = 0;
new_phase ( PHASE_INITIALIZE );
script_env = NULL;
/* Initialize syslog facilities */
reopen_log();
if ( gethostname ( hostname, MAXNAMELEN ) < 0 )
{
option_error ( "Couldn't get hostname: %m" );
exit ( 1 );
}
hostname[MAXNAMELEN-1] = 0;
/* make sure we don't create world or group writable files. */
umask ( umask ( 0777 ) | 022 );
uid = getuid();
privileged = uid == 0;
slprintf ( numbuf, sizeof ( numbuf ), "%d", uid );
script_setenv ( "ORIG_UID", numbuf, 0 );
ngroups = getgroups ( NGROUPS_MAX, groups );
/*
* Initialize magic number generator now so that protocols may
* use magic numbers in initialization.
*/
magic_init();
/*
* Initialize each protocol.
*/
for ( i = 0; ( protp = protocols[i] ) != NULL; ++i )
{
( *protp->init ) ( 0 );
}
/*
* Initialize the default channel.
*/
tty_init();
progname = *argv;
/*
* Parse, in order, the system options file, the user's options file,
* and the command line arguments.
*/
if ( !options_from_file ( _PATH_SYSOPTIONS, !privileged, 0, 1 ) || !options_from_user() || !parse_args ( argc - 1, argv + 1 ) )
{
exit ( EXIT_OPTION_ERROR );
}
/* add by wangchenxi */
getchar();
devnam_fixed = 1; /* can no longer change device name */
/*
* Work out the device name, if it hasn't already been specified,
* and parse the tty's options file.
*/
if ( the_channel->process_extra_options )
{
( *the_channel->process_extra_options ) ();
}
if ( debug )
{
setlogmask ( LOG_UPTO ( LOG_DEBUG ) );
}
/*
* Check that we are running as root.
*/
if ( geteuid() != 0 )
{
option_error ( "must be root to run %s, since it is not setuid-root", argv[0] );
exit ( EXIT_NOT_ROOT );
}
if ( !ppp_available() )
{
option_error ( "%s", no_ppp_msg );
exit ( EXIT_NO_KERNEL_SUPPORT );
}
/*
* Check that the options given are valid and consistent.
*/
check_options();
if ( !sys_check_options() )
{
exit ( EXIT_OPTION_ERROR );
}
auth_check_options();
#ifdef HAVE_MULTILINK
mp_check_options();
#endif
for ( i = 0; ( protp = protocols[i] ) != NULL; ++i )
{
if ( protp->check_options != NULL )
( *protp->check_options ) ();
}
if ( the_channel->check_options )
{
( *the_channel->check_options ) ();
}
if ( dump_options || dryrun )
{
init_pr_log ( NULL, LOG_INFO );
print_options ( pr_log, NULL );
end_pr_log();
}
if ( dryrun )
{
die ( 0 );
}
/* Make sure fds 0, 1, 2 are open to somewhere. */
fd_devnull = open ( _PATH_DEVNULL, O_RDWR );
if ( fd_devnull < 0 )
{
fatal ( "Couldn't open %s: %m", _PATH_DEVNULL );
}
while ( fd_devnull <= 2 )
{
i = dup ( fd_devnull );
if ( i < 0 )
fatal ( "Critical shortage of file descriptors: dup failed: %m" );
fd_devnull = i;
}
/*
* Initialize system-dependent stuff.
*/
sys_init();
#ifdef USE_TDB
pppdb = tdb_open ( _PATH_PPPDB, 0, 0, O_RDWR | O_CREAT, 0644 );
if ( pppdb != NULL )
{
slprintf ( db_key, sizeof ( db_key ), "pppd%d", getpid() );
update_db_entry();
}
else
{
warn ( "Warning: couldn't open ppp database %s", _PATH_PPPDB );
if ( multilink )
{
warn ( "Warning: disabling multilink" );
multilink = 0;
}
}
#endif
/*
* Detach ourselves from the terminal, if required,
* and identify who is running us.
*/
if ( !nodetach && !updetach )
detach();
p = getlogin();
if ( p == NULL )
{
pw = getpwuid ( uid );
if ( pw != NULL && pw->pw_name != NULL )
p = pw->pw_name;
else
p = "(unknown)";
}
syslog ( LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid );
script_setenv ( "PPPLOGNAME", p, 0 );
if ( devnam[0] )
script_setenv ( "DEVICE", devnam, 1 );
slprintf ( numbuf, sizeof ( numbuf ), "%d", getpid() );
script_setenv ( "PPPD_PID", numbuf, 1 );
setup_signals();
create_linkpidfile ( getpid() );
waiting = 0;
/*
* If we're doing dial-on-demand, set up the interface now.
*/
if ( demand )
{
/*
* Open the loopback channel and set it up to be the ppp interface.
*/
fd_loop = open_ppp_loopback();
set_ifunit ( 1 );
/*
* Configure the interface and mark it up, etc.
*/
demand_conf();
}
do_callback = 0;
for ( ;; )
{
bundle_eof = 0;
bundle_terminating = 0;
listen_time = 0;
need_holdoff = 1;
devfd = -1;
status = EXIT_OK;
++unsuccess;
doing_callback = do_callback;
do_callback = 0;
if ( demand && !doing_callback )
{
/*
* Don't do anything until we see some activity.
*/
new_phase ( PHASE_DORMANT );
demand_unblock();
add_fd ( fd_loop );
for ( ;; )
{
handle_events();
if ( asked_to_quit )
break;
if ( get_loop_output() )
break;
}
remove_fd ( fd_loop );
if ( asked_to_quit )
break;
/*
* Now we want to bring up the link.
*/
demand_block();
info ( "Starting link" );
}
gettimeofday ( &start_time, NULL );
script_unsetenv ( "CONNECT_TIME" );
script_unsetenv ( "BYTES_SENT" );
script_unsetenv ( "BYTES_RCVD" );
lcp_open ( 0 ); /* Start protocol */
start_link ( 0 );
while ( phase != PHASE_DEAD )
{
handle_events();
get_input();
if ( kill_link )
lcp_close ( 0, "User request" );
if ( asked_to_quit )
{
bundle_terminating = 1;
if ( phase == PHASE_MASTER )
mp_bundle_terminated();
}
if ( open_ccp_flag )
{
if ( phase == PHASE_NETWORK || phase == PHASE_RUNNING )
{
ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
( *ccp_protent.open ) ( 0 );
}
}
}
/* restore FSMs to original state */
lcp_close ( 0, "" );
if ( !persist || asked_to_quit || ( maxfail > 0 && unsuccess >= maxfail ) )
break;
if ( demand )
demand_discard();
t = need_holdoff ? holdoff : 0;
if ( holdoff_hook )
t = ( *holdoff_hook ) ();
if ( t > 0 )
{
new_phase ( PHASE_HOLDOFF );
TIMEOUT ( holdoff_end, NULL, t );
do
{
handle_events();
if ( kill_link )
new_phase ( PHASE_DORMANT ); /* allow signal to end holdoff */
}
while ( phase == PHASE_HOLDOFF );
if ( !persist )
break;
}
}
/* Wait for scripts to finish */
reap_kids();
if ( n_children > 0 )
{
if ( child_wait > 0 )
TIMEOUT ( childwait_end, NULL, child_wait );
if ( debug )
{
struct subprocess *chp;
dbglog ( "Waiting for %d child processes...", n_children );
for ( chp = children; chp != NULL; chp = chp->next )
dbglog ( " script %s, pid %d", chp->prog, chp->pid );
}
while ( n_children > 0 && !childwait_done )
{
handle_events();
if ( kill_link && !childwait_done )
childwait_end ( NULL );
}
}
die ( status );
return 0;
}
/*
* handle_events - wait for something to happen and respond to it.
*/
static void handle_events()
{
struct timeval timo;
kill_link = open_ccp_flag = 0;
if ( sigsetjmp ( sigjmp, 1 ) == 0 )
{
sigprocmask ( SIG_BLOCK, &signals_handled, NULL );
if ( got_sighup || got_sigterm || got_sigusr2 || got_sigchld )
{
sigprocmask ( SIG_UNBLOCK, &signals_handled, NULL );
}
else
{
waiting = 1;
sigprocmask ( SIG_UNBLOCK, &signals_handled, NULL );
wait_input ( timeleft ( &timo ) );
}
}
waiting = 0;
calltimeout();
if ( got_sighup )
{
info ( "Hangup (SIGHUP)" );
kill_link = 1;
got_sighup = 0;
if ( status != EXIT_HANGUP )
status = EXIT_USER_REQUEST;
}
if ( got_sigterm )
{
info ( "Terminating on signal %d", got_sigterm );
kill_link = 1;
asked_to_quit = 1;
persist = 0;
status = EXIT_USER_REQUEST;
got_sigterm = 0;
}
if ( got_sigchld )
{
got_sigchld = 0;
reap_kids(); /* Don't leave dead kids lying around */
}
if ( got_sigusr2 )
{
open_ccp_flag = 1;
got_sigusr2 = 0;
}
}
/*
* setup_signals - initialize signal handling.
*/
static void setup_signals()
{
struct sigaction sa;
/*
* Compute mask of all interesting signals and install signal handlers
* for each. Only one signal handler may be active at a time. Therefore,
* all other signals should be masked when any handler is executing.
*/
sigemptyset ( &signals_handled );
sigaddset ( &signals_handled, SIGHUP );
sigaddset ( &signals_handled, SIGINT );
sigaddset ( &signals_handled, SIGTERM );
sigaddset ( &signals_handled, SIGCHLD );
sigaddset ( &signals_handled, SIGUSR2 );
#define SIGNAL(s, handler) do { /
sa.sa_handler = handler; /
if (sigaction(s, &sa, NULL) < 0) /
fatal("Couldn't establish signal handler (%d): %m", s); /
} while (0)
sa.sa_mask = signals_handled;
sa.sa_flags = 0;
SIGNAL ( SIGHUP, hup ); /* Hangup */
SIGNAL ( SIGINT, term ); /* Interrupt */
SIGNAL ( SIGTERM, term ); /* Terminate */
SIGNAL ( SIGCHLD, chld );
SIGNAL ( SIGUSR1, toggle_debug ); /* Toggle debug flag */
SIGNAL ( SIGUSR2, open_ccp ); /* Reopen CCP */
/*
* Install a handler for other signals which would otherwise
* cause pppd to exit without cleaning up.
*/
SIGNAL ( SIGABRT, bad_signal );
SIGNAL ( SIGALRM, bad_signal );
SIGNAL ( SIGFPE, bad_signal );
SIGNAL ( SIGILL, bad_signal );
SIGNAL ( SIGPIPE, bad_signal );
SIGNAL ( SIGQUIT, bad_signal );
SIGNAL ( SIGSEGV, bad_signal );
#ifdef SIGBUS
SIGNAL ( SIGBUS, bad_signal );
#endif
#ifdef SIGEMT
SIGNAL ( SIGEMT, bad_signal );
#endif
#ifdef SIGPOLL
SIGNAL ( SIGPOLL, bad_signal );
#endif
#ifdef SIGPROF
SIGNAL ( SIGPROF, bad_signal );
#endif
#ifdef SIGSYS
SIGNAL ( SIGSYS, bad_signal );
#endif
#ifdef SIGTRAP
SIGNAL ( SIGTRAP, bad_signal );
#endif
#ifdef SIGVTALRM
SIGNAL ( SIGVTALRM, bad_signal );
#endif
#ifdef SIGXCPU
SIGNAL ( SIGXCPU, bad_signal );
#endif
#ifdef SIGXFSZ
SIGNAL ( SIGXFSZ, bad_signal );
#endif
/*
* Apparently we can get a SIGPIPE when we call syslog, if
* syslogd has died and been restarted. Ignoring it seems
* be sufficient.
*/
signal ( SIGPIPE, SIG_IGN );
}
/*
* set_ifunit - do things we need to do once we know which ppp
* unit we are using.
*/
void set_ifunit ( int iskey )
{
info ( "Using interface %s%d", PPP_DRV_NAME, ifunit );
slprintf ( ifname, sizeof ( ifname ), "%s%d", PPP_DRV_NAME, ifunit );
script_setenv ( "IFNAME", ifname, iskey );
if ( iskey )
{
create_pidfile ( getpid() ); /* write pid to file */
create_linkpidfile ( getpid() );
}
}
/*
* detach - detach us from the controlling terminal.
*/
void detach()
{
int pid;
char numbuf[16];
int pipefd[2];
if ( detached )
return;
if ( pipe ( pipefd ) == -1 )
pipefd[0] = pipefd[1] = -1;
if ( ( pid = fork() ) < 0 )
{
error ( "Couldn't detach (fork failed: %m)" );
die ( 1 ); /* or just return? */
}
if ( pid != 0 )
{
/* parent */
notify ( pidchange, pid );
/* update pid files if they have been written already */
if ( pidfilename[0] )
create_pidfile ( pid );
if ( linkpidfile[0] )
create_linkpidfile ( pid );
exit ( 0 ); /* parent dies */
}
setsid();
chdir ( "/" );
dup2 ( fd_devnull, 0 );
dup2 ( fd_devnull, 1 );
dup2 ( fd_devnull, 2 );
detached = 1;
if ( log_default )
log_to_fd = -1;
slprintf ( numbuf, sizeof ( numbuf ), "%d", getpid() );
script_setenv ( "PPPD_PID", numbuf, 1 );
/* wait for parent to finish updating pid & lock files and die */
close ( pipefd[1] );
complete_read ( pipefd[0], numbuf, 1 );
close ( pipefd[0] );
}
/*
* reopen_log - (re)open our connection to syslog.
*/
void reopen_log()
{
openlog ( "pppd", LOG_PID | LOG_NDELAY, LOG_PPP );
setlogmask ( LOG_UPTO ( LOG_INFO ) );
}
/*
* Create a file containing our process ID.
*/
static void create_pidfile ( pid )
int pid;
{
FILE *pidfile;
slprintf ( pidfilename, sizeof ( pidfilename ), "%s%s.pid",
_PATH_VARRUN, ifname );
if ( ( pidfile = fopen ( pidfilename, "w" ) ) != NULL )
{
fprintf ( pidfile, "%d/n", pid );
( void ) fclose ( pidfile );
}
else
{
error ( "Failed to create pid file %s: %m", pidfilename );
pidfilename[0] = 0;
}
}
void create_linkpidfile ( pid )
int pid;
{
FILE *pidfile;
if ( linkname[0] == 0 )
return;
script_setenv ( "LINKNAME", linkname, 1 );
slprintf ( linkpidfile, sizeof ( linkpidfile ), "%sppp-%s.pid",
_PATH_VARRUN, linkname );
if ( ( pidfile = fopen ( linkpidfile, "w" ) ) != NULL )
{
fprintf ( pidfile, "%d/n", pid );
if ( ifname[0] )
fprintf ( pidfile, "%s/n", ifname );
( void ) fclose ( pidfile );
}
else
{
error ( "Failed to create pid file %s: %m", linkpidfile );
linkpidfile[0] = 0;
}
}
/*
* remove_pidfile - remove our pid files
*/
void remove_pidfiles()
{
if ( pidfilename[0] != 0 && unlink ( pidfilename ) < 0 && errno != ENOENT )
warn ( "unable to delete pid file %s: %m", pidfilename );
pidfilename[0] = 0;
if ( linkpidfile[0] != 0 && unlink ( linkpidfile ) < 0 && errno != ENOENT )
warn ( "unable to delete pid file %s: %m", linkpidfile );
linkpidfile[0] = 0;
}
/*
* holdoff_end - called via a timeout when the holdoff period ends.
*/
static void holdoff_end ( void *arg )
{
new_phase ( PHASE_DORMANT );
}
/* List of protocol names, to make our messages a little more informative. */
struct protocol_list
{
u_short proto;
const char *name;
} protocol_list[] =
{
{ 0x21, "IP" },
{ 0x23, "OSI Network Layer" },
{ 0x25, "Xerox NS IDP" },
{ 0x27, "DECnet Phase IV" },
{ 0x29, "Appletalk" },
{ 0x2b, "Novell IPX" },
{ 0x2d, "VJ compressed TCP/IP" },
{ 0x2f, "VJ uncompressed TCP/IP" },
{ 0x31, "Bridging PDU" },
{ 0x33, "Stream Protocol ST-II" },
{ 0x35, "Banyan Vines" },
{ 0x39, "AppleTalk EDDP" },
{ 0x3b, "AppleTalk SmartBuffered" },
{ 0x3d, "Multi-Link" },
{ 0x3f, "NETBIOS Framing" },
{ 0x41, "Cisco Systems" },
{ 0x43, "Ascom Timeplex" },
{ 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" },
{ 0x47, "DCA Remote Lan" },
{ 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
{ 0x4b, "SNA over 802.2" },
{ 0x4d, "SNA" },
{ 0x4f, "IP6 Header Compression" },
{ 0x51, "KNX Bridging Data" },
{ 0x53, "Encryption" },
{ 0x55, "Individual Link Encryption" },
{ 0x57, "IPv6" },
{ 0x59, "PPP Muxing" },
{ 0x5b, "Vendor-Specific Network Protocol" },
{ 0x61, "RTP IPHC Full Header" },
{ 0x63, "RTP IPHC Compressed TCP" },
{ 0x65, "RTP IPHC Compressed non-TCP" },
{ 0x67, "RTP IPHC Compressed UDP 8" },
{ 0x69, "RTP IPHC Compressed RTP 8" },
{ 0x6f, "Stampede Bridging" },
{ 0x73, "MP+" },
{ 0xc1, "NTCITS IPI" },
{ 0xfb, "single-link compression" },
{ 0xfd, "Compressed Datagram" },
{ 0x0201, "802.1d Hello Packets" },
{ 0x0203, "IBM Source Routing BPDU" },
{ 0x0205, "DEC LANBridge100 Spanning Tree" },
{ 0x0207, "Cisco Discovery Protocol" },
{ 0x0209, "Netcs Twin Routing" },
{ 0x020b, "STP - Scheduled Transfer Protocol" },
{ 0x020d, "EDP - Extreme Discovery Protocol" },
{ 0x0211, "Optical Supervisory Channel Protocol" },
{ 0x0213, "Optical Supervisory Channel Protocol" },
{ 0x0231, "Luxcom" },
{ 0x0233, "Sigma Network Systems" },
{ 0x0235, "Apple Client Server Protocol" },
{ 0x0281, "MPLS Unicast" },
{ 0x0283, "MPLS Multicast" },
{ 0x0285, "IEEE p1284.4 standard - data packets" },
{ 0x0287, "ETSI TETRA Network Protocol Type 1" },
{ 0x0289, "Multichannel Flow Treatment Protocol" },
{ 0x2063, "RTP IPHC Compressed TCP No Delta" },
{ 0x2065, "RTP IPHC Context State" },
{ 0x2067, "RTP IPHC Compressed UDP 16" },
{ 0x2069, "RTP IPHC Compressed RTP 16" },
{ 0x4001, "Cray Communications Control Protocol" },
{ 0x4003, "CDPD Mobile Network Registration Protocol" },
{ 0x4005, "Expand accelerator protocol" },
{ 0x4007, "ODSICP NCP" },
{ 0x4009, "DOCSIS DLL" },
{ 0x400B, "Cetacean Network Detection Protocol" },
{ 0x4021, "Stacker LZS" },
{ 0x4023, "RefTek Protocol" },
{ 0x4025, "Fibre Channel" },
{ 0x4027, "EMIT Protocols" },
{ 0x405b, "Vendor-Specific Protocol (VSP)" },
{ 0x8021, "Internet Protocol Control Protocol" },
{ 0x8023, "OSI Network Layer Control Protocol" },
{ 0x8025, "Xerox NS IDP Control Protocol" },
{ 0x8027, "DECnet Phase IV Control Protocol" },
{ 0x8029, "Appletalk Control Protocol" },
{ 0x802b, "Novell IPX Control Protocol" },
{ 0x8031, "Bridging NCP" },
{ 0x8033, "Stream Protocol Control Protocol" },
{ 0x8035, "Banyan Vines Control Protocol" },
{ 0x803d, "Multi-Link Control Protocol" },
{ 0x803f, "NETBIOS Framing Control Protocol" },
{ 0x8041, "Cisco Systems Control Protocol" },
{ 0x8043, "Ascom Timeplex" },
{ 0x8045, "Fujitsu LBLB Control Protocol" },
{ 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" },
{ 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
{ 0x804b, "SNA over 802.2 Control Protocol" },
{ 0x804d, "SNA Control Protocol" },
{ 0x804f, "IP6 Header Compression Control Protocol" },
{ 0x8051, "KNX Bridging Control Protocol" },
{ 0x8053, "Encryption Control Protocol" },
{ 0x8055, "Individual Link Encryption Control Protocol" },
{ 0x8057, "IPv6 Control Protocol" },
{ 0x8059, "PPP Muxing Control Protocol" },
{ 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" },
{ 0x806f, "Stampede Bridging Control Protocol" },
{ 0x8073, "MP+ Control Protocol" },
{ 0x80c1, "NTCITS IPI Control Protocol" },
{ 0x80fb, "Single Link Compression Control Protocol" },
{ 0x80fd, "Compression Control Protocol" },
{ 0x8207, "Cisco Discovery Protocol Control" },
{ 0x8209, "Netcs Twin Routing" },
{ 0x820b, "STP - Control Protocol" },
{ 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" },
{ 0x8235, "Apple Client Server Protocol Control" },
{ 0x8281, "MPLSCP" },
{ 0x8285, "IEEE p1284.4 standard - Protocol Control" },
{ 0x8287, "ETSI TETRA TNP1 Control Protocol" },
{ 0x8289, "Multichannel Flow Treatment Protocol" },
{ 0xc021, "Link Control Protocol" },
{ 0xc023, "Password Authentication Protocol" },
{ 0xc025, "Link Quality Report" },
{ 0xc027, "Shiva Password Authentication Protocol" },
{ 0xc029, "CallBack Control Protocol (CBCP)" },
{ 0xc02b, "BACP Bandwidth Allocation Control Protocol" },
{ 0xc02d, "BAP" },
{ 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" },
{ 0xc081, "Container Control Protocol" },
{ 0xc223, "Challenge Handshake Authentication Protocol" },
{ 0xc225, "RSA Authentication Protocol" },
{ 0xc227, "Extensible Authentication Protocol" },
{ 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" },
{ 0xc26f, "Stampede Bridging Authorization Protocol" },
{ 0xc281, "Proprietary Authentication Protocol" },
{ 0xc283, "Proprietary Authentication Protocol" },
{ 0xc481, "Proprietary Node ID Authentication Protocol" },
{ 0, NULL },
};
/*
* protocol_name - find a name for a PPP protocol.
*/
const char * protocol_name ( int proto )
{
struct protocol_list *lp;
for ( lp = protocol_list; lp->proto != 0; ++lp )
if ( proto == lp->proto )
return lp->name;
return NULL;
}
/*
* get_input - called when incoming data is available.
*/
static void get_input()
{
int len, i;
u_char *p;
u_short protocol;
struct protent *protp;
p = inpacket_buf; /* point to beginning of packet buffer */
len = read_packet ( inpacket_buf );
if ( len < 0 )
return;
if ( len == 0 )
{
if ( bundle_eof && multilink_master )
{
notice ( "Last channel has disconnected" );
mp_bundle_terminated();
return;
}
notice ( "Modem hangup" );
hungup = 1;
status = EXIT_HANGUP;
lcp_lowerdown ( 0 ); /* serial link is no longer available */
link_terminated ( 0 );
return;
}
if ( len < PPP_HDRLEN )
{
dbglog ( "received short packet:%.*B", len, p );
return;
}
dump_packet ( "rcvd", p, len );
if ( snoop_recv_hook ) snoop_recv_hook ( p, len );
p += 2; /* Skip address and control */
GETSHORT ( protocol, p );
len -= PPP_HDRLEN;
/*
* Toss all non-LCP packets unless LCP is OPEN.
*/
if ( protocol != PPP_LCP && lcp_fsm[0].state != OPENED )
{
dbglog ( "Discarded non-LCP packet when LCP not open" );
return;
}
/*
* Until we get past the authentication phase, toss all packets
* except LCP, LQR and authentication packets.
*/
if ( phase <= PHASE_AUTHENTICATE
&& ! ( protocol == PPP_LCP || protocol == PPP_LQR
|| protocol == PPP_PAP || protocol == PPP_CHAP ||
protocol == PPP_EAP ) )
{
dbglog ( "discarding proto 0x%x in phase %d",
protocol, phase );
return;
}
/*
* Upcall the proper protocol input routine.
*/
for ( i = 0; ( protp = protocols[i] ) != NULL; ++i )
{
if ( protp->protocol == protocol && protp->enabled_flag )
{
( *protp->input ) ( 0, p, len );
return;
}
if ( protocol == ( protp->protocol & ~0x8000 ) && protp->enabled_flag
&& protp->datainput != NULL )
{
- tmp.c
- tmp.c
- tmp.c
- tmp.c
- tmp.c
- tmp
- tmp
- tmp
- tmp
- tmp
- tmp
- TMP
- tmp
- tmp
- tmp
- tmp
- Tmp
- tmp
- 如何在 Visual Studio 中像编辑普通 HTML 文件一样地编辑 SPARK 文件
- 数据加密中的DES加密算法详解
- 昨天冬至的饺子还在我肚子里转悠
- 正则表达式匹配单双引号
- POJ 1775 Sum of Factorials DFS 贪心
- tmp.c
- tmp.c
- tmp.c
- Symbian证书扫盲贴
- stl std::find使用
- Socket send函数和recv函数详解以及利用select()函数来进行指定时间的阻塞【转】
- exp/imp 与 expdp/impdp 对比 及使用中的一些优化事项
- Lucene学习总结之一:全文检索的基本原理
- Android全屏绘制