Source: ../../libproto/packet.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2009 XORP, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License, Version
// 2.1, June 1999 as published by the Free Software Foundation.
// Redistribution and/or modification of this program under the terms of
// any other version of the GNU Lesser General Public License is not
// permitted.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
// see the GNU Lesser General Public License, Version 2.1, a copy of
// which can be found in the XORP LICENSE.lgpl file.
//
// XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net
// $XORP: xorp/libproto/packet.hh,v 1.23 2009/01/05 18:30:55 jtc Exp $
#ifndef __LIBPROTO_PACKET_HH__
#define __LIBPROTO_PACKET_HH__
#include "libxorp/xorp.h"
#include "libxorp/ipv4.hh"
#include "libxorp/ipv6.hh"
#include "libxorp/mac.hh"
//
// Network protocols related constants
//
#ifndef ETHERTYPE_IP
#define ETHERTYPE_IP 0x0800 // IP protocol
#endif
#ifndef ETHERTYPE_ARP
#define ETHERTYPE_ARP 0x0806 // Address Resolution Protocol
#endif
#ifndef IPPROTO_VRRP
#define IPPROTO_VRRP 112 // Virtual Router Redundancy Protocol
#endif
/**
* Extract an 8-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer with the data.
* @return an 8-bit number from the beginning of a buffer.
*/
inline
uint8_t
extract_8(const uint8_t *ptr)
{
uint8_t val;
val = ptr[0];
return val;
}
/**
* Embed an 8-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer to store the data.
* @param val the 8-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_8(uint8_t *ptr, uint8_t val)
{
ptr[0] = val;
}
/**
* Extract a 16-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer with the data.
* @return a 16-bit number from the beginning of a buffer.
*/
inline
uint16_t
extract_16(const uint8_t *ptr)
{
uint16_t val;
val = ptr[0];
val <<= 8;
val |= ptr[1];
return val;
}
/**
* Embed a 16-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer to store the data.
* @param val the 16-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_16(uint8_t *ptr, uint16_t val)
{
ptr[0] = (val >> 8) & 0xff;
ptr[1] = val & 0xff;
}
/**
* Extract a 24-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer with the data.
* @return a 24-bit number from the beginning of a buffer.
*/
inline
uint32_t
extract_24(const uint8_t *ptr)
{
uint32_t val;
val = ptr[0];
val <<= 8;
val |= ptr[1];
val <<= 8;
val |= ptr[2];
return val;
}
/**
* Embed a 24-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer to store the data.
* @param val the 24-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_24(uint8_t *ptr, uint32_t val)
{
ptr[0] = (val >> 16) & 0xff;
ptr[1] = (val >> 8) & 0xff;
ptr[2] = val & 0xff;
}
/**
* Extract a 32-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer with the data.
* @return a 32-bit number from the beginning of a buffer.
*/
inline
uint32_t
extract_32(const uint8_t *ptr)
{
uint32_t val;
val = ptr[0];
val <<= 8;
val |= ptr[1];
val <<= 8;
val |= ptr[2];
val <<= 8;
val |= ptr[3];
return val;
}
/**
* Embed a 32-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in network order.
*
* @param ptr the buffer to store the data.
* @param val the 32-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_32(uint8_t *ptr, uint32_t val)
{
ptr[0] = (val >> 24) & 0xff;
ptr[1] = (val >> 16) & 0xff;
ptr[2] = (val >> 8) & 0xff;
ptr[3] = val & 0xff;
}
/**
* Extract an 8-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer with the data.
* @return an 8-bit number from the beginning of a buffer.
*/
inline
uint8_t
extract_host_8(const uint8_t *ptr)
{
uint8_t val;
val = ptr[0];
return val;
}
/**
* Embed an 8-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer to store the data.
* @param val the 8-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_host_8(uint8_t *ptr, uint8_t val)
{
ptr[0] = val;
}
/**
* Extract a 16-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer with the data.
* @return a 16-bit number from the beginning of a buffer.
*/
inline
uint16_t
extract_host_16(const uint8_t *ptr)
{
union {
uint16_t val;
uint8_t c[sizeof(uint16_t)];
} u;
u.c[0] = ptr[0];
u.c[1] = ptr[1];
return u.val;
}
/**
* Embed a 16-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer to store the data.
* @param val the 16-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_host_16(uint8_t *ptr, uint16_t val)
{
union {
uint16_t val;
uint8_t c[sizeof(uint16_t)];
} u;
u.val = val;
ptr[0] = u.c[0];
ptr[1] = u.c[1];
}
/*
* XXX: Note that we don't define extract_host_24() and embed_host_24(),
* because 3 octets of data might occupy either 3 or 4 octets (depending
* on the byte ordering). Hence, extract_host_32() and embed_host_32()
* should be used instead.
*/
/**
* Extract a 32-bit number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer with the data.
* @return a 32-bit number from the beginning of a buffer.
*/
inline
uint32_t
extract_host_32(const uint8_t *ptr)
{
union {
uint32_t val;
uint8_t c[sizeof(uint32_t)];
} u;
u.c[0] = ptr[0];
u.c[1] = ptr[1];
u.c[2] = ptr[2];
u.c[3] = ptr[3];
return u.val;
}
/**
* Embed a 32-bit number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer to store the data.
* @param val the 32-bit value to embed into the beginning of the buffer.
*/
inline
void
embed_host_32(uint8_t *ptr, uint32_t val)
{
union {
uint32_t val;
uint8_t c[sizeof(uint32_t)];
} u;
u.val = val;
ptr[0] = u.c[0];
ptr[1] = u.c[1];
ptr[2] = u.c[2];
ptr[3] = u.c[3];
}
/**
* Extract an integer number from the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer with the data.
* @return an integer number from the beginning of a buffer.
*/
inline
int
extract_host_int(const uint8_t *ptr)
{
union {
int val;
uint8_t c[sizeof(int)];
} u;
for (size_t i = 0; i < sizeof(int); i++) {
u.c[i] = ptr[i];
}
return u.val;
}
/**
* Embed an integer number into the beginning of a buffer.
*
* Note that the integers in the buffer are stored in host order.
*
* @param ptr the buffer to store the data.
* @param val the integer value to embed into the beginning of the buffer.
*/
inline
void
embed_host_int(uint8_t *ptr, int val)
{
union {
int val;
uint8_t c[sizeof(int)];
} u;
u.val = val;
for (size_t i = 0; i < sizeof(int); i++) {
ptr[i] = u.c[i];
}
}
/**
* @short IPv4 packet header.
*
* The IPv4 packet header has the following content:
*
* ip_vhl (1 byte): // IP ver/hdrlen (version << 4 | header length >> 2)
* ip_tos (1 byte): // Type of service
* ip_len (2 bytes): // Total length
* ip_id (2 bytes): // Identification
* ip_off (2 bytes): // Fragment offset field (least-significant 13 bits)
* ip_ttl (1 byte): // Time to live
* ip_p (1 byte): // Protocol
* ip_sum (2 bytes): // Checksum
* ip_src (4 bytes): // Source address
* ip_dst (4 bytes): // Destination address
*/
class IpHeader4 {
public:
IpHeader4(const uint8_t* data)
: _data(data),
_ip_vhl(_data + _ip_vhl_offset),
_ip_tos(_data + _ip_tos_offset),
_ip_len(_data + _ip_len_offset),
_ip_id(_data + _ip_id_offset),
_ip_off(_data + _ip_off_offset),
_ip_ttl(_data + _ip_ttl_offset),
_ip_p(_data + _ip_p_offset),
_ip_sum(_data + _ip_sum_offset),
_ip_src(_data + _ip_src_offset),
_ip_dst(_data + _ip_dst_offset)
{
static_assert(IpHeader4::SIZE == _ip_vhl_sizeof + _ip_tos_sizeof
+ _ip_len_sizeof + _ip_id_sizeof + _ip_off_sizeof
+ _ip_ttl_sizeof + _ip_p_sizeof + _ip_sum_sizeof
+ _ip_src_sizeof + _ip_dst_sizeof);
static_assert(IpHeader4::SIZE == _ip_dst_offset + _ip_dst_sizeof);
}
static const size_t SIZE = 20; // The header size
static const uint8_t IP_VERSION = 4; // IPv4 version
/**
* Get the IPv4 packet header size.
*
* Note that this is the header size only without any header options.
*
* @return the IPv4 packet header size.
*/
static size_t size() { return IpHeader4::SIZE; }
/**
* Get the buffer data.
*
* @return the buffer data.
*/
const uint8_t* data() const { return (_data); }
/**
* Methods to get various IP header fields.
*/
uint8_t ip_vhl() const { return extract_8(_ip_vhl); }
uint8_t ip_tos() const { return extract_8(_ip_tos); }
uint16_t ip_len() const { return extract_16(_ip_len); }
uint16_t ip_id() const { return extract_16(_ip_id); }
uint16_t ip_off() const { return extract_16(_ip_off); }
uint8_t ip_ttl() const { return extract_8(_ip_ttl); }
uint8_t ip_p() const { return extract_8(_ip_p); }
uint16_t ip_sum() const { return extract_16(_ip_sum); }
IPv4 ip_src() const { return IPv4(_ip_src); }
IPv4 ip_dst() const { return IPv4(_ip_dst); }
/*
* A method to extract the ip_len value that is presumably stored
* in host order.
*
* @return the ip_len value that is presumably stored in host order.
*/
uint16_t ip_len_host() const{ return extract_host_16(_ip_len); }
/**
* Get the IP protocol version of the header.
*
* @return the IP protocol version of the header.
*/
uint8_t ip_version() const {
uint8_t v = ip_vhl();
return ((v >> 4) & 0x0f);
}
/**
* Get the IPv4 packet header size (including any header options).
*
* @return the IPv4 packet header size (including any header options).
*/
uint8_t ip_header_len() const { return ((ip_vhl() & 0x0f) << 2); }
/**
* Get the IPv4 fragment offset (excluding the fragment flags).
*
* @return the IPv4 fragment offset (excluding the fragment flags).
*/
uint16_t ip_fragment_offset() const {
return (ip_off() & IpHeader4::FRAGMENT_OFFSET_MASK);
}
/**
* Get the IPv4 fragment flags.
*
* @return the IPv4 fragment flags.
*/
uint16_t ip_fragment_flags() const {
return (ip_off() & IpHeader4::FRAGMENT_FLAGS_MASK);
}
/**
* Test whether the IP header version is valid.
*
* @return true if the IP header version is valid, otherwise false.
*/
bool is_valid_version() const {
return (ip_version() == IpHeader4::IP_VERSION);
}
/**
* Fragment an IPv4 packet.
*
* Note: If the original packet is not larger than the MTU, then the packet
* is not fragmented (i.e., @ref fragments is empty), and the return
* value is XORP_OK.
*
* @param mtu the MTU for fragmenting the packet.
* @param fragments the return-by-reference fragments of the IPv4 packet.
* @param do_checksum if true, compute and set the checksum in the IPv4
* header, otherwise reset it to zero.
* @param error_msg the error message (if error).
* @return XORP_OK on success, otherwise XORP_ERROR.
*/
int fragment(size_t mtu, list<vector<uint8_t> >& fragments,
bool do_checksum, string& error_msg) const;
protected:
// IPv4 header related constants
static const uint16_t FRAGMENT_OFFSET_MASK = 0x1fff;
static const uint16_t FRAGMENT_FLAGS_MASK = 0xe000;
static const uint16_t FRAGMENT_FLAGS_IP_DF = 0x4000; // Don't fragment
static const uint16_t FRAGMENT_FLAGS_IP_MF = 0x2000; // More fragments
static const uint8_t OPTIONS_IPOPT_EOL = 0; // End of option list
static const uint8_t OPTIONS_IPOPT_NOP = 1; // No operation
static const size_t OPTIONS_IPOPT_OLEN = 1; // Option length offset
static const uint8_t OPTIONS_COPIED_FLAG = 0x80; // Option copied flag
// Sizes of the fields
static const size_t _ip_vhl_sizeof = 1;
static const size_t _ip_tos_sizeof = 1;
static const size_t _ip_len_sizeof = 2;
static const size_t _ip_id_sizeof = 2;
static const size_t _ip_off_sizeof = 2;
static const size_t _ip_ttl_sizeof = 1;
static const size_t _ip_p_sizeof = 1;
static const size_t _ip_sum_sizeof = 2;
static const size_t _ip_src_sizeof = 4;
static const size_t _ip_dst_sizeof = 4;
// Offsets for the fields
static const size_t _ip_vhl_offset = 0;
static const size_t _ip_tos_offset = _ip_vhl_offset + _ip_vhl_sizeof;
static const size_t _ip_len_offset = _ip_tos_offset + _ip_tos_sizeof;
static const size_t _ip_id_offset = _ip_len_offset + _ip_len_sizeof;
static const size_t _ip_off_offset = _ip_id_offset + _ip_id_sizeof;
static const size_t _ip_ttl_offset = _ip_off_offset + _ip_off_sizeof;
static const size_t _ip_p_offset = _ip_ttl_offset + _ip_ttl_sizeof;
static const size_t _ip_sum_offset = _ip_p_offset + _ip_p_sizeof;
static const size_t _ip_src_offset = _ip_sum_offset + _ip_sum_sizeof;
static const size_t _ip_dst_offset = _ip_src_offset + _ip_src_sizeof;
private:
const uint8_t* _data; // The buffer data
// Pointers to the fields
const uint8_t* _ip_vhl; // IP version and header length
const uint8_t* _ip_tos; // Type of service
const uint8_t* _ip_len; // Total length
const uint8_t* _ip_id; // Identification
const uint8_t* _ip_off; // Fragment offset field
const uint8_t* _ip_ttl; // Time to live
const uint8_t* _ip_p; // Protocol
const uint8_t* _ip_sum; // Checksum
const uint8_t* _ip_src; // Source address
const uint8_t* _ip_dst; // Destination address
};
/**
* @short Class for writing data to IPv4 packet header.
*/
class IpHeader4Writer : public IpHeader4 {
public:
IpHeader4Writer(uint8_t* data)
: IpHeader4(data),
_data(data),
_ip_vhl(_data + _ip_vhl_offset),
_ip_tos(_data + _ip_tos_offset),
_ip_len(_data + _ip_len_offset),
_ip_id(_data + _ip_id_offset),
_ip_off(_data + _ip_off_offset),
_ip_ttl(_data + _ip_ttl_offset),
_ip_p(_data + _ip_p_offset),
_ip_sum(_data + _ip_sum_offset),
_ip_src(_data + _ip_src_offset),
_ip_dst(_data + _ip_dst_offset)
{}
/**
* Get the buffer data.
*
* @return the buffer data.
*/
uint8_t* data() { return (_data); }
/**
* Methods to set various IP header fields.
*/
void set_ip_vhl(uint8_t v) { embed_8(_ip_vhl, v); }
void set_ip_tos(uint8_t v) { embed_8(_ip_tos, v); }
void set_ip_len(uint16_t v) { embed_16(_ip_len, v); }
void set_ip_id(uint16_t v) { embed_16(_ip_id, v); }
void set_ip_off(uint16_t v) { embed_16(_ip_off, v); }
void set_ip_ttl(uint8_t v) { embed_8(_ip_ttl, v); }
void set_ip_p(uint8_t v) { embed_8(_ip_p, v); }
void set_ip_sum(uint16_t v) { embed_16(_ip_sum, v); }
void set_ip_src(const IPv4& v) { v.copy_out(_ip_src); }
void set_ip_dst(const IPv4& v) { v.copy_out(_ip_dst); }
/**
* A method to compute and set the IP checksum.
*/
void compute_checksum();
/*
* A method to embed the ip_len value by storing it in host order.
*
* @param v the ip_len value that will be stored in host order.
*/
void set_ip_len_host(uint16_t v) { embed_host_16(_ip_len, v); }
/**
* Set the IP protocol version of the header.
*
* @param v the IP protocol version of the header.
*/
void set_ip_version(uint8_t v) {
uint8_t vhl = ((v << 4) | (ip_header_len() >> 2));
set_ip_vhl(vhl);
}
/**
* Set the IPv4 packet header size (including any header options).
*
* @param v the IPv4 packet header size (including any header options).
*/
void set_ip_header_len(uint8_t v) {
uint8_t vhl = ((ip_version() << 4) | (v >> 2));
set_ip_vhl(vhl);
}
/**
* Set the IPv4 fragment offset (excluding the fragment flags).
*
* @param v the IPv4 fragment offset (excluding the fragment flags).
*/
void set_ip_fragment_offset(uint16_t v) {
uint16_t off = v & IpHeader4::FRAGMENT_OFFSET_MASK;
off |= ip_fragment_flags();
set_ip_off(off);
}
/**
* Set the IPv4 fragment flags.
*
* @param v the IPv4 fragment flags.
*/
void set_ip_fragment_flags(uint16_t v) {
uint16_t off = v & IpHeader4::FRAGMENT_FLAGS_MASK;
off |= ip_fragment_offset();
set_ip_off(off);
}
private:
uint8_t* _data; // The buffer data
// Pointers to the fields
uint8_t* _ip_vhl; // IP version and header length
uint8_t* _ip_tos; // Type of service
uint8_t* _ip_len; // Total length
uint8_t* _ip_id; // Identification
uint8_t* _ip_off; // Fragment offset field
uint8_t* _ip_ttl; // Time to live
uint8_t* _ip_p; // Protocol
uint8_t* _ip_sum; // Checksum
uint8_t* _ip_src; // Source address
uint8_t* _ip_dst; // Destination address
};
/**
* @short IPv6 packet header.
*
* The IPv6 packet header has the following content:
*
* ip_vtc_flow (4 bytes): // 4 bits vers., 8 bits traf. class, 20 bits flow-ID
* ip_plen (2 bytes): // Payload length
* ip_nxt (1 byte): // Next header
* ip_hlim (1 byte): // Hop limit
* ip_src (16 bytes): // Source address
* ip_dst (16 bytes): // Destination address
*/
class IpHeader6 {
public:
IpHeader6(const uint8_t* data)
: _data(data),
_ip_vtc_flow(_data + _ip_vtc_flow_offset),
_ip_plen(_data + _ip_plen_offset),
_ip_nxt(_data + _ip_nxt_offset),
_ip_hlim(_data + _ip_hlim_offset),
_ip_src(_data + _ip_src_offset),
_ip_dst(_data + _ip_dst_offset)
{
static_assert(IpHeader6::SIZE == _ip_vtc_flow_sizeof
+ _ip_plen_sizeof + _ip_nxt_sizeof + _ip_hlim_sizeof
+ _ip_src_sizeof + _ip_dst_sizeof);
static_assert(IpHeader6::SIZE == _ip_dst_offset + _ip_dst_sizeof);
}
static const size_t SIZE = 40; // The header size
static const uint8_t IP_VERSION = 6; // IPv6 version
/**
* Get the IPv6 packet header size.
*
* Note that this is the header size only without any extention headers.
*
* @return the IPv6 packet header size.
*/
static size_t size() { return IpHeader6::SIZE; }
/**
* Get the buffer data.
*
* @return the buffer data.
*/
const uint8_t* data() const { return (_data); }
/**
* Methods to get various IP header fields.
*/
uint32_t ip_vtc_flow() const { return extract_32(_ip_vtc_flow); }
uint16_t ip_plen() const { return extract_16(_ip_plen); }
uint8_t ip_nxt() const { return extract_8(_ip_nxt); }
uint8_t ip_hlim() const { return extract_8(_ip_hlim); }
IPv6 ip_src() const { return IPv6(_ip_src); }
IPv6 ip_dst() const { return IPv6(_ip_dst); }
/**
* Get the IP protocol version of the header.
*
* @return the IP protocol version of the header.
*/
uint8_t ip_version() const {
uint32_t v = ip_vtc_flow() & IpHeader6::VERSION_MASK;
return ((v >> IpHeader6::VERSION_SHIFT) & 0x0f);
}
/**
* Get the IPv6 traffic class.
*
* @return the IPv6 traffic class.
*/
uint8_t ip_traffic_class() const {
uint32_t tc = ip_vtc_flow() & IpHeader6::TRAFFIC_CLASS_MASK;
return ((tc >> IpHeader6::TRAFFIC_CLASS_SHIFT) & 0xff);
}
/**
* Get the IPv6 flow label.
*
* @return the IPv6 flow label.
*/
uint32_t ip_flow_label() const {
uint32_t flow = ip_vtc_flow() & IpHeader6::FLOW_LABEL_MASK;
return (flow >> IpHeader6::FLOW_LABEL_SHIFT);
}
/**
* Test whether the IP header version is valid.
*
* @return true if the IP header version is valid, otherwise false.
*/
bool is_valid_version() const {
return (ip_version() == IpHeader6::IP_VERSION);
}
protected:
static const uint32_t VERSION_MASK = 0xf0000000;
static const uint32_t TRAFFIC_CLASS_MASK = 0x0ff00000;
static const uint32_t FLOW_LABEL_MASK = 0x000fffff;
static const size_t VERSION_SHIFT = 28;
static const size_t TRAFFIC_CLASS_SHIFT = 20;
static const size_t FLOW_LABEL_SHIFT = 0;
// Sizes of the fields
static const size_t _ip_vtc_flow_sizeof = 4;
static const size_t _ip_plen_sizeof = 2;
static const size_t _ip_nxt_sizeof = 1;
static const size_t _ip_hlim_sizeof = 1;
static const size_t _ip_src_sizeof = 16;
static const size_t _ip_dst_sizeof = 16;
// Offsets for the fields
static const size_t _ip_vtc_flow_offset = 0;
static const size_t _ip_plen_offset = _ip_vtc_flow_offset + _ip_vtc_flow_sizeof;
static const size_t _ip_nxt_offset = _ip_plen_offset + _ip_plen_sizeof;
static const size_t _ip_hlim_offset = _ip_nxt_offset + _ip_nxt_sizeof;
static const size_t _ip_src_offset = _ip_hlim_offset + _ip_hlim_sizeof;
static const size_t _ip_dst_offset = _ip_src_offset + _ip_src_sizeof;
private:
const uint8_t* _data; // The buffer data
// Pointers to the fields
const uint8_t* _ip_vtc_flow; // IP version, traffic class and flow label
const uint8_t* _ip_plen; // Payload length
const uint8_t* _ip_nxt; // Next header
const uint8_t* _ip_hlim; // Hop limit
const uint8_t* _ip_src; // Source address
const uint8_t* _ip_dst; // Destination address
};
/**
* @short Class for writing data to IPv6 packet header.
*/
class IpHeader6Writer : public IpHeader6 {
public:
IpHeader6Writer(uint8_t* data)
: IpHeader6(data),
_data(data),
_ip_vtc_flow(_data + _ip_vtc_flow_offset),
_ip_plen(_data + _ip_plen_offset),
_ip_nxt(_data + _ip_nxt_offset),
_ip_hlim(_data + _ip_hlim_offset),
_ip_src(_data + _ip_src_offset),
_ip_dst(_data + _ip_dst_offset)
{}
/**
* Get the buffer data.
*
* @return the buffer data.
*/
uint8_t* data() { return (_data); }
/**
* Methods to set various IP header fields.
*/
void set_ip_vtc_flow(uint32_t v) { embed_32(_ip_vtc_flow, v); }
void set_ip_plen(uint16_t v) { embed_16(_ip_plen, v); }
void set_ip_nxt(uint8_t v) { embed_8(_ip_nxt, v); }
void set_ip_hlim(uint8_t v) { embed_8(_ip_hlim, v); }
void set_ip_src(const IPv6& v) { v.copy_out(_ip_src); }
void set_ip_dst(const IPv6& v) { v.copy_out(_ip_dst); }
/**
* Set the IP protocol version of the header.
*
* @param v the IP protocol version of the header.
*/
void set_ip_version(uint8_t v) {
uint32_t vtc_flow = ip_vtc_flow() & ~IpHeader6::VERSION_MASK;
uint32_t shifted_v = v;
shifted_v <<= IpHeader6::VERSION_SHIFT;
vtc_flow |= shifted_v;
set_ip_vtc_flow(vtc_flow);
}
/**
* Set the IPv6 traffic class.
*
* @param v the IPv6 traffic class.
*/
void set_ip_traffic_class(uint8_t v) {
uint32_t vtc_flow = ip_vtc_flow() & ~IpHeader6::TRAFFIC_CLASS_MASK;
uint32_t shifted_v = v;
shifted_v <<= IpHeader6::TRAFFIC_CLASS_SHIFT;
vtc_flow |= shifted_v;
set_ip_vtc_flow(vtc_flow);
}
/**
* Set the IPv6 flow label.
*
* @param v the IPv6 flow label.
*/
void set_ip_flow_label(uint32_t v) {
uint32_t vtc_flow = ip_vtc_flow() & ~IpHeader6::FLOW_LABEL_MASK;
uint32_t shifted_v = v;
shifted_v <<= IpHeader6::FLOW_LABEL_SHIFT;
vtc_flow |= shifted_v;
set_ip_vtc_flow(vtc_flow);
}
private:
uint8_t* _data; // The buffer data
// Pointers to the fields
uint8_t* _ip_vtc_flow; // IP version, traffic class and flow label
uint8_t* _ip_plen; // Payload length
uint8_t* _ip_nxt; // Next header
uint8_t* _ip_hlim; // Hop limit
uint8_t* _ip_src; // Source address
uint8_t* _ip_dst; // Destination address
};
/**
* @short Exception thrown when parsing malformed packets.
*/
class BadPacketException : public XorpReasonedException {
public:
BadPacketException(const char* file, size_t line, const string& why = "")
: XorpReasonedException("BadPacketException", file, line, why) {}
};
/**
* @short an ARP packet.
*/
struct ArpHeader {
typedef vector<uint8_t> PAYLOAD;
enum Op {
ARP_REQUEST = 1,
ARP_REPLY
};
enum HwFmt {
HW_ETHER = 1
};
/**
* Create an ARP packet. The caller must allocate memory and ensure enough
* space (sizeof(ArpHeader) + (2 hw addresses) + (2 network addresses)).
*
* @return the ARP header.
* @param data pointer where data should be stored.
*/
static ArpHeader& assign(uint8_t* data);
/**
* Parse an ARP packet.
*
* @return the ARP header.
* @param payload the ARP header and data.
*/
static const ArpHeader& assign(const PAYLOAD& payload);
/**
* Create a gratuitous ARP. I.e., an ARP request for my own IP address -
* the one used in the source section of the ARP packet.
*
* @param output data (output argument).
* @param MAC address of IP.
* @param ip IP address to create request for.
*/
static void make_gratuitous(PAYLOAD& payload, const Mac& mac,
const IPv4& ip);
/**
* Set the sender information in the ARP packet.
*
* @param mac source MAC address.
* @param ip source IP address.
*/
void set_sender(const Mac& mac, const IPv4& ip);
/**
* Create an ARP request for an IP address.
*
* @param ip IP address to ask request for.
*/
void set_request(const IPv4& ip);
/**
* Create an ARP reply.
*
* @param mac MAC address of requested IP address.
* @param ip IP address requested in the ARP request.
*/
void set_reply(const Mac& mac, const IPv4& ip);
/**
* The size of the ARP packet (ARP header + data).
*
* @return the size of the ARP packet.
*/
uint32_t size() const;
/**
* Determine whether it is an ARP request. This (usually) implies whether
* or not it is an ARP reply.
*
* @return true if it is an ARP request.
*/
bool is_request() const;
/**
* If an ARP request, return the IP address that is being asked for.
*
* @return the IP address being asked for.
*/
IPv4 get_request() const;
/**
* If this is an ARP request, create an ARP reply with the give MAC address.
*
* @param out the ARP reply data (output parameter).
* @param mac the MAC address of the requested IP address.
*/
void make_reply(PAYLOAD& out, const Mac& mac) const;
uint16_t ah_hw_fmt;
uint16_t ah_proto_fmt;
uint8_t ah_hw_len;
uint8_t ah_proto_len;
uint16_t ah_op;
uint8_t ah_data[0];
};
#endif // __LIBPROTO_PACKET_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:10:46 2009, using kdoc 2.0a54+XORP.