Exemple #1
0
/*
 * @return 1 if forwarded, 0 if discarded
 */
int ForwardPktOnLink (tw_lp * lp, Link * lnk, Packet * p)
{  
  double t, now = tw_now (lp);

  if (lnk->lastPktOutTime_ <= now) {  
    /* No packet is being sent out. Therefore forward it right now */
    t = p->size_ * 8 / ((double) lnk->bw_); /* Transmission delay */
    lnk->lastPktOutTime_ = now + t;
    p->inPort_ = lnk->nbPort_; /* This will copied to the outgoing packet */
    return ForwardPacket (lp, tw_getlp (lnk->neighbour_), p, t + lnk->latency_);
  }
      
  if (p->size_ + (lnk->lastPktOutTime_ - now) / 8 * lnk->bw_ 
      > lnk->bufSize_ + SMALL_FLOAT) {
    /* Buffer is full. Discard the packet
     * The buffered packets include the one being sent except the portion
     * that has been sent. */

#ifdef DEBUG_PKT_DISCARD
    printf ("%lf : pkt(%d:%lu) at %d discarded\n",
            tw_now (lp), _addrToIdx[p->srcAddr_], p->od_.sqn_, lp->id);
    fflush (stdout);
#endif    
  
    return 0;
  }
  
  /* The buffer is not zero, some packet is being sent.
   * Schedule to forward this packet at a future time */
  p->inPort_ = lnk->nbPort_; /* This will copied to the outgoing packet */
  lnk->lastPktOutTime_ += p->size_ * 8 / ((double) lnk->bw_);    
  return ForwardPacket (lp, tw_getlp (lnk->neighbour_), p, 
                        lnk->lastPktOutTime_ + lnk->latency_ - now);
}
void CClientManager::SetEventFlag(TPacketSetEventFlag* p)
{
	ForwardPacket(HEADER_DG_SET_EVENT_FLAG, p, sizeof(TPacketSetEventFlag));

	bool bChanged = false;

	typeof(m_map_lEventFlag.begin()) it = m_map_lEventFlag.find(p->szFlagName);
	if (it == m_map_lEventFlag.end())
	{
		bChanged = true;
		m_map_lEventFlag.insert(std::make_pair(std::string(p->szFlagName), p->lValue));
	}
	else if (it->second != p->lValue)
	{
		bChanged = true;
		it->second = p->lValue;
	}

	if (bChanged)
	{
		char szQuery[1024];
		snprintf(szQuery, sizeof(szQuery),
				"REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(0, '%s', '', %ld)",
				GetTablePostfix(), p->szFlagName, p->lValue);
		szQuery[1023] = '\0';

		//CDBManager::instance().ReturnQuery(szQuery, QID_QUEST_SAVE, 0, NULL);
		CDBManager::instance().AsyncQuery(szQuery);
		sys_log(0, "HEADER_GD_SET_EVENT_FLAG : Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
		return;
	}
	sys_log(0, "HEADER_GD_SET_EVENT_FLAG : No Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
}
void CClientManager::GuildCreate(CPeer * peer, DWORD dwGuildID)
{
	sys_log(0, "GuildCreate %u", dwGuildID);
	ForwardPacket(HEADER_DG_GUILD_LOAD, &dwGuildID, sizeof(DWORD));

	CGuildManager::instance().Load(dwGuildID);
}
void CClientManager::UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer)
{
	char szQuery[512];

	snprintf(szQuery, sizeof(szQuery), "REPLACE INTO horse_name VALUES(%u, '%s')", data->dwPlayerID, data->szHorseName);

	std::auto_ptr<SQLMsg> pmsg_insert(CDBManager::instance().DirectQuery(szQuery));

	ForwardPacket(HEADER_DG_UPDATE_HORSE_NAME, data, sizeof(TPacketUpdateHorseName), 0, peer);
}
void CClientManager::GuildChangeMaster(TPacketChangeGuildMaster* p)
{
	if (CGuildManager::instance().ChangeMaster(p->dwGuildID, p->idFrom, p->idTo) == true)
	{
		TPacketChangeGuildMaster packet;
		packet.dwGuildID = p->dwGuildID;
		packet.idFrom = 0;
		packet.idTo = 0;

		ForwardPacket(HEADER_DG_ACK_CHANGE_GUILD_MASTER, &packet, sizeof(packet));
	}
}
void CClientManager::SendGuildSkillUsable(DWORD guild_id, DWORD dwSkillVnum, bool bUsable)
{
	sys_log(0, "SendGuildSkillUsable Send %u %d %s", guild_id, dwSkillVnum, bUsable?"true":"false");

	TPacketGuildSkillUsableChange p;

	p.dwGuild = guild_id;
	p.dwSkillVnum = dwSkillVnum;
	p.bUsable = bUsable;

	ForwardPacket(HEADER_DG_GUILD_SKILL_USABLE_CHANGE, &p, sizeof(TPacketGuildSkillUsableChange));
}
void CClientManager::GuildRemoveMember(CPeer* peer, TPacketGuild* p)
{
	sys_log(0, "GuildRemoveMember %u %u", p->dwGuild, p->dwInfo);

	char szQuery[512];
	snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE pid=%u and guild_id=%u", GetTablePostfix(), p->dwInfo, p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);

	snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(%u, 'guild_manage', 'withdraw_time', %u)", GetTablePostfix(), p->dwInfo, (DWORD) GetCurrentTime());
	CDBManager::instance().AsyncQuery(szQuery);

	ForwardPacket(HEADER_DG_GUILD_REMOVE_MEMBER, p, sizeof(TPacketGuild));
}
void CClientManager::GuildAddMember(CPeer* peer, TPacketGDGuildAddMember * p)
{
	CGuildManager::instance().TouchGuild(p->dwGuild);
	sys_log(0, "GuildAddMember %u %u", p->dwGuild, p->dwPID);

	char szQuery[512];

	snprintf(szQuery, sizeof(szQuery), 
			"INSERT INTO guild_member%s VALUES(%u, %u, %d, 0, 0)",
			GetTablePostfix(), p->dwPID, p->dwGuild, p->bGrade);

	std::auto_ptr<SQLMsg> pmsg_insert(CDBManager::instance().DirectQuery(szQuery));

	snprintf(szQuery, sizeof(szQuery), 
			"SELECT pid, grade, is_general, offer, level, job, name FROM guild_member%s, player%s WHERE guild_id = %u and pid = id and pid = %u", GetTablePostfix(), GetTablePostfix(), p->dwGuild, p->dwPID);

	std::auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));

	if (pmsg->Get()->uiNumRows == 0)
	{
		sys_err("Query failed when getting guild member data %s", pmsg->stQuery.c_str());
		return;
	}

	MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);

	if (!row[0] || !row[1])
		return;

	TPacketDGGuildMember dg;

	dg.dwGuild = p->dwGuild;
	str_to_number(dg.dwPID, row[0]);
	str_to_number(dg.bGrade, row[1]);
	str_to_number(dg.isGeneral, row[2]);
	str_to_number(dg.dwOffer, row[3]);
	str_to_number(dg.bLevel, row[4]);
	str_to_number(dg.bJob, row[5]);
	strlcpymt(dg.szName, row[6], sizeof(dg.szName));

	ForwardPacket(HEADER_DG_GUILD_ADD_MEMBER, &dg, sizeof(TPacketDGGuildMember));
}
void CServerKillCamForwarder::DropOldestPacket()
{
	if (m_history.Empty())
	{
		CryFatalError("We're trying to drop a packet to make space for new data but there's nothing left in the buffer\n");
	}
	BufferType::iterator itPacket=m_history.Begin();
	IActor *pActor=*(IActor**)m_history.GetData(sizeof(IActor*));
	CActor::KillCamFPData *pPacket=(CActor::KillCamFPData*)m_history.GetData(sizeof(CActor::KillCamFPData));
	// If packet in queue to be forwarded, send immediately before dropping
	for (std::deque<SForwardingPacket>::iterator it=m_forwarding.begin(), end=m_forwarding.end(); it!=end; ++it)
	{
		SForwardingPacket &forward=*it;
		if (forward.iterator<=itPacket && forward.pActor==pActor && forward.packetID==pPacket->m_packetId)
		{
			CryLog("Server forwarder queue is overflowing! Forcing packet send to free space\n");
			ForwardPacket(forward, pPacket);
		}
	}
}
void CClientManager::LoadEventFlag()
{
	char szQuery[1024];
	snprintf(szQuery, sizeof(szQuery), "SELECT szName, lValue FROM quest%s WHERE dwPID = 0", GetTablePostfix());
	std::auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));

	SQLResult* pRes = pmsg->Get();
	if (pRes->uiNumRows)
	{
		MYSQL_ROW row;
		while ((row = mysql_fetch_row(pRes->pSQLResult)))
		{
			TPacketSetEventFlag p;
			strlcpymt(p.szFlagName, row[0], sizeof(p.szFlagName));
			str_to_number(p.lValue, row[1]);
			sys_log(0, "EventFlag Load %s %d", p.szFlagName, p.lValue);
			m_map_lEventFlag.insert(std::make_pair(std::string(p.szFlagName), p.lValue));
			ForwardPacket(HEADER_DG_SET_EVENT_FLAG, &p, sizeof(TPacketSetEventFlag));
		}
	}
}
void CServerKillCamForwarder::Update()
{
	CTimeValue now=gEnv->pTimer->GetCurrTime();
	const float k_timeout=2.0f;
	if (!m_forwarding.empty())
	{
		int maxCycles=m_forwarding.size();
		bool bSent=false;
		do 
		{
			SForwardingPacket &forward=m_forwarding.front();
			CActor::KillCamFPData* packet=FindPacket(forward.iterator, forward.pActor, forward.packetID);
			if (packet)
			{
				ForwardPacket(forward, packet);
				bSent=true;
				if (forward.m_sent>=forward.m_numPackets)
					m_forwarding.pop_front();
			}
			else
			{
				if (forward.m_sent!=forward.m_numPackets)
				{
					CryLog("Underflowed forwarding packetID %d from actor %s after sending %d packets\n", forward.packetID, forward.pActor->GetEntity()->GetName(), forward.m_sent);
					if (forward.m_lastPacketTime.GetDifferenceInSeconds(now)>=k_timeout)
					{
						CryLog("Underflowing packet timed out, did the client disconnect? Giving up :(\n");
					}
					else
					{
						// Re-add to the end of the list for trying later (forward packet can arrive before all source packets have arrived)
						m_forwarding.push_back(forward);
					}
				}
				m_forwarding.pop_front();
				maxCycles--;
			}
		} while (!bSent && maxCycles>0);
	}
}
void CClientManager::GuildDisband(CPeer* peer, TPacketGuild* p)
{
	sys_log(0, "GuildDisband %u", p->dwGuild);

	char szQuery[512];

	snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild%s WHERE id=%u", GetTablePostfix(), p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);

	snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_grade%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);

	snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) SELECT pid, 'guild_manage', 'withdraw_time', %u FROM guild_member%s WHERE guild_id = %u", GetTablePostfix(), (DWORD) GetCurrentTime(), GetTablePostfix(), p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);

	snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);
	
	snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_comment%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
	CDBManager::instance().AsyncQuery(szQuery);

	ForwardPacket(HEADER_DG_GUILD_DISBAND, p, sizeof(TPacketGuild));
}
void CClientManager::GuildChangeMemberData(CPeer* peer, TPacketGuildChangeMemberData* p)
{
	sys_log(0, "GuildChangeMemberData %u %u %d %d", p->pid, p->offer, p->level, p->grade);
	ForwardPacket(HEADER_DG_GUILD_CHANGE_MEMBER_DATA, p, sizeof(TPacketGuildChangeMemberData), 0, peer);
}
Exemple #14
0
/* -------------------------------------------------------------------------
 * Function   : BmfTunPacketCaptured
 * Description: Handle an IP packet, captured outgoing on the tuntap interface
 * Input      : encapsulationUdpData - space for the encapsulation header, followed by
 *                the captured outgoing IP packet
 * Output     : none
 * Return     : none
 * Data Used  : none
 * Notes      : The packet is assumed to be captured on a socket of family
 *              PF_PACKET and type SOCK_DGRAM (cooked).
 * ------------------------------------------------------------------------- */
