/*++ 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; } }