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

📄 discovery.c

📁 实现点到点的以太网协议,用于拨号上网,是拨号上网的基础部分软件模块.
💻 C
📖 第 1 页 / 共 2 页
字号:
    pc.seenServiceName = 0;	    do {	if (BPF_BUFFER_IS_EMPTY) {	    tv.tv_sec = timeout;	    tv.tv_usec = 0;		    FD_ZERO(&readable);	    FD_SET(conn->discoverySocket, &readable);	    while(1) {		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);		if (r >= 0 || errno != EINTR) break;	    }	    if (r < 0) {		fatalSys("select (waitForPADO)");	    }	    if (r == 0) return;        /* Timed out */	}		/* Get the packet */	receivePacket(conn->discoverySocket, &packet, &len);	/* Check length */	if (ntohs(packet.length) + HDR_SIZE > len) {	    syslog(LOG_ERR, "Bogus PPPoE length field (%u)",		   (unsigned int) ntohs(packet.length));	    continue;	}#ifdef USE_BPF	/* If it's not a Discovery packet, loop again */	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;#endif	if (conn->debugFile) {	    dumpPacket(conn->debugFile, &packet, "RCVD");	    fprintf(conn->debugFile, "\n");	    fflush(conn->debugFile);	}	/* If it's not for us, loop again */	if (!packetIsForMe(conn, &packet)) continue;	if (packet.code == CODE_PADO) {	    if (BROADCAST(packet.ethHdr.h_source)) {		printErr("Ignoring PADO packet from broadcast MAC address");		continue;	    }	    parsePacket(&packet, parsePADOTags, &pc);	    if (!pc.seenACName) {		printErr("Ignoring PADO packet with no AC-Name tag");		continue;	    }	    if (!pc.seenServiceName) {		printErr("Ignoring PADO packet with no Service-Name tag");		continue;	    }	    conn->numPADOs++;	    if (conn->printACNames) {		printf("--------------------------------------------------\n");	    }	    if (pc.acNameOK && pc.serviceNameOK) {		memcpy(conn->peerEth, packet.ethHdr.h_source, ETH_ALEN);		if (conn->printACNames) {		    printf("AC-Ethernet-Address: %02x:%02x:%02x:%02x:%02x:%02x\n",			   (unsigned) conn->peerEth[0], 			   (unsigned) conn->peerEth[1],			   (unsigned) conn->peerEth[2],			   (unsigned) conn->peerEth[3],			   (unsigned) conn->peerEth[4],			   (unsigned) conn->peerEth[5]);		    continue;		}		conn->discoveryState = STATE_RECEIVED_PADO;		break;	    }	}    } while (conn->discoveryState != STATE_RECEIVED_PADO);}/************************************************************************%FUNCTION: sendPADR*%ARGUMENTS:* conn -- PPPoE connection structur*%RETURNS:* Nothing*%DESCRIPTION:* Sends a PADR packet***********************************************************************/voidsendPADR(PPPoEConnection *conn){    PPPoEPacket packet;    PPPoETag *svc = (PPPoETag *) packet.payload;    unsigned char *cursor = packet.payload;    UINT16_t namelen = 0;    UINT16_t plen;    if (conn->serviceName) {	namelen = (UINT16_t) strlen(conn->serviceName);    }    plen = TAG_HDR_SIZE + namelen;    CHECK_ROOM(cursor, packet.payload, plen);    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_Discovery);    packet.ver = 1;    packet.type = 1;    packet.code = CODE_PADR;    packet.session = 0;    svc->type = TAG_SERVICE_NAME;    svc->length = htons(namelen);    if (conn->serviceName) {	memcpy(svc->payload, conn->serviceName, namelen);    }    cursor += namelen + TAG_HDR_SIZE;    /* If we're using Host-Uniq, copy it over */    if (conn->useHostUniq) {	PPPoETag hostUniq;	pid_t pid = getpid();	hostUniq.type = htons(TAG_HOST_UNIQ);	hostUniq.length = htons(sizeof(pid));	memcpy(hostUniq.payload, &pid, sizeof(pid));	CHECK_ROOM(cursor, packet.payload, sizeof(pid)+TAG_HDR_SIZE);	memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);	cursor += sizeof(pid) + TAG_HDR_SIZE;	plen += sizeof(pid) + TAG_HDR_SIZE;    }    /* Copy cookie and relay-ID if needed */    if (conn->cookie.type) {	CHECK_ROOM(cursor, packet.payload,		   ntohs(conn->cookie.length) + TAG_HDR_SIZE);	memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);	cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;	plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;    }    if (conn->relayId.type) {	CHECK_ROOM(cursor, packet.payload,		   ntohs(conn->relayId.length) + TAG_HDR_SIZE);	memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);	cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;	plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;    }    packet.length = htons(plen);    sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));    if (conn->debugFile) {	dumpPacket(conn->debugFile, &packet, "SENT");	fprintf(conn->debugFile, "\n");	fflush(conn->debugFile);    }}/***********************************************************************%FUNCTION: waitForPADS*%ARGUMENTS:* conn -- PPPoE connection info* timeout -- how long to wait (in seconds)*%RETURNS:* Nothing*%DESCRIPTION:* Waits for a PADS packet and copies useful information***********************************************************************/voidwaitForPADS(PPPoEConnection *conn, int timeout){    fd_set readable;    int r;    struct timeval tv;    PPPoEPacket packet;    int len;    do {	if (BPF_BUFFER_IS_EMPTY) {	    tv.tv_sec = timeout;	    tv.tv_usec = 0;	    	    FD_ZERO(&readable);	    FD_SET(conn->discoverySocket, &readable);	    	    while(1) {		r = select(conn->discoverySocket+1, &readable, NULL, NULL, &tv);		if (r >= 0 || errno != EINTR) break;	    }	    if (r < 0) {		fatalSys("select (waitForPADS)");	    }	    if (r == 0) return;	}	/* Get the packet */	receivePacket(conn->discoverySocket, &packet, &len);	/* Check length */	if (ntohs(packet.length) + HDR_SIZE > len) {	    syslog(LOG_ERR, "Bogus PPPoE length field (%u)",		   (unsigned int) ntohs(packet.length));	    continue;	}#ifdef USE_BPF	/* If it's not a Discovery packet, loop again */	if (etherType(&packet) != Eth_PPPOE_Discovery) continue;#endif	if (conn->debugFile) {	    dumpPacket(conn->debugFile, &packet, "RCVD");	    fprintf(conn->debugFile, "\n");	    fflush(conn->debugFile);	}	/* If it's not from the AC, it's not for me */	if (memcmp(packet.ethHdr.h_source, conn->peerEth, ETH_ALEN)) continue;	/* If it's not for us, loop again */	if (!packetIsForMe(conn, &packet)) continue;	/* Is it PADS?  */	if (packet.code == CODE_PADS) {	    /* Parse for goodies */	    parsePacket(&packet, parsePADSTags, conn);	    conn->discoveryState = STATE_SESSION;	    break;	}    } while (conn->discoveryState != STATE_SESSION);    /* Don't bother with ntohs; we'll just end up converting it back... */    conn->session = packet.session;    syslog(LOG_INFO, "PPP session is %d", (int) ntohs(conn->session));    /* RFC 2516 says session id MUST NOT be zero or 0xFFFF */    if (ntohs(conn->session) == 0 || ntohs(conn->session) == 0xFFFF) {	syslog(LOG_ERR, "Access concentrator used a session value of %x -- the AC is violating RFC 2516", (unsigned int) ntohs(conn->session));    }}/***********************************************************************%FUNCTION: discovery*%ARGUMENTS:* conn -- PPPoE connection info structure*%RETURNS:* Nothing*%DESCRIPTION:* Performs the PPPoE discovery phase***********************************************************************/voiddiscovery(PPPoEConnection *conn){    int padiAttempts = 0;    int padrAttempts = 0;    int timeout = PADI_TIMEOUT;    /* Skip discovery and don't open discovery socket? */    if (conn->skipDiscovery && conn->noDiscoverySocket) {	conn->discoveryState = STATE_SESSION;	return;    }    conn->discoverySocket =	openInterface(conn->ifName, Eth_PPPOE_Discovery, conn->myEth);    /* Skip discovery? */    if (conn->skipDiscovery) {	conn->discoveryState = STATE_SESSION;	return;    }    do {	padiAttempts++;	if (padiAttempts > MAX_PADI_ATTEMPTS) {	    warn("Timeout waiting for PADO packets");	    close(conn->discoverySocket);	    conn->discoverySocket = -1;	    return;	}	sendPADI(conn);	conn->discoveryState = STATE_SENT_PADI;	waitForPADO(conn, timeout);	/* If we're just probing for access concentrators, don't do	   exponential backoff.  This reduces the time for an unsuccessful	   probe to 15 seconds. */	if (!conn->printACNames) {	    timeout *= 2;	}	if (conn->printACNames && conn->numPADOs) {	    break;	}    } while (conn->discoveryState == STATE_SENT_PADI);    /* If we're only printing access concentrator names, we're done */    if (conn->printACNames) {	die(0);    }    timeout = PADI_TIMEOUT;    do {	padrAttempts++;	if (padrAttempts > MAX_PADI_ATTEMPTS) {	    warn("Timeout waiting for PADS packets");	    close(conn->discoverySocket);	    conn->discoverySocket = -1;	    return;	}	sendPADR(conn);	conn->discoveryState = STATE_SENT_PADR;	waitForPADS(conn, timeout);	timeout *= 2;    } while (conn->discoveryState == STATE_SENT_PADR);    /* We're done. */    conn->discoveryState = STATE_SESSION;    return;}

⌨️ 快捷键说明

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