Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

416 lines
9.2 KiB

//=============================================================================
// Copyright (c) 1998 Microsoft Corporation
// File Name: packet.c
// Abstract:
//
// Author: K.S.Lokesh (lokeshs@) 1-1-98
//=============================================================================
#include "pchdvmrp.h"
#pragma hdrstop
VOID
ProcessDvmrpProbe(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
);
VOID
ProcessDvmrpReport(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
);
VOID
ProcessDvmrpPrune(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
);
VOID
ProcessDvmrpGraft(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
);
VOID
ProcessDvmrpGraftAck(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
);
//-----------------------------------------------------------------------------
// _JoinMulticastGroup
//-----------------------------------------------------------------------------
DWORD
JoinMulticastGroup (
SOCKET Sock,
DWORD Group,
DWORD IfIndex,
IPADDR IpAddr
)
{
struct ip_mreq imOption;
DWORD Error = NO_ERROR;
DWORD Retval;
LPSTR lpszGroup = "tobefilled";
LPSTR lpszAddr = "tobefilled";
imOption.imr_multiaddr.s_addr = Group;
imOption.imr_interface.s_addr = IpAddr;
Retval = setsockopt(Sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(PBYTE)&imOption, sizeof(imOption));
if (Retval == SOCKET_ERROR) {
Error = WSAGetLastError();
Trace4(ERR,
"error %d joining multicast group(%d.%d.%d.%d) on interface "
"(%d) %d.%d.%d.%d",
Error, PRINT_IPADDR(Group), IfIndex, PRINT_IPADDR(IpAddr));
Logerr2(JOIN_GROUP_FAILED, "%s,%s", lpszGroup, lpszAddr, Error);
}
return Error;
}
//-----------------------------------------------------------------------------
// _PostAsyncRecv
//-----------------------------------------------------------------------------
DWORD
PostAsyncRecv(
PIF_TABLE_ENTRY pite
)
{
DWORD Error = NO_ERROR;
PASYNC_SOCKET_DATA pSocketData = pite->pSocketData;
pSocketData->Flags = 0;
pSocketData->FromLen = sizeof(SOCKADDR);
Error = WSARecvFrom(pite->Socket, &pSocketData->WsaBuf, 1,
&pSocketData->NumBytesReceived, &pSocketData->Flags,
(SOCKADDR FAR *)&pSocketData->SrcAddress,
&pSocketData->FromLen, &pSocketData->Overlapped, NULL);
if (Error!=SOCKET_ERROR) {
Trace0(RECEIVE, "the WSAReceiveFrom returned immediately\n");
}
else {
Error = WSAGetLastError();
if (Error!=WSA_IO_PENDING) {
Trace1(RECEIVE,
"WSARecvFrom returned in PostAsyncRecv() with error code:%0x",
Error);
Logerr0(RECVFROM_FAILED, Error);
}
else
Trace0(RECEIVE, "WSARecvFrom() returned WSA_IO_PENDING in ???");
}
return Error;
}
//-----------------------------------------------------------------------------
// _McastSetTtl
// set the ttl value for multicast data. the default ttl for multicast is 1.
//-----------------------------------------------------------------------------
DWORD
McastSetTtl(
SOCKET sock,
UCHAR ttl
)
{
INT dwTtl = ttl;
DWORD Error=NO_ERROR;
Error = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&dwTtl, sizeof(dwTtl));
if (Error != 0) {
Error = WSAGetLastError();
Trace1(ERR, "error:%d: unable to set ttl value", Error);
return Error;
}
return Error;
}
//-----------------------------------------------------------------------------
// _ProcessAsyncReceivePacket
//-----------------------------------------------------------------------------
VOID
ProcessAsyncReceivePacket(
DWORD ErrorCode,
DWORD NumBytesRecv,
LPOVERLAPPED pOverlapped
)
{
PASYNC_SOCKET_DATA pSocketData;
DWORD IfIndex, Error;
IPADDR SrcAddr, DstnAddr;
CHAR SrcAddrString[20];
DWORD PacketSize, IpHdrLen;
UCHAR *pPacket;
LPBYTE Buffer;
DVMRP_HEADER UNALIGNED *pDvmrpHdr;
PIF_TABLE_ENTRY pite = NULL;
PIP_HEADER pIpHdr;
UCHAR PacketType;
//
// kslksl
// How to get pite?
//
IfIndex = pite->IfIndex;
//
// if the IO completed due to socket being closed, check if the
// refcount is down to 0, in which case safely delete the pite entry
//
if ( (ErrorCode != NO_ERROR) || (NumBytesRecv == 0)) {
//
// kslksl
//
if (InterlockedDecrement(&pite->RefCount) == 0)
DVMRP_FREE(pite);
return;
}
pSocketData = CONTAINING_RECORD(pOverlapped, ASYNC_SOCKET_DATA,
Overlapped);
//
// get interface read lock
//
ACQUIRE_IF_LOCK_SHARED(pite->IfIndex, "ProcessAsyncReceivePacket");
BEGIN_BREAKOUT_BLOCK1 {
// if interface is not active, then free pite if required and return
if (!IS_IF_ACTIVATED(pite)) {
if (InterlockedDecrement(&pite->RefCount) == 0) {
DVMRP_FREE(pite);
}
Trace1(RECEIVE,
"Received packet on inactive interface:%d", IfIndex);
Error = ERROR_CAN_NOT_COMPLETE;
GOTO_END_BLOCK1;
}
// set source addr of packet
SrcAddr = pSocketData->SrcAddress.sin_addr.s_addr;
lstrcpy(SrcAddrString, INET_NTOA(SrcAddr));
// check that the packet has min length
if (NumBytesRecv < MIN_PACKET_SIZE) {
LPSTR lpszAddr = "<tbd>";
Trace2(RECEIVE,
"Received very short packet of length:%d from:%s",
IfIndex, SrcAddrString);
Logwarn2(PACKET_TOO_SMALL, lpszAddr, SrcAddrString, NO_ERROR);
Error = ERROR_CAN_NOT_COMPLETE;
GOTO_END_BLOCK1;
}
//
// set packet ptr, IpHdr ptr, dwNumBytes, DstnMcastAddr
//
Buffer = pSocketData->WsaBuf.buf;
IpHdrLen = (Buffer[0]&0x0F)*4;
pIpHdr = (PIP_HEADER)Buffer;
pPacket = &Buffer[IpHdrLen];
PacketSize = NumBytesRecv - IpHdrLen;
DstnAddr = (ULONG)pIpHdr->Dstn.s_addr;
pDvmrpHdr = (DVMRP_HEADER UNALIGNED *) pPacket;
//
// verify that the packet has igmp type
//
if (pIpHdr->Protocol!=0x2) {
Trace4(RECEIVE,
"Packet received with IpDstnAddr(%d.%d.%d.%d) from (%s) on "
"interface:%d is not of Igmp type(%d)",
PRINT_IPADDR(pIpHdr->Dstn.s_addr),
SrcAddrString, pite->IfIndex, pIpHdr->Protocol
);
Error = ERROR_CAN_NOT_COMPLETE;
GOTO_END_BLOCK1;
}
//
// verify that the packet has dvmrp type field
//
if ( pDvmrpHdr->Vertype != 0x13) {
Error = ERROR_CAN_NOT_COMPLETE;
GOTO_END_BLOCK1;
}
#if 0
// kslksl
//
// Verify Igmp checksum
//
if (xsum(pDvmrpHdr, sizeof(DVMRP_HEADER)) != 0xffff) {
Trace0(RECEIVE, "Wrong checksum packet received");
GOTO_END_BLOCK1
}
#endif
//
// verify that the packet has correct code
//
PacketType = pDvmrpHdr->Code;
switch (PacketType) {
case DVMRP_PROBE:
{
ProcessDvmrpProbe(pite, pPacket, PacketSize, SrcAddr);
break;
}
case DVMRP_REPORT:
{
ProcessDvmrpReport(pite, pPacket, PacketSize, SrcAddr);
break;
}
case DVMRP_PRUNE:
{
ProcessDvmrpPrune(pite, pPacket, PacketSize, SrcAddr);
break;
}
case DVMRP_GRAFT:
{
ProcessDvmrpGraft(pite, pPacket, PacketSize, SrcAddr);
break;
}
case DVMRP_GRAFT_ACK:
{
ProcessDvmrpGraftAck(pite, pPacket, PacketSize, SrcAddr);
break;
}
}
} END_BREAKOUT_BLOCK1;
PostAsyncRecv(pite);
}//end ProcessAsyncReceive
VOID
ProcessDvmrpProbe(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
)
{
}
VOID
ProcessDvmrpReport(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
)
{
}
VOID
ProcessDvmrpPrune(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
)
{
}
VOID
ProcessDvmrpGraft(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
)
{
}
VOID
ProcessDvmrpGraftAck(
PIF_TABLE_ENTRY pite,
UCHAR *Packet,
ULONG PacketSize,
IPADDR SrcAddr
)
{
}