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.
239 lines
5.4 KiB
239 lines
5.4 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rippkt.c
|
|
|
|
Abstract:
|
|
|
|
Common RIP packet functions
|
|
|
|
Author:
|
|
|
|
Stefan Solomon 09/01/1995
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/*++
|
|
|
|
Function: SetRipIpxHeader
|
|
|
|
Descr: sets the IPX packet header for a RIP packet to be sent
|
|
from this machine & the RIP Operation Code
|
|
|
|
Arguments:
|
|
hdrp - packet header pointer
|
|
icbp - pointer to the interface CB on which the packet will be sent
|
|
dstnode - destination node
|
|
dstsocket - destination socket
|
|
RipOpCode - operation to be set in the packet RIP header
|
|
|
|
Remark: the packet length is not set by this function
|
|
|
|
--*/
|
|
|
|
VOID
|
|
SetRipIpxHeader(PUCHAR hdrp, // pointer to the packet header
|
|
PICB icbp,
|
|
PUCHAR dstnode,
|
|
PUCHAR dstsocket,
|
|
USHORT RipOpcode)
|
|
{
|
|
PUTUSHORT2SHORT(hdrp + IPXH_CHECKSUM, 0xFFFF);
|
|
*(hdrp + IPXH_XPORTCTL) = 0;
|
|
*(hdrp + IPXH_PKTTYPE) = 1; // RIP packet
|
|
memcpy(hdrp + IPXH_DESTNET, icbp->AdapterBindingInfo.Network, 4);
|
|
memcpy(hdrp + IPXH_DESTNODE, dstnode, 6);
|
|
memcpy(hdrp + IPXH_DESTSOCK, dstsocket, 2);
|
|
memcpy(hdrp + IPXH_SRCNET, icbp->AdapterBindingInfo.Network, 4);
|
|
memcpy(hdrp + IPXH_SRCNODE, icbp->AdapterBindingInfo.LocalNode, 6);
|
|
PUTUSHORT2SHORT(hdrp + IPXH_SRCSOCK, IPX_RIP_SOCKET);
|
|
|
|
// set the opcode
|
|
PUTUSHORT2SHORT(hdrp + RIP_OPCODE, RipOpcode);
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: SetNetworkEntry
|
|
|
|
Descr: sets a RIP network entry in the RIP packet
|
|
|
|
--*/
|
|
|
|
VOID
|
|
SetNetworkEntry(PUCHAR pktp, // ptr where to set the net entry
|
|
PIPX_ROUTE IpxRoutep,
|
|
USHORT LinkTickCount) // add to the route tick count
|
|
{
|
|
memcpy(pktp + NE_NETNUMBER, IpxRoutep->Network, 4);
|
|
if (IpxRoutep->HopCount<16)
|
|
PUTUSHORT2SHORT(pktp + NE_NROFHOPS, IpxRoutep->HopCount+1);
|
|
else
|
|
PUTUSHORT2SHORT(pktp + NE_NROFHOPS, IpxRoutep->HopCount);
|
|
|
|
// adjust the tick count with the adapter link speed (expressed as ticks)
|
|
PUTUSHORT2SHORT(pktp + NE_NROFTICKS, IpxRoutep->TickCount + LinkTickCount);
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: MakeRipGenResponsePacket
|
|
|
|
Descr: fills in a gen response packet network entries
|
|
|
|
Returns: the packet length. Note that a length of RIP_INFO means
|
|
empty packet and a length of RIP_PACKET_LEN means full packet.
|
|
|
|
--*/
|
|
|
|
USHORT
|
|
MakeRipGenResponsePacket(PWORK_ITEM wip,
|
|
PUCHAR dstnodep,
|
|
PUCHAR dstsocket)
|
|
{
|
|
PUCHAR hdrp;
|
|
USHORT resplen;
|
|
IPX_ROUTE IpxRoute;
|
|
HANDLE EnumHandle;
|
|
PICB icbp; // interface to send the gen response on
|
|
PICB route_icbp; // interface on which the route resides
|
|
|
|
hdrp = wip->Packet;
|
|
EnumHandle = wip->WorkItemSpecific.WIS_EnumRoutes.RtmEnumerationHandle;
|
|
icbp = wip->icbp;
|
|
|
|
// create the IPX packet header
|
|
SetRipIpxHeader(hdrp,
|
|
icbp,
|
|
dstnodep,
|
|
dstsocket,
|
|
RIP_RESPONSE);
|
|
|
|
resplen = RIP_INFO;
|
|
|
|
while(resplen < RIP_PACKET_LEN)
|
|
{
|
|
if(EnumGetNextRoute(EnumHandle, &IpxRoute) != NO_ERROR) {
|
|
|
|
break;
|
|
}
|
|
|
|
// check if this route can be advertised over this interface
|
|
if(IsRouteAdvertisable(icbp, &IpxRoute)) {
|
|
|
|
// if this is the local client if, we advertise only the internal
|
|
// net over it
|
|
if(icbp->InterfaceType == LOCAL_WORKSTATION_DIAL) {
|
|
|
|
if(IpxRoute.InterfaceIndex != 0) {
|
|
|
|
// skip if not internal net
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// check if the network doesn't appear also on the interface we
|
|
// will broadcast WITH THE SAME METRIC
|
|
if(IsDuplicateBestRoute(icbp, &IpxRoute)) {
|
|
|
|
continue;
|
|
}
|
|
|
|
SetNetworkEntry(hdrp + resplen, &IpxRoute, icbp->LinkTickCount);
|
|
resplen += NE_ENTRYSIZE;
|
|
}
|
|
}
|
|
|
|
// set the packet size in the IPX packet header
|
|
PUTUSHORT2SHORT(hdrp + IPXH_LENGTH, resplen);
|
|
|
|
return resplen;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: SendRipGenRequest
|
|
|
|
Descr: sends a RIP General Request packet over the specified interface
|
|
|
|
Remark: >> called with the interface lock held <<
|
|
|
|
--*/
|
|
|
|
DWORD
|
|
SendRipGenRequest(PICB icbp)
|
|
{
|
|
PWORK_ITEM wip;
|
|
UCHAR ripsocket[2];
|
|
USHORT pktlen;
|
|
|
|
PUTUSHORT2SHORT(ripsocket, IPX_RIP_SOCKET);
|
|
|
|
if((wip = AllocateWorkItem(SEND_PACKET_TYPE)) == NULL) {
|
|
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
wip->icbp = icbp;
|
|
wip->AdapterIndex = icbp->AdapterBindingInfo.AdapterIndex;
|
|
|
|
SetRipIpxHeader(wip->Packet,
|
|
icbp,
|
|
bcastnode,
|
|
ripsocket,
|
|
RIP_REQUEST);
|
|
|
|
memcpy(wip->Packet + RIP_INFO + NE_NETNUMBER, bcastnet, 4);
|
|
PUTUSHORT2SHORT(wip->Packet + RIP_INFO + NE_NROFHOPS, 0xFFFF);
|
|
PUTUSHORT2SHORT(wip->Packet + RIP_INFO + NE_NROFTICKS, 0xFFFF);
|
|
|
|
pktlen = RIP_INFO + NE_ENTRYSIZE;
|
|
|
|
PUTUSHORT2SHORT(wip->Packet + IPXH_LENGTH, pktlen);
|
|
|
|
if(SendSubmit(wip) != NO_ERROR) {
|
|
|
|
FreeWorkItem(wip);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function: IsRouteAdvertisable
|
|
|
|
Descr: checks if the route can be advertised over this interface
|
|
|
|
Arguments: interface to advertise on
|
|
route
|
|
|
|
Remark: >> called with interface lock taken <<
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
IsRouteAdvertisable(PICB icbp,
|
|
PIPX_ROUTE IpxRoutep)
|
|
{
|
|
if((icbp->InterfaceIndex != IpxRoutep->InterfaceIndex) &&
|
|
PassRipSupplyFilter(icbp, IpxRoutep->Network) &&
|
|
((IpxRoutep->Flags & DO_NOT_ADVERTISE_ROUTE) == 0)) {
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|