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

📄 pppoe-server.c

📁 网上的一个开源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/************************************************************************* pppoe-server.c** Implementation of a user-space PPPoE server** Copyright (C) 2000 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.** $Id: pppoe-server.c,v 1.91 2005/08/10 00:25:21 dfs Exp $** LIC: GPL************************************************************************/static char const RCSID[] ="$Id: pppoe-server.c,v 1.91 2005/08/10 00:25:21 dfs Exp $";#include "config.h"#if defined(HAVE_NETPACKET_PACKET_H) || defined(HAVE_LINUX_IF_PACKET_H)#define _POSIX_SOURCE 1 /* For sigaction defines */#endif#define _BSD_SOURCE 1 /* for gethostname */#include "pppoe-server.h"#include "md5.h"#ifdef HAVE_SYSLOG_H#include <syslog.h>#endif#include <errno.h>#include <string.h>#include <stdlib.h>#include <fcntl.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_GETOPT_H#include <getopt.h>#endif#ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>#endif#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#include <time.h>#include <signal.h>#ifdef HAVE_LICENSE#include "license.h"#include "licensed-only/servfuncs.h"static struct License const *ServerLicense;static struct License const *ClusterLicense;#else#define control_session_started(x) (void) 0#define control_session_terminated(x) (void) 0#define control_exit() (void) 0#define realpeerip peerip#endif#ifdef HAVE_L2TPextern PppoeSessionFunctionTable L2TPSessionFunctionTable;extern void pppoe_to_l2tp_add_interface(EventSelector *es,					Interface *interface);#endifstatic void InterfaceHandler(EventSelector *es,			int fd, unsigned int flags, void *data);static void startPPPD(ClientSession *sess);static void sendErrorPADS(int sock, unsigned char *source, unsigned char *dest,			  int errorTag, char *errorMsg);#define CHECK_ROOM(cursor, start, len) \do {\    if (((cursor)-(start))+(len) > MAX_PPPOE_PAYLOAD) { \	syslog(LOG_ERR, "Would create too-long packet"); \	return; \    } \} while(0)static void PppoeStopSession(ClientSession *ses, char const *reason);static int PppoeSessionIsActive(ClientSession *ses);/* Service-Names we advertise */#define MAX_SERVICE_NAMES 64static int NumServiceNames = 0;static char const *ServiceNames[MAX_SERVICE_NAMES];PppoeSessionFunctionTable DefaultSessionFunctionTable = {    PppoeStopSession,    PppoeSessionIsActive,    NULL};/* An array of client sessions */ClientSession *Sessions = NULL;ClientSession *FreeSessions = NULL;ClientSession *LastFreeSession = NULL;ClientSession *BusySessions = NULL;/* Interfaces we're listening on */Interface interfaces[MAX_INTERFACES];int NumInterfaces = 0;/* The number of session slots */size_t NumSessionSlots;/* Number of active sessions */size_t NumActiveSessions = 0;/* Offset of first session */size_t SessOffset = 0;/* Event Selector */EventSelector *event_selector;/* Use Linux kernel-mode PPPoE? */static int UseLinuxKernelModePPPoE = 0;static int Debug = 0;static int CheckPoolSyntax = 0;/* Synchronous mode */static int Synchronous = 0;/* Random seed for cookie generation */#define SEED_LEN 16#define MD5_LEN 16#define COOKIE_LEN (MD5_LEN + sizeof(pid_t)) /* Cookie is 16-byte MD5 + PID of server */static unsigned char CookieSeed[SEED_LEN];#define MAXLINE 512/* Default interface if no -I option given */#define DEFAULT_IF "eth0"/* Access concentrator name */char *ACName = NULL;/* Options to pass to pppoe process */char PppoeOptions[SMALLBUF] = "";/* Our local IP address */unsigned char LocalIP[IPV4ALEN] = {10, 0, 0, 1}; /* Counter optionally STARTS here */unsigned char RemoteIP[IPV4ALEN] = {10, 67, 15, 1}; /* Counter STARTS here *//* Do we increment local IP for each connection? */int IncrLocalIP = 0;/* Do we randomize session numbers? */int RandomizeSessionNumbers = 0;/* Do we pass the "unit" option to pppd?  (2.4 or greater) */int PassUnitOptionToPPPD = 0;static PPPoETag hostUniq;static PPPoETag relayId;static PPPoETag receivedCookie;static PPPoETag requestedService;#define HOSTNAMELEN 256/***********************************************************************%FUNCTION: childHandler*%ARGUMENTS:* pid -- pid of child* status -- exit status* ses -- which session terminated*%RETURNS:* Nothing*%DESCRIPTION:* Called synchronously when a child dies.  Remove from busy list.***********************************************************************/static voidchildHandler(pid_t pid, int status, void *s){    ClientSession *session = s;    /* Temporary structure for sending PADT's. */    PPPoEConnection conn;#ifdef HAVE_L2TP    /* We're acting as LAC, so when child exits, become a PPPoE <-> L2TP       relay */    if (session->flags & FLAG_ACT_AS_LAC) {	syslog(LOG_INFO, "Session %d for client "	       "%02x:%02x:%02x:%02x:%02x:%02x handed off to LNS %s",	       ntohs(session->sess),	       session->eth[0], session->eth[1], session->eth[2],	       session->eth[3], session->eth[4], session->eth[5],	       inet_ntoa(session->tunnel_endpoint.sin_addr));	session->pid = 0;	session->funcs = &L2TPSessionFunctionTable;	return;    }#endif    memset(&conn, 0, sizeof(conn));    conn.useHostUniq = 0;    syslog(LOG_INFO,	   "Session %d closed for client "	   "%02x:%02x:%02x:%02x:%02x:%02x (%d.%d.%d.%d) on %s",	   ntohs(session->sess),	   session->eth[0], session->eth[1], session->eth[2],	   session->eth[3], session->eth[4], session->eth[5],	   (int) session->realpeerip[0], (int) session->realpeerip[1],	   (int) session->realpeerip[2], (int) session->realpeerip[3],	   session->ethif->name);    memcpy(conn.myEth, session->ethif->mac, ETH_ALEN);    conn.discoverySocket = session->ethif->sock;    conn.session = session->sess;    memcpy(conn.peerEth, session->eth, ETH_ALEN);    if (!(session->flags & FLAG_SENT_PADT)) {	if (session->flags & FLAG_RECVD_PADT) {	    sendPADT(&conn, "RP-PPPoE: Received PADT from peer");	} else {	    sendPADT(&conn, "RP-PPPoE: Child pppd process terminated");	}	session->flags |= FLAG_SENT_PADT;    }    session->serviceName = "";    control_session_terminated(session);    if (pppoe_free_session(session) < 0) {	return;    }}/***********************************************************************%FUNCTION: incrementIPAddress (static)*%ARGUMENTS:* addr -- a 4-byte array representing IP address*%RETURNS:* Nothing*%DESCRIPTION:* Increments addr in-place***********************************************************************/static voidincrementIPAddress(unsigned char ip[IPV4ALEN]){    ip[3]++;    if (!ip[3]) {	ip[2]++;	if (!ip[2]) {	    ip[1]++;	    if (!ip[1]) {		ip[0]++;	    }	}    }}/***********************************************************************%FUNCTION: killAllSessions*%ARGUMENTS:* None*%RETURNS:* Nothing*%DESCRIPTION:* Kills all pppd processes (and hence all PPPoE sessions)***********************************************************************/voidkillAllSessions(void){    ClientSession *sess = BusySessions;    while(sess) {	sess->funcs->stop(sess, "Shutting Down");	sess = sess->next;    }#ifdef HAVE_L2TP    pppoe_close_l2tp_tunnels();#endif}/***********************************************************************%FUNCTION: parseAddressPool*%ARGUMENTS:* fname -- name of file containing IP address pool.* install -- if true, install IP addresses in sessions.*%RETURNS:* Number of valid IP addresses found.*%DESCRIPTION:* Reads a list of IP addresses from a file.***********************************************************************/static intparseAddressPool(char const *fname, int install){    FILE *fp = fopen(fname, "r");    int numAddrs = 0;    unsigned int a, b, c, d;    unsigned int e, f, g, h;    char line[MAXLINE];    if (!fp) {	sysErr("Cannot open address pool file");	exit(1);    }    while (!feof(fp)) {	if (!fgets(line, MAXLINE, fp)) {	    break;	}	if ((sscanf(line, "%u.%u.%u.%u:%u.%u.%u.%u",		    &a, &b, &c, &d, &e, &f, &g, &h) == 8) &&	    a < 256 && b < 256 && c < 256 && d < 256 &&	    e < 256 && f < 256 && g < 256 && h < 256) {	    /* Both specified (local:remote) */	    if (install) {		Sessions[numAddrs].myip[0] = (unsigned char) a;		Sessions[numAddrs].myip[1] = (unsigned char) b;		Sessions[numAddrs].myip[2] = (unsigned char) c;		Sessions[numAddrs].myip[3] = (unsigned char) d;		Sessions[numAddrs].peerip[0] = (unsigned char) e;		Sessions[numAddrs].peerip[1] = (unsigned char) f;		Sessions[numAddrs].peerip[2] = (unsigned char) g;		Sessions[numAddrs].peerip[3] = (unsigned char) h;#ifdef HAVE_LICENSE		memcpy(Sessions[numAddrs].realpeerip,		       Sessions[numAddrs].peerip, IPV4ALEN);#endif	    }	    numAddrs++;	} else if ((sscanf(line, "%u.%u.%u.%u-%u", &a, &b, &c, &d, &e) == 5) &&		   a < 256 && b < 256 && c < 256 && d < 256 && e < 256) {	    /* Remote specied as a.b.c.d-e.  Example: 1.2.3.4-8 yields:	       1.2.3.4, 1.2.3.5, 1.2.3.6, 1.2.3.7, 1.2.3.8 */	    /* Swap d and e so that e >= d */	    if (e < d) {		f = d;		d = e;		e = f;	    }	    if (install) {		while (d <= e) {		    Sessions[numAddrs].peerip[0] = (unsigned char) a;		    Sessions[numAddrs].peerip[1] = (unsigned char) b;		    Sessions[numAddrs].peerip[2] = (unsigned char) c;		    Sessions[numAddrs].peerip[3] = (unsigned char) d;#ifdef HAVE_LICENSE		    memcpy(Sessions[numAddrs].realpeerip,			   Sessions[numAddrs].peerip, IPV4ALEN);#endif		d++;		numAddrs++;		}	    } else {		numAddrs += (e-d) + 1;	    }	} else if ((sscanf(line, "%u.%u.%u.%u", &a, &b, &c, &d) == 4) &&		   a < 256 && b < 256 && c < 256 && d < 256) {	    /* Only remote specified */	    if (install) {		Sessions[numAddrs].peerip[0] = (unsigned char) a;		Sessions[numAddrs].peerip[1] = (unsigned char) b;		Sessions[numAddrs].peerip[2] = (unsigned char) c;		Sessions[numAddrs].peerip[3] = (unsigned char) d;#ifdef HAVE_LICENSE		memcpy(Sessions[numAddrs].realpeerip,		       Sessions[numAddrs].peerip, IPV4ALEN);#endif	    }	    numAddrs++;	}    }    fclose(fp);    if (!numAddrs) {	rp_fatal("No valid ip addresses found in pool file");    }    return numAddrs;}/***********************************************************************%FUNCTION: parsePADITags*%ARGUMENTS:* type -- tag type* len -- tag length* data -- tag data* extra -- extra user data.*%RETURNS:* Nothing*%DESCRIPTION:* Picks interesting tags out of a PADI packet***********************************************************************/voidparsePADITags(UINT16_t type, UINT16_t len, unsigned char *data,	      void *extra){    switch(type) {    case TAG_SERVICE_NAME:	/* Copy requested service name */	requestedService.type = htons(type);	requestedService.length = htons(len);	memcpy(requestedService.payload, data, len);	break;    case TAG_RELAY_SESSION_ID:	relayId.type = htons(type);	relayId.length = htons(len);	memcpy(relayId.payload, data, len);	break;    case TAG_HOST_UNIQ:	hostUniq.type = htons(type);	hostUniq.length = htons(len);	memcpy(hostUniq.payload, data, len);	break;    }}/***********************************************************************%FUNCTION: parsePADRTags*%ARGUMENTS:* type -- tag type* len -- tag length* data -- tag data* extra -- extra user data.*%RETURNS:* Nothing*%DESCRIPTION:* Picks interesting tags out of a PADR packet***********************************************************************/voidparsePADRTags(UINT16_t type, UINT16_t len, unsigned char *data,	      void *extra){    switch(type) {    case TAG_RELAY_SESSION_ID:	relayId.type = htons(type);	relayId.length = htons(len);	memcpy(relayId.payload, data, len);	break;    case TAG_HOST_UNIQ:	hostUniq.type = htons(type);	hostUniq.length = htons(len);	memcpy(hostUniq.payload, data, len);	break;    case TAG_AC_COOKIE:	receivedCookie.type = htons(type);	receivedCookie.length = htons(len);	memcpy(receivedCookie.payload, data, len);	break;    case TAG_SERVICE_NAME:	requestedService.type = htons(type);	requestedService.length = htons(len);	memcpy(requestedService.payload, data, len);	break;    }}/***********************************************************************%FUNCTION: fatalSys*%ARGUMENTS:* str -- error message*%RETURNS:* Nothing*%DESCRIPTION:* Prints a message plus the errno value to stderr and syslog and exits.***********************************************************************/voidfatalSys(char const *str){    char buf[SMALLBUF];    snprintf(buf, SMALLBUF, "%s: %s", str, strerror(errno));    printErr(buf);    control_exit();    exit(EXIT_FAILURE);}/***********************************************************************%FUNCTION: sysErr*%ARGUMENTS:* str -- error message*%RETURNS:* Nothing*%DESCRIPTION:* Prints a message plus the errno value to syslog.***********************************************************************/voidsysErr(char const *str){    char buf[1024];    sprintf(buf, "%.256s: %.256s", str, strerror(errno));    printErr(buf);}/***********************************************************************%FUNCTION: rp_fatal*%ARGUMENTS:* str -- error message*%RETURNS:* Nothing*%DESCRIPTION:* Prints a message to stderr and syslog and exits.***********************************************************************/voidrp_fatal(char const *str){    printErr(str);    control_exit();    exit(EXIT_FAILURE);}

⌨️ 快捷键说明

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