/********************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1990-1992 **/ /********************************************************************/ /* :ts=4 */ //*** ipstatus.c - IP status routines. // // This module contains all routines related to status indications. // #include "oscfg.h" #include "cxport.h" #include "ndis.h" #include "ip.h" #include "ipdef.h" #include "llipif.h" #include "iproute.h" #include "ipinfo.h" #if 0 EXTERNAL_LOCK(PILock) #endif extern ProtInfo IPProtInfo[]; // Protocol information table. extern int NextPI; // Next PI field to be used. extern ProtInfo *RawPI; // Raw IP protinfo //* FindULStatus - Find the upper layer status handler. // // Called when we need to find the upper layer status handler for a particular // protocol. // // Entry: Protocol - Protocol to look up // // Returns: A pointer to the ULStatus proc, or NULL if it can't find one. // ULStatusProc FindULStatus(uchar Protocol) { ULStatusProc StatusProc = (ULStatusProc)NULL; int i; #if 0 CTELockHandle Handle; CTEGetLock(&PILock, &Handle); #endif for ( i = 0; i < NextPI; i++) { if (IPProtInfo[i].pi_protocol == Protocol) { StatusProc = IPProtInfo[i].pi_status; #if 0 CTEFreeLock(&PILock, Handle); #endif return StatusProc; } } if (RawPI != NULL) { StatusProc = RawPI->pi_status; } #if 0 CTEFreeLock(&PILock, Handle); #endif return StatusProc; } //* ULMTUNotify - Notify the upper layers of an MTU change. // // Called when we need to notify the upper layers of an MTU change. We'll // loop through the status table, calling each status proc with the info. // // This routine doesn't do any locking of the protinfo table. We might need // to check this. // // Input: Dest - Destination address affected. // Src - Source address affected. // Prot - Protocol that triggered change, if any. // Ptr - Pointer to protocol info, if any. // NewMTU - New MTU to tell them about. // // Returns: Nothing. // void ULMTUNotify(IPAddr Dest, IPAddr Src, uchar Prot, void *Ptr, uint NewMTU) { ULStatusProc StatusProc; int i; // First, notify the specific client that a frame has been dropped // and needs to be retransmitted. StatusProc = FindULStatus(Prot); if (StatusProc != NULL) (*StatusProc)(IP_NET_STATUS, IP_SPEC_MTU_CHANGE, Dest, Src, NULL_IP_ADDR, NewMTU, Ptr); // Now notify all UL entities that the MTU has changed. for (i = 0; i < NextPI; i++) { StatusProc = IPProtInfo[i].pi_status; if (StatusProc != NULL) (*StatusProc)(IP_HW_STATUS, IP_MTU_CHANGE, Dest, Src, NULL_IP_ADDR, NewMTU, Ptr); } } #ifdef CHICAGO //* IPULUnloadNotify - Notify clients that we're unloading. // // Called when we receive an unload message. We'll notify the upper layers // that we're unloading. // // Input: Nothing. // // Returns: Nothing. // void IPULUnloadNotify(void) { ULStatusProc StatusProc; int i; // Now notify all UL entities that the MTU has changed. for (i = 0; i < NextPI; i++) { StatusProc = IPProtInfo[i].pi_status; if (StatusProc != NULL) (*StatusProc)(IP_HW_STATUS, IP_UNLOAD, NULL_IP_ADDR, NULL_IP_ADDR, NULL_IP_ADDR, 0, NULL); } } #endif //* IPStatus - Handle a link layer status call. // // This is the routine called by the link layer when some sort of 'important' // status change occurs. // // Entry: Context - Context value we gave to the link layer. // Status - Status change code. // Buffer - Pointer to buffer of status information. // BufferSize - Size of Buffer. // // Returns: Nothing. // void IPStatus(void *Context, uint Status, void *Buffer, uint BufferSize) { NetTableEntry *NTE = (NetTableEntry *)Context; LLIPSpeedChange *LSC; LLIPMTUChange *LMC; LLIPAddrMTUChange *LAM; uint NewMTU; Interface *IF; switch (Status) { case LLIP_STATUS_SPEED_CHANGE: if (BufferSize < sizeof(LLIPSpeedChange)) break; LSC = (LLIPSpeedChange *)Buffer; NTE->nte_if->if_speed = LSC->lsc_speed; break; case LLIP_STATUS_MTU_CHANGE: if (BufferSize < sizeof(LLIPMTUChange)) break; // Walk through the NTEs on the IF, updating their MTUs. IF = NTE->nte_if; LMC = (LLIPMTUChange *)Buffer; IF->if_mtu = LMC->lmc_mtu; NewMTU = LMC->lmc_mtu - sizeof(IPHeader); NTE = IF->if_nte; while (NTE != NULL) { NTE->nte_mss = NewMTU; NTE = NTE->nte_ifnext; } RTWalk(SetMTUOnIF, IF, &NewMTU); break; case LLIP_STATUS_ADDR_MTU_CHANGE: if (BufferSize < sizeof(LLIPAddrMTUChange)) break; // The MTU for a specific remote address has changed. Update all // routes that use that remote address as a first hop, and then // add a host route to that remote address, specifying the new // MTU. LAM = (LLIPAddrMTUChange *)Buffer; NewMTU = LAM->lam_mtu - sizeof(IPHeader); RTWalk(SetMTUToAddr, &LAM->lam_addr, &NewMTU); AddRoute(LAM->lam_addr, HOST_MASK, IPADDR_LOCAL, NTE->nte_if, NewMTU, 1, IRE_PROTO_LOCAL, ATYPE_OVERRIDE, GetRouteContext(LAM->lam_addr, NTE->nte_addr)); break; default: break; } }