xorp

packet_assembly.hh

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations