⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 4 页
字号:
		    kill_link = 0;		}		if (get_loop_output())		    break;		if (got_sigchld)		    reap_kids(0);	    }	    remove_fd(fd_loop);	    if (kill_link && !persist)		break;	    /*	     * Now we want to bring up the link.	     */	    demand_block();	    info("Starting link");	}	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;	if (ptycommand != NULL || notty || record_file != NULL) {	    if (!get_pty(&pty_master, &pty_slave, ppp_devnam, uid)) {		error("Couldn't allocate pseudo-tty");		status = EXIT_FATAL_ERROR;		goto fail;	    }	    set_up_tty(pty_slave, 1);	}	/*	 * Lock the device if we've been asked to.	 */	status = EXIT_LOCK_FAILED;	if (lockflag && !privopen) {	    if (lock(devnam) < 0)		goto fail;	    locked = 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;	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;		if (!devnam_info.priv && !privopen)		    seteuid(uid);		ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);		err = errno;		if (!devnam_info.priv && !privopen)		    seteuid(0);		if (ttyfd >= 0)		    break;		errno = err;		if (err != EINTR) {		    error("Failed to open %s: %m", devnam);		    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");	    /*	     * Do the equivalent of `mesg n' to stop broadcast messages.	     */	    if (fstat(ttyfd, &statbuf) < 0		|| fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {		warn("Couldn't restrict write permissions to %s: %m", devnam);	    } else		tty_mode = statbuf.st_mode;	    /*	     * 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;	}	/*	 * If the notty and/or record option was specified,	 * start up the character shunt now.	 */	status = EXIT_PTYCMD_FAILED;	if (ptycommand != NULL) {	    if (record_file != NULL) {		int ipipe[2], opipe[2], ok;		if (pipe(ipipe) < 0 || pipe(opipe) < 0)		    fatal("Couldn't create pipes for record option: %m");		ok = device_script(ptycommand, opipe[0], ipipe[1], 1) == 0		    && start_charshunt(ipipe[0], opipe[1]);		close(ipipe[0]);		close(ipipe[1]);		close(opipe[0]);		close(opipe[1]);		if (!ok)		    goto fail;	    } else {		if (device_script(ptycommand, pty_master, pty_master, 1) < 0)		    goto fail;		ttyfd = pty_slave;		close(pty_master);		pty_master = -1;	    }	} else if (notty) {	    if (!start_charshunt(0, 1))		goto fail;	} else if (record_file != NULL) {	    if (!start_charshunt(ttyfd, ttyfd))		goto fail;	}	/* 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(initializer, ttyfd, ttyfd, 0) < 0) {		    error("Initializer script failed");		    status = EXIT_INIT_FAILED;		    goto fail;		}		if (kill_link)		    goto disconnect;		info("Serial port initialized.");	    }	    if (connector && connector[0]) {		if (device_script(connector, ttyfd, ttyfd, 0) < 0) {		    error("Connect script failed");		    status = EXIT_CONNECT_FAILED;		    goto fail;		}		if (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);		    status = EXIT_OPEN_FAILED;		}		if (!persist || errno != EINTR || hungup || kill_link)		    goto fail;	    }	    close(i);	}	slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);	script_setenv("SPEED", numbuf);	/* run welcome script, if any */	if (welcomer && welcomer[0]) {	    if (device_script(welcomer, ttyfd, ttyfd, 0) < 0)		warn("Welcome script failed");	}	/* set up the serial device as a ppp interface */	fd_ppp = establish_ppp(ttyfd);	if (fd_ppp < 0) {	    status = EXIT_FATAL_ERROR;	    goto disconnect;	}	if (!demand) {	    	    info("Using interface ppp%d", ifunit);	    slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);	    script_setenv("IFNAME", ifname);	    create_pidfile();	/* write pid to file */	}	/*	 * Start opening the connection and wait for	 * incoming events (reply, timeout, etc.).	 */	notice("Connect: %s <--> %s", ifname, ppp_devnam);	gettimeofday(&start_time, NULL);	link_stats_valid = 0;	script_unsetenv("CONNECT_TIME");	script_unsetenv("BYTES_SENT");	script_unsetenv("BYTES_RCVD");	lcp_lowerup(0);	/*	 * If we are initiating this connection, wait for a short	 * time for something from the peer.  This can avoid bouncing	 * our packets off his tty before he has it set up.	 */	add_fd(fd_ppp);	if (connect_delay != 0 && (connector != NULL || ptycommand != NULL)) {	    struct timeval t;	    t.tv_sec = connect_delay / 1000;	    t.tv_usec = connect_delay % 1000;	    wait_input(&t);	}	lcp_open(0);		/* Start protocol */	open_ccp_flag = 0;	status = EXIT_NEGOTIATION_FAILED;	new_phase(PHASE_ESTABLISH);	while (phase != PHASE_DEAD) {	    if (sigsetjmp(sigjmp, 1) == 0) {		sigprocmask(SIG_BLOCK, &mask, NULL);		if (kill_link || open_ccp_flag || got_sigchld) {		    sigprocmask(SIG_UNBLOCK, &mask, NULL);		} else {		    waiting = 1;		    sigprocmask(SIG_UNBLOCK, &mask, NULL);		    wait_input(timeleft(&timo));		}	    }	    waiting = 0;	    calltimeout();	    get_input();	    if (kill_link) {		lcp_close(0, "User request");		kill_link = 0;	    }	    if (open_ccp_flag) {		if (phase == PHASE_NETWORK || phase == PHASE_RUNNING) {		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */		    (*ccp_protent.open)(0);		}		open_ccp_flag = 0;	    }	    if (got_sigchld)		reap_kids(0);	/* Don't leave dead kids lying around */	}	/*	 * Print connect time and statistics.	 */	if (link_stats_valid) {	    int t = (link_connect_time + 5) / 6;    /* 1/10ths of minutes */	    info("Connect time %d.%d minutes.", t/10, t%10);	    info("Sent %d bytes, received %d bytes.",		 link_stats.bytes_out, link_stats.bytes_in);	}	/*	 * Delete pid file before disestablishing ppp.  Otherwise it	 * can happen that another pppd gets the same unit and then	 * we delete its pid file.	 */	if (!demand) {	    if (pidfilename[0] != 0		&& unlink(pidfilename) < 0 && errno != ENOENT) 		warn("unable to delete pid file %s: %m", pidfilename);	    pidfilename[0] = 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.	 */	remove_fd(fd_ppp);	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(disconnect_script, ttyfd, ttyfd, 0) < 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 (locked) {	    unlock();	    locked = 0;	}	if (!demand) {	    if (pidfilename[0] != 0		&& unlink(pidfilename) < 0 && errno != ENOENT) 		warn("unable to delete pid file %s: %m", pidfilename);	    pidfilename[0] = 0;	}	if (!persist || (maxfail > 0 && unsuccess >= maxfail))	    break;	kill_link = 0;	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 {		if (sigsetjmp(sigjmp, 1) == 0) {		    sigprocmask(SIG_BLOCK, &mask, NULL);		    if (kill_link || got_sigchld) {			sigprocmask(SIG_UNBLOCK, &mask, NULL);		    } else {			waiting = 1;			sigprocmask(SIG_UNBLOCK, &mask, NULL);			wait_input(timeleft(&timo));		    }		}		waiting = 0;		calltimeout();		if (kill_link) {		    kill_link = 0;		    new_phase(PHASE_DORMANT); /* allow signal to end holdoff */		}		if (got_sigchld)		    reap_kids(0);	    } while (phase == PHASE_HOLDOFF);	    if (!persist)		break;	}    }    /* Wait for scripts to finish */    /* XXX should have a timeout here */    while (n_children > 0) {	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);	}	if (reap_kids(1) < 0)	    break;    }    die(status);    return 0;}/* * detach - detach us from the controlling terminal. */voiddetach(){    int pid;    if (detached)	return;    if ((pid = fork()) < 0) {	error("Couldn't detach (fork failed: %m)");	die(1);			/* or just return? */    }    if (pid != 0) {	/* parent */	if (locked)	    relock(pid);	exit(0);		/* parent dies */    }    setsid();    chdir("/");    close(0);    close(1);    close(2);    detached = 1;    log_to_fd = -1;    /* update pid files if they have been written already */    if (pidfilename[0])	create_pidfile();    if (linkpidfile[0])	create_linkpidfile();}/* * reopen_log - (re)open our connection to syslog. */voidreopen_log(){#ifdef ULTRIX    openlog("pppd", LOG_PID);#else    openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);    setlogmask(LOG_UPTO(LOG_INFO));#endif}/* * Create a file containing our process ID. */static voidcreate_pidfile(){    FILE *pidfile;    char numbuf[16];    slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",	     _PATH_VARRUN, ifname);    if ((pidfile = fopen(pidfilename, "w")) != NULL) {	fprintf(pidfile, "%d\n", getpid());	(void) fclose(pidfile);    } else {	error("Failed to create pid file %s: %m", pidfilename);	pidfilename[0] = 0;    }    slprintf(numbuf, sizeof(numbuf), "%d", getpid());    script_setenv("PPPD_PID", numbuf);    if (linkpidfile[0])	create_linkpidfile();}static voidcreate_linkpidfile(){    FILE *pidfile;    if (linkname[0] == 0)	return;    slprintf(linkpidfile, sizeof(linkpidfile), "%sppp-%s.pid",	     _PATH_VARRUN, linkname);    if ((pidfile = fopen(linkpidfile, "w")) != NULL) {	fprintf(pidfile, "%d\n", getpid());	if (pidfilename[0])	    fprintf(pidfile, "%s\n", ifname);	(void) fclose(pidfile);    } else {	error("Failed to create pid file %s: %m", linkpidfile);	linkpidfile[0] = 0;    }    script_setenv("LINKNAME", linkname);}/* * holdoff_end - called via a timeout when the holdoff period ends. */static voidholdoff_end(arg)    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" },    { 0x6f,	"Stampede Bridging" },    { 0xfb,	"single-link compression" },    { 0xfd,	"1st choice compression" },    { 0x0201,	"802.1d Hello Packets" },    { 0x0203,	"IBM Source Routing BPDU" },    { 0x0205,	"DEC LANBridge100 Spanning Tree" },    { 0x0231,	"Luxcom" },    { 0x0233,	"Sigma Network Systems" },    { 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" },

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -