📄 rtemsmain.c
字号:
/* * main.c - Point-to-Point Protocol main module * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#define RCSID "$Id: rtemsmain.c,v 1.3.4.1 2003/04/10 13:09:09 joel 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 <netdb.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 <rtems.h>#include <rtems/rtems_bsdnet.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.h"#include "ccp.h"#include "pathnames.h"#include "patchlevel.h"#include "rtemsdialer.h"#ifdef CBCP_SUPPORT#include "cbcp.h"#endif#ifdef IPX_CHANGE#include "ipxcp.h"#endif /* IPX_CHANGE */#ifdef AT_CHANGE#include "atcp.h"#endifstatic const char rcsid[] = RCSID;/* interface vars */char ifname[32]; /* Interface name */int pppifunit; /* Interface unit number */char hostname[MAXNAMELEN]; /* Our hostname */static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */int ttyfd; /* Serial port file descriptor */int baud_rate; /* Actual bits/second for serial device */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 */struct stat devstat; /* result of stat() on devnam */int prepass = 0; /* doing prepass to find device name */int devnam_fixed; /* set while in options.ttyxx file */volatile int pppd_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 */char *callback_script; /* script for doing callback */dialerfp pppd_dialer;int (*holdoff_hook) __P((void)) = NULL;int (*new_phase_hook) __P((int)) = NULL;static int fd_ppp = -1; /* fd for talking PPP */static int pty_master; /* fd for master side of pty */static int pty_slave; /* fd for slave side of pty */static int real_ttyfd; /* fd for actual serial port (not pty) */int pppd_phase; /* where the link is at */int pppd_kill_link;int open_ccp_flag;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 */char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";static struct timeval start_time; /* Time when link was started. */struct pppd_stats link_stats;int link_connect_time;int link_stats_valid;/* Prototypes for procedures local to this file. */static void cleanup __P((void));static void close_tty __P((void));static void get_input __P((void));static void calltimeout __P((void));static struct timeval *timeleft __P((struct timeval *));static void holdoff_end __P((void *));static int device_script __P((int, int, char *));extern char *ttyname __P((int));extern char *getlogin __P((void));int pppdmain __P((int, char *[]));/* * 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,#ifdef IPX_CHANGE &ipxcp_protent,#endif#ifdef AT_CHANGE &atcp_protent,#endif NULL};intpppdmain(argc, argv) int argc; char *argv[];{ int i, fdflags, t; char *connector; struct timeval timo; struct protent *protp; new_phase(PHASE_INITIALIZE); script_env = NULL; hostname[MAXNAMELEN-1] = 0; privileged = 1; privileged_option = 1; /* * Initialize magic number generator now so that protocols may * use magic numbers in initialization. */ magic_init();#ifdef XXX_XXX /* moved code the the rtems_pppd_reset_options function */ /* * Initialize to the standard option set, then parse, in order, * the system options file, the user's options file, * the tty's options file, and the command line arguments. */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0);#endif if (!ppp_available()) { option_error(no_ppp_msg); return(EXIT_NO_KERNEL_SUPPORT); } /* * Check that the options given are valid and consistent. */ if (!sys_check_options()) { return(EXIT_OPTION_ERROR); } if (!auth_check_options()) { return(EXIT_OPTION_ERROR); } for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->check_options != NULL) (*protp->check_options)(); /* default holdoff to 0 if no connect script has been given */ if (connect_script == 0 && !holdoff_specified) holdoff = 0; if (default_device) nodetach = 1; /* * Initialize system-dependent stuff. */ sys_init(); /* if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); */ do_callback = 0; for (;;) { need_holdoff = 1; ttyfd = -1; real_ttyfd = -1; pppd_status = EXIT_OK; ++unsuccess; doing_callback = do_callback; do_callback = 0; new_phase(PHASE_SERIALCONN); /* * Get a pty master/slave pair if the pty, notty, or record * options were specified. */ strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam)); pty_master = -1; pty_slave = -1; /* * Open the serial device and set it up to be the ppp interface. * First we open it in non-blocking mode so we can set the * various termios flags appropriately. If we aren't dialling * out and we want to use the modem lines, we reopen it later * in order to wait for the carrier detect signal from the modem. */ hungup = 0; pppd_kill_link = 0; connector = doing_callback? callback_script: connect_script; if (devnam[0] != 0) { for (;;) { /* If the user specified the device name, become the user before opening it. */ int err; ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); err = errno; if (ttyfd >= 0) { break; } errno = err; if (err != EINTR) { error("Failed to open %s: %m", devnam); pppd_status = EXIT_OPEN_FAILED; } if (!persist || err != EINTR) goto fail; } if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) warn("Couldn't reset non-blocking mode on device: %m"); /* * Set line speed, flow control, etc. * If we have a non-null connection or initializer script, * on most systems we set CLOCAL for now so that we can talk * to the modem before carrier comes up. But this has the * side effect that we might miss it if CD drops before we * get to clear CLOCAL below. On systems where we can talk * successfully to the modem with CLOCAL clear and CD down, * we could clear CLOCAL at this point. */ set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0) || initializer != NULL)); real_ttyfd = ttyfd; } /* run connection script */ if ((connector && connector[0]) || initializer) { if (real_ttyfd != -1) { /* XXX do this if doing_callback == CALLBACK_DIALIN? */ if (!default_device && modem) { setdtr(real_ttyfd, 0); /* in case modem is off hook */ sleep(1); setdtr(real_ttyfd, 1); } } if (initializer && initializer[0]) { if (device_script(ttyfd, DIALER_INIT, initializer) < 0) { error("Initializer script failed"); pppd_status = EXIT_INIT_FAILED; goto fail; } if (pppd_kill_link) goto disconnect; info("Serial port initialized."); } if (connector && connector[0]) { if (device_script(ttyfd, DIALER_CONNECT, connector) < 0) { error("Connect script failed"); pppd_status = EXIT_CONNECT_FAILED; goto fail; } if (pppd_kill_link) goto disconnect; info("Serial connection established."); } /* set line speed, flow control, etc.; clear CLOCAL if modem option */ if (real_ttyfd != -1) set_up_tty(real_ttyfd, 0); if (doing_callback == CALLBACK_DIALIN) connector = NULL; } /* reopen tty if necessary to wait for carrier */ if (connector == NULL && modem && devnam[0] != 0) { for (;;) { if ((i = open(devnam, O_RDWR)) >= 0) break; if (errno != EINTR) { error("Failed to reopen %s: %m", devnam); pppd_status = EXIT_OPEN_FAILED; } if (!persist || errno != EINTR || hungup || pppd_kill_link) goto fail; } close(i); } info("Serial connection established."); sleep(1); /* run welcome script, if any */ if (welcomer && welcomer[0]) { if (device_script(ttyfd, DIALER_WELCOME, welcomer) < 0) warn("Welcome script failed"); } /* set up the serial device as a ppp interface */ fd_ppp = establish_ppp(ttyfd); if (fd_ppp < 0) { pppd_status = EXIT_FATAL_ERROR; goto disconnect; } if (!demand) { info("Using interface ppp%d", pppifunit); slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit); } /* * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ notice("Connect: %s <--> %s", ifname, ppp_devnam); gettimeofday(&start_time, NULL); lcp_lowerup(0); lcp_open(0); /* Start protocol */ open_ccp_flag = 0; pppd_status = EXIT_NEGOTIATION_FAILED; new_phase(PHASE_ESTABLISH); while (pppd_phase != PHASE_DEAD) { wait_input(timeleft(&timo)); calltimeout(); get_input(); if (pppd_kill_link) { lcp_close(0, "User request"); pppd_kill_link = 0; } if (open_ccp_flag) { if (pppd_phase == PHASE_NETWORK || pppd_phase == PHASE_RUNNING) { ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ (*ccp_protent.open)(0); } open_ccp_flag = 0; } } /* * If we may want to bring the link up again, transfer * the ppp unit back to the loopback. Set the * real serial device back to its normal mode of operation. */ clean_check(); if (demand) restore_loop(); disestablish_ppp(ttyfd); fd_ppp = -1; if (!hungup) lcp_lowerdown(0); /* * Run disconnector script, if requested. * XXX we may not be able to do this if the line has hung up! */ disconnect: if (disconnect_script && !hungup) { new_phase(PHASE_DISCONNECT); if (real_ttyfd >= 0) set_up_tty(real_ttyfd, 1); if (device_script(ttyfd, DIALER_DISCONNECT, disconnect_script) < 0) { warn("disconnect script failed"); } else { info("Serial link disconnected."); } } fail: if (pty_master >= 0) close(pty_master); if (pty_slave >= 0) close(pty_slave); if (real_ttyfd >= 0) close_tty(); if (!persist || (maxfail > 0 && unsuccess >= maxfail)) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -