xorp

packets.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 
00003 // Copyright (c) 2001-2011 XORP, Inc and Others
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/packets.hh,v 1.30 2008/10/02 21:58:16 bms Exp $
00021 
00022 #ifndef __RIP_PACKET_ENTRIES_HH__
00023 #define __RIP_PACKET_ENTRIES_HH__
00024 
00025 #include "libxorp/ipv4.hh"
00026 #include "libxorp/ipv4net.hh"
00027 #include "libxorp/ipv6.hh"
00028 #include "libxorp/ipv6net.hh"
00029 #include "libxorp/utility.h"
00030 
00031 #include "libproto/packet.hh"
00032 
00033 #include "constants.hh"
00034 
00045 class RipPacketHeader {
00046 public:
00047     RipPacketHeader(const uint8_t* data)
00048     : _data(data),
00049       _command(_data + _command_offset),
00050       _version(_data + _version_offset),
00051       _unused0(_data + _unused0_offset),
00052       _unused1(_data + _unused1_offset)
00053     {
00054     x_static_assert(RipPacketHeader::SIZE == _command_sizeof
00055               + _version_sizeof + _unused0_sizeof + _unused1_sizeof);
00056     x_static_assert(RipPacketHeader::SIZE == _unused1_offset
00057               + _unused1_sizeof);
00058     }
00059 
00060     static const uint8_t REQUEST  = 1;
00061     static const uint8_t RESPONSE = 2;
00062     static const uint8_t IPv4_VERSION = RIP_AF_CONSTANTS<IPv4>::PACKET_VERSION;
00063     static const uint8_t IPv6_VERSION = RIP_AF_CONSTANTS<IPv6>::PACKET_VERSION;
00064     static const size_t SIZE = 4;   // The header size
00065 
00071     static size_t size()    { return RipPacketHeader::SIZE; }
00072 
00073     uint8_t command() const { return extract_8(_command); }
00074     uint8_t version() const { return extract_8(_version); }
00075     uint8_t unused0() const { return extract_8(_unused0); }
00076     uint8_t unused1() const { return extract_8(_unused1); }
00077 
00078     bool valid_command() const;
00079     bool valid_version(uint8_t v) const { return version() == v; }
00080     bool valid_padding() const;
00081 
00082 protected:
00083     // Sizes of the fields
00084     static const size_t _command_sizeof = 1;
00085     static const size_t _version_sizeof = 1;
00086     static const size_t _unused0_sizeof = 1;
00087     static const size_t _unused1_sizeof = 1;
00088 
00089     // Offsets for the fields
00090     static const size_t _command_offset = 0;
00091     static const size_t _version_offset = _command_offset + _command_sizeof;
00092     static const size_t _unused0_offset = _version_offset + _version_sizeof;
00093     static const size_t _unused1_offset = _unused0_offset + _unused0_sizeof;
00094 
00095 private:
00096     const uint8_t* _data;   // The buffer data
00097 
00098     // Pointers to the fields
00099     const uint8_t* _command;    // 1 - request, 2 - response
00100     const uint8_t* _version;    // 1 - IPv4 RIPv1/IPv6 RIPng, 2 - IPv4 RIP v2
00101     const uint8_t* _unused0;
00102     const uint8_t* _unused1;
00103 };
00104 
00105 inline bool
00106 RipPacketHeader::valid_command() const
00107 {
00108     return command() == REQUEST || command() == RESPONSE;
00109 }
00110 
00111 inline bool
00112 RipPacketHeader::valid_padding() const
00113 {
00114     return (unused0() | unused1()) == 0;
00115 }
00116 
00117 /*
00118  * @short Class for writing data to RIP packet header.
00119  */
00120 class RipPacketHeaderWriter : public RipPacketHeader {
00121 public:
00122     RipPacketHeaderWriter(uint8_t* data)
00123     : RipPacketHeader(data),
00124       _data(data),
00125       _command(_data + _command_offset),
00126       _version(_data + _version_offset),
00127       _unused0(_data + _unused0_offset),
00128       _unused1(_data + _unused1_offset)
00129     {}
00130 
00131     void initialize(uint8_t cmd, uint8_t vers);
00132 
00133 private:
00134     uint8_t* _data;     // The buffer data
00135 
00136     // Pointers to the fields
00137     uint8_t* _command;      // 1 - request, 2 - response
00138     uint8_t* _version;      // 1 - IPv4 RIPv1/IPv6 RIPng, 2 - IPv4 RIP v2
00139     uint8_t* _unused0;
00140     uint8_t* _unused1;
00141 };
00142 
00143 inline void
00144 RipPacketHeaderWriter::initialize(uint8_t cmd, uint8_t vers)
00145 {
00146     embed_8(_command, cmd);
00147     embed_8(_version, vers);
00148     embed_8(_unused0, 0);
00149     embed_8(_unused1, 0);
00150 }
00151 
00158 template <typename A>
00159 class PacketRouteEntry {
00160 };
00161 
00162 /*
00163  * @short Class for writing data to RIP route entry.
00164  *
00165  * This structure is useful only it's specialized forms
00166  * @ref PacketRouteEntryWriter<IPv4> and @ref PacketRouteEntryWriter<IPv6>.
00167  */
00168 template <typename A>
00169 class PacketRouteEntryWriter {
00170 };
00171 
00175 static const size_t RIPv2_MIN_PACKET_BYTES = 4;
00176 static const size_t RIP_MIN_PACKET_BYTES = 4;
00177 
00181 static const size_t RIPv2_MIN_AUTH_PACKET_BYTES = 4 + 20;
00182 
00186 static const size_t RIPv2_MAX_PACKET_BYTES = 4 + 20 * RIPv2_ROUTES_PER_PACKET;
00187 
00188 
00211 template <>
00212 class PacketRouteEntry<IPv4> {
00213 public:
00214     PacketRouteEntry(const uint8_t* data)
00215     : _data(data),
00216       _af(_data + _af_offset),
00217       _tag(_data + _tag_offset),
00218       _addr(_data + _addr_offset),
00219       _mask(_data + _mask_offset),
00220       _nh(_data + _nh_offset),
00221       _metric(_data + _metric_offset)
00222     {
00223     x_static_assert(PacketRouteEntry<IPv4>::SIZE == _af_sizeof + _tag_sizeof
00224               + _addr_sizeof + _mask_sizeof + _nh_sizeof
00225               + _metric_sizeof);
00226     x_static_assert(PacketRouteEntry<IPv4>::SIZE == _metric_offset
00227               + _metric_sizeof);
00228     }
00229 
00230     static const size_t SIZE = 20;  // The entry size
00231 
00237     static size_t size()    { return PacketRouteEntry<IPv4>::SIZE; }
00238 
00239     uint16_t    addr_family() const     { return extract_16(_af); }
00240     uint16_t    tag() const     { return extract_16(_tag); }
00241     IPv4    addr() const        { return IPv4(_addr); }
00242     uint32_t    prefix_len() const;
00243     IPv4Net net() const;
00244     IPv4    nexthop() const     { return IPv4(_nh); }
00245     uint32_t    metric() const      { return extract_32(_metric); }
00246 
00250     bool    is_table_request() const;
00251 
00255     bool    is_auth_entry() const;
00256 
00257     static const uint16_t ADDR_FAMILY = 2;
00258     static const uint16_t ADDR_FAMILY_DUMP = 0;
00259     static const uint16_t ADDR_FAMILY_AUTH = 0xffff;
00260 
00261 protected:
00262     // Sizes of the fields
00263     static const size_t _af_sizeof  = 2;
00264     static const size_t _tag_sizeof = 2;
00265     static const size_t _addr_sizeof    = 4;
00266     static const size_t _mask_sizeof    = 4;
00267     static const size_t _nh_sizeof  = 4;
00268     static const size_t _metric_sizeof  = 4;
00269 
00270     // Offsets for the fields
00271     static const size_t _af_offset  = 0;
00272     static const size_t _tag_offset = _af_offset + _af_sizeof;
00273     static const size_t _addr_offset    = _tag_offset + _tag_sizeof;
00274     static const size_t _mask_offset    = _addr_offset + _addr_sizeof;
00275     static const size_t _nh_offset  = _mask_offset + _mask_sizeof;
00276     static const size_t _metric_offset  = _nh_offset + _nh_sizeof;
00277 
00278 private:
00279     const uint8_t* _data;   // The buffer data
00280 
00281     // Pointers to the fields
00282     const uint8_t* _af;
00283     const uint8_t* _tag;
00284     const uint8_t* _addr;
00285     const uint8_t* _mask;
00286     const uint8_t* _nh;
00287     const uint8_t* _metric;
00288 };
00289 
00290 inline uint32_t
00291 PacketRouteEntry<IPv4>::prefix_len() const
00292 {
00293     return IPv4(_mask).mask_len();
00294 }
00295 
00296 inline IPv4Net
00297 PacketRouteEntry<IPv4>::net() const
00298 {
00299     return IPv4Net(IPv4(_addr), IPv4(_mask).mask_len());
00300 }
00301 
00302 inline bool
00303 PacketRouteEntry<IPv4>::is_table_request() const
00304 {
00305     return addr_family() == ADDR_FAMILY_DUMP && metric() == RIP_INFINITY;
00306 }
00307 
00308 inline bool
00309 PacketRouteEntry<IPv4>::is_auth_entry() const
00310 {
00311     return addr_family() == ADDR_FAMILY_AUTH;
00312 }
00313 
00314 /*
00315  * @short Class for writing data to RIP IPv4 route entry.
00316  */
00317 template <>
00318 class PacketRouteEntryWriter<IPv4> : public PacketRouteEntry<IPv4> {
00319 public:
00320     PacketRouteEntryWriter(uint8_t* data)
00321     : PacketRouteEntry<IPv4>(data),
00322       _data(data),
00323       _af(_data + _af_offset),
00324       _tag(_data + _tag_offset),
00325       _addr(_data + _addr_offset),
00326       _mask(_data + _mask_offset),
00327       _nh(_data + _nh_offset),
00328       _metric(_data + _metric_offset)
00329     {}
00330 
00334     void initialize(uint16_t        tag,
00335             const IPv4Net&  net,
00336             IPv4        nh,
00337             uint32_t        cost);
00338 
00342     void initialize_table_request();
00343 
00344 private:
00345     uint8_t* _data;     // The buffer data
00346 
00347     // Pointers to the fields
00348     uint8_t* _af;
00349     uint8_t* _tag;
00350     uint8_t* _addr;
00351     uint8_t* _mask;
00352     uint8_t* _nh;
00353     uint8_t* _metric;
00354 };
00355 
00356 inline void
00357 PacketRouteEntryWriter<IPv4>::initialize(uint16_t   tag,
00358                      const IPv4Net& net,
00359                      IPv4       nh,
00360                      uint32_t   cost)
00361 {
00362     embed_16(_af, ADDR_FAMILY);
00363     embed_16(_tag, tag);
00364     net.masked_addr().copy_out(_addr);
00365     net.netmask().copy_out(_mask);
00366     nh.copy_out(_nh);
00367     embed_32(_metric, cost);
00368 }
00369 
00370 inline void
00371 PacketRouteEntryWriter<IPv4>::initialize_table_request()
00372 {
00373     embed_16(_af, ADDR_FAMILY_DUMP);
00374     embed_16(_tag, 0);
00375     IPv4::ZERO().copy_out(_addr);
00376     IPv4::ZERO().copy_out(_mask);
00377     IPv4::ZERO().copy_out(_nh);
00378     embed_32(_metric, RIP_INFINITY);
00379 }
00380 
00381 
00401 class PlaintextPacketRouteEntry4 {
00402 public:
00403     PlaintextPacketRouteEntry4(const uint8_t* data)
00404     : _data(data),
00405       _af(_data + _af_offset),
00406       _auth(_data + _auth_offset),
00407       _pw(_data + _pw_offset)
00408     {
00409     x_static_assert(PlaintextPacketRouteEntry4::SIZE == _af_sizeof
00410               + _auth_sizeof + _pw_sizeof);
00411     x_static_assert(PlaintextPacketRouteEntry4::SIZE == _pw_offset 
00412               + _pw_sizeof);
00413     }
00414 
00415     static const size_t SIZE = 20;  // The entry size
00416 
00422     static size_t size()    { return PlaintextPacketRouteEntry4::SIZE; }
00423 
00424     uint16_t addr_family() const    { return extract_16(_af); }
00425     uint16_t auth_type() const      { return extract_16(_auth); }
00426     string   password() const;
00427 
00428     static const uint16_t ADDR_FAMILY = 0xffff;
00429     static const uint16_t AUTH_TYPE = 2;
00430 
00431 protected:
00432     // Sizes of the fields
00433     static const size_t _af_sizeof  = 2;
00434     static const size_t _auth_sizeof    = 2;
00435     static const size_t _pw_sizeof  = 16;
00436 
00437     // Offsets for the fields
00438     static const size_t _af_offset  = 0;
00439     static const size_t _auth_offset    = _af_offset + _af_sizeof;
00440     static const size_t _pw_offset  = _auth_offset + _auth_sizeof;
00441 
00442 private:
00443     const uint8_t* _data;   // The buffer data
00444 
00445     // Pointers to the fields
00446     const uint8_t* _af;
00447     const uint8_t* _auth;
00448     const uint8_t* _pw;
00449 };
00450 
00451 inline string
00452 PlaintextPacketRouteEntry4::password() const
00453 {
00454     return string(reinterpret_cast<const char *>(_pw), 0, _pw_sizeof);
00455 }
00456 
00460 class PlaintextPacketRouteEntry4Writer : public PlaintextPacketRouteEntry4 {
00461 public:
00462     PlaintextPacketRouteEntry4Writer(uint8_t* data)
00463     : PlaintextPacketRouteEntry4(data),
00464       _data(data),
00465       _af(_data + _af_offset),
00466       _auth(_data + _auth_offset),
00467       _pw(_data + _pw_offset)
00468     {}
00469 
00473     void initialize(const string& s);
00474 
00475 private:
00476     uint8_t* _data;     // The buffer data
00477 
00478     // Pointers to the fields
00479     uint8_t* _af;
00480     uint8_t* _auth;
00481     uint8_t* _pw;
00482 };
00483 
00484 inline void
00485 PlaintextPacketRouteEntry4Writer::initialize(const string& s)
00486 {
00487     embed_16(_af, ADDR_FAMILY);
00488     embed_16(_auth, AUTH_TYPE);
00489     memset(_pw, 0, _pw_sizeof);
00490     s.copy(reinterpret_cast<char *>(_pw), _pw_sizeof);
00491 }
00492 
00493 
00523 class MD5PacketRouteEntry4 {
00524 public:
00525     MD5PacketRouteEntry4(const uint8_t* data)
00526     : _data(data),
00527       _af(_data + _af_offset),
00528       _auth(_data + _auth_offset),
00529       _auth_off(_data + _auth_off_offset),
00530       _key_id(_data + _key_id_offset),
00531       _auth_bytes(_data + _auth_bytes_offset),
00532       _seqno(_data + _seqno_offset),
00533       _mbz(_data + _mbz_offset)
00534     {
00535     x_static_assert(MD5PacketRouteEntry4::SIZE == _af_sizeof + _auth_sizeof
00536               + _auth_off_sizeof + _key_id_sizeof + _auth_bytes_sizeof
00537               + _seqno_sizeof + _mbz_sizeof);
00538     x_static_assert(MD5PacketRouteEntry4::SIZE == _mbz_offset + _mbz_sizeof);
00539     }
00540 
00541     static const size_t SIZE = 20;  // The entry size
00542 
00548     static size_t size()        { return MD5PacketRouteEntry4::SIZE; }
00549 
00550     uint16_t addr_family() const    { return extract_16(_af); }
00551     uint16_t auth_type() const      { return extract_16(_auth); }
00552     uint16_t auth_off() const       { return extract_16(_auth_off); }
00553     uint8_t  key_id() const     { return extract_8(_key_id); }
00554     uint8_t  auth_bytes() const     { return extract_8(_auth_bytes); }
00555     uint32_t seqno() const      { return extract_32(_seqno); }
00556 
00557     static const uint16_t ADDR_FAMILY = 0xffff;
00558     static const uint16_t AUTH_TYPE = 3;
00559 
00560 protected:
00561     // Sizes of the fields
00562     static const size_t _af_sizeof      = 2;
00563     static const size_t _auth_sizeof        = 2;
00564     static const size_t _auth_off_sizeof    = 2;
00565     static const size_t _key_id_sizeof      = 1;
00566     static const size_t _auth_bytes_sizeof  = 1;
00567     static const size_t _seqno_sizeof       = 4;
00568     static const size_t _mbz_sizeof     = 8;
00569 
00570     // Offsets for the fields
00571     static const size_t _af_offset  = 0;
00572     static const size_t _auth_offset    = _af_offset + _af_sizeof;
00573     static const size_t _auth_off_offset = _auth_offset + _auth_sizeof;
00574     static const size_t _key_id_offset  = _auth_off_offset + _auth_off_sizeof;
00575     static const size_t _auth_bytes_offset = _key_id_offset + _key_id_sizeof;
00576     static const size_t _seqno_offset = _auth_bytes_offset + _auth_bytes_sizeof;
00577     static const size_t _mbz_offset = _seqno_offset + _seqno_sizeof;
00578 
00579 private:
00580     const uint8_t* _data;   // The buffer data
00581 
00582     // Pointers to the fields
00583     const uint8_t* _af;     // 0xffff - Authentication header
00584     const uint8_t* _auth;   // Authentication type
00585     const uint8_t* _auth_off;   // Offset of authentication data
00586     const uint8_t* _key_id; // Key number used
00587     const uint8_t* _auth_bytes; // Auth data length at end of packet
00588     const uint8_t* _seqno;  // Monotonically increasing seqno
00589     const uint8_t* _mbz;    // Must-be-zero
00590 };
00591 
00595 class MD5PacketRouteEntry4Writer : public MD5PacketRouteEntry4 {
00596 public:
00597     MD5PacketRouteEntry4Writer(uint8_t* data)
00598     : MD5PacketRouteEntry4(data),
00599       _data(data),
00600       _af(_data + _af_offset),
00601       _auth(_data + _auth_offset),
00602       _auth_off(_data + _auth_off_offset),
00603       _key_id(_data + _key_id_offset),
00604       _auth_bytes(_data + _auth_bytes_offset),
00605       _seqno(_data + _seqno_offset),
00606       _mbz(_data + _mbz_offset)
00607     {}
00608 
00609     void set_auth_off(uint16_t b)   { embed_16(_auth_off, b); }
00610     void set_key_id(uint8_t id)     { embed_8(_key_id, id); }
00611     void set_auth_bytes(uint8_t b)  { embed_8(_auth_bytes, b); }
00612     void set_seqno(uint32_t sno)    { embed_32(_seqno, sno); }
00613 
00617     void initialize(uint16_t pkt_bytes,
00618             uint8_t  key_id,
00619             uint8_t  auth_bytes,
00620             uint32_t seqno);
00621 
00622 private:
00623     uint8_t* _data;     // The buffer data
00624 
00625     // Pointers to the fields
00626     uint8_t* _af;       // 0xffff - Authentication header
00627     uint8_t* _auth;     // Authentication type
00628     uint8_t* _auth_off;     // Offset of authentication data
00629     uint8_t* _key_id;       // Key number used
00630     uint8_t* _auth_bytes;   // Auth data length at end of packet
00631     uint8_t* _seqno;        // Monotonically increasing seqno
00632     uint8_t* _mbz;      // Must-be-zero
00633 };
00634 
00635 inline void
00636 MD5PacketRouteEntry4Writer::initialize(uint16_t auth_off,
00637                        uint8_t  key_id,
00638                        uint8_t  auth_bytes,
00639                        uint32_t seqno)
00640 {
00641     embed_16(_af, ADDR_FAMILY);
00642     embed_16(_auth, AUTH_TYPE);
00643     set_auth_off(auth_off);
00644     set_key_id(key_id);
00645     set_auth_bytes(auth_bytes);
00646     set_seqno(seqno);
00647     memset(_mbz, 0, _mbz_sizeof);
00648 }
00649 
00650 
00660 class MD5PacketTrailer {
00661 public:
00662     MD5PacketTrailer(const uint8_t* data)
00663     : _data(data),
00664       _af(_data + _af_offset),
00665       _one(_data + _one_offset),
00666       _auth_data(_data + _auth_data_offset)
00667     {
00668     x_static_assert(MD5PacketTrailer::SIZE == _af_sizeof + _one_sizeof
00669               + _auth_data_sizeof);
00670     x_static_assert(MD5PacketTrailer::SIZE == _auth_data_offset
00671               + _auth_data_sizeof);
00672     }
00673 
00674     static const size_t SIZE = 20;  // The trailer size
00675 
00681     static size_t size()        { return MD5PacketTrailer::SIZE; }
00682 
00683     uint16_t addr_family() const    { return extract_16(_af); }
00684     const uint8_t* auth_data() const    { return _auth_data; }
00685     uint32_t auth_data_bytes() const    { return _auth_data_sizeof; }
00686     uint32_t auth_data_offset() const   { return _auth_data_offset; }
00687     bool valid() const;
00688 
00689 protected:
00690     // Sizes of the fields
00691     static const size_t _af_sizeof      = 2;
00692     static const size_t _one_sizeof     = 2;
00693     static const size_t _auth_data_sizeof   = 16;
00694 
00695     // Offsets for the fields
00696     static const size_t _af_offset      = 0;
00697     static const size_t _one_offset     = _af_offset + _af_sizeof;
00698     static const size_t _auth_data_offset   = _one_offset + _one_sizeof;
00699 
00700 private:
00701     const uint8_t* _data;   // The buffer data
00702 
00703     // Pointers to the fields
00704     const uint8_t* _af;     // 0xffff - Authentication header
00705     const uint8_t* _one;    // 0x01   - RFC2082 defined
00706     const uint8_t* _auth_data;  // 16 bytes of data
00707 };
00708 
00709 inline bool
00710 MD5PacketTrailer::valid() const
00711 {
00712     return (addr_family() == 0xffff) && (extract_16(_one) == 1);
00713 }
00714 
00718 class MD5PacketTrailerWriter : public MD5PacketTrailer {
00719 public:
00720     MD5PacketTrailerWriter(uint8_t* data)
00721     : MD5PacketTrailer(data),
00722       _data(data),
00723       _af(_data + _af_offset),
00724       _one(_data + _one_offset),
00725       _auth_data(_data + _auth_data_offset)
00726     {}
00727 
00731     void initialize();
00732 
00733     uint8_t* auth_data()    { return _auth_data; }
00734 
00735 private:
00736     uint8_t* _data;     // The buffer data
00737 
00738     // Pointers to the fields
00739     uint8_t* _af;       // 0xffff - Authentication header
00740     uint8_t* _one;      // 0x01   - RFC2082 defined
00741     uint8_t* _auth_data;    // 16 bytes of data
00742 };
00743 
00744 inline void
00745 MD5PacketTrailerWriter::initialize()
00746 {
00747     embed_16(_af, 0xffff);
00748     embed_16(_one, 1);
00749 }
00750 
00751 
00767 template <>
00768 class PacketRouteEntry<IPv6> {
00769 public:
00770     PacketRouteEntry(const uint8_t* data)
00771     : _data(data),
00772       _prefix(_data + _prefix_offset),
00773       _tag(_data + _tag_offset),
00774       _prefix_len(_data + _prefix_len_offset),
00775       _metric(_data + _metric_offset)
00776     {
00777     x_static_assert(PacketRouteEntry<IPv6>::SIZE == _prefix_sizeof
00778               + _tag_sizeof + _prefix_len_sizeof + _metric_sizeof);
00779     x_static_assert(PacketRouteEntry<IPv6>::SIZE == _metric_offset
00780               + _metric_sizeof);
00781     }
00782 
00783     static const size_t SIZE = 20;  // The entry size
00784 
00790     static size_t size()    { return PacketRouteEntry<IPv6>::SIZE; }
00791 
00792     bool        is_nexthop() const;
00793 
00797     bool        is_table_request() const;
00798 
00799     IPv6        nexthop() const;
00800 
00801     uint16_t tag() const;
00802     uint32_t prefix_len() const { return extract_8(_prefix_len); }
00803     IPv6Net  net() const;
00804     uint8_t  metric() const;
00805 
00806     static const uint8_t NEXTHOP_METRIC = 0xff;
00807 
00808 
00809 protected:
00810     // Sizes of the fields
00811     static const size_t _prefix_sizeof      = 16;
00812     static const size_t _tag_sizeof     = 2;
00813     static const size_t _prefix_len_sizeof  = 1;
00814     static const size_t _metric_sizeof      = 1;
00815 
00816     // Offsets for the fields
00817     static const size_t _prefix_offset  = 0;
00818     static const size_t _tag_offset = _prefix_offset + _prefix_sizeof;
00819     static const size_t _prefix_len_offset = _tag_offset + _tag_sizeof;
00820     static const size_t _metric_offset  = _prefix_len_offset + _prefix_len_sizeof;
00821 
00822 private:
00823     const uint8_t* _data;   // The buffer data
00824 
00825     // Pointers to the fields
00826     const uint8_t* _prefix;
00827     const uint8_t* _tag;
00828     const uint8_t* _prefix_len;
00829     const uint8_t* _metric;
00830 };
00831 
00832 inline bool
00833 PacketRouteEntry<IPv6>::is_nexthop() const
00834 {
00835     return metric() == NEXTHOP_METRIC;
00836 }
00837 
00838 inline IPv6
00839 PacketRouteEntry<IPv6>::nexthop() const
00840 {
00841     return IPv6(_prefix);
00842 }
00843 
00844 inline uint16_t
00845 PacketRouteEntry<IPv6>::tag() const
00846 {
00847     return extract_16(_tag);
00848 }
00849 
00850 inline IPv6Net
00851 PacketRouteEntry<IPv6>::net() const
00852 {
00853     return IPv6Net(IPv6(_prefix), prefix_len());
00854 }
00855 
00856 inline uint8_t
00857 PacketRouteEntry<IPv6>::metric() const
00858 {
00859     return extract_8(_metric);
00860 }
00861 
00862 inline bool
00863 PacketRouteEntry<IPv6>::is_table_request() const
00864 {
00865     if (metric() != RIP_INFINITY) {
00866     return false;
00867     }
00868     if (prefix_len() != 0) {
00869     return false;
00870     }
00871     IPv6 addr(_prefix);
00872     return (addr.is_zero());
00873 }
00874 
00875 /*
00876  * @short Class for writing data to RIP IPv6 route entry.
00877  */
00878 template <>
00879 class PacketRouteEntryWriter<IPv6> : public PacketRouteEntry<IPv6> {
00880 public:
00881     PacketRouteEntryWriter(uint8_t* data)
00882     : PacketRouteEntry<IPv6>(data),
00883       _data(data),
00884       _prefix(_data + _prefix_offset),
00885       _tag(_data + _tag_offset),
00886       _prefix_len(_data + _prefix_len_offset),
00887       _metric(_data + _metric_offset)
00888     {}
00889 
00893     void        initialize_route(uint16_t       route_tag,
00894                      const IPv6Net& net,
00895                      uint8_t        cost);
00896 
00900     void        initialize_nexthop(const IPv6& nexthop);
00901 
00905     void        initialize_table_request();
00906 
00907 private:
00908     uint8_t* _data;     // The buffer data
00909 
00910     // Pointers to the fields
00911     uint8_t* _prefix;
00912     uint8_t* _tag;
00913     uint8_t* _prefix_len;
00914     uint8_t* _metric;
00915 };
00916 
00917 inline void
00918 PacketRouteEntryWriter<IPv6>::initialize_route(uint16_t     tag,
00919                            const IPv6Net&   net,
00920                            uint8_t      cost)
00921 {
00922     net.masked_addr().copy_out(_prefix);
00923     embed_16(_tag, tag);
00924     embed_8(_prefix_len, net.prefix_len());
00925     embed_8(_metric, cost);
00926 }
00927 
00928 inline void
00929 PacketRouteEntryWriter<IPv6>::initialize_nexthop(const IPv6& nexthop)
00930 {
00931     nexthop.copy_out(_prefix);
00932     embed_16(_tag, 0);
00933     embed_8(_prefix_len, 0);
00934     embed_8(_metric, NEXTHOP_METRIC);
00935 }
00936 
00937 inline void
00938 PacketRouteEntryWriter<IPv6>::initialize_table_request()
00939 {
00940     IPv6::ZERO().copy_out(_prefix);
00941     embed_16(_tag, 0);
00942     embed_8(_prefix_len, 0);
00943     embed_8(_metric, RIP_INFINITY);
00944 }
00945 
00946 
00952 template <typename A>
00953 class RipPacket {
00954 public:
00955     typedef A Addr;
00956 
00960     const Addr& address() const { return _addr; }
00961 
00965     uint16_t    port() const    { return _port; }
00966 
00970     uint32_t    max_entries() const { return _max_entries; }
00971 
00978     void    set_max_entries(uint32_t max_entries);
00979 
00980     RipPacket(const Addr& addr,
00981           uint16_t    port,
00982           uint32_t    max_entries = RIPv2_ROUTES_PER_PACKET)
00983     : _addr(addr), _port(port), _max_entries(0)
00984     {
00985     set_max_entries(max_entries);
00986     }
00987 
00991     const uint8_t* header_ptr() const;
00992 
00996     uint8_t* header_ptr();
00997 
01005     const uint8_t* route_entry_ptr(uint32_t entry_no) const;
01006 
01014     uint8_t* route_entry_ptr(uint32_t entry_no);
01015 
01016     void append_data(const uint8_t* data, uint32_t data_bytes);
01017     void append_data(const vector<uint8_t>& data);
01018 
01019     vector<uint8_t>&      data()        { return _data; }
01020     const vector<uint8_t>& data() const     { return _data; }
01021     uint32_t          data_bytes() const    { return _data.size(); }
01022     const uint8_t*    data_ptr() const  { return base_ptr(); }
01023     uint8_t*          data_ptr()        { return base_ptr(); }
01024 
01025 private:
01026     Addr        _addr;  // Src addr on inbound, dst address on outbound
01027     uint16_t        _port;  // Src port on inbound, dst port on outbound
01028     vector<uint8_t> _data;  // Data buffer
01029     uint32_t _max_entries;  // Maximum number of route entries in packet
01030 
01031     const uint8_t* base_ptr() const { return &(_data[0]); }
01032     uint8_t* base_ptr()         { return &(_data[0]); }
01033 };
01034 
01035 template <typename A>
01036 const uint8_t*
01037 RipPacket<A>::header_ptr() const
01038 {
01039     return (base_ptr());
01040 }
01041 
01042 template <typename A>
01043 uint8_t*
01044 RipPacket<A>::header_ptr()
01045 {
01046     return (base_ptr());
01047 }
01048 
01049 template <typename A>
01050 const uint8_t*
01051 RipPacket<A>::route_entry_ptr(uint32_t entry_no) const
01052 {
01053     if (entry_no >= _max_entries)
01054     return NULL;
01055 
01056     const uint8_t* p = base_ptr() + RipPacketHeader::size() +
01057     entry_no * PacketRouteEntry<A>::size();
01058     return p;
01059 }
01060 
01061 template <typename A>
01062 uint8_t*
01063 RipPacket<A>::route_entry_ptr(uint32_t entry_no)
01064 {
01065     if (entry_no >= _max_entries)
01066     return NULL;
01067 
01068     uint8_t* p = base_ptr() + RipPacketHeader::size() +
01069     entry_no * PacketRouteEntry<A>::size();
01070     return p;
01071 }
01072 
01073 template <typename A>
01074 void
01075 RipPacket<A>::append_data(const uint8_t* data, uint32_t data_bytes)
01076 {
01077     _data.insert(_data.end(), data, data + data_bytes);
01078 }
01079 
01080 template <typename A>
01081 void
01082 RipPacket<A>::append_data(const vector<uint8_t>& data)
01083 {
01084     _data.insert(_data.end(), data.begin(), data.end());
01085 }
01086 
01087 template <typename A>
01088 void
01089 RipPacket<A>::set_max_entries(uint32_t max_entries)
01090 {
01091     if (max_entries != _max_entries) {
01092     _data.resize(PacketRouteEntry<A>::size() * max_entries
01093              + RipPacketHeader::size());
01094     _max_entries = max_entries;
01095     }
01096 }
01097 
01098 #endif // __RIP_PACKETS_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations