|
xorp
|
00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- 00002 00003 // Copyright (c) 2001-2009 XORP, Inc. 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License, Version 2, June 00007 // 1991 as published by the Free Software Foundation. Redistribution 00008 // and/or modification of this program under the terms of any other 00009 // version of the GNU General Public License is not permitted. 00010 // 00011 // This program is distributed in the hope that it will be useful, but 00012 // WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, 00014 // see the GNU General Public License, Version 2, a copy of which can be 00015 // found in the XORP LICENSE.gpl file. 00016 // 00017 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; 00018 // http://xorp.net 00019 00020 // $XORP: xorp/rip/packet_assembly.hh,v 1.16 2008/10/02 21:58:16 bms Exp $ 00021 00022 #ifndef __RIP_PACKET_ASSEMBLY_HH__ 00023 #define __RIP_PACKET_ASSEMBLY_HH__ 00024 00025 #include "rip_module.h" 00026 #include "libxorp/xlog.h" 00027 00028 #include "auth.hh" 00029 #include "packets.hh" 00030 #include "port.hh" 00031 00038 template <typename A> 00039 class PacketAssemblerSpecState 00040 {}; 00041 00048 template <> 00049 class PacketAssemblerSpecState<IPv4> 00050 { 00051 private: 00052 AuthHandlerBase& _ah; 00053 public: 00057 PacketAssemblerSpecState(Port<IPv4>& port) 00058 : _ah(*(port.af_state().auth_handler())) 00059 {} 00060 00064 PacketAssemblerSpecState(AuthHandlerBase& auth_handler) 00065 : _ah(auth_handler) 00066 {} 00067 00071 AuthHandlerBase& ah() { return _ah; } 00072 00076 const AuthHandlerBase& ah() const { return _ah; } 00077 }; 00078 00079 00090 template <> 00091 class PacketAssemblerSpecState<IPv6> 00092 { 00093 private: 00094 uint32_t _max_entries; 00095 IPv6 _lnh; 00096 00097 public: 00098 PacketAssemblerSpecState(Port<IPv6>& ) 00099 : _max_entries(25), _lnh(IPv6::ALL_ONES()) 00100 {} 00101 PacketAssemblerSpecState() 00102 : _max_entries(25), _lnh(IPv6::ALL_ONES()) 00103 {} 00104 00105 uint32_t max_entries() const; 00106 void reset_last_nexthop(); 00107 void set_last_nexthop(const IPv6& ip6); 00108 const IPv6& last_nexthop() const; 00109 }; 00110 00111 inline uint32_t 00112 PacketAssemblerSpecState<IPv6>::max_entries() const 00113 { 00114 return _max_entries; 00115 } 00116 00117 inline void 00118 PacketAssemblerSpecState<IPv6>::reset_last_nexthop() 00119 { 00120 _lnh = IPv6::ALL_ONES(); 00121 } 00122 00123 inline void 00124 PacketAssemblerSpecState<IPv6>::set_last_nexthop(const IPv6& ip6) 00125 { 00126 _lnh = ip6; 00127 } 00128 00129 inline const IPv6& 00130 PacketAssemblerSpecState<IPv6>::last_nexthop() const 00131 { 00132 return _lnh; 00133 } 00134 00135 00144 template <typename A> 00145 class ResponsePacketAssembler { 00146 public: 00147 typedef A Addr; 00148 typedef IPNet<A> Net; 00149 typedef PacketAssemblerSpecState<A> SpState; 00150 00151 public: 00157 ResponsePacketAssembler(Port<A>& port); 00158 00164 ResponsePacketAssembler(SpState& sp); 00165 00169 ~ResponsePacketAssembler(); 00170 00174 void packet_start(RipPacket<A>* pkt); 00175 00182 bool packet_add_route(const Net& net, 00183 const Addr& nexthop, 00184 uint16_t cost, 00185 uint16_t tag); 00186 00192 bool packet_full() const; 00193 00203 bool packet_finish(list<RipPacket<A>* >& auth_packets); 00204 00205 private: 00209 ResponsePacketAssembler(const ResponsePacketAssembler&); 00210 00214 ResponsePacketAssembler& operator=(const ResponsePacketAssembler&); 00215 00216 protected: 00217 RipPacket<A>* _pkt; 00218 uint32_t _pos; 00219 SpState _sp_state; 00220 }; 00221 00222 00229 template <typename A> 00230 class RequestTablePacketAssembler { 00231 public: 00232 typedef A Addr; 00233 typedef IPNet<A> Net; 00234 typedef PacketAssemblerSpecState<A> SpState; 00235 00236 public: 00237 RequestTablePacketAssembler(Port<A>& port) : _sp_state(port) {} 00238 00247 bool prepare(RipPacket<A>* pkt, 00248 list<RipPacket<A>* >& auth_packets); 00249 00250 protected: 00251 SpState _sp_state; 00252 }; 00253 00254 00255 // ---------------------------------------------------------------------------- 00256 // ResponsePacketAssembler<IPv4> implementation 00257 00258 template <> 00259 inline 00260 ResponsePacketAssembler<IPv4>::ResponsePacketAssembler(Port<IPv4>& port) 00261 : _pkt(0), _pos(0), _sp_state(port) 00262 { 00263 } 00264 00265 template <> 00266 inline 00267 ResponsePacketAssembler<IPv4>::ResponsePacketAssembler(SpState& sp) 00268 : _pkt(0), _pos(0), _sp_state(sp) 00269 { 00270 } 00271 00272 template <> 00273 inline 00274 ResponsePacketAssembler<IPv4>::~ResponsePacketAssembler() 00275 { 00276 } 00277 00278 template <> 00279 inline void 00280 ResponsePacketAssembler<IPv4>::packet_start(RipPacket<IPv4>* pkt) 00281 { 00282 _pkt = pkt; 00283 00284 const AuthHandlerBase& ah = _sp_state.ah(); 00285 _pos = ah.head_entries(); 00286 _pkt->set_max_entries(ah.head_entries() + ah.max_routing_entries()); 00287 00288 RipPacketHeaderWriter rph(_pkt->header_ptr()); 00289 rph.initialize(RipPacketHeader::RESPONSE, RipPacketHeader::IPv4_VERSION); 00290 } 00291 00292 template <> 00293 inline bool 00294 ResponsePacketAssembler<IPv4>::packet_full() const 00295 { 00296 const AuthHandlerBase& ah = _sp_state.ah(); 00297 return _pos == ah.max_routing_entries(); 00298 } 00299 00300 template <> 00301 inline bool 00302 ResponsePacketAssembler<IPv4>::packet_add_route(const Net& net, 00303 const Addr& nexthop, 00304 uint16_t cost, 00305 uint16_t tag) 00306 { 00307 if (packet_full()) { 00308 return false; 00309 } 00310 uint8_t* pre_ptr = _pkt->route_entry_ptr(_pos); 00311 PacketRouteEntryWriter<IPv4> pre(pre_ptr); 00312 pre.initialize(tag, net, nexthop, cost); 00313 _pos++; 00314 return true; 00315 } 00316 00317 template <> 00318 inline bool 00319 ResponsePacketAssembler<IPv4>::packet_finish( 00320 list<RipPacket<IPv4>* >& auth_packets) 00321 { 00322 AuthHandlerBase& ah = _sp_state.ah(); 00323 00324 _pkt->set_max_entries(_pos); 00325 size_t n_routes = 0; 00326 if ((ah.authenticate_outbound(*_pkt, auth_packets, n_routes) != true) 00327 || (n_routes == 0)) { 00328 XLOG_ERROR("Outbound authentication error: %s\n", ah.error().c_str()); 00329 return false; 00330 } 00331 return true; 00332 } 00333 00334 // ---------------------------------------------------------------------------- 00335 // ResponsePacketAssembler<IPv6> implementation 00336 00337 template <> 00338 inline 00339 ResponsePacketAssembler<IPv6>::ResponsePacketAssembler(Port<IPv6>& port) 00340 : _pkt(0), _pos(0), _sp_state(port) 00341 { 00342 } 00343 00344 template <> 00345 inline 00346 ResponsePacketAssembler<IPv6>::ResponsePacketAssembler(SpState& sp) 00347 : _pkt(0), _pos(0), _sp_state(sp) 00348 { 00349 } 00350 00351 template <> 00352 inline 00353 ResponsePacketAssembler<IPv6>::~ResponsePacketAssembler() 00354 { 00355 } 00356 00357 template <> 00358 inline void 00359 ResponsePacketAssembler<IPv6>::packet_start(RipPacket<IPv6>* pkt) 00360 { 00361 _pkt = pkt; 00362 _pos = 0; 00363 _sp_state.reset_last_nexthop(); 00364 RipPacketHeaderWriter rph(_pkt->header_ptr()); 00365 rph.initialize(RipPacketHeader::RESPONSE, RipPacketHeader::IPv6_VERSION); 00366 } 00367 00368 template <> 00369 inline bool 00370 ResponsePacketAssembler<IPv6>::packet_full() const 00371 { 00372 return (_sp_state.max_entries() - _pos) <= 2; 00373 } 00374 00375 template <> 00376 inline bool 00377 ResponsePacketAssembler<IPv6>::packet_add_route(const Net& net, 00378 const Addr& nexthop, 00379 uint16_t cost, 00380 uint16_t tag) 00381 { 00382 uint8_t* pre_ptr; 00383 00384 if (packet_full()) { 00385 return false; 00386 } 00387 if (nexthop != _sp_state.last_nexthop()) { 00388 pre_ptr = _pkt->route_entry_ptr(_pos); 00389 PacketRouteEntryWriter<IPv6> pre(pre_ptr); 00390 pre.initialize_nexthop(nexthop); 00391 _pos++; 00392 _sp_state.set_last_nexthop(nexthop); 00393 } 00394 pre_ptr = _pkt->route_entry_ptr(_pos); 00395 PacketRouteEntryWriter<IPv6> pre(pre_ptr); 00396 pre.initialize_route(tag, net, cost); 00397 _pos++; 00398 return true; 00399 } 00400 00401 template <> 00402 inline bool 00403 ResponsePacketAssembler<IPv6>::packet_finish( 00404 list<RipPacket<IPv6>* >& auth_packets) 00405 { 00406 _pkt->set_max_entries(_pos); 00407 00408 RipPacket<IPv6>* packet = new RipPacket<IPv6>(*_pkt); 00409 auth_packets.push_back(packet); 00410 00411 return true; 00412 } 00413 00414 00415 // ---------------------------------------------------------------------------- 00416 // RequestTablePacketAssembler<IPv4> implementation 00417 00418 template<> 00419 inline bool 00420 RequestTablePacketAssembler<IPv4>::prepare(RipPacket<IPv4>* pkt, 00421 list<RipPacket<IPv4>* >& auth_packets) 00422 { 00423 RipPacketHeaderWriter rph(pkt->header_ptr()); 00424 rph.initialize(RipPacketHeader::REQUEST, RipPacketHeader::IPv4_VERSION); 00425 00426 AuthHandlerBase& ah = _sp_state.ah(); 00427 pkt->set_max_entries(1 + ah.head_entries()); 00428 00429 uint8_t* pre_ptr = pkt->route_entry_ptr(ah.head_entries()); 00430 PacketRouteEntryWriter<IPv4> pre(pre_ptr); 00431 pre.initialize_table_request(); 00432 00433 size_t n_routes = 0; 00434 if ((ah.authenticate_outbound(*pkt, auth_packets, n_routes) != true) 00435 || (n_routes == 0)) { 00436 XLOG_ERROR("Outbound authentication error: %s\n", ah.error().c_str()); 00437 return false; 00438 } 00439 return true; 00440 } 00441 00442 00443 // ---------------------------------------------------------------------------- 00444 // RequestTablePacketAssembler<IPv6> implementation 00445 00446 template<> 00447 inline bool 00448 RequestTablePacketAssembler<IPv6>::prepare(RipPacket<IPv6>* pkt, 00449 list<RipPacket<IPv6>* >& auth_packets) 00450 { 00451 RipPacketHeaderWriter rph(pkt->header_ptr()); 00452 rph.initialize(RipPacketHeader::REQUEST, RipPacketHeader::IPv6_VERSION); 00453 pkt->set_max_entries(1); 00454 00455 uint8_t* pre_ptr = pkt->route_entry_ptr(0); 00456 PacketRouteEntryWriter<IPv6> pre(pre_ptr); 00457 pre.initialize_table_request(); 00458 00459 RipPacket<IPv6>* packet = new RipPacket<IPv6>(*pkt); 00460 auth_packets.push_back(packet); 00461 00462 return true; 00463 } 00464 00465 #endif // __RIP_PACKET_ASSEMBLY_HH__