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

📄 pppoe-server.c

📁 网上的一个开源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
* argc, argv -- usual suspects*%RETURNS:* Exit status*%DESCRIPTION:* Main program of PPPoE server***********************************************************************/intmain(int argc, char **argv){    FILE *fp;    int i, j;    int opt;    int d[IPV4ALEN];    int beDaemon = 1;    int found;    unsigned int discoveryType, sessionType;    char *addressPoolFname = NULL;#ifdef HAVE_LICENSE    int use_clustering = 0;#endif#ifndef HAVE_LINUX_KERNEL_PPPOE    char *options = "hI:C:L:R:T:m:FN:f:o:sp:lrudPc:S:1";#else    char *options = "hI:C:L:R:T:m:FN:f:o:skp:lrudPc:S:1";#endif    if (getuid() != geteuid() ||	getgid() != getegid()) {	fprintf(stderr, "SECURITY WARNING: pppoe-server will NOT run suid or sgid.  Fix your installation.\n");	exit(1);    }    memset(interfaces, 0, sizeof(interfaces));    /* Initialize syslog */    openlog("pppoe-server", LOG_PID, LOG_DAEMON);    /* Default number of session slots */    NumSessionSlots = DEFAULT_MAX_SESSIONS;    NumActiveSessions = 0;    /* Parse command-line options */    while((opt = getopt(argc, argv, options)) != -1) {	switch(opt) {#ifdef HAVE_LINUX_KERNEL_PPPOE	case 'k':	    UseLinuxKernelModePPPoE = 1;	    break;#endif	case 'S':	    if (NumServiceNames == MAX_SERVICE_NAMES) {		fprintf(stderr, "Too many '-S' options (%d max)",			MAX_SERVICE_NAMES);		exit(1);	    }	    ServiceNames[NumServiceNames] = strdup(optarg);	    if (!ServiceNames[NumServiceNames]) {		fprintf(stderr, "Out of memory");		exit(1);	    }	    NumServiceNames++;	    break;	case 'c':#ifndef HAVE_LICENSE	    fprintf(stderr, "Clustering capability not available.\n");	    exit(1);#else	    cluster_handle_option(optarg);	    use_clustering = 1;	    break;#endif	case 'd':	    Debug = 1;	    break;	case 'P':	    CheckPoolSyntax = 1;	    break;	case 'u':	    PassUnitOptionToPPPD = 1;	    break;	case 'r':	    RandomizeSessionNumbers = 1;	    break;	case 'l':	    IncrLocalIP = 1;	    break;	case 'p':	    addressPoolFname = optarg;	    break;	case 's':	    Synchronous = 1;	    /* Pass the Synchronous option on to pppoe */	    snprintf(PppoeOptions + strlen(PppoeOptions),		     SMALLBUF-strlen(PppoeOptions),		     " -s");	    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;	    /* This option gets passed to pppoe */	    snprintf(PppoeOptions + strlen(PppoeOptions),		     SMALLBUF-strlen(PppoeOptions),		     " -%c %s", opt, optarg);	    break;	case 'F':	    beDaemon = 0;	    break;	case 'N':	    if (sscanf(optarg, "%d", &opt) != 1) {		usage(argv[0]);		exit(EXIT_FAILURE);	    }	    if (opt <= 0) {		fprintf(stderr, "-N: Value must be positive\n");		exit(EXIT_FAILURE);	    }	    NumSessionSlots = opt;	    break;	case 'o':	    if (sscanf(optarg, "%d", &opt) != 1) {		usage(argv[0]);		exit(EXIT_FAILURE);	    }	    if (opt < 0) {		fprintf(stderr, "-o: Value must be non-negative\n");		exit(EXIT_FAILURE);	    }	    SessOffset = (size_t) opt;	    break;	case 'I':	    if (NumInterfaces >= MAX_INTERFACES) {		fprintf(stderr, "Too many -I options (max %d)\n",			MAX_INTERFACES);		exit(EXIT_FAILURE);	    }	    found = 0;	    for (i=0; i<NumInterfaces; i++) {		if (!strncmp(interfaces[i].name, optarg, IFNAMSIZ)) {		    found = 1;		    break;		}	    }	    if (!found) {		strncpy(interfaces[NumInterfaces].name, optarg, IFNAMSIZ);		NumInterfaces++;	    }	    break;	case 'C':	    SET_STRING(ACName, optarg);	    break;	case 'L':	case 'R':	    /* Get local/remote IP address */	    if (sscanf(optarg, "%d.%d.%d.%d", &d[0], &d[1], &d[2], &d[3]) != 4) {		usage(argv[0]);		exit(EXIT_FAILURE);	    }	    for (i=0; i<IPV4ALEN; i++) {		if (d[i] < 0 || d[i] > 255) {		    usage(argv[0]);		    exit(EXIT_FAILURE);		}		if (opt == 'L') {		    LocalIP[i] = (unsigned char) d[i];		} else {		    RemoteIP[i] = (unsigned char) d[i];		}	    }	    break;	case 'T':	case 'm':	    /* These just get passed to pppoe */	    snprintf(PppoeOptions + strlen(PppoeOptions),		     SMALLBUF-strlen(PppoeOptions),		     " -%c %s", opt, optarg);	    break;	case 'h':	    usage(argv[0]);	    exit(EXIT_SUCCESS);	case '1':#ifdef HAVE_LICENSE	    MaxSessionsPerUser = 1;#else	    fprintf(stderr, "-1 option not valid.\n");	    exit(1);#endif	    break;	}    }#ifdef HAVE_LICENSE    License_SetVersion(SERVPOET_VERSION);    License_ReadBundleFile("/etc/rp/bundle.txt");    License_ReadFile("/etc/rp/license.txt");    ServerLicense = License_GetFeature("PPPOE-SERVER");    if (!ServerLicense) {	fprintf(stderr, "License: GetFeature failed: %s\n",		License_ErrorMessage());	exit(1);    }#endif#ifdef USE_LINUX_PACKET#ifndef HAVE_STRUCT_SOCKADDR_LL    fprintf(stderr, "The PPPoE server does not work on Linux 2.0 kernels.\n");    exit(EXIT_FAILURE);#endif#endif    if (!NumInterfaces) {	strcpy(interfaces[0].name, DEFAULT_IF);	NumInterfaces = 1;    }    if (!ACName) {	ACName = malloc(HOSTNAMELEN);	if (gethostname(ACName, HOSTNAMELEN) < 0) {	    fatalSys("gethostname");	}    }    /* If address pool filename given, count number of addresses */    if (addressPoolFname) {	NumSessionSlots = parseAddressPool(addressPoolFname, 0);	if (CheckPoolSyntax) {	    printf("%d\n", NumSessionSlots);	    exit(0);	}    }    /* Max 65534 - SessOffset sessions */    if (NumSessionSlots + SessOffset > 65534) {	fprintf(stderr, "-N and -o options must add up to at most 65534\n");	exit(EXIT_FAILURE);    }    /* Allocate memory for sessions */    Sessions = calloc(NumSessionSlots, sizeof(ClientSession));    if (!Sessions) {	rp_fatal("Cannot allocate memory for session slots");    }    /* Fill in local addresses first (let pool file override later */    for (i=0; i<NumSessionSlots; i++) {	memcpy(Sessions[i].myip, LocalIP, sizeof(LocalIP));	if (IncrLocalIP) {	    incrementIPAddress(LocalIP);	}    }    /* Fill in remote IP addresses from pool (may also overwrite local ips) */    if (addressPoolFname) {	(void) parseAddressPool(addressPoolFname, 1);    }    /* For testing -- generate sequential remote IP addresses */    for (i=0; i<NumSessionSlots; i++) {	Sessions[i].pid = 0;	Sessions[i].funcs = &DefaultSessionFunctionTable;	Sessions[i].sess = htons(i+1+SessOffset);	if (!addressPoolFname) {	    memcpy(Sessions[i].peerip, RemoteIP, sizeof(RemoteIP));#ifdef HAVE_LICENSE	    memcpy(Sessions[i].realpeerip, RemoteIP, sizeof(RemoteIP));#endif	    incrementIPAddress(RemoteIP);	}    }    /* Initialize our random cookie.  Try /dev/urandom; if that fails,       use PID and rand() */    fp = fopen("/dev/urandom", "r");    if (fp) {	unsigned int x;	fread(&x, 1, sizeof(x), fp);	srand(x);	fread(&CookieSeed, 1, SEED_LEN, fp);	fclose(fp);    } else {	srand((unsigned int) getpid() * (unsigned int) time(NULL));	CookieSeed[0] = getpid() & 0xFF;	CookieSeed[1] = (getpid() >> 8) & 0xFF;	for (i=2; i<SEED_LEN; i++) {	    CookieSeed[i] = (rand() >> (i % 9)) & 0xFF;	}    }    if (RandomizeSessionNumbers) {	int *permutation;	int tmp;	permutation = malloc(sizeof(int) * NumSessionSlots);	if (!permutation) {	    fprintf(stderr, "Could not allocate memory to randomize session numbers\n");	    exit(EXIT_FAILURE);	}	for (i=0; i<NumSessionSlots; i++) {	    permutation[i] = i;	}	for (i=0; i<NumSessionSlots-1; i++) {	    j = i + rand() % (NumSessionSlots - i);	    if (j != i) {		tmp = permutation[j];		permutation[j] = permutation[i];		permutation[i] = tmp;	    }	}	/* Link sessions together */	FreeSessions = &Sessions[permutation[0]];	LastFreeSession = &Sessions[permutation[NumSessionSlots-1]];	for (i=0; i<NumSessionSlots-1; i++) {	    Sessions[permutation[i]].next = &Sessions[permutation[i+1]];	}	Sessions[permutation[NumSessionSlots-1]].next = NULL;	free(permutation);    } else {	/* Link sessions together */	FreeSessions = &Sessions[0];	LastFreeSession = &Sessions[NumSessionSlots - 1];	for (i=0; i<NumSessionSlots-1; i++) {	    Sessions[i].next = &Sessions[i+1];	}	Sessions[NumSessionSlots-1].next = NULL;    }    if (Debug) {	/* Dump session array and exit */	ClientSession *ses = FreeSessions;	while(ses) {	    printf("Session %d local %d.%d.%d.%d remote %d.%d.%d.%d\n",		   ntohs(ses->sess),		   ses->myip[0], ses->myip[1],		   ses->myip[2], ses->myip[3],		   ses->peerip[0], ses->peerip[1],		   ses->peerip[2], ses->peerip[3]);	    ses = ses->next;	}	exit(0);    }    /* Open all the interfaces */    for (i=0; i<NumInterfaces; i++) {	interfaces[i].sock = openInterface(interfaces[i].name, Eth_PPPOE_Discovery, interfaces[i].mac);    }    /* Ignore SIGPIPE */    signal(SIGPIPE, SIG_IGN);    /* Create event selector */    event_selector = Event_CreateSelector();    if (!event_selector) {	rp_fatal("Could not create EventSelector -- probably out of memory");    }    /* Set signal handlers for SIGTERM and SIGINT */    if (Event_HandleSignal(event_selector, SIGTERM, termHandler) < 0 ||	Event_HandleSignal(event_selector, SIGINT, termHandler) < 0) {	fatalSys("Event_HandleSignal");    }    /* Control channel */#ifdef HAVE_LICENSE    if (control_init(argc, argv, event_selector)) {	rp_fatal("control_init failed");    }#endif    /* Create event handler for each interface */    for (i = 0; i<NumInterfaces; i++) {	interfaces[i].eh = Event_AddHandler(event_selector,					    interfaces[i].sock,					    EVENT_FLAG_READABLE,					    InterfaceHandler,					    &interfaces[i]);#ifdef HAVE_L2TP	interfaces[i].session_sock = -1;#endif	if (!interfaces[i].eh) {	    rp_fatal("Event_AddHandler failed");	}    }#ifdef HAVE_LICENSE    if (use_clustering) {	ClusterLicense = License_GetFeature("PPPOE-CLUSTER");	if (!ClusterLicense) {	    fprintf(stderr, "License: GetFeature failed: %s\n",		    License_ErrorMessage());	    exit(1);	}	if (!License_Expired(ClusterLicense)) {	    if (cluster_init(event_selector) < 0) {		rp_fatal("cluster_init failed");	    }	}    }#endif#ifdef HAVE_L2TP    for (i=0; i<NumInterfaces; i++) {	pppoe_to_l2tp_add_interface(event_selector,				    &interfaces[i]);    }#endif    /* Daemonize -- UNIX Network Programming, Vol. 1, Stevens */    if (beDaemon) {	i = fork();	if (i < 0) {	    fatalSys("fork");	} else if (i != 0) {	    /* parent */	    exit(EXIT_SUCCESS);	}	setsid();	signal(SIGHUP, SIG_IGN);	i = fork();	if (i < 0) {	    fatalSys("fork");	} else if (i != 0) {	    exit(EXIT_SUCCESS);	}	chdir("/");	/* Point stdin/stdout/stderr to /dev/null */	for (i=0; i<3; i++) {	    close(i);	}	i = open("/dev/null", O_RDWR);	if (i >= 0) {	    dup2(i, 0);	    dup2(i, 1);	    dup2(i, 2);	    if (i > 2) close(i);	}    }    for(;;) {	i = Event_HandleEvent(event_selector);	if (i < 0) {	    fatalSys("Event_HandleEvent");	}#ifdef HAVE_LICENSE	if (License_Expired(ServerLicense)) {	    syslog(LOG_INFO, "Server license has expired -- killing all PPPoE sessions");	    killAllSessions();	    control_exit();	    exit(0);	}#endif    }    return 0;}voidserverProcessPacket(Interface *i){    int len;    PPPoEPacket packet;    int sock = i->sock;    if (receivePacket(sock, &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;    }    /* Sanity check on packet */    if (packet.ver != 1 || packet.type != 1) {	/* Syslog an error */	return;    }    switch(packet.code) {    case CODE_PADI:	processPADI(i, &packet, len);	break;    case CODE_PADR:	processPADR(i, &packet, len);	break;    case CODE_PADT:	/* Kill the child */	processPADT(i, &packet, len);	break;    case CODE_SESS:	/* Ignore SESS -- children will handle them */	break;    case CODE_PADO:    case CODE_PADS:

⌨️ 快捷键说明

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