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

📄 relay.c

📁 网上的一个开源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    memcpy(cliHash->peerMac, cliMac, ETH_ALEN);    cliHash->sesNum = sess->sesNum;    cliHash->ses = sess;    addHash(acHash);    addHash(cliHash);    /* Log */    syslog(LOG_INFO,	   "Opened session: server=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d), client=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d)",	   acHash->peerMac[0], acHash->peerMac[1],	   acHash->peerMac[2], acHash->peerMac[3],	   acHash->peerMac[4], acHash->peerMac[5],	   acHash->interface->name,	   ntohs(acHash->sesNum),	   cliHash->peerMac[0], cliHash->peerMac[1],	   cliHash->peerMac[2], cliHash->peerMac[3],	   cliHash->peerMac[4], cliHash->peerMac[5],	   cliHash->interface->name,	   ntohs(cliHash->sesNum));    return sess;}/***********************************************************************%FUNCTION: freeSession*%ARGUMENTS:* ses -- session to free* msg -- extra message to log on syslog.*%RETURNS:* Nothing*%DESCRIPTION:* Frees data used by a PPPoE session -- adds hashes and session back* to the free list***********************************************************************/voidfreeSession(PPPoESession *ses, char const *msg){    syslog(LOG_INFO,	   "Closed session: server=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d), client=%02x:%02x:%02x:%02x:%02x:%02x(%s:%d): %s",	   ses->acHash->peerMac[0], ses->acHash->peerMac[1],	   ses->acHash->peerMac[2], ses->acHash->peerMac[3],	   ses->acHash->peerMac[4], ses->acHash->peerMac[5],	   ses->acHash->interface->name,	   ntohs(ses->acHash->sesNum),	   ses->clientHash->peerMac[0], ses->clientHash->peerMac[1],	   ses->clientHash->peerMac[2], ses->clientHash->peerMac[3],	   ses->clientHash->peerMac[4], ses->clientHash->peerMac[5],	   ses->clientHash->interface->name,	   ntohs(ses->clientHash->sesNum), msg);    /* Unlink from active sessions */    if (ses->prev) {	ses->prev->next = ses->next;    } else {	ActiveSessions = ses->next;    }    if (ses->next) {	ses->next->prev = ses->prev;    }    /* Link onto free list -- this is a singly-linked list, so       we do not care about prev */    ses->next = FreeSessions;    FreeSessions = ses;    unhash(ses->acHash);    unhash(ses->clientHash);    NumSessions--;}/***********************************************************************%FUNCTION: unhash*%ARGUMENTS:* sh -- session hash to free*%RETURNS:* Nothing*%DESCRIPTION:* Frees a session hash -- takes it out of hash table and puts it on* free list.***********************************************************************/voidunhash(SessionHash *sh){    unsigned int b = hash(sh->peerMac, sh->sesNum) % HASHTAB_SIZE;    if (sh->prev) {	sh->prev->next = sh->next;    } else {	Buckets[b] = sh->next;    }    if (sh->next) {	sh->next->prev = sh->prev;    }    /* Add to free list (singly-linked) */    sh->next = FreeHashes;    FreeHashes = sh;}/***********************************************************************%FUNCTION: addHash*%ARGUMENTS:* sh -- a session hash*%RETURNS:* Nothing*%DESCRIPTION:* Adds a SessionHash to the hash table***********************************************************************/voidaddHash(SessionHash *sh){    unsigned int b = hash(sh->peerMac, sh->sesNum) % HASHTAB_SIZE;    sh->next = Buckets[b];    sh->prev = NULL;    if (sh->next) {	sh->next->prev = sh;    }    Buckets[b] = sh;}/***********************************************************************%FUNCTION: hash*%ARGUMENTS:* mac -- an Ethernet address* sesNum -- a session number*%RETURNS:* A hash value combining Ethernet address with session number.* Currently very simplistic; we may need to experiment with different* hash values.***********************************************************************/unsigned inthash(unsigned char const *mac, UINT16_t sesNum){    unsigned int ans1 =	((unsigned int) mac[0]) |	(((unsigned int) mac[1]) << 8) |	(((unsigned int) mac[2]) << 16) |	(((unsigned int) mac[3]) << 24);    unsigned int ans2 =	((unsigned int) sesNum) |	(((unsigned int) mac[4]) << 16) |	(((unsigned int) mac[5]) << 24);    return ans1 ^ ans2;}/***********************************************************************%FUNCTION: findSession*%ARGUMENTS:* mac -- an Ethernet address* sesNum -- a session number*%RETURNS:* The session hash for peer address "mac", session number sesNum***********************************************************************/SessionHash *findSession(unsigned char const *mac, UINT16_t sesNum){    unsigned int b = hash(mac, sesNum) % HASHTAB_SIZE;    SessionHash *sh = Buckets[b];    while(sh) {	if (!memcmp(mac, sh->peerMac, ETH_ALEN) && sesNum == sh->sesNum) {	    return sh;	}	sh = sh->next;    }    return NULL;}/***********************************************************************%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: %.256s", str, strerror(errno));    printErr(buf);    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);    exit(EXIT_FAILURE);}/***********************************************************************%FUNCTION: relayLoop*%ARGUMENTS:* None*%RETURNS:* Nothing*%DESCRIPTION:* Runs the relay loop.  This function never returns***********************************************************************/voidrelayLoop(){    fd_set readable, readableCopy;    int maxFD;    int i, r;    int sock;    /* Build the select set */    FD_ZERO(&readable);    maxFD = 0;    for (i=0; i<NumInterfaces; i++) {	sock = Interfaces[i].discoverySock;	if (sock > maxFD) maxFD = sock;	FD_SET(sock, &readable);	sock = Interfaces[i].sessionSock;	if (sock > maxFD) maxFD = sock;	FD_SET(sock, &readable);	if (CleanPipe[0] > maxFD) maxFD = CleanPipe[0];	FD_SET(CleanPipe[0], &readable);    }    maxFD++;    for(;;) {	readableCopy = readable;	for(;;) {	    r = select(maxFD, &readableCopy, NULL, NULL, NULL);	    if (r >= 0 || errno != EINTR) break;	}	if (r < 0) {	    sysErr("select (relayLoop)");	    continue;	}	/* Handle session packets first */	for (i=0; i<NumInterfaces; i++) {	    if (FD_ISSET(Interfaces[i].sessionSock, &readableCopy)) {		relayGotSessionPacket(&Interfaces[i]);	    }	}	/* Now handle discovery packets */	for (i=0; i<NumInterfaces; i++) {	    if (FD_ISSET(Interfaces[i].discoverySock, &readableCopy)) {		relayGotDiscoveryPacket(&Interfaces[i]);	    }	}	/* Handle the session-cleaning process */	if (FD_ISSET(CleanPipe[0], &readableCopy)) {	    char dummy;	    CleanCounter = 0;	    read(CleanPipe[0], &dummy, 1);	    if (IdleTimeout) cleanSessions();	}    }}/***********************************************************************%FUNCTION: relayGotDiscoveryPacket*%ARGUMENTS:* iface -- interface on which packet is waiting*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a discovery packet.***********************************************************************/voidrelayGotDiscoveryPacket(PPPoEInterface const *iface){    PPPoEPacket packet;    int size;    if (receivePacket(iface->discoverySock, &packet, &size) < 0) {	return;    }    /* Ignore unknown code/version */    if (packet.ver != 1 || packet.type != 1) {	return;    }    /* Validate length */    if (ntohs(packet.length) + HDR_SIZE > size) {	syslog(LOG_ERR, "Bogus PPPoE length field (%u)",	       (unsigned int) ntohs(packet.length));	return;    }    /* Drop Ethernet frame padding */    if (size > ntohs(packet.length) + HDR_SIZE) {	size = ntohs(packet.length) + HDR_SIZE;    }    switch(packet.code) {    case CODE_PADT:	relayHandlePADT(iface, &packet, size);	break;    case CODE_PADI:	relayHandlePADI(iface, &packet, size);	break;    case CODE_PADO:	relayHandlePADO(iface, &packet, size);	break;    case CODE_PADR:	relayHandlePADR(iface, &packet, size);	break;    case CODE_PADS:	relayHandlePADS(iface, &packet, size);	break;    default:	syslog(LOG_ERR, "Discovery packet on %s with unknown code %d",	       iface->name, (int) packet.code);    }}/***********************************************************************%FUNCTION: relayGotSessionPacket*%ARGUMENTS:* iface -- interface on which packet is waiting*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a session packet.***********************************************************************/voidrelayGotSessionPacket(PPPoEInterface const *iface){    PPPoEPacket packet;    int size;    SessionHash *sh;    PPPoESession *ses;    if (receivePacket(iface->sessionSock, &packet, &size) < 0) {	return;    }    /* Ignore unknown code/version */    if (packet.ver != 1 || packet.type != 1) {	return;    }    /* Must be a session packet */    if (packet.code != CODE_SESS) {	syslog(LOG_ERR, "Session packet with code %d", (int) packet.code);	return;    }    /* Ignore session packets whose destination address isn't ours */    if (memcmp(packet.ethHdr.h_dest, iface->mac, ETH_ALEN)) {	return;    }    /* Validate length */    if (ntohs(packet.length) + HDR_SIZE > size) {	syslog(LOG_ERR, "Bogus PPPoE length field (%u)",	       (unsigned int) ntohs(packet.length));	return;    }    /* Drop Ethernet frame padding */    if (size > ntohs(packet.length) + HDR_SIZE) {	size = ntohs(packet.length) + HDR_SIZE;    }    /* We're in business!  Find the hash */    sh = findSession(packet.ethHdr.h_source, packet.session);    if (!sh) {	/* Don't log this.  Someone could be running the client and the	   relay on the same box. */	return;    }    /* Relay it */    ses = sh->ses;    ses->epoch = Epoch;    sh = sh->peer;    packet.session = sh->sesNum;    memcpy(packet.ethHdr.h_source, sh->interface->mac, ETH_ALEN);    memcpy(packet.ethHdr.h_dest, sh->peerMac, ETH_ALEN);#if 0    fprintf(stderr, "Relaying %02x:%02x:%02x:%02x:%02x:%02x(%s:%d) to %02x:%02x:%02x:%02x:%02x:%02x(%s:%d)\n",	    sh->peer->peerMac[0], sh->peer->peerMac[1], sh->peer->peerMac[2],	    sh->peer->peerMac[3], sh->peer->peerMac[4], sh->peer->peerMac[5],	    sh->peer->interface->name, ntohs(sh->peer->sesNum),	    sh->peerMac[0], sh->peerMac[1], sh->peerMac[2],	    sh->peerMac[3], sh->peerMac[4], sh->peerMac[5],	    sh->interface->name, ntohs(sh->sesNum));#endif    sendPacket(NULL, sh->interface->sessionSock, &packet, size);}/***********************************************************************%FUNCTION: relayHandlePADT*%ARGUMENTS:* iface -- interface on which packet was received* packet -- the PADT packet*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a PADT packet.***********************************************************************/voidrelayHandlePADT(PPPoEInterface const *iface,		PPPoEPacket *packet,		int size){    SessionHash *sh;    PPPoESession *ses;    sh = findSession(packet->ethHdr.h_source, packet->session);    if (!sh) {	return;    }    /* Relay the PADT to the peer */    sh = sh->peer;    ses = sh->ses;    packet->session = sh->sesNum;    memcpy(packet->ethHdr.h_source, sh->interface->mac, ETH_ALEN);    memcpy(packet->ethHdr.h_dest, sh->peerMac, ETH_ALEN);    sendPacket(NULL, sh->interface->sessionSock, packet, size);    /* Destroy the session */    freeSession(ses, "Received PADT");}/***********************************************************************%FUNCTION: relayHandlePADI*%ARGUMENTS:* iface -- interface on which packet was received* packet -- the PADI packet*%RETURNS:* Nothing*%DESCRIPTION:* Receives and processes a PADI packet.***********************************************************************/voidrelayHandlePADI(PPPoEInterface const *iface,		PPPoEPacket *packet,		int size){    PPPoETag tag;    unsigned char *loc;    int i, r;    int ifIndex;    /* Can a client legally be behind this interface? */    if (!iface->clientOK) {	syslog(LOG_ERR,	       "PADI 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;    }    /* Source address must be unicast */    if (NOT_UNICAST(packet->ethHdr.h_source)) {	syslog(LOG_ERR,	       "PADI 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 broadcast */    if (NOT_BROADCAST(packet->ethHdr.h_dest)) {	syslog(LOG_ERR,	       "PADI packet from %02x:%02x:%02x:%02x:%02x:%02x on interface %s not to a broadcast 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;    }    /* Get array index of interface */    ifIndex = iface - Interfaces;    loc = findTag(packet, TAG_RELAY_SESSION_ID, &tag);

⌨️ 快捷键说明

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