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

📄 pppoe.c

📁 在linux上实现拨号上网的功能,可以在平台arm上运行,移植性比较好。最新的代码3.10版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************* pppoe.c** Implementation of user-space PPPoE redirector for Linux.** Copyright (C) 2000-2006 by Roaring Penguin Software Inc.** This program may be distributed according to the terms of the GNU* General Public License, version 2 or (at your option) any later version.** LIC: GPL************************************************************************/static char const RCSID[] ="$Id$";#include "pppoe.h"#ifdef HAVE_SYSLOG_H#include <syslog.h>#endif#ifdef HAVE_GETOPT_H#include <getopt.h>#endif#include <string.h>#include <stdlib.h>#include <errno.h>#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_UIO_H#include <sys/uio.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef USE_LINUX_PACKET#include <sys/ioctl.h>#include <fcntl.h>#endif#include <signal.h>#ifdef HAVE_N_HDLC#ifndef N_HDLC#include <linux/termios.h>#endif#endif/* Default interface if no -I option given */#define DEFAULT_IF "eth0"/* Global variables -- options */int optInactivityTimeout = 0;	/* Inactivity timeout */int optClampMSS          = 0;	/* Clamp MSS to this value */int optSkipSession       = 0;	/* Perform discovery, print session info				   and exit */int optFloodDiscovery    = 0;   /* Flood server with discovery requests.				   USED FOR STRESS-TESTING ONLY.  DO NOT				   USE THE -F OPTION AGAINST A REAL ISP */PPPoEConnection *Connection = NULL; /* Must be global -- used				       in signal handler */int persist = 0; 		/* We are not a pppd plugin *//************************************************************************%FUNCTION: sendSessionPacket*%ARGUMENTS:* conn -- PPPoE connection* packet -- the packet to send* len -- length of data to send*%RETURNS:* Nothing*%DESCRIPTION:* Transmits a session packet to the peer.***********************************************************************/voidsendSessionPacket(PPPoEConnection *conn, PPPoEPacket *packet, int len){    packet->length = htons(len);    if (optClampMSS) {	clampMSS(packet, "outgoing", optClampMSS);    }    if (sendPacket(conn, conn->sessionSocket, packet, len + HDR_SIZE) < 0) {	if (errno == ENOBUFS) {	    /* No buffer space is a transient error */	    return;	}	exit(EXIT_FAILURE);    }#ifdef DEBUGGING_ENABLED    if (conn->debugFile) {	dumpPacket(conn->debugFile, packet, "SENT");	fprintf(conn->debugFile, "\n");	fflush(conn->debugFile);    }#endif}#ifdef USE_BPF/***********************************************************************%FUNCTION: sessionDiscoveryPacket*%ARGUMENTS:* packet -- the discovery packet that was received*%RETURNS:* Nothing*%DESCRIPTION:* We got a discovery packet during the session stage.  This most likely* means a PADT.** The BSD version uses a single socket for both discovery and session* packets.  When a packet comes in over the wire once we are in* session mode, either syncReadFromEth() or asyncReadFromEth() will* have already read the packet and determined it to be a discovery* packet before passing it here.***********************************************************************/static voidsessionDiscoveryPacket(PPPoEPacket *packet){    /* Sanity check */    if (packet->code != CODE_PADT) {	return;    }    /* It's a PADT, all right.  Is it for us? */    if (packet->session != Connection->session) {	/* Nope, ignore it */	return;    }    if (memcmp(packet->ethHdr.h_dest, Connection->myEth, ETH_ALEN)) {	return;    }    if (memcmp(packet->ethHdr.h_source, Connection->peerEth, ETH_ALEN)) {	return;    }    syslog(LOG_INFO,	   "Session %d terminated -- received PADT from peer",	   (int) ntohs(packet->session));    parsePacket(packet, parseLogErrs, NULL);    sendPADT(Connection, "Received PADT from peer");    exit(EXIT_SUCCESS);}#else/***********************************************************************%FUNCTION: sessionDiscoveryPacket*%ARGUMENTS:* conn -- PPPoE connection*%RETURNS:* Nothing*%DESCRIPTION:* We got a discovery packet during the session stage.  This most likely* means a PADT.***********************************************************************/static voidsessionDiscoveryPacket(PPPoEConnection *conn){    PPPoEPacket packet;    int len;    if (receivePacket(conn->discoverySocket, &packet, &len) < 0) {	return;    }    /* Check length */    if (ntohs(packet.length) + HDR_SIZE > len) {	syslog(LOG_ERR, "Bogus PPPoE length field (%u)",	       (unsigned int) ntohs(packet.length));	return;    }    if (packet.code != CODE_PADT) {	/* Not PADT; ignore it */	return;    }    /* It's a PADT, all right.  Is it for us? */    if (packet.session != conn->session) {	/* Nope, ignore it */	return;    }    if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) {	return;    }    if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) {	return;    }#ifdef DEBUGGING_ENABLED    if (conn->debugFile) {	dumpPacket(conn->debugFile, &packet, "RCVD");	fprintf(conn->debugFile, "\n");	fflush(conn->debugFile);    }#endif    syslog(LOG_INFO,	   "Session %d terminated -- received PADT from peer",	   (int) ntohs(packet.session));    parsePacket(&packet, parseLogErrs, NULL);    sendPADT(conn, "Received PADT from peer");    exit(EXIT_SUCCESS);}#endif /* USE_BPF *//***********************************************************************%FUNCTION: session*%ARGUMENTS:* conn -- PPPoE connection info*%RETURNS:* Nothing*%DESCRIPTION:* Handles the "session" phase of PPPoE***********************************************************************/voidsession(PPPoEConnection *conn){    fd_set readable;    PPPoEPacket packet;    struct timeval tv;    struct timeval *tvp = NULL;    int maxFD = 0;    int r;    /* Drop privileges */    dropPrivs();    /* Prepare for select() */    if (conn->sessionSocket > maxFD)   maxFD = conn->sessionSocket;    if (conn->discoverySocket > maxFD) maxFD = conn->discoverySocket;    maxFD++;    /* Fill in the constant fields of the packet to save time */    memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);    memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);    packet.ethHdr.h_proto = htons(Eth_PPPOE_Session);    packet.ver = 1;    packet.type = 1;    packet.code = CODE_SESS;    packet.session = conn->session;    initPPP();#ifdef USE_BPF    /* check for buffered session data */    while (BPF_BUFFER_HAS_DATA) {	if (conn->synchronous) {	    syncReadFromEth(conn, conn->sessionSocket, optClampMSS);	} else {	    asyncReadFromEth(conn, conn->sessionSocket, optClampMSS);	}    }#endif    for (;;) {	if (optInactivityTimeout > 0) {	    tv.tv_sec = optInactivityTimeout;	    tv.tv_usec = 0;	    tvp = &tv;	}	FD_ZERO(&readable);	FD_SET(0, &readable);     /* ppp packets come from stdin */	if (conn->discoverySocket >= 0) {	    FD_SET(conn->discoverySocket, &readable);	}	FD_SET(conn->sessionSocket, &readable);	while(1) {	    r = select(maxFD, &readable, NULL, NULL, tvp);	    if (r >= 0 || errno != EINTR) break;	}	if (r < 0) {	    fatalSys("select (session)");	}	if (r == 0) { /* Inactivity timeout */	    syslog(LOG_ERR, "Inactivity timeout... something wicked happened on session %d",		   (int) ntohs(conn->session));	    sendPADT(conn, "RP-PPPoE: Inactivity timeout");	    exit(EXIT_FAILURE);	}	/* Handle ready sockets */	if (FD_ISSET(0, &readable)) {	    if (conn->synchronous) {		syncReadFromPPP(conn, &packet);	    } else {		asyncReadFromPPP(conn, &packet);	    }	}	if (FD_ISSET(conn->sessionSocket, &readable)) {	    do {		if (conn->synchronous) {		    syncReadFromEth(conn, conn->sessionSocket, optClampMSS);		} else {		    asyncReadFromEth(conn, conn->sessionSocket, optClampMSS);		}	    } while (BPF_BUFFER_HAS_DATA);	}#ifndef USE_BPF	/* BSD uses a single socket, see *syncReadFromEth() */	/* for calls to sessionDiscoveryPacket() */	if (conn->discoverySocket >= 0) {	    if (FD_ISSET(conn->discoverySocket, &readable)) {		sessionDiscoveryPacket(conn);	    }	}#endif    }}/************************************************************************%FUNCTION: sigPADT*%ARGUMENTS:* src -- signal received*%RETURNS:* Nothing*%DESCRIPTION:* If an established session exists send PADT to terminate from session*  from our end***********************************************************************/static voidsigPADT(int src){  syslog(LOG_DEBUG,"Received signal %d on session %d.",	 (int)src, (int) ntohs(Connection->session));  sendPADTf(Connection, "RP-PPPoE: Received signal %d", src);  exit(EXIT_SUCCESS);}/***********************************************************************%FUNCTION: usage*%ARGUMENTS:* argv0 -- program name*%RETURNS:* Nothing*%DESCRIPTION:* Prints usage information and exits.***********************************************************************/voidusage(char const *argv0){    fprintf(stderr, "Usage: %s [options]\n", argv0);    fprintf(stderr, "Options:\n");#ifdef USE_BPF    fprintf(stderr, "   -I if_name     -- Specify interface (REQUIRED)\n");#else    fprintf(stderr, "   -I if_name     -- Specify interface (default %s.)\n",	    DEFAULT_IF);#endif#ifdef DEBUGGING_ENABLED    fprintf(stderr, "   -D filename    -- Log debugging information in filename.\n");#endif    fprintf(stderr,	    "   -T timeout     -- Specify inactivity timeout in seconds.\n"	    "   -t timeout     -- Initial timeout for discovery packets in seconds\n"	    "   -V             -- Print version and exit.\n"	    "   -A             -- Print access concentrator names and exit.\n"	    "   -S name        -- Set desired service name.\n"	    "   -C name        -- Set desired access concentrator name.\n"	    "   -U             -- Use Host-Unique to allow multiple PPPoE sessions.\n"	    "   -s             -- Use synchronous PPP encapsulation.\n"	    "   -m MSS         -- Clamp incoming and outgoing MSS options.\n"	    "   -p pidfile     -- Write process-ID to pidfile.\n"	    "   -e sess:mac    -- Skip discovery phase; use existing session.\n"	    "   -n             -- Do not open discovery socket.\n"	    "   -k             -- Kill a session with PADT (requires -e)\n"	    "   -d             -- Perform discovery, print session info and exit.\n"	    "   -f disc:sess   -- Set Ethernet frame types (hex).\n"	    "   -h             -- Print usage information.\n\n"	    "PPPoE Version %s, Copyright (C) 2001-2006 Roaring Penguin Software Inc.\n"	    "PPPoE comes with ABSOLUTELY NO WARRANTY.\n"	    "This is free software, and you are welcome to redistribute it under the terms\n"	    "of the GNU General Public License, version 2 or any later version.\n"	    "http://www.roaringpenguin.com\n", VERSION);    exit(EXIT_SUCCESS);}/***********************************************************************%FUNCTION: main*%ARGUMENTS:* argc, argv -- count and values of command-line arguments*%RETURNS:* Nothing*%DESCRIPTION:* Main program***********************************************************************/intmain(int argc, char *argv[]){    int opt;    int n;    unsigned int m[6];		/* MAC address in -e option */    unsigned int s;		/* Temporary to hold session */    FILE *pidfile;    unsigned int discoveryType, sessionType;    char const *options;    PPPoEConnection conn;#ifdef HAVE_N_HDLC    int disc = N_HDLC;    long flags;#endif    if (getuid() != geteuid() ||	getgid() != getegid()) {	IsSetID = 1;    }    /* Initialize connection info */    memset(&conn, 0, sizeof(conn));    conn.discoverySocket = -1;    conn.sessionSocket = -1;    conn.discoveryTimeout = PADI_TIMEOUT;    /* For signal handler */    Connection = &conn;    /* Initialize syslog */    openlog("pppoe", LOG_PID, LOG_DAEMON);#ifdef DEBUGGING_ENABLED    options = "I:VAT:D:hS:C:Usm:np:e:kdf:F:t:";#else    options = "I:VAT:hS:C:Usm:np:e:kdf:F:t:";#endif    while((opt = getopt(argc, argv, options)) != -1) {	switch(opt) {	case 't':	    if (sscanf(optarg, "%d", &conn.discoveryTimeout) != 1) {		fprintf(stderr, "Illegal argument to -t: Should be -t timeout\n");		exit(EXIT_FAILURE);	    }	    if (conn.discoveryTimeout < 1) {		conn.discoveryTimeout = 1;	    }	    break;	case 'F':	    if (sscanf(optarg, "%d", &optFloodDiscovery) != 1) {		fprintf(stderr, "Illegal argument to -F: Should be -F numFloods\n");		exit(EXIT_FAILURE);	    }	    if (optFloodDiscovery < 1) optFloodDiscovery = 1;	    fprintf(stderr,		    "WARNING: DISCOVERY FLOOD IS MEANT FOR STRESS-TESTING\n"		    "A PPPOE SERVER WHICH YOU OWN.  DO NOT USE IT AGAINST\n"		    "A REAL ISP.  YOU HAVE 5 SECONDS TO ABORT.\n");	    sleep(5);	    break;	case 'f':	    if (sscanf(optarg, "%x:%x", &discoveryType, &sessionType) != 2) {		fprintf(stderr, "Illegal argument to -f: Should be disc:sess in hex\n");		exit(EXIT_FAILURE);	    }	    Eth_PPPOE_Discovery = (UINT16_t) discoveryType;	    Eth_PPPOE_Session   = (UINT16_t) sessionType;	    break;	case 'd':	    optSkipSession = 1;	    break;	case 'k':	    conn.killSession = 1;	    break;

⌨️ 快捷键说明

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