//============================================================================= // 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 = ""; 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 ) { }