static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData)
{
  union olsr_ip_addr srcIp;
  union olsr_ip_addr dstIp;
  union olsr_ip_addr broadAddr;
  struct TBmfInterface* walker;
  unsigned char* ipPacket;
  u_int16_t ipPacketLen;
  struct ip* ipHeader;
  u_int32_t crc32;
  struct TEncapHeader* encapHdr;
#ifndef NODEBUG
  struct ipaddr_str srcIpBuf, dstIpBuf;
#endif
  ipPacket = GetIpPacket(encapsulationUdpData);
  ipPacketLen = GetIpTotalLength(ipPacket);
  ipHeader = GetIpHeader(encapsulationUdpData);

  dstIp.v4 = ipHeader->ip_dst;
  broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);

  /* Only forward multicast packets. If configured, also forward local broadcast packets */
  if (IsMulticast(&dstIp) ||
      (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr)))
  {
    /* continue */
  }
  else
  {
    return;
  }

  srcIp.v4 = ipHeader->ip_src;

  OLSR_PRINTF(
    8,
    "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n",
    PLUGIN_NAME_SHORT,
    (long)ipPacketLen,
    EtherTunTapIfName,
    olsr_ip_to_string(&srcIpBuf, &srcIp),
    olsr_ip_to_string(&dstIpBuf, &dstIp));

  /* Calculate packet fingerprint */
  crc32 = PacketCrc32(ipPacket, ipPacketLen);

  /* Check if this packet was seen recently */
  if (CheckAndMarkRecentPacket(crc32))
  {
    OLSR_PRINTF(
      8,
      "%s: --> discarding: packet is duplicate\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  /* Compose encapsulation header */
  encapHdr = (struct TEncapHeader*) encapsulationUdpData;
  memset (encapHdr, 0, ENCAP_HDR_LEN);
  encapHdr->type = BMF_ENCAP_TYPE;
  encapHdr->len = BMF_ENCAP_LEN;
  encapHdr->reserved = 0;
  encapHdr->crc32 = htonl(crc32);

  /* Check with each network interface what needs to be done on it */
  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
  {
    /* Is the forwarding interface OLSR-enabled? */
    if (walker->olsrIntf != NULL)
    {
      /* On an OLSR interface: encapsulate and forward packet. */
      EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
    }
    else
    {
      /* On a non-OLSR interface: what to do?
       * Answer 1: nothing. Multicast routing between non-OLSR interfaces
       * is to be done by other protocols (e.g. PIM, DVMRP).
       * Answer 2 (better): Forward it. */
      ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
    } /* if */
  } /* for */
} /* BmfTunPacketCaptured */
Exemple #15
0
/* -------------------------------------------------------------------------
 * Function   : BmfEncapsulationPacketReceived
 * Description: Handle a received BMF-encapsulation packet
 * Input      : intf - the network interface on which the packet was received
 *              forwardedBy - the IP node that forwarded the packet to me
 *              forwardedTo - the destination IP address of the encapsulation
 *                packet, in case the packet was received promiscuously.
 *                Pass NULL if the packet is received normally (unicast or
 *                broadcast).
 *              encapsulationUdpData - the encapsulating IP UDP data, containting
 *                the BMF encapsulation header, followed by the encapsulated
 *                IP packet
 * Output     : none
 * Return     : none
 * Data Used  : BmfInterfaces
 * ------------------------------------------------------------------------- */
static void BmfEncapsulationPacketReceived(
  struct TBmfInterface* intf,
  union olsr_ip_addr* forwardedBy,
  union olsr_ip_addr* forwardedTo,
  unsigned char* encapsulationUdpData)
{
  int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
  unsigned char* ipPacket; /* The encapsulated IP packet */
  u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
  struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
  union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
  union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
  struct TEncapHeader* encapsulationHdr;
  struct TBmfInterface* walker;
#ifndef NODEBUG
  struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
#endif
  /* Are we talking to ourselves? */
  if (if_ifwithaddr(forwardedBy) != NULL)
  {
    return;
  }

  /* Discard encapsulated packets received on a non-OLSR interface */
  if (intf->olsrIntf == NULL)
  {
    return;
  }

  /* Retrieve details about the encapsulated IP packet */
  ipPacket = GetIpPacket(encapsulationUdpData);
  ipPacketLen = GetIpTotalLength(ipPacket);
  ipHeader = GetIpHeader(encapsulationUdpData);

  mcSrc.v4 = ipHeader->ip_src;
  mcDst.v4 = ipHeader->ip_dst;

  /* Increase counter */
  intf->nBmfPacketsRx++;

  /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
  OLSR_PRINTF(
    8,
    "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
    PLUGIN_NAME_SHORT,
    (long)ipPacketLen,
    intf->ifName,
    olsr_ip_to_string(&mcSrcBuf, &mcSrc),
    olsr_ip_to_string(&mcDstBuf, &mcDst),
    olsr_ip_to_string(&forwardedByBuf, forwardedBy),
    forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");

  /* Get encapsulation header */
  encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;

  /* Verify correct format of BMF encapsulation header */
  if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
      encapsulationHdr->len != BMF_ENCAP_LEN ||
      ntohs(encapsulationHdr->reserved != 0))
  {
    OLSR_PRINTF(
      8,
      "%s: --> discarding: format of BMF encapsulation header not recognized\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  /* Check if this packet was seen recently */
  if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
  {
    /* Increase counter */
    intf->nBmfPacketsRxDup++;

    OLSR_PRINTF(
      8,
      "%s: --> discarding: packet is duplicate\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  if (EtherTunTapFd >= 0)
  {
    /* Unpack the encapsulated IP packet and deliver it locally, by sending
     * a copy into the local IP stack via the EtherTunTap interface */

    union olsr_ip_addr broadAddr;
    int nBytesToWrite, nBytesWritten;
    unsigned char* bufferToWrite;

    /* If the encapsulated IP packet is a local broadcast packet,
     * update its destination address to match the subnet of the EtherTunTap
     * interface */
    broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
    CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);

    bufferToWrite = ipPacket;
    nBytesToWrite = ipPacketLen;

    /* Write the packet into the EtherTunTap interface for local delivery */
    nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
    if (nBytesWritten != nBytesToWrite)
    {
      BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
    }
    else
    {
      OLSR_PRINTF(
        8,
        "%s: --> unpacked and delivered locally on \"%s\"\n",
        PLUGIN_NAME_SHORT,
        EtherTunTapIfName);
    }
  } /* if (EtherTunTapFd >= 0) */

  /* Check if I am MPR for the forwarder */
  iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);

  /* Check with each network interface what needs to be done on it */
  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
  {
    /* What to do with the packet on a non-OLSR interface? Unpack
     * encapsulated packet, and forward it.
     *
     * What to do with the packet on an OLSR interface? Forward it only
     * if the forwarding node has selected us as MPR (iAmMpr).
     *
     * Note that the packet is always coming in on an OLSR interface, because
     * it is an encapsulated BMF packet. */

    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
    if (walker->olsrIntf == NULL)
    {
      ForwardPacket (walker, ipPacket, ipPacketLen, "unpacked and forwarded to non-OLSR interface");
    } /* if (walker->olsrIntf == NULL) */

    /* To an OLSR interface: forward the packet, but only if this node is
     * selected as MPR by the forwarding node */
    else if (iAmMpr)
    {
      EncapsulateAndForwardPacket (
        walker,
        encapsulationUdpData,
        &mcSrc,
        forwardedBy,
        forwardedTo);
    }  /* else if (iAmMpr) */

    else /* walker->olsrIntf != NULL && !iAmMpr */
    {
#ifndef NODEBUG
      struct ipaddr_str buf;
#endif
      /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
       * case, don't forward. */
      OLSR_PRINTF(
        8,
        "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
        PLUGIN_NAME_SHORT,
        walker->ifName,
        olsr_ip_to_string(&buf, forwardedBy));
    } /* else */
  } /* for */
} /* BmfEncapsulationPacketReceived */
Exemple #16
0
/* -------------------------------------------------------------------------
 * Function   : BmfPacketCaptured
 * Description: Handle a captured IP packet
 * Input      : intf - the network interface on which the packet was captured
 *              sllPkttype - the type of packet. Either PACKET_OUTGOING,
 *                PACKET_BROADCAST or PACKET_MULTICAST.
 *              encapsulationUdpData - space for the encapsulation header, followed by
 *                the captured IP packet
 * Output     : none
 * Return     : none
 * Data Used  : BmfInterfaces
 * Notes      : The IP packet is assumed to be captured on a socket of family
 *              PF_PACKET and type SOCK_DGRAM (cooked).
 * ------------------------------------------------------------------------- */
static void BmfPacketCaptured(
  struct TBmfInterface* intf,
  unsigned char sllPkttype,
  unsigned char* encapsulationUdpData)
{
  union olsr_ip_addr src; /* Source IP address in captured packet */
  union olsr_ip_addr dst; /* Destination IP address in captured packet */
  union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */
  struct TBmfInterface* walker;
  int isFromOlsrIntf;
  int isFromOlsrNeighbor;
  int iAmMpr;
  unsigned char* ipPacket; /* The captured IP packet... */
  u_int16_t ipPacketLen; /* ...and its length */
  struct ip* ipHeader; /* The IP header inside the captured IP packet */
  u_int32_t crc32;
  struct TEncapHeader* encapHdr;
#ifndef NODEBUG
  struct ipaddr_str srcBuf, dstBuf;
#endif
  ipHeader = GetIpHeader(encapsulationUdpData);

  dst.v4 = ipHeader->ip_dst;

  /* Only forward multicast packets. If configured, also forward local broadcast packets */
  if (IsMulticast(&dst) ||
      (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr)))
  {
    /* continue */
  }
  else
  {
    return;
  }

  ipPacket = GetIpPacket(encapsulationUdpData);

  /* Don't forward fragments of IP packets: there is no way to distinguish fragments
   * of BMF encapsulation packets from other fragments.
   * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment
   * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier
   * than the first fragment, so that the list is not yet up to date and the second
   * fragment is not recognized as a BMF packet.
   * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */
  if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket))
  {
    return;
  }

  /* Increase counter */
  intf->nBmfPacketsRx++;

  /* Check if the frame is captured on an OLSR-enabled interface */
  isFromOlsrIntf = (intf->olsrIntf != NULL);

  /* Retrieve the length of the captured packet */
  ipPacketLen = GetIpTotalLength(ipPacket);

  src.v4 = ipHeader->ip_src;

  OLSR_PRINTF(
    8,
    "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n",
    PLUGIN_NAME_SHORT,
    sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming",
    (long)ipPacketLen,
    isFromOlsrIntf ? "OLSR" : "non-OLSR",
    intf->ifName,
    olsr_ip_to_string(&srcBuf, &src),
    olsr_ip_to_string(&dstBuf, &dst));

  /* Lookup main address of source in the MID table of OLSR */
  origIp = MainAddressOf(&src);

  /* Calculate packet fingerprint */
  crc32 = PacketCrc32(ipPacket, ipPacketLen);

  /* Check if this packet was seen recently */
  if (CheckAndMarkRecentPacket(crc32))
  {
    /* Increase counter */
    intf->nBmfPacketsRxDup++;

    OLSR_PRINTF(
      8,
      "%s: --> discarding: packet is duplicate\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  /* Compose encapsulation header */
  encapHdr = (struct TEncapHeader*) encapsulationUdpData;
  memset (encapHdr, 0, ENCAP_HDR_LEN);
  encapHdr->type = BMF_ENCAP_TYPE;
  encapHdr->len = BMF_ENCAP_LEN;
  encapHdr->reserved = 0;
  encapHdr->crc32 = htonl(crc32);

  /* Check if the frame is captured on an OLSR interface from an OLSR neighbor.
   * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call
   * would do here (something like 'get_any_link_to_neighbor()'). */
  isFromOlsrNeighbor =
    (isFromOlsrIntf /* The frame is captured on an OLSR interface... */
    && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ 

  /* Check with OLSR if I am MPR for that neighbor */
  iAmMpr = olsr_lookup_mprs_set(origIp) != NULL;

  /* Check with each network interface what needs to be done on it */
  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
  {
    /* Is the forwarding interface OLSR-enabled? */
    int isToOlsrIntf = (walker->olsrIntf != NULL);

    /* Depending on certain conditions, we decide whether or not to forward
     * the packet, and if it is forwarded, in which form (encapsulated
     * or not, TTL decreased or not). These conditions are:
     * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf)
     * - is the packet going out on an OLSR interface or not? (isToOlsrIntf)
     * - if the packet if coming in on an OLSR interface:
     *   - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor)
     *   - has the node that forwarded the packet selected me as MPR? (iAmMpr)
     *
     * Based on these conditions, the following cases can be distinguished:
     *
     * - Case 1: Packet coming in on an OLSR interface. What to
     *   do with it on an OLSR interface?
     *   Answer:
     *   - Case 1.1: If the forwarding node is an OLSR neighbor that has *not*
     *     selected me as MPR: don't forward the packet.
     *   - Case 1.2: If the forwarding node is an OLSR neighbor that has selected
     *     me as MPR: encapsulate and forward the packet.
     *   - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate
     *     and forward the packet.
     *     NOTE: Case 1.3 is a special case. In the perfect world, we expect to
     *     see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however,
     *     ignorant users will connect a host not running OLSR, to a LAN in
     *     which there are hosts running OLSR. Of course these ignorant users,
     *     expecting magic, want to see their multicast packets being forwarded
     *     through the network.
     *
     * - Case 2: Packet coming in on an OLSR interface. What to do with it on a
     *   non-OLSR interface?
     *   Answer: Forward it.
     *
     * - Case 3: Packet coming in on a non-OLSR interface. What to
     *   do with it on an OLSR interface?
     *   Answer: Encapsulate and forward it.
     *
     * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a
     *   non-OLSR interface?
     *   Answer 1: nothing. Multicast routing between non-OLSR interfaces
     *   is to be done by other protocols (e.g. PIM, DVMRP).
     *   Answer 2 (better): Forward it.
     */

    if (isFromOlsrIntf && isToOlsrIntf)
    {
      /* Case 1: Forward from an OLSR interface to an OLSR interface */

      if (isFromOlsrNeighbor && !iAmMpr)
      {
        /* Case 1.1 */
        {
#ifndef NODEBUG
          struct ipaddr_str buf;
#endif
          OLSR_PRINTF(
            8,
            "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n",
            PLUGIN_NAME_SHORT,
            walker->ifName,
            olsr_ip_to_string(&buf, &src));
        }    
      }
      else if (sllPkttype == PACKET_OUTGOING && intf == walker)
      {
        OLSR_PRINTF(
          8,
          "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n",
          PLUGIN_NAME_SHORT,
          walker->ifName);
      }
      else
      {
        /* Case 1.2 and 1.3 */
        EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
      }
    } /* if (isFromOlsrIntf && isToOlsrIntf) */

    else if (isFromOlsrIntf && !isToOlsrIntf)
    {
      /* Case 2: Forward from OLSR interface to non-OLSR interface */
      ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface");
    } /* else if (isFromOlsrIntf && !isToOlsrIntf) */

    else if (!isFromOlsrIntf && isToOlsrIntf)
    {
      /* Case 3: Forward from a non-OLSR interface to an OLSR interface.
       * Encapsulate and forward packet. */
      EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL);
    } /* else if (!isFromOlsrIntf && isToOlsrIntf) */

    else
    {
      /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */

      /* Don't forward on interface on which packet was received */
      if (intf == walker)
      {
        OLSR_PRINTF(
          8,
          "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n",
          PLUGIN_NAME_SHORT,
          walker->ifName);
      }

      else
      {
        ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface");
      } /* if (intf == walker) */
    } /* if */
  } /* for */
} /* BmfPacketCaptured */
void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
{
	switch (p->bWar)
	{
		case GUILD_WAR_SEND_DECLARE:
			sys_log(0, "GuildWar: GUILD_WAR_SEND_DECLARE type(%s) guild(%d - %d)",  __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().AddDeclare(p->bType, p->dwGuildFrom, p->dwGuildTo);
			break;

		case GUILD_WAR_REFUSE:
			sys_log(0, "GuildWar: GUILD_WAR_REFUSE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
			break;
			/*
			   case GUILD_WAR_WAIT_START:
			   CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);

			   if (!CGuildManager::instance().WaitStart(p))
			   p->bWar = GUILD_WAR_CANCEL;

			   break;
			   */

		case GUILD_WAR_WAIT_START:
			sys_log(0, "GuildWar: GUILD_WAR_WAIT_START type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
		case GUILD_WAR_RESERVE:	// 길드전 예약
			if (p->bWar != GUILD_WAR_WAIT_START)
				sys_log(0, "GuildWar: GUILD_WAR_RESERVE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);

			if (!CGuildManager::instance().ReserveWar(p))
				p->bWar = GUILD_WAR_CANCEL;
			else
				p->bWar = GUILD_WAR_RESERVE;

			break;

		case GUILD_WAR_ON_WAR:		// 길드전을 시작 시킨다. (필드전은 바로 시작 됨)
			sys_log(0, "GuildWar: GUILD_WAR_ON_WAR type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo);
			break;

		case GUILD_WAR_OVER:		// 길드전 정상 종료
			sys_log(0, "GuildWar: GUILD_WAR_OVER type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice);
			break;

		case GUILD_WAR_END:		// 길드전 비정상 종료
			sys_log(0, "GuildWar: GUILD_WAR_END type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
			return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.

		case GUILD_WAR_CANCEL :
			sys_log(0, "GuildWar: GUILD_WAR_CANCEL type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
			CGuildManager::instance().CancelWar(p->dwGuildFrom, p->dwGuildTo);
			break;
	}

	ForwardPacket(HEADER_DG_GUILD_WAR, p, sizeof(TPacketGuildWar));
}
void CClientManager::GuildChangeGrade(CPeer* peer, TPacketGuild* p)
{
	sys_log(0, "GuildChangeGrade %u %u", p->dwGuild, p->dwInfo);
	ForwardPacket(HEADER_DG_GUILD_CHANGE_GRADE, p, sizeof(TPacketGuild));
}
void CClientManager::GuildExpUpdate(CPeer* peer, TPacketGuildExpUpdate* p)
{
	sys_log(0, "GuildExpUpdate %d", p->amount);
	ForwardPacket(HEADER_DG_GUILD_EXP_UPDATE, p, sizeof(TPacketGuildExpUpdate), 0, peer);
}
void CClientManager::GuildSkillUpdate(CPeer* peer, TPacketGuildSkillUpdate* p)
{
	sys_log(0, "GuildSkillUpdate %d", p->amount);
	ForwardPacket(HEADER_DG_GUILD_SKILL_UPDATE, p, sizeof(TPacketGuildSkillUpdate));
}