00001 // 00002 // Copyright (C) 2006 Andras Babos and Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #include "HelloHandler.h" 00019 #include "IPControlInfo.h" 00020 #include "OSPFRouter.h" 00021 #include "OSPFArea.h" 00022 #include "OSPFInterface.h" 00023 #include "OSPFNeighbor.h" 00024 00025 OSPF::HelloHandler::HelloHandler(OSPF::Router* containingRouter) : 00026 OSPF::IMessageHandler(containingRouter) 00027 { 00028 } 00029 00030 void OSPF::HelloHandler::ProcessPacket(OSPFPacket* packet, OSPF::Interface* intf, OSPF::Neighbor* unused) 00031 { 00032 OSPFHelloPacket* helloPacket = check_and_cast<OSPFHelloPacket*> (packet); 00033 bool rebuildRoutingTable = false; 00034 00035 /* The values of the Network Mask, HelloInterval, 00036 and RouterDeadInterval fields in the received Hello packet must 00037 be checked against the values configured for the receiving 00038 interface. Any mismatch causes processing to stop and the 00039 packet to be dropped. 00040 */ 00041 if ((intf->GetHelloInterval() == helloPacket->getHelloInterval()) && 00042 (intf->GetRouterDeadInterval() == helloPacket->getRouterDeadInterval())) 00043 { 00044 OSPF::Interface::OSPFInterfaceType interfaceType = intf->GetType(); 00045 /* There is one exception to the above rule: on point-to-point 00046 networks and on virtual links, the Network Mask in the received 00047 Hello Packet should be ignored. 00048 */ 00049 if (!((interfaceType != OSPF::Interface::PointToPoint) && 00050 (interfaceType != OSPF::Interface::Virtual) && 00051 (intf->GetAddressRange().mask != IPv4AddressFromULong(helloPacket->getNetworkMask().getInt())) 00052 ) 00053 ) 00054 { 00055 /* The setting of the E-bit found in the Hello Packet's Options field must match this area's 00056 ExternalRoutingCapability. 00057 */ 00058 if (intf->GetArea()->GetExternalRoutingCapability() == helloPacket->getOptions().E_ExternalRoutingCapability) { 00059 IPControlInfo* controlInfo = check_and_cast<IPControlInfo *> (helloPacket->getControlInfo()); 00060 OSPF::IPv4Address srcAddress = IPv4AddressFromULong(controlInfo->getSrcAddr().getInt()); 00061 bool neighborChanged = false; 00062 bool neighborsDRStateChanged = false; 00063 bool drChanged = false; 00064 bool backupSeen = false; 00065 OSPF::Neighbor* neighbor; 00066 00067 /* If the receiving interface connects to a broadcast, Point-to- 00068 MultiPoint or NBMA network the source is identified by the IP 00069 source address found in the Hello's IP header. 00070 */ 00071 if ((interfaceType == OSPF::Interface::Broadcast) || 00072 (interfaceType == OSPF::Interface::PointToMultiPoint) || 00073 (interfaceType == OSPF::Interface::NBMA)) 00074 { 00075 neighbor = intf->GetNeighborByAddress(srcAddress); 00076 } else { 00077 /* If the receiving interface connects to a point-to-point link or a virtual link, 00078 the source is identified by the Router ID found in the Hello's OSPF packet header. 00079 */ 00080 neighbor = intf->GetNeighborByID(helloPacket->getRouterID().getInt()); 00081 } 00082 00083 if (neighbor != NULL) { 00084 router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor); 00085 00086 IPv4Address designatedAddress = neighbor->GetDesignatedRouter().ipInterfaceAddress; 00087 IPv4Address backupAddress = neighbor->GetBackupDesignatedRouter().ipInterfaceAddress; 00088 char newPriority = helloPacket->getRouterPriority(); 00089 unsigned long source = controlInfo->getSrcAddr().getInt(); 00090 unsigned long newDesignatedRouter = helloPacket->getDesignatedRouter().getInt(); 00091 unsigned long newBackupRouter = helloPacket->getBackupDesignatedRouter().getInt(); 00092 OSPF::DesignatedRouterID dRouterID; 00093 00094 if ((interfaceType == OSPF::Interface::Virtual) && 00095 (neighbor->GetState() == OSPF::Neighbor::DownState)) 00096 { 00097 neighbor->SetPriority(helloPacket->getRouterPriority()); 00098 neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval()); 00099 } 00100 00101 /* If a change in the neighbor's Router Priority field 00102 was noted, the receiving interface's state machine is 00103 scheduled with the event NeighborChange. 00104 */ 00105 if (neighbor->GetPriority() != newPriority) { 00106 neighborChanged = true; 00107 } 00108 00109 /* If the neighbor is both declaring itself to be Designated 00110 Router(Hello Packet's Designated Router field = Neighbor IP 00111 address) and the Backup Designated Router field in the 00112 packet is equal to 0.0.0.0 and the receiving interface is in 00113 state Waiting, the receiving interface's state machine is 00114 scheduled with the event BackupSeen. 00115 */ 00116 if ((newDesignatedRouter == source) && 00117 (newBackupRouter == 0) && 00118 (intf->GetState() == OSPF::Interface::WaitingState)) 00119 { 00120 backupSeen = true; 00121 } else { 00122 /* Otherwise, if the neighbor is declaring itself to be Designated Router and it 00123 had not previously, or the neighbor is not declaring itself 00124 Designated Router where it had previously, the receiving 00125 interface's state machine is scheduled with the event 00126 NeighborChange. 00127 */ 00128 if (((newDesignatedRouter == source) && 00129 (newDesignatedRouter != ULongFromIPv4Address(designatedAddress))) || 00130 ((newDesignatedRouter != source) && 00131 (source == ULongFromIPv4Address(designatedAddress)))) 00132 { 00133 neighborChanged = true; 00134 neighborsDRStateChanged = true; 00135 } 00136 } 00137 00138 /* If the neighbor is declaring itself to be Backup Designated 00139 Router(Hello Packet's Backup Designated Router field = 00140 Neighbor IP address) and the receiving interface is in state 00141 Waiting, the receiving interface's state machine is 00142 scheduled with the event BackupSeen. 00143 */ 00144 if ((newBackupRouter == source) && 00145 (intf->GetState() == OSPF::Interface::WaitingState)) 00146 { 00147 backupSeen = true; 00148 } else { 00149 /* Otherwise, if the neighbor is declaring itself to be Backup Designated Router 00150 and it had not previously, or the neighbor is not declaring 00151 itself Backup Designated Router where it had previously, the 00152 receiving interface's state machine is scheduled with the 00153 event NeighborChange. 00154 */ 00155 if (((newBackupRouter == source) && 00156 (newBackupRouter != ULongFromIPv4Address(backupAddress))) || 00157 ((newBackupRouter != source) && 00158 (source == ULongFromIPv4Address(backupAddress)))) 00159 { 00160 neighborChanged = true; 00161 } 00162 } 00163 00164 neighbor->SetNeighborID(helloPacket->getRouterID().getInt()); 00165 neighbor->SetPriority(newPriority); 00166 neighbor->SetAddress(srcAddress); 00167 dRouterID.routerID = newDesignatedRouter; 00168 dRouterID.ipInterfaceAddress = IPv4AddressFromULong(newDesignatedRouter); 00169 if (newDesignatedRouter != ULongFromIPv4Address(designatedAddress)) { 00170 designatedAddress = dRouterID.ipInterfaceAddress; 00171 drChanged = true; 00172 } 00173 neighbor->SetDesignatedRouter(dRouterID); 00174 dRouterID.routerID = newBackupRouter; 00175 dRouterID.ipInterfaceAddress = IPv4AddressFromULong(newBackupRouter); 00176 if (newBackupRouter != ULongFromIPv4Address(backupAddress)) { 00177 backupAddress = dRouterID.ipInterfaceAddress; 00178 drChanged = true; 00179 } 00180 neighbor->SetBackupDesignatedRouter(dRouterID); 00181 if (drChanged) { 00182 neighbor->SetUpDesignatedRouters(false); 00183 } 00184 00185 /* If the neighbor router's Designated or Backup Designated Router 00186 has changed it's necessary to look up the Router IDs belonging to the 00187 new addresses. 00188 */ 00189 if (!neighbor->DesignatedRoutersAreSetUp()) { 00190 OSPF::Neighbor* designated = intf->GetNeighborByAddress(designatedAddress); 00191 OSPF::Neighbor* backup = intf->GetNeighborByAddress(backupAddress); 00192 00193 if (designated != NULL) { 00194 dRouterID.routerID = designated->GetNeighborID(); 00195 dRouterID.ipInterfaceAddress = designated->GetAddress(); 00196 neighbor->SetDesignatedRouter(dRouterID); 00197 } 00198 if (backup != NULL) { 00199 dRouterID.routerID = backup->GetNeighborID(); 00200 dRouterID.ipInterfaceAddress = backup->GetAddress(); 00201 neighbor->SetBackupDesignatedRouter(dRouterID); 00202 } 00203 if ((designated != NULL) && (backup != NULL)) { 00204 neighbor->SetUpDesignatedRouters(true); 00205 } 00206 } 00207 } else { 00208 OSPF::DesignatedRouterID dRouterID; 00209 bool designatedSetUp = false; 00210 bool backupSetUp = false; 00211 00212 neighbor = new OSPF::Neighbor(helloPacket->getRouterID().getInt()); 00213 neighbor->SetPriority(helloPacket->getRouterPriority()); 00214 neighbor->SetAddress(srcAddress); 00215 neighbor->SetRouterDeadInterval(helloPacket->getRouterDeadInterval()); 00216 00217 router->GetMessageHandler()->PrintEvent("Hello packet received", intf, neighbor); 00218 00219 dRouterID.routerID = helloPacket->getDesignatedRouter().getInt(); 00220 dRouterID.ipInterfaceAddress = IPv4AddressFromULong(dRouterID.routerID); 00221 00222 OSPF::Neighbor* designated = intf->GetNeighborByAddress(dRouterID.ipInterfaceAddress); 00223 00224 // Get the Designated Router ID from the corresponding Neighbor Object. 00225 if (designated != NULL) { 00226 if (designated->GetNeighborID() != dRouterID.routerID) { 00227 dRouterID.routerID = designated->GetNeighborID(); 00228 } 00229 designatedSetUp = true; 00230 } 00231 neighbor->SetDesignatedRouter(dRouterID); 00232 00233 dRouterID.routerID = helloPacket->getBackupDesignatedRouter().getInt(); 00234 dRouterID.ipInterfaceAddress = IPv4AddressFromULong(dRouterID.routerID); 00235 00236 OSPF::Neighbor* backup = intf->GetNeighborByAddress(dRouterID.ipInterfaceAddress); 00237 00238 // Get the Backup Designated Router ID from the corresponding Neighbor Object. 00239 if (backup != NULL) { 00240 if (backup->GetNeighborID() != dRouterID.routerID) { 00241 dRouterID.routerID = backup->GetNeighborID(); 00242 } 00243 backupSetUp = true; 00244 } 00245 neighbor->SetBackupDesignatedRouter(dRouterID); 00246 if (designatedSetUp && backupSetUp) { 00247 neighbor->SetUpDesignatedRouters(true); 00248 } 00249 intf->AddNeighbor(neighbor); 00250 } 00251 00252 neighbor->ProcessEvent(OSPF::Neighbor::HelloReceived); 00253 if ((interfaceType == OSPF::Interface::NBMA) && 00254 (intf->GetRouterPriority() == 0) && 00255 (neighbor->GetState() >= OSPF::Neighbor::InitState)) 00256 { 00257 intf->SendHelloPacket(neighbor->GetAddress()); 00258 } 00259 00260 unsigned long interfaceAddress = ULongFromIPv4Address(intf->GetAddressRange().address); 00261 unsigned int neighborsNeighborCount = helloPacket->getNeighborArraySize(); 00262 unsigned int i; 00263 /* The list of neighbors contained in the Hello Packet is 00264 examined. If the router itself appears in this list, the 00265 neighbor state machine should be executed with the event TwoWayReceived. 00266 */ 00267 for (i = 0; i < neighborsNeighborCount; i++) { 00268 if (helloPacket->getNeighbor(i).getInt() == interfaceAddress) { 00269 neighbor->ProcessEvent(OSPF::Neighbor::TwoWayReceived); 00270 break; 00271 } 00272 } 00273 /* Otherwise, the neighbor state machine should 00274 be executed with the event OneWayReceived, and the processing 00275 of the packet stops. 00276 */ 00277 if (i == neighborsNeighborCount) { 00278 neighbor->ProcessEvent(OSPF::Neighbor::OneWayReceived); 00279 } 00280 00281 if (neighborChanged) { 00282 intf->ProcessEvent(OSPF::Interface::NeighborChange); 00283 /* In some cases neighbors get stuck in TwoWay state after a DR 00284 or Backup change. (CalculateDesignatedRouter runs before the 00285 neighbors' signal of DR change + this router does not become 00286 neither DR nor backup -> IsAdjacencyOK does not get called.) 00287 So to make it work(workaround) we'll call IsAdjacencyOK for 00288 all neighbors in TwoWay state from here. This shouldn't break 00289 anything because if the neighbor state doesn't have to change 00290 then NeedAdjacency returns false and nothing happnes in 00291 IsAdjacencyOK. 00292 */ 00293 unsigned int neighborCount = intf->GetNeighborCount(); 00294 for (i = 0; i < neighborCount; i++) { 00295 OSPF::Neighbor* stuckNeighbor = intf->GetNeighbor(i); 00296 if (stuckNeighbor->GetState() == OSPF::Neighbor::TwoWayState) { 00297 stuckNeighbor->ProcessEvent(OSPF::Neighbor::IsAdjacencyOK); 00298 } 00299 } 00300 00301 if (neighborsDRStateChanged) { 00302 OSPF::RouterLSA* routerLSA = intf->GetArea()->FindRouterLSA(router->GetRouterID()); 00303 00304 if (routerLSA != NULL) { 00305 long sequenceNumber = routerLSA->getHeader().getLsSequenceNumber(); 00306 if (sequenceNumber == MAX_SEQUENCE_NUMBER) { 00307 routerLSA->getHeader().setLsAge(MAX_AGE); 00308 intf->GetArea()->FloodLSA(routerLSA); 00309 routerLSA->IncrementInstallTime(); 00310 } else { 00311 OSPF::RouterLSA* newLSA = intf->GetArea()->OriginateRouterLSA(); 00312 00313 newLSA->getHeader().setLsSequenceNumber(sequenceNumber + 1); 00314 newLSA->getHeader().setLsChecksum(0); // TODO: calculate correct LS checksum 00315 rebuildRoutingTable |= routerLSA->Update(newLSA); 00316 delete newLSA; 00317 00318 intf->GetArea()->FloodLSA(routerLSA); 00319 } 00320 } 00321 } 00322 } 00323 00324 if (backupSeen) { 00325 intf->ProcessEvent(OSPF::Interface::BackupSeen); 00326 } 00327 } 00328 } 00329 } 00330 00331 if (rebuildRoutingTable) { 00332 router->RebuildRoutingTable(); 00333 } 00334 }