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

📄 relay.c

📁 网上的一个开源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (!loc) {	tag.type = htons(TAG_RELAY_SESSION_ID);	tag.length = htons(MY_RELAY_TAG_LEN);	memcpy(tag.payload, &ifIndex, sizeof(ifIndex));	memcpy(tag.payload+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN);	/* Add a relay tag if there's room */	r = addTag(packet, &tag);	if (r < 0) return;	size += r;    } else {	/* We do not re-use relay-id tags.  Drop the frame.  The RFC says the	   relay agent SHOULD return a Generic-Error tag, but this does not	   make sense for PADI packets. */	return;    }    /* Broadcast the PADI on all AC-capable interfaces except the interface       on which it came */    for (i=0; i < NumInterfaces; i++) {	if (iface == &Interfaces[i]) continue;	if (!Interfaces[i].acOK) continue;	memcpy(packet->ethHdr.h_source, Interfaces[i].mac, ETH_ALEN);	sendPacket(NULL, Interfaces[i].discoverySock, packet, size);    }}/***********************************************************************%FUNCTION: relayHandlePADO*%ARGUMENTS:* iface -- interface on which packet was received* packet -- the PADO packet*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a PADO packet.***********************************************************************/voidrelayHandlePADO(PPPoEInterface const *iface,		PPPoEPacket *packet,		int size){    PPPoETag tag;    unsigned char *loc;    int ifIndex;    int acIndex;    /* Can a server legally be behind this interface? */    if (!iface->acOK) {	syslog(LOG_ERR,	       "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    acIndex = iface - Interfaces;    /* Source address must be unicast */    if (NOT_UNICAST(packet->ethHdr.h_source)) {	syslog(LOG_ERR,	       "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Destination address must be interface's MAC address */    if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) {	return;    }    /* Find relay tag */    loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag);    if (!loc) {	syslog(LOG_ERR,	       "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* If it's the wrong length, ignore it */    if (ntohs(tag.length) != MY_RELAY_TAG_LEN) {	syslog(LOG_ERR,	       "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Extract interface index */    memcpy(&ifIndex, tag.payload, sizeof(ifIndex));    if (ifIndex < 0 || ifIndex >= NumInterfaces ||	!Interfaces[ifIndex].clientOK ||	iface == &Interfaces[ifIndex]) {	syslog(LOG_ERR,	       "PADO packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Replace Relay-ID tag with opposite-direction tag */    memcpy(loc+TAG_HDR_SIZE, &acIndex, sizeof(acIndex));    memcpy(loc+TAG_HDR_SIZE+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN);    /* Set destination address to MAC address in relay ID */    memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN);    /* Set source address to MAC address of interface */    memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN);    /* Send the PADO to the proper client */    sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size);}/***********************************************************************%FUNCTION: relayHandlePADR*%ARGUMENTS:* iface -- interface on which packet was received* packet -- the PADR packet*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a PADR packet.***********************************************************************/voidrelayHandlePADR(PPPoEInterface const *iface,		PPPoEPacket *packet,		int size){    PPPoETag tag;    unsigned char *loc;    int ifIndex;    int cliIndex;    /* Can a client legally be behind this interface? */    if (!iface->clientOK) {	syslog(LOG_ERR,	       "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    cliIndex = iface - Interfaces;    /* Source address must be unicast */    if (NOT_UNICAST(packet->ethHdr.h_source)) {	syslog(LOG_ERR,	       "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Destination address must be interface's MAC address */    if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) {	return;    }    /* Find relay tag */    loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag);    if (!loc) {	syslog(LOG_ERR,	       "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* If it's the wrong length, ignore it */    if (ntohs(tag.length) != MY_RELAY_TAG_LEN) {	syslog(LOG_ERR,	       "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Extract interface index */    memcpy(&ifIndex, tag.payload, sizeof(ifIndex));    if (ifIndex < 0 || ifIndex >= NumInterfaces ||	!Interfaces[ifIndex].acOK ||	iface == &Interfaces[ifIndex]) {	syslog(LOG_ERR,	       "PADR packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Replace Relay-ID tag with opposite-direction tag */    memcpy(loc+TAG_HDR_SIZE, &cliIndex, sizeof(cliIndex));    memcpy(loc+TAG_HDR_SIZE+sizeof(ifIndex), packet->ethHdr.h_source, ETH_ALEN);    /* Set destination address to MAC address in relay ID */    memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN);    /* Set source address to MAC address of interface */    memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN);    /* Send the PADR to the proper access concentrator */    sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size);}/***********************************************************************%FUNCTION: relayHandlePADS*%ARGUMENTS:* iface -- interface on which packet was received* packet -- the PADS packet*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a PADS packet.***********************************************************************/voidrelayHandlePADS(PPPoEInterface const *iface,		PPPoEPacket *packet,		int size){    PPPoETag tag;    unsigned char *loc;    int ifIndex;    int acIndex;    PPPoESession *ses = NULL;    SessionHash *sh;    /* Can a server legally be behind this interface? */    if (!iface->acOK) {	syslog(LOG_ERR,	       "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not permitted",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    acIndex = iface - Interfaces;    /* Source address must be unicast */    if (NOT_UNICAST(packet->ethHdr.h_source)) {	syslog(LOG_ERR,	       "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not from a unicast address",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Destination address must be interface's MAC address */    if (memcmp(packet->ethHdr.h_dest, iface->mac, ETH_ALEN)) {	return;    }    /* Find relay tag */    loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag);    if (!loc) {	syslog(LOG_ERR,	       "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* If it's the wrong length, ignore it */    if (ntohs(tag.length) != MY_RELAY_TAG_LEN) {	syslog(LOG_ERR,	       "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s does not have correct length Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* Extract interface index */    memcpy(&ifIndex, tag.payload, sizeof(ifIndex));    if (ifIndex < 0 || ifIndex >= NumInterfaces ||	!Interfaces[ifIndex].clientOK ||	iface == &Interfaces[ifIndex]) {	syslog(LOG_ERR,	       "PADS packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s has invalid interface in Relay-Session-Id tag",	       packet->ethHdr.h_source[0],	       packet->ethHdr.h_source[1],	       packet->ethHdr.h_source[2],	       packet->ethHdr.h_source[3],	       packet->ethHdr.h_source[4],	       packet->ethHdr.h_source[5],	       iface->name);	return;    }    /* If session ID is zero, it's the AC respoding with an error.       Just relay it; do not create a session */    if (packet->session != htons(0)) {	/* Check for existing session */	sh = findSession(packet->ethHdr.h_source, packet->session);	if (sh) ses = sh->ses;	/* If already an existing session, assume it's a duplicate PADS.  Send	   the frame, but do not create a new session.  Is this the right	   thing to do?  Arguably, should send an error to the client and	   a PADT to the server, because this could happen due to a	   server crash and reboot. */	if (!ses) {	    /* Create a new session */	    ses = createSession(iface, &Interfaces[ifIndex],				packet->ethHdr.h_source,				loc + TAG_HDR_SIZE + sizeof(ifIndex), packet->session);	    if (!ses) {		/* Can't allocate session -- send error PADS to client and		   PADT to server */		PPPoETag hostUniq, *hu;		if (findTag(packet, TAG_HOST_UNIQ, &hostUniq)) {		    hu = &hostUniq;		} else {		    hu = NULL;		}		relaySendError(CODE_PADS, htons(0), &Interfaces[ifIndex],			       loc + TAG_HDR_SIZE + sizeof(ifIndex),			       hu, "RP-PPPoE: Relay: Unable to allocate session");		relaySendError(CODE_PADT, packet->session, iface,			       packet->ethHdr.h_source, NULL,			       "RP-PPPoE: Relay: Unable to allocate session");		return;	    }	}	/* Replace session number */	packet->session = ses->sesNum;    }    /* Remove relay-ID tag */    removeBytes(packet, loc, MY_RELAY_TAG_LEN + TAG_HDR_SIZE);    size -= (MY_RELAY_TAG_LEN + TAG_HDR_SIZE);    /* Set destination address to MAC address in relay ID */    memcpy(packet->ethHdr.h_dest, tag.payload + sizeof(ifIndex), ETH_ALEN);    /* Set source address to MAC address of interface */    memcpy(packet->ethHdr.h_source, Interfaces[ifIndex].mac, ETH_ALEN);    /* Send the PADS to the proper client */    sendPacket(NULL, Interfaces[ifIndex].discoverySock, packet, size);}/***********************************************************************%FUNCTION: relaySendError*%ARGUMENTS:* code -- PPPoE packet code (PADS or PADT, typically)* session -- PPPoE session number* iface -- interface on which to send frame* mac -- Ethernet address to which frame should be sent* hostUniq -- if non-NULL, a hostUniq tag to add to error frame* errMsg -- error message to insert into Generic-Error tag.*%RETURNS:* Nothing*%DESCRIPTION:* Sends either a PADS or PADT packet with a Generic-Error tag and an* error message.***********************************************************************/voidrelaySendError(unsigned char code,	       UINT16_t session,	       PPPoEInterface const *iface,	       unsigned char const *mac,	       PPPoETag const *hostUniq,	       char const *errMsg){    PPPoEPacket packet;    PPPoETag errTag;    int size;    memcpy(packet.ethHdr.h_source, iface->mac, ETH_ALEN);    memcpy(packet.ethHdr.h_dest, mac, ETH_ALEN);    packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);    packet.type = 1;    packet.ver = 1;    packet.code = code;    packet.session = session;    packet.length = htons(0);    if (hostUniq) {	if (addTag(&packet, hostUniq) < 0) return;    }    errTag.type = htons(TAG_GENERIC_ERROR);    errTag.length = htons(strlen(errMsg));    strcpy((char *) errTag.payload, errMsg);    if (addTag(&packet, &errTag) < 0) return;    size = ntohs(packet.length) + HDR_SIZE;    if (code == CODE_PADT) {	sendPacket(NULL, iface->discoverySock, &packet, size);    } else {	sendPacket(NULL, iface->sessionSock, &packet, size);    }}/***********************************************************************%FUNCTION: alarmHandler*%ARGUMENTS:* sig -- signal number*%RETURNS:* Nothing*%DESCRIPTION:* SIGALRM handler.  Increments Epoch; if necessary, writes a byte of* data to the alarm pipe to trigger the stale-session cleaner.***********************************************************************/voidalarmHandler(int sig){    alarm(1);    Epoch++;    CleanCounter++;    if (CleanCounter == CleanPeriod) {	write(CleanPipe[1], "", 1);    }}/***********************************************************************%FUNCTION: cleanSessions*%ARGUMENTS:* None*%RETURNS:* Nothing*%DESCRIPTION:* Goes through active sessions and cleans sessions idle for longer* than IdleTimeout seconds.***********************************************************************/void cleanSessions(void){    PPPoESession *cur, *next;    cur = ActiveSessions;    while(cur) {	next = cur->next;	if (Epoch - cur->epoch > IdleTimeout) {	    /* Send PADT to each peer */	    relaySendError(CODE_PADT, cur->acHash->sesNum,			   cur->acHash->interface,			   cur->acHash->peerMac, NULL,			   "RP-PPPoE: Relay: Session exceeded idle timeout");	    relaySendError(CODE_PADT, cur->clientHash->sesNum,			   cur->clientHash->interface,			   cur->clientHash->peerMac, NULL,			   "RP-PPPoE: Relay: Session exceeded idle timeout");	    freeSession(cur, "Idle Timeout");	}	cur = next;    }}

⌨️ 快捷键说明

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