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

📄 pppoe.c

📁 Linux平台下的pppoe拨号程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	    // Copy MAC address of peer 	    for (n=0; n<6; n++) {		conn.peerEth[n] = (unsigned char) m[n];	    }	    //Convert session 	    conn.session = htons(s);	    //Skip discovery phase! 	    conn.skipDiscovery = 1;	    break;	case 'p':	    pidfile = fopen(optarg, "w");	    if (pidfile) {		fprintf(pidfile, "%lu\n", (unsigned long) getpid());		fclose(pidfile);	    }	    break;	case 'S':	    SET_STRING(conn.serviceName, optarg);	    break;	case 'C':	    SET_STRING(conn.acName, optarg);	    break;	case 's':	    conn.synchronous = 1;	    break;	case 'U':	    conn.useHostUniq = 1;	    break;	case 'D':	    conn.debugFile = fopen(optarg, "w");	    if (!conn.debugFile) {		fprintf(stderr, "Could not open %s: %s\n",			optarg, strerror(errno));		exit(EXIT_FAILURE);	    }	    fprintf(conn.debugFile, "rp-pppoe-%s\n", VERSION);	    fflush(conn.debugFile);	    break;	case 'T':	    optInactivityTimeout = (int) strtol(optarg, NULL, 10);	    if (optInactivityTimeout < 0) {		optInactivityTimeout = 0;	    }	    break;	case 'm':	    optClampMSS = (int) strtol(optarg, NULL, 10);	    if (optClampMSS < 536) {		fprintf(stderr, "-m: %d is too low (min 536)\n", optClampMSS);		exit(EXIT_FAILURE);	    }	    if (optClampMSS > 1452) {		fprintf(stderr, "-m: %d is too high (max 1452)\n", optClampMSS);		exit(EXIT_FAILURE);	    }	    break;	case 'I':	    SET_STRING(conn.ifName, optarg);	    break;	case 'V':	    printf("Roaring Penguin PPPoE Version %s\n", VERSION);	    exit(EXIT_SUCCESS);	case 'A':	    conn.printACNames = 1;	    break;	case 'h':	    usage(argv[0]);	    break;	default:	    usage(argv[0]);	}    }    //Pick a default interface name     if (!conn.ifName) {#ifdef USE_BPF	fprintf(stderr, "No interface specified (-I option)\n");	exit(EXIT_FAILURE);#else	SET_STRING(conn.ifName, DEFAULT_IF);#endif    }    //Set signal handlers: send PADT on HUP; ignore TERM and INT     if (!conn.printACNames) {	signal(SIGTERM, SIG_IGN);	signal(SIGINT, SIG_IGN);	signal(SIGHUP, sigPADT);#ifdef HAVE_N_HDLC	if (conn.synchronous) {	    if (ioctl(0, TIOCSETD, &disc) < 0) {		printErr("Unable to set line discipline to N_HDLC.  Make sure your kernel supports the N_HDLC line discipline, or do not use the SYNCHRONOUS option.  Quitting.");		exit(EXIT_FAILURE);	    } else {		syslog(LOG_INFO,		       "Changed pty line discipline to N_HDLC for synchronous mode");	    }	    //There is a bug in Linux's select which returns a descriptor	     //* as readable if N_HDLC line discipline is on, even if	     //* it isn't really readable.  This return happens only when	     //* select() times out.  To avoid blocking forever in read(),	    // * make descriptor 0 non-blocking 	    flags = fcntl(0, F_GETFL);	    if (flags < 0) fatalSys("fcntl(F_GETFL)");	    if (fcntl(0, F_SETFL, (long) flags | O_NONBLOCK) < 0) {		fatalSys("fcntl(F_SETFL)");	    }	}#endif    }    if (optFloodDiscovery) {	for (n=0; n < optFloodDiscovery; n++) {	    if (conn.printACNames) {		fprintf(stderr, "Sending discovery flood %d\n", n+1);	    }	    discovery(&conn);	    conn.discoveryState = STATE_SENT_PADI;	    close(conn.discoverySocket);	}	exit(EXIT_SUCCESS);    }    discovery(&conn);    if (optSkipSession) {	printf("%u:%02x:%02x:%02x:%02x:%02x:%02x\n",	       ntohs(conn.session),	       conn.peerEth[0],	       conn.peerEth[1],	       conn.peerEth[2],	       conn.peerEth[3],	       conn.peerEth[4],	       conn.peerEth[5]);	exit(EXIT_SUCCESS);    }    session(&conn);    return 0;}/***********************************************************************%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[1024];    sprintf(buf, "%.256s: Session %d: %.256s",	    str, (int) ntohs(Connection->session), strerror(errno));    printErr(buf);    sendPADTf(Connection, "RP-PPPoE: System call error: %s",	      strerror(errno));    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);    sendPADTf(Connection, "RP-PPPoE: Session %d: %.256s",	      (int) ntohs(Connection->session), str);    exit(EXIT_FAILURE);}/***********************************************************************%FUNCTION: asyncReadFromEth*%ARGUMENTS:* conn -- PPPoE connection info* sock -- Ethernet socket* clampMss -- if non-zero, do MSS-clamping*%RETURNS:* Nothing*%DESCRIPTION:* Reads a packet from the Ethernet interface and sends it to async PPP* device.***********************************************************************/voidasyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss){    PPPoEPacket packet;    int len;    int plen;    int i;    unsigned char pppBuf[4096];    unsigned char *ptr = pppBuf;    unsigned char c;    UINT16_t fcs;    unsigned char header[2] = {FRAME_ADDR, FRAME_CTRL};    unsigned char tail[2];#ifdef USE_BPF    int type;#endif    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;    }    if (conn->debugFile) {	dumpPacket(conn->debugFile, &packet, "RCVD");	fprintf(conn->debugFile, "\n");	fflush(conn->debugFile);    }#ifdef USE_BPF    //Make sure this is a session packet before processing further     type = etherType(&packet);    if (type == Eth_PPPOE_Discovery) {	sessionDiscoveryPacket(&packet);    } else if (type != Eth_PPPOE_Session) {	return;    }#endif    //Sanity check     if (packet.code != CODE_SESS) {	syslog(LOG_ERR, "Unexpected packet code %d", (int) packet.code);	return;    }    if (packet.ver != 1) {	syslog(LOG_ERR, "Unexpected packet version %d", (int) packet.ver);	return;    }    if (packet.type != 1) {	syslog(LOG_ERR, "Unexpected packet type %d", (int) packet.type);	return;    }    if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) {	return;    }    if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) {	 //Not for us -- must be another session.  This is not an error,	   //so don't log anything.  	return;    }    if (packet.session != conn->session) {	//Not for us -- must be another session.  This is not an error,	  // so don't log anything.  	return;    }    plen = ntohs(packet.length);    if (plen + HDR_SIZE > len) {	syslog(LOG_ERR, "Bogus length field in session packet %d (%d)",	       (int) plen, (int) len);	return;    }    //Clamp MSS     if (clampMss) {	clampMSS(&packet, "incoming", clampMss);    }    // Compute FCS     fcs = pppFCS16(PPPINITFCS16, header, 2);    fcs = pppFCS16(fcs, packet.payload, plen) ^ 0xffff;    tail[0] = fcs & 0x00ff;    tail[1] = (fcs >> 8) & 0x00ff;    // Build a buffer to send to PPP     *ptr++ = FRAME_FLAG;    *ptr++ = FRAME_ADDR;    *ptr++ = FRAME_ESC;    *ptr++ = FRAME_CTRL ^ FRAME_ENC;    for (i=0; i<plen; i++) {	c = packet.payload[i];	if (c == FRAME_FLAG || c == FRAME_ADDR || c == FRAME_ESC || c < 0x20) {	    *ptr++ = FRAME_ESC;	    *ptr++ = c ^ FRAME_ENC;	} else {	    *ptr++ = c;	}    }    for (i=0; i<2; i++) {	c = tail[i];	if (c == FRAME_FLAG || c == FRAME_ADDR || c == FRAME_ESC || c < 0x20) {	    *ptr++ = FRAME_ESC;	    *ptr++ = c ^ FRAME_ENC;	} else {	    *ptr++ = c;	}    }    *ptr++ = FRAME_FLAG;    // Ship it out     if (write(1, pppBuf, (ptr-pppBuf)) < 0) {	fatalSys("asyncReadFromEth: write");    }}/***********************************************************************%FUNCTION: syncReadFromEth*%ARGUMENTS:* conn -- PPPoE connection info* sock -- Ethernet socket* clampMss -- if true, clamp MSS.*%RETURNS:* Nothing*%DESCRIPTION:* Reads a packet from the Ethernet interface and sends it to sync PPP* device.***********************************************************************/voidsyncReadFromEth(PPPoEConnection *conn, int sock, int clampMss){    PPPoEPacket packet;    int len;    int plen;    struct iovec vec[2];    unsigned char dummy[2];	unsigned char buf[2000];#ifdef USE_BPF    int type;#endif    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;    }    if (conn->debugFile) {	dumpPacket(conn->debugFile, &packet, "RCVD");	fprintf(conn->debugFile, "\n");	fflush(conn->debugFile);    }#ifdef USE_BPF    //Make sure this is a session packet before processing further     type = etherType(&packet);    if (type == Eth_PPPOE_Discovery) {	sessionDiscoveryPacket(&packet);    } else if (type != Eth_PPPOE_Session) {	return;    }#endif    //Sanity check     if (packet.code != CODE_SESS) {	syslog(LOG_ERR, "Unexpected packet code %d", (int) packet.code);	return;    }    if (packet.ver != 1) {	syslog(LOG_ERR, "Unexpected packet version %d", (int) packet.ver);	return;    }    if (packet.type != 1) {	syslog(LOG_ERR, "Unexpected packet type %d", (int) packet.type);	return;    }    if (memcmp(packet.ethHdr.h_dest, conn->myEth, ETH_ALEN)) {	//Not for us -- must be another session.  This is not an error,	//   so don't log anything.  	return;    }    if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) {	//Not for us -- must be another session.  This is not an error,	//   so don't log anything.  	return;    }    if (packet.session != conn->session) {	// Not for us -- must be another session.  This is not an error,	 //  so don't log anything.  	return;    }    plen = ntohs(packet.length);    if (plen + HDR_SIZE > len) {	syslog(LOG_ERR, "Bogus length field in session packet %d (%d)",	       (int) plen, (int) len);	return;    }    // Clamp MSS     if (clampMss) {	clampMSS(&packet, "incoming", clampMss);    }    // Ship it out     /*vec[0].iov_base = (void *) dummy;    dummy[0] = FRAME_ADDR;    dummy[1] = FRAME_CTRL;    vec[0].iov_len = 2;    vec[1].iov_base = (void *) packet.payload;    vec[1].iov_len = plen;		if (writev(1, vec, 2) < 0) {	fatalSys("syncReadFromEth: write");    }		*/	buf[0]=FRAME_ADDR;	buf[1]=FRAME_CTRL;		memcpy((void*)&buf[2],(void*)packet.payload,plen);	if (write(1,(void*)buf,plen+2) < 0) 	{		fatalSys("syncReadFromEth: write");    }   }//守护进程初始化void init_daemon(void){	int pid;	int i;	if(pid=fork()) exit(0);//是父进程,结束父进程	else if(pid< 0) exit(1);//fork失败,退出, 是第一子进程,后台继续执行	setsid();	//第一子进程成为新的会话组长和进程组长		//并与控制终端分离	if(pid=fork()) exit(0);//是第一子进程,结束第一子进程	else if(pid< 0) exit(1);//fork失败,退出, 是第二子进程,继续, 第二子进程不再是会话组长	//关闭打开的文件描述符	for(i=0;i< NOFILE;++i) close(i);		chdir("/tmp");	//改变工作目录到/tmp	umask(0);	//重设文件创建掩模	return;}

⌨️ 快捷键说明

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