diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/isn/rip/ripaux.c | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/rip/ripaux.c b/private/ntos/tdi/isn/rip/ripaux.c new file mode 100644 index 000000000..f61bbb573 --- /dev/null +++ b/private/ntos/tdi/isn/rip/ripaux.c @@ -0,0 +1,455 @@ +/*******************************************************************/ +/* Copyright(c) 1993 Microsoft Corporation */ +/*******************************************************************/ + +//*** +// +// Filename: ripaux.c +// +// Description: Misc aux routines for doing RIP +// +// Author: Stefan Solomon (stefans) November 5, 1993. +// +// Revision History: +// +//*** + +#include "rtdefs.h" + +typedef struct _NIC_NODE { + + LIST_ENTRY NodeLinkage; + LIST_ENTRY BcastPktsList; + USHORT NicId; + } NIC_NODE, *PNIC_NODE; + +//*** +// +// Function: AddRouteToBcastSndReq +// +// Descr: Builds a list of nodes where each node represents a +// Nic. Each node has an attached list of broadcast packets +// which contain the list of routes to be advertised. +// At each invokation, the coresponding nic node is located +// (or created) and the route information is set in the +// broadcast packet attached to the node. +// +//*** + +UINT +AddRouteToBcastSndReq(PLIST_ENTRY nodelistp, + PIPX_ROUTE_ENTRY rtep) +{ + PLIST_ENTRY nextp; + PNIC_NODE nodep; + BOOLEAN found; + PRIP_UPDATE_SNDREQ respcbp = NULL; // ptr to changes response to bcast + PUCHAR hdrp; // Ipx pkt header + USHORT pktlen; + PLIST_ENTRY lep; + + // traverse the nodes list looking for our nic id. + nextp = nodelistp->Flink; + found = FALSE; + + while(nextp != nodelistp) { + + nodep = CONTAINING_RECORD(nextp, NIC_NODE, NodeLinkage); + if(nodep->NicId == rtep->NicId) { + + found = TRUE; + break; + } + + nextp = nextp->Flink; + } + + if(!found) { + + // create the node we need + if((nodep = ExAllocatePool(NonPagedPool, sizeof(NIC_NODE))) == NULL) { + + // can't create the node + return 1; + } + + InitializeListHead(&nodep->BcastPktsList); + nodep->NicId = rtep->NicId; + + // create a send bcast request structure and add it to the node + if((respcbp = ExAllocatePool(NonPagedPool, + sizeof(RIP_UPDATE_SNDREQ) + RIP_SNDPKT_MAXLEN)) == NULL) { + + // free the node + ExFreePool(nodep); + return 1; + } + + InsertTailList(&nodep->BcastPktsList, &respcbp->RipSndReq.NicLinkage); + + // get the Ipx packet length and Ipx packet header + hdrp = (PUCHAR)respcbp->RipSndPktBuff.IpxPacket; + pktlen = RIP_INFO; + + // now add the node to the nodes list + InsertTailList(nodelistp, &nodep->NodeLinkage); + + } + else + { + // we found the node + // now go to the last packet in the node and check if there is room for + // a network entry + ASSERT(!IsListEmpty(&nodep->BcastPktsList)); + lep = nodep->BcastPktsList.Blink; + respcbp = CONTAINING_RECORD(lep, RIP_UPDATE_SNDREQ, RipSndReq.NicLinkage); + + // get IPX packet length + hdrp = (PUCHAR)respcbp->RipSndPktBuff.IpxPacket; + GETSHORT2USHORT(&pktlen, hdrp + IPXH_LENGTH); + + if(pktlen >= RIP_RESPONSE_PACKET_LEN) { + + // this packet is full + // create a new send bcast request structure and add it to the node + if((respcbp = ExAllocatePool(NonPagedPool, + sizeof(RIP_UPDATE_SNDREQ) + RIP_SNDPKT_MAXLEN)) == NULL) { + + return 1; + } + + InsertTailList(&nodep->BcastPktsList, &respcbp->RipSndReq.NicLinkage); + + // get the Ipx packet length and Ipx packet header + hdrp = (PUCHAR)respcbp->RipSndPktBuff.IpxPacket; + pktlen = RIP_INFO; + } + } + + // add the new route entry to the bcast pkt + SetNetworkEntry(hdrp + pktlen, rtep); + + // increment the packet length and put it in the packet + pktlen += NE_ENTRYSIZE; + PUTUSHORT2SHORT(hdrp + IPXH_LENGTH, pktlen); + + RtPrint(DBG_RIPAUX, ("IpxRouter: AddRouteToBcastSndReq: net entry added for NicId %d\n", nodep->NicId)); + + return 0; +} + +//*** +// +// Function: GetBcastSndReq +// +// Descr: For each call it tries to remove one broadcast packet +// from the list. If the nic node list of packets is empty +// after the removeal, the nic node is freed. +// +//*** + +PRIP_SNDREQ +GetBcastSndReq(PLIST_ENTRY nodelistp, + PUSHORT NicIdp) +{ + PNIC_NODE nodep; + PRIP_SNDREQ sndreqp; + PLIST_ENTRY lep; + + if(IsListEmpty(nodelistp)) { + + return NULL; + } + + lep = nodelistp->Flink; + nodep = CONTAINING_RECORD(lep, NIC_NODE, NodeLinkage); + + ASSERT(!IsListEmpty(&nodep->BcastPktsList)); + + lep = RemoveHeadList(&nodep->BcastPktsList); + sndreqp = CONTAINING_RECORD(lep, RIP_SNDREQ, NicLinkage); + *NicIdp = nodep->NicId; + + if(IsListEmpty(&nodep->BcastPktsList)) { + + RemoveEntryList(&nodep->NodeLinkage); + ExFreePool(nodep); + } + + RtPrint(DBG_RIPAUX, ("IpxRouter: GetBcastSndReq: got snd req pkt for NicId %d\n", *NicIdp)); + + return sndreqp; +} + +//*** +// +// Function: BroadcastRipUpdate +// +// Descr: Set up the snd req for this bcast and dispatch it. +// If wait on event is requested, wait until send completes. +// +//*** + +VOID +BroadcastRipUpdate(PRIP_SNDREQ sndreqp, // send request + PNICCB niccbp, // do not send on this nic + PKEVENT eventp) // wait if this event is not NULL +{ + sndreqp->SndReqId = RIP_UPDATE; + sndreqp->SendOnAllNics = TRUE; + memcpy(sndreqp->DestNode, bcastaddress, IPX_NODE_LEN); + sndreqp->DestSock = IPX_RIP_SOCKET; + sndreqp->DoNotSendNicCbp = niccbp; // do not send update on this nic + sndreqp->SenderNicCbp = NULL; + + sndreqp->SndCompleteEventp = eventp; + + if(eventp != NULL) { + + // WAIT on event after the bcast req is dispatched. + KeResetEvent(eventp); + + // dispatch the bcast request + RipDispatchSndReq(sndreqp); + + // wait for this request to complete. + KeWaitForSingleObject( + eventp, + Executive, + KernelMode, + FALSE, + (PLARGE_INTEGER)NULL + ); + + KeResetEvent(eventp); + + } + else + { + // NO WAIT -> dispatch the bcast request and return + RipDispatchSndReq(sndreqp); + } +} + +//*** +// +// Function: BroadcastRipGeneralResponse +// +// Descr: Set up the snd req for this bcast and dispatch it. +// +//*** + +VOID +BroadcastRipGeneralResponse(PRIP_SNDREQ sndreqp) +{ + sndreqp->SndReqId = RIP_GEN_RESPONSE; + sndreqp->SendOnAllNics = TRUE; // send on all + memcpy(sndreqp->DestNode, bcastaddress, IPX_NODE_LEN); + sndreqp->DestSock = IPX_RIP_SOCKET; + sndreqp->DoNotSendNicCbp = NULL; // send without exception + sndreqp->SenderNicCbp = NULL; + sndreqp->SndCompleteEventp = NULL; + + RipDispatchSndReq(sndreqp); +} + + +//*** +// +// Function: BroadcastWanNetUpdate +// +// Descr: Broadcasts RIP update for one WAN network entry +// +//*** + +VOID +BroadcastWanNetUpdate(PIPX_ROUTE_ENTRY rtep, // route entry to bcast + PNICCB niccbp, // do not send on this nic + PKEVENT eventp) // synch event +{ + PRIP_UPDATE_SNDREQ respcbp = NULL; // ptr to changes response to bcast + PUCHAR sndhdrp; + USHORT sndpktlen; + PRIP_SNDREQ sndreqp; + + // allocate a send request struct to bcast changes in the routing table + if((respcbp = ExAllocatePool(NonPagedPool, + sizeof(RIP_UPDATE_SNDREQ) + RIP_SNDPKT_MINLEN)) == NULL) { + //!!! + return; + } + + // get the ipx hdr ptr for the send packet + sndhdrp = (PUCHAR)respcbp->RipSndPktBuff.IpxPacket; + + // set the initial length + sndpktlen = RIP_INFO; + + // fill in the network entry structure in the packet with the + // info from the route entry + SetNetworkEntry(sndhdrp + sndpktlen, rtep); + + // increment the send packet length to the next network entry + sndpktlen += NE_ENTRYSIZE; + + // set the new packet length + PUTUSHORT2SHORT(sndhdrp + IPXH_LENGTH, sndpktlen); + + // set up the request to send a bcast response with the changes + sndreqp = &respcbp->RipSndReq; + + BroadcastRipUpdate(sndreqp, niccbp, eventp); +} + + + + + + + + + + + + + + +//*** Routines for handling the hash table of node numbers -> nic ptrs mapping. + +// The WAN nodes hash table + +NDIS_SPIN_LOCK WanNodeHTLock; + +LIST_ENTRY WanNodeHT[NODE_HTSIZE]; + +//*** +// +// Function: InitWanNodeHT +// +// Descr: +// +//*** + +VOID +InitWanNodeHT(VOID) +{ + int i; + PLIST_ENTRY WanNodeHTBucketp; + + INITIALIZE_SPIN_LOCK(&WanNodeHTLock); + + WanNodeHTBucketp = WanNodeHT; + + for(i=0; i<NODE_HTSIZE; i++, WanNodeHTBucketp++) { + + InitializeListHead(WanNodeHTBucketp); + } +} + + +//*** +// +// Function: ndhash +// +// Descr: compute the hash index for this node +// +//*** + +int +ndhash(PUCHAR nodep) +{ + USHORT ndindex = 6; + int hv = 0; // hash value + + while(ndindex--) { + + hv += nodep[ndindex] & 0xff; + } + + return hv % NODE_HTSIZE; +} + +//*** +// +// Function: GetWanNodeNiccb +// +// Descr: get the nic CB for a given WAN node +// +//*** + +PNICCB +GetWanNodeNiccbp(PUCHAR nodep) +{ + int hv; + PLIST_ENTRY nextp; + PNICCB niccbp; + + hv = ndhash(nodep); + + ACQUIRE_SPIN_LOCK(&WanNodeHTLock); + + // walk the niccbs list until we get to the node + nextp = WanNodeHT[hv].Flink; + + while(nextp != &WanNodeHT[hv]) { + + niccbp = CONTAINING_RECORD(nextp, NICCB, WanHtLinkage); + + if(!memcmp(niccbp->RemoteNode, nodep, 6)) { + + RELEASE_SPIN_LOCK(&WanNodeHTLock); + return niccbp; + } + + nextp = niccbp->WanHtLinkage.Flink; + } + + RELEASE_SPIN_LOCK(&WanNodeHTLock); + + return NULL; +} + + +//*** +// +// Function: AddWanNodeToHT +// +// Descr: Inserts a new node in the WAN nodes Hash Table +// +//*** + +VOID +AddWanNodeToHT(PNICCB niccbp) +{ + int hv; + + hv = ndhash(niccbp->RemoteNode); + + ACQUIRE_SPIN_LOCK(&WanNodeHTLock); + + InsertTailList(&WanNodeHT[hv], &niccbp->WanHtLinkage); + + RELEASE_SPIN_LOCK(&WanNodeHTLock); +} + +//*** +// +// Function: RemoveWanNodeFromHT +// +// Descr: Removes a WAN node from the WAN nodes Hash Table +// +//*** + +VOID +RemoveWanNodeFromHT(PNICCB niccbp) +{ + int hv; + + hv = ndhash(niccbp->RemoteNode); + + ACQUIRE_SPIN_LOCK(&WanNodeHTLock); + + RemoveEntryList(&niccbp->WanHtLinkage); + + RELEASE_SPIN_LOCK(&WanNodeHTLock); +} |