+3XX. [func] tomek
+ libdhcp++: Option6 and Pkt6 now follow the same design as
+ options and packet for DHCPv4. General code refactoring after
+ end of 2011 year release.
+ (Trac #1540, git TBD)
+
359. [bug] kevin
Corrected SOA serial check in xfrout. It now compares the SOA
serial of an IXFR query with that of the server based serial
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
bool
Dhcpv4Srv::run() {
while (!shutdown_) {
- boost::shared_ptr<Pkt4> query; // client's message
- boost::shared_ptr<Pkt4> rsp; // server's response
+ Pkt4Ptr query; // client's message
+ Pkt4Ptr rsp; // server's response
query = IfaceMgr::instance().receive4();
#if 0
// uncomment this once ticket 1350 is merged.
IOAddress srvId("127.0.0.1");
- serverid_ = boost::shared_ptr<Option>(
+ serverid_ = OptionPtr(
new Option4AddrLst(Option::V4, DHO_DHCP_SERVER_IDENTIFIER, srvId));
#endif
}
-void Dhcpv4Srv::copyDefaultFields(const boost::shared_ptr<Pkt4>& question,
- boost::shared_ptr<Pkt4>& answer) {
+void Dhcpv4Srv::copyDefaultFields(const Pkt4Ptr& question, Pkt4Ptr& answer) {
answer->setIface(question->getIface());
answer->setIndex(question->getIndex());
answer->setCiaddr(question->getCiaddr());
}
-void Dhcpv4Srv::appendDefaultOptions(boost::shared_ptr<Pkt4>& msg, uint8_t msg_type) {
- boost::shared_ptr<Option> opt;
+void Dhcpv4Srv::appendDefaultOptions(Pkt4Ptr& msg, uint8_t msg_type) {
+ OptionPtr opt;
// add Message Type Option (type 53)
std::vector<uint8_t> tmp;
tmp.push_back(static_cast<uint8_t>(msg_type));
- opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DHCP_MESSAGE_TYPE, tmp));
+ opt = OptionPtr(new Option(Option::V4, DHO_DHCP_MESSAGE_TYPE, tmp));
msg->addOption(opt);
// DHCP Server Identifier (type 54)
- opt = boost::shared_ptr<Option>
+ opt = OptionPtr
(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER, IOAddress(HARDCODED_SERVER_ID)));
msg->addOption(opt);
}
-void Dhcpv4Srv::appendRequestedOptions(boost::shared_ptr<Pkt4>& msg) {
- boost::shared_ptr<Option> opt;
+void Dhcpv4Srv::appendRequestedOptions(Pkt4Ptr& msg) {
+ OptionPtr opt;
// Domain name (type 15)
vector<uint8_t> domain(HARDCODED_DOMAIN_NAME.begin(), HARDCODED_DOMAIN_NAME.end());
- opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DOMAIN_NAME, domain));
+ opt = OptionPtr(new Option(Option::V4, DHO_DOMAIN_NAME, domain));
msg->addOption(opt);
// TODO: Add Option_String class
// DNS servers (type 6)
- opt = boost::shared_ptr<Option>
- (new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS, IOAddress(HARDCODED_DNS_SERVER)));
+ opt = OptionPtr(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS, IOAddress(HARDCODED_DNS_SERVER)));
msg->addOption(opt);
}
-void Dhcpv4Srv::tryAssignLease(boost::shared_ptr<Pkt4>& msg) {
- boost::shared_ptr<Option> opt;
+void Dhcpv4Srv::tryAssignLease(Pkt4Ptr& msg) {
+ OptionPtr opt;
// TODO: Implement actual lease assignment here
msg->setYiaddr(IOAddress(HARDCODED_LEASE));
// IP Address Lease time (type 51)
- opt = boost::shared_ptr<Option>(new Option(Option::V4, DHO_DHCP_LEASE_TIME));
+ opt = OptionPtr(new Option(Option::V4, DHO_DHCP_LEASE_TIME));
opt->setUint32(HARDCODED_LEASE_TIME);
msg->addOption(opt);
// TODO: create Option_IntArray that holds list of integers, similar to Option4_AddrLst
// Subnet mask (type 1)
- opt = boost::shared_ptr<Option>
- (new Option4AddrLst(DHO_SUBNET_MASK, IOAddress(HARDCODED_NETMASK)));
+ opt = OptionPtr(new Option4AddrLst(DHO_SUBNET_MASK, IOAddress(HARDCODED_NETMASK)));
msg->addOption(opt);
// Router (type 3)
- opt = boost::shared_ptr<Option>
- (new Option4AddrLst(DHO_ROUTERS, IOAddress(HARDCODED_GATEWAY)));
+ opt = OptionPtr(new Option4AddrLst(DHO_ROUTERS, IOAddress(HARDCODED_GATEWAY)));
msg->addOption(opt);
}
-boost::shared_ptr<Pkt4>
-Dhcpv4Srv::processDiscover(boost::shared_ptr<Pkt4>& discover) {
- boost::shared_ptr<Pkt4> offer = boost::shared_ptr<Pkt4>
+Pkt4Ptr Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
+ Pkt4Ptr offer = Pkt4Ptr
(new Pkt4(DHCPOFFER, discover->getTransid()));
copyDefaultFields(discover, offer);
return (offer);
}
-boost::shared_ptr<Pkt4>
-Dhcpv4Srv::processRequest(boost::shared_ptr<Pkt4>& request) {
- boost::shared_ptr<Pkt4> ack = boost::shared_ptr<Pkt4>
+Pkt4Ptr Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
+ Pkt4Ptr ack = Pkt4Ptr
(new Pkt4(DHCPACK, request->getTransid()));
copyDefaultFields(request, ack);
return (ack);
}
-void Dhcpv4Srv::processRelease(boost::shared_ptr<Pkt4>& release) {
+void Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
/// TODO: Implement this.
cout << "Received RELEASE on " << release->getIface() << " interface." << endl;
}
-void Dhcpv4Srv::processDecline(boost::shared_ptr<Pkt4>& decline) {
+void Dhcpv4Srv::processDecline(Pkt4Ptr& decline) {
/// TODO: Implement this.
cout << "Received DECLINE on " << decline->getIface() << " interface." << endl;
}
-boost::shared_ptr<Pkt4> Dhcpv4Srv::processInform(boost::shared_ptr<Pkt4>& inform) {
+Pkt4Ptr Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
/// TODO: Currently implemented echo mode. Implement this for real
return (inform);
}
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#ifndef DHCPV4_SRV_H
#define DHCPV4_SRV_H
-#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <dhcp/dhcp4.h>
#include <dhcp/pkt4.h>
/// @param solicit DISCOVER message received from client
///
/// @return OFFER message or NULL
- boost::shared_ptr<Pkt4>
- processDiscover(boost::shared_ptr<Pkt4>& discover);
+ Pkt4Ptr processDiscover(Pkt4Ptr& discover);
/// @brief Processes incoming REQUEST and returns REPLY response.
///
/// @param request a message received from client
///
/// @return ACK or NACK message
- boost::shared_ptr<Pkt4> processRequest(boost::shared_ptr<Pkt4>& request);
+ Pkt4Ptr processRequest(Pkt4Ptr& request);
/// @brief Stub function that will handle incoming RELEASE messages.
///
/// this function does not return anything.
///
/// @param release message received from client
- void processRelease(boost::shared_ptr<Pkt4>& release);
+ void processRelease(Pkt4Ptr& release);
/// @brief Stub function that will handle incoming DHCPDECLINE messages.
///
/// @param decline message received from client
- void processDecline(boost::shared_ptr<Pkt4>& decline);
+ void processDecline(Pkt4Ptr& decline);
/// @brief Stub function that will handle incoming INFORM messages.
///
/// @param infRequest message received from client
- boost::shared_ptr<Pkt4> processInform(boost::shared_ptr<Pkt4>& inform);
+ Pkt4Ptr processInform(Pkt4Ptr& inform);
/// @brief Copies default parameters from client's to server's message
///
///
/// @param question any message sent by client
/// @param answer any message server is going to send as response
- void copyDefaultFields(const boost::shared_ptr<Pkt4>& question,
- boost::shared_ptr<Pkt4>& answer);
-
+ void copyDefaultFields(const Pkt4Ptr& question, Pkt4Ptr& answer);
/// @brief Appends options requested by client.
///
/// (sent in PRL) or are enforced by server.
///
/// @param msg outgoing message (options will be added here)
- void appendRequestedOptions(boost::shared_ptr<Pkt4>& msg);
-
+ void appendRequestedOptions(Pkt4Ptr& msg);
/// @brief Assigns a lease and appends corresponding options
///
/// used fixed, hardcoded lease.
///
/// @param msg OFFER or ACK message (lease options will be added here)
- void tryAssignLease(boost::shared_ptr<Pkt4>& msg);
-
+ void tryAssignLease(Pkt4Ptr& msg);
/// @brief Appends default options to a message
///
/// @param msg message object (options will be added to it)
/// @param msg_type specifies message type
- void appendDefaultOptions(boost::shared_ptr<Pkt4>& msg, uint8_t msg_type);
+ void appendDefaultOptions(Pkt4Ptr& msg, uint8_t msg_type);
/// @brief Returns server-intentifier option
///
/// @return server-id option
- boost::shared_ptr<isc::dhcp::Option>
- getServerID() { return serverid_; }
+ OptionPtr getServerID() { return serverid_; }
/// @brief Sets server-identifier.
///
void setServerID();
/// server DUID (to be sent in server-identifier option)
- boost::shared_ptr<isc::dhcp::Option> serverid_;
+ OptionPtr serverid_;
/// indicates if shutdown is in progress. Setting it to true will
/// initiate server shutdown procedure.
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
bool
Dhcpv6Srv::run() {
while (!shutdown) {
- boost::shared_ptr<Pkt6> query; // client's message
- boost::shared_ptr<Pkt6> rsp; // server's response
+ Pkt6Ptr query; // client's message
+ Pkt6Ptr rsp; // server's response
query = IfaceMgr::instance().receive6();
<< query->getType() << endl;
}
- cout << "Received " << query->data_len_ << " bytes packet type="
+ cout << "Received " << query->getBuffer().getLength() << " bytes packet type="
<< query->getType() << endl;
cout << query->toText();
if (rsp) {
- rsp->remote_addr_ = query->remote_addr_;
- rsp->local_addr_ = query->local_addr_;
- rsp->remote_port_ = DHCP6_CLIENT_PORT;
- rsp->local_port_ = DHCP6_SERVER_PORT;
- rsp->ifindex_ = query->ifindex_;
- rsp->iface_ = query->iface_;
+ rsp->setRemoteAddr(query->getRemoteAddr());
+ rsp->setLocalAddr(query->getLocalAddr());
+ rsp->setRemotePort(DHCP6_CLIENT_PORT);
+ rsp->setLocalPort(DHCP6_SERVER_PORT);
+ rsp->setIndex(query->getIndex());
+ rsp->setIface(query->getIface());
cout << "Replying with:" << rsp->getType() << endl;
cout << rsp->toText();
cout << "----" << endl;
/// TODO implement this for real once interface detection is done.
/// Use hardcoded server-id for now
- boost::shared_array<uint8_t> srvid(new uint8_t[14]);
+ OptionBuffer srvid(14);
srvid[0] = 0;
srvid[1] = 1; // DUID type 1 = DUID-LLT (see section 9.2 of RFC3315)
srvid[2] = 0;
}
serverid_ = boost::shared_ptr<Option>(new Option(Option::V6,
D6O_SERVERID,
- srvid,
- 0, 14));
+ srvid.begin(),
+ srvid.end()));
}
-void Dhcpv6Srv::copyDefaultOptions(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer) {
+void Dhcpv6Srv::copyDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
// add client-id
boost::shared_ptr<Option> clientid = question->getOption(D6O_CLIENTID);
if (clientid) {
// TODO: Should throw if there is no client-id (except anonymous INF-REQUEST)
}
-void Dhcpv6Srv::appendDefaultOptions(const boost::shared_ptr<Pkt6>& /*question*/,
- boost::shared_ptr<Pkt6>& answer) {
+void Dhcpv6Srv::appendDefaultOptions(const Pkt6Ptr& /*question*/, Pkt6Ptr& answer) {
// TODO: question is currently unused, but we need it at least to know
// message type we are answering
}
-void Dhcpv6Srv::appendRequestedOptions(const boost::shared_ptr<Pkt6>& /*question*/,
- boost::shared_ptr<Pkt6>& answer) {
+void Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& /*question*/, Pkt6Ptr& answer) {
// TODO: question is currently unused, but we need to extract ORO from it
// and act on its content. Now we just send DNS-SERVERS option.
answer->addOption(dnsservers);
}
-void Dhcpv6Srv::assignLeases(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer) {
+void Dhcpv6Srv::assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer) {
/// TODO Rewrite this once LeaseManager is implemented.
// answer client's IA (this is mostly a dummy,
}
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processSolicit(const boost::shared_ptr<Pkt6>& solicit) {
+Pkt6Ptr Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
- boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE,
- solicit->getTransid()));
+ Pkt6Ptr advertise(new Pkt6(DHCPV6_ADVERTISE, solicit->getTransid()));
copyDefaultOptions(solicit, advertise);
appendDefaultOptions(solicit, advertise);
return (advertise);
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRequest(const boost::shared_ptr<Pkt6>& request) {
+Pkt6Ptr Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- request->getTransid()));
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, request->getTransid()));
copyDefaultOptions(request, reply);
appendDefaultOptions(request, reply);
return (reply);
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRenew(const boost::shared_ptr<Pkt6>& renew) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- renew->getTransid(),
- Pkt6::UDP));
+Pkt6Ptr Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, renew->getTransid()));
return reply;
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRebind(const boost::shared_ptr<Pkt6>& rebind) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
+Pkt6Ptr Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY,
rebind->getTransid(),
Pkt6::UDP));
return reply;
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processConfirm(const boost::shared_ptr<Pkt6>& confirm) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- confirm->getTransid(),
- Pkt6::UDP));
+Pkt6Ptr Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, confirm->getTransid()));
return reply;
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processRelease(const boost::shared_ptr<Pkt6>& release) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- release->getTransid(),
- Pkt6::UDP));
+Pkt6Ptr Dhcpv6Srv::processRelease(const Pkt6Ptr& release) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, release->getTransid()));
return reply;
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processDecline(const boost::shared_ptr<Pkt6>& decline) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- decline->getTransid(),
- Pkt6::UDP));
+Pkt6Ptr Dhcpv6Srv::processDecline(const Pkt6Ptr& decline) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, decline->getTransid()));
return reply;
}
-boost::shared_ptr<Pkt6>
-Dhcpv6Srv::processInfRequest(const boost::shared_ptr<Pkt6>& infRequest) {
- boost::shared_ptr<Pkt6> reply(new Pkt6(DHCPV6_REPLY,
- infRequest->getTransid(),
- Pkt6::UDP));
+Pkt6Ptr Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) {
+ Pkt6Ptr reply(new Pkt6(DHCPV6_REPLY, infRequest->getTransid()));
return reply;
}
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#ifndef DHCPV6_SRV_H
#define DHCPV6_SRV_H
-#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <dhcp/dhcp6.h>
#include <dhcp/pkt6.h>
/// @brief Returns server-intentifier option
///
/// @return server-id option
- boost::shared_ptr<isc::dhcp::Option>
- getServerID() { return serverid_; }
+ OptionPtr getServerID() { return serverid_; }
/// @brief Main server processing loop.
///
/// @param solicit SOLICIT message received from client
///
/// @return ADVERTISE, REPLY message or NULL
- boost::shared_ptr<Pkt6>
- processSolicit(const boost::shared_ptr<Pkt6>& solicit);
+ Pkt6Ptr processSolicit(const Pkt6Ptr& solicit);
/// @brief Processes incoming REQUEST and returns REPLY response.
///
/// @param request a message received from client
///
/// @return REPLY message or NULL
- boost::shared_ptr<Pkt6>
- processRequest(const boost::shared_ptr<Pkt6>& request);
+ Pkt6Ptr processRequest(const Pkt6Ptr& request);
/// @brief Stub function that will handle incoming RENEW messages.
///
/// @param renew message received from client
- boost::shared_ptr<Pkt6>
- processRenew(const boost::shared_ptr<Pkt6>& renew);
+ Pkt6Ptr processRenew(const Pkt6Ptr& renew);
/// @brief Stub function that will handle incoming REBIND messages.
///
/// @param rebind message received from client
- boost::shared_ptr<Pkt6>
- processRebind(const boost::shared_ptr<Pkt6>& rebind);
+ Pkt6Ptr processRebind(const Pkt6Ptr& rebind);
/// @brief Stub function that will handle incoming CONFIRM messages.
///
/// @param confirm message received from client
- boost::shared_ptr<Pkt6>
- processConfirm(const boost::shared_ptr<Pkt6>& confirm);
+ Pkt6Ptr processConfirm(const Pkt6Ptr& confirm);
/// @brief Stub function that will handle incoming RELEASE messages.
///
/// @param release message received from client
- boost::shared_ptr<Pkt6>
- processRelease(const boost::shared_ptr<Pkt6>& release);
+ Pkt6Ptr processRelease(const Pkt6Ptr& release);
/// @brief Stub function that will handle incoming DECLINE messages.
///
/// @param decline message received from client
- boost::shared_ptr<Pkt6>
- processDecline(const boost::shared_ptr<Pkt6>& decline);
+ Pkt6Ptr processDecline(const Pkt6Ptr& decline);
/// @brief Stub function that will handle incoming INF-REQUEST messages.
///
/// @param infRequest message received from client
- boost::shared_ptr<Pkt6>
- processInfRequest(const boost::shared_ptr<Pkt6>& infRequest);
+ Pkt6Ptr processInfRequest(const Pkt6Ptr& infRequest);
/// @brief Copies required options from client message to server answer
///
///
/// @param question client's message (options will be copied from here)
/// @param answer server's message (options will be copied here)
- void copyDefaultOptions(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer);
+ void copyDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
/// @brief Appends default options to server's answer.
///
///
/// @param question client's message
/// @param answer server's message (options will be added here)
- void appendDefaultOptions(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer);
+ void appendDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
/// @brief Appends requested options to server's answer.
///
///
/// @param question client's message
/// @param answer server's message (options will be added here)
- void appendRequestedOptions(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer);
+ void appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
/// @brief Assigns leases.
///
///
/// @param question client's message (with requested IA_NA)
/// @param answer server's message (IA_NA options will be added here)
- void assignLeases(const boost::shared_ptr<Pkt6>& question,
- boost::shared_ptr<Pkt6>& answer);
+ void assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer);
/// @brief Sets server-identifier.
///
ASSERT_NO_THROW( srv = new NakedDhcpv6Srv(); );
// a dummy content for client-id
- boost::shared_array<uint8_t> clntDuid(new uint8_t[32]);
+ OptionBuffer clntDuid(32);
for (int i = 0; i < 32; i++)
clntDuid[i] = 100 + i;
- boost::shared_ptr<Pkt6> sol =
- boost::shared_ptr<Pkt6>(new Pkt6(DHCPV6_SOLICIT,
- 1234, Pkt6::UDP));
+ Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234, Pkt6::UDP));
boost::shared_ptr<Option6IA> ia =
boost::shared_ptr<Option6IA>(new Option6IA(D6O_IA_NA, 234));
// - server-id
// - IA that includes IAADDR
- boost::shared_ptr<Option> clientid =
- boost::shared_ptr<Option>(new Option(Option::V6, D6O_CLIENTID,
- clntDuid, 0, 16));
+ OptionPtr clientid = OptionPtr(new Option(Option::V6, D6O_CLIENTID,
+ clntDuid.begin(),
+ clntDuid.begin()+16));
sol->addOption(clientid);
boost::shared_ptr<Pkt6> reply = srv->processSolicit(sol);
EXPECT_EQ( DHCPV6_ADVERTISE, reply->getType() );
EXPECT_EQ( 1234, reply->getTransid() );
- boost::shared_ptr<Option> tmp = reply->getOption(D6O_IA_NA);
+ OptionPtr tmp = reply->getOption(D6O_IA_NA);
ASSERT_TRUE( tmp );
Option6IA* reply_ia = dynamic_cast<Option6IA*>(tmp.get());
isc_throw(Unexpected, "Failed to create UDP6 socket.");
}
- /* Set the REUSEADDR option so that we don't fail to start if
- we're being restarted. */
+ // Set the REUSEADDR option so that we don't fail to start if
+ // we're being restarted.
int flag = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof(flag)) < 0) {
<< "/port=" << port);
}
#ifdef IPV6_RECVPKTINFO
- /* RFC3542 - a new way */
+ // RFC3542 - a new way
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&flag, sizeof(flag)) != 0) {
close(sock);
isc_throw(Unexpected, "setsockopt: IPV6_RECVPKTINFO failed.");
}
#else
- /* RFC2292 - an old way */
+ // RFC2292 - an old way
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
&flag, sizeof(flag)) != 0) {
close(sock);
struct in6_pktinfo *pktinfo;
struct cmsghdr *cmsg;
- Iface* iface = getIface(pkt->iface_);
+ Iface* iface = getIface(pkt->getIface());
if (!iface) {
isc_throw(BadValue, "Unable to send Pkt6. Invalid interface ("
- << pkt->iface_ << ") specified.");
+ << pkt->getIface() << ") specified.");
}
memset(&control_buf_[0], 0, control_buf_len_);
sockaddr_in6 to;
memset(&to, 0, sizeof(to));
to.sin6_family = AF_INET6;
- to.sin6_port = htons(pkt->remote_port_);
+ to.sin6_port = htons(pkt->getRemotePort());
memcpy(&to.sin6_addr,
- pkt->remote_addr_.getAddress().to_v6().to_bytes().data(),
+ pkt->getRemoteAddr().getAddress().to_v6().to_bytes().data(),
16);
- to.sin6_scope_id = pkt->ifindex_;
+ to.sin6_scope_id = pkt->getIndex();
m.msg_name = &to;
m.msg_namelen = sizeof(to);
// Set the data buffer we're sending. (Using this wacky
// "scatter-gather" stuff... we only have a single chunk
// of data to send, so we declare a single vector entry.)
- v.iov_base = (char *) &pkt->data_[0];
- v.iov_len = pkt->data_len_;
+ v.iov_base = (char *) pkt->getBuffer().getData();
+ v.iov_len = pkt->getBuffer().getLength();
m.msg_iov = &v;
m.msg_iovlen = 1;
cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
memset(pktinfo, 0, sizeof(*pktinfo));
- pktinfo->ipi6_ifindex = pkt->ifindex_;
+ pktinfo->ipi6_ifindex = pkt->getIndex();
m.msg_controllen = cmsg->cmsg_len;
result = sendmsg(getSocket(*pkt), &m, 0);
if (result < 0) {
isc_throw(Unexpected, "Pkt6 send failed: sendmsg() returned " << result);
}
- cout << "Sent " << pkt->data_len_ << " bytes over socket " << getSocket(*pkt)
+ cout << "Sent " << pkt->getBuffer().getLength() << " bytes over socket " << getSocket(*pkt)
<< " on " << iface->getFullName() << " interface: "
- << " dst=[" << pkt->remote_addr_.toText() << "]:" << pkt->remote_port_
- << ", src=" << pkt->local_addr_.toText() << "]:" << pkt->remote_port_
+ << " dst=[" << pkt->getRemoteAddr().toText() << "]:" << pkt->getRemotePort()
+ << ", src=" << pkt->getLocalAddr().toText() << "]:" << pkt->getLocalPort()
<< endl;
return (result);
return (pkt);
}
-boost::shared_ptr<Pkt6>
-IfaceMgr::receive6() {
+Pkt6Ptr IfaceMgr::receive6() {
struct msghdr m;
struct iovec v;
int result;
struct in6_pktinfo* pktinfo;
struct sockaddr_in6 from;
struct in6_addr to_addr;
- boost::shared_ptr<Pkt6> pkt;
- char addr_str[INET6_ADDRSTRLEN];
-
- try {
- // RFC3315 states that server responses may be
- // fragmented if they are over MTU. There is no
- // text whether client's packets may be larger
- // than 1500. Nevertheless to be on the safe side
- // we use larger buffer. This buffer limit is checked
- // during reception (see iov_len below), so we are
- // safe
- pkt = boost::shared_ptr<Pkt6>(new Pkt6(65536));
- } catch (const std::exception& ex) {
- cout << "Failed to create new packet." << endl;
- return (boost::shared_ptr<Pkt6>()); // NULL
- }
+ int ifindex;
+ Pkt6Ptr pkt;
+
+ // RFC3315 states that server responses may be
+ // fragmented if they are over MTU. There is no
+ // text whether client's packets may be larger
+ // than 1500. For now, we can assume that
+ // we don't support packets larger than 1500.
+ const uint32_t RCVBUFSIZE = 1500;
+ static uint8_t buf[RCVBUFSIZE];
memset(&control_buf_[0], 0, control_buf_len_);
memset(&from, 0, sizeof(from));
memset(&to_addr, 0, sizeof(to_addr));
- /*
- * Initialize our message header structure.
- */
+ // Initialize our message header structure.
memset(&m, 0, sizeof(m));
- /*
- * Point so we can get the from address.
- */
+ // Point so we can get the from address.
m.msg_name = &from;
m.msg_namelen = sizeof(from);
- /*
- * Set the data buffer we're receiving. (Using this wacky
- * "scatter-gather" stuff... but we that doesn't really make
- * sense for us, so we use a single vector entry.)
- */
- v.iov_base = (void*)&pkt->data_[0];
- v.iov_len = pkt->data_len_;
+ // Set the data buffer we're receiving. (Using this wacky
+ // "scatter-gather" stuff... but we that doesn't really make
+ // sense for us, so we use a single vector entry.)
+ v.iov_base = (void*)buf;
+ v.iov_len = RCVBUFSIZE;
m.msg_iov = &v;
m.msg_iovlen = 1;
- /*
- * Getting the interface is a bit more involved.
- *
- * We set up some space for a "control message". We have
- * previously asked the kernel to give us packet
- * information (when we initialized the interface), so we
- * should get the destination address from that.
- */
+ // Getting the interface is a bit more involved.
+ //
+ // We set up some space for a "control message". We have
+ // previously asked the kernel to give us packet
+ // information (when we initialized the interface), so we
+ // should get the destination address from that.
m.msg_control = &control_buf_[0];
m.msg_controllen = control_buf_len_;
result = recvmsg(candidate->sockfd_, &m, 0);
if (result >= 0) {
- /*
- * If we did read successfully, then we need to loop
- * through the control messages we received and
- * find the one with our destination address.
- *
- * We also keep a flag to see if we found it. If we
- * didn't, then we consider this to be an error.
- */
+ // If we did read successfully, then we need to loop
+ // through the control messages we received and
+ // find the one with our destination address.
+ //
+ // We also keep a flag to see if we found it. If we
+ // didn't, then we consider this to be an error.
int found_pktinfo = 0;
cmsg = CMSG_FIRSTHDR(&m);
while (cmsg != NULL) {
(cmsg->cmsg_type == IPV6_PKTINFO)) {
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
to_addr = pktinfo->ipi6_addr;
- pkt->ifindex_ = pktinfo->ipi6_ifindex;
+ ifindex = pktinfo->ipi6_ifindex;
found_pktinfo = 1;
}
cmsg = CMSG_NXTHDR(&m, cmsg);
return (boost::shared_ptr<Pkt6>()); // NULL
}
- // That's ugly.
- // TODO add IOAddress constructor that will take struct in6_addr*
- // TODO: there's from_bytes() method added in IOAddress. Use it!
- inet_ntop(AF_INET6, &to_addr, addr_str,INET6_ADDRSTRLEN);
- pkt->local_addr_ = IOAddress(string(addr_str));
- // TODO: there's from_bytes() method added in IOAddress. Use it!
- inet_ntop(AF_INET6, &from.sin6_addr, addr_str, INET6_ADDRSTRLEN);
- pkt->remote_addr_ = IOAddress(string(addr_str));
+ try {
+ pkt = Pkt6Ptr(new Pkt6(buf, result));
+ } catch (const std::exception& ex) {
+ cout << "Failed to create new packet." << endl;
+ return (boost::shared_ptr<Pkt6>()); // NULL
+ }
+
+ pkt->setLocalAddr(IOAddress::from_bytes(AF_INET6, (const uint8_t*)&to_addr));
+ pkt->setRemoteAddr(IOAddress::from_bytes(AF_INET6, (const uint8_t*)&from.sin6_addr));
+
+ pkt->setRemotePort(ntohs(from.sin6_port));
- pkt->remote_port_ = ntohs(from.sin6_port);
+ pkt->setIndex(ifindex);
- Iface* received = getIface(pkt->ifindex_);
+ Iface* received = getIface(pkt->getIndex());
if (received) {
- pkt->iface_ = received->getName();
+ pkt->setIface(received->getName());
} else {
cout << "Received packet over unknown interface (ifindex="
- << pkt->ifindex_ << ")." << endl;
+ << pkt->getIndex() << ")." << endl;
return (boost::shared_ptr<Pkt6>()); // NULL
}
- pkt->data_len_ = result;
-
// TODO Move this to LOG_DEBUG
- cout << "Received " << pkt->data_len_ << " bytes over "
- << pkt->iface_ << "/" << pkt->ifindex_ << " interface: "
- << " src=" << pkt->remote_addr_.toText()
- << ", dst=" << pkt->local_addr_.toText()
+ cout << "Received " << pkt->getBuffer().getLength() << " bytes over "
+ << pkt->getIface() << "/" << pkt->getIndex() << " interface: "
+ << " src=" << pkt->getRemoteAddr().toText()
+ << ", dst=" << pkt->getLocalAddr().toText()
<< endl;
return (pkt);
uint16_t
IfaceMgr::getSocket(isc::dhcp::Pkt6 const& pkt) {
- Iface* iface = getIface(pkt.iface_);
+ Iface* iface = getIface(pkt.getIface());
if (!iface) {
isc_throw(BadValue, "Tried to find socket for non-existent interface "
- << pkt.iface_);
+ << pkt.getIface());
}
SocketCollection::const_iterator s;
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
using namespace isc::dhcp;
using namespace isc::util;
+// static array with factories for options
+std::map<unsigned short, Option::Factory*> LibDHCP::v4factories_;
+
// static array with factories for options
std::map<unsigned short, Option::Factory*> LibDHCP::v6factories_;
-unsigned int
-LibDHCP::unpackOptions6(const boost::shared_array<uint8_t> buf,
- unsigned int buf_len,
- unsigned int offset, unsigned int parse_len,
- isc::dhcp::Option::OptionCollection& options) {
- if (offset + parse_len > buf_len) {
- isc_throw(OutOfRange, "Option parse failed. Tried to parse "
- << parse_len << " bytes at offset " << offset
- << ": out of buffer");
- }
- unsigned int end = offset + parse_len;
+
+uint32_t LibDHCP::unpackOptions6(const OptionBuffer& buf,
+ isc::dhcp::Option::OptionCollection& options) {
+ uint32_t offset = 0;
+ unsigned int end = buf.size();
while (offset +4 <= end) {
uint16_t opt_type = buf[offset]*256 + buf[offset+1];
cout << "Option " << opt_type << " truncated." << endl;
return (offset);
}
- boost::shared_ptr<Option> opt;
+ OptionPtr opt;
switch (opt_type) {
case D6O_IA_NA:
case D6O_IA_PD:
// cout << "Creating Option6IA" << endl;
- opt = boost::shared_ptr<Option>(new Option6IA(opt_type,
- buf, buf_len,
- offset,
- opt_len));
+ opt = OptionPtr(new Option6IA(opt_type,
+ buf.begin() + offset,
+ buf.begin() + offset + opt_len));
break;
case D6O_IAADDR:
// cout << "Creating Option6IAAddr" << endl;
- opt = boost::shared_ptr<Option>(new Option6IAAddr(opt_type,
- buf, buf_len,
- offset, opt_len));
+ opt = OptionPtr(new Option6IAAddr(opt_type,
+ buf.begin() + offset,
+ buf.begin() + offset + opt_len));
break;
default:
// cout << "Creating Option" << endl;
- opt = boost::shared_ptr<Option>(new Option(Option::V6,
- opt_type,
- buf,
- offset,
- opt_len));
+ opt = OptionPtr(new Option(Option::V6,
+ opt_type,
+ buf.begin() + offset,
+ buf.begin() + offset + opt_len));
break;
}
// add option to options
return (offset);
}
-void
-LibDHCP::unpackOptions4(const std::vector<uint8_t>& buf,
- isc::dhcp::Option::OptionCollection& options) {
+uint32_t LibDHCP::unpackOptions4(const OptionBuffer& buf,
+ isc::dhcp::Option::OptionCollection& options) {
size_t offset = 0;
// 2 - header of DHCPv4 option
uint8_t opt_type = buf[offset++];
if (opt_type == DHO_END)
- return; // just return. Don't need to add DHO_END option
+ return (offset); // just return. Don't need to add DHO_END option
if (offset + 1 >= buf.size()) {
- isc_throw(OutOfRange, "Attempt to parse truncated option "
- << opt_type);
+ isc_throw(OutOfRange, "Attempt to parse truncated option "
+ << opt_type);
}
uint8_t opt_len = buf[offset++];
<< "-byte long buffer.");
}
- boost::shared_ptr<Option> opt;
+ OptionPtr opt;
switch(opt_type) {
default:
- opt = boost::shared_ptr<Option>(new Option(Option::V4, opt_type,
- buf.begin()+offset,
- buf.begin()+offset+opt_len));
+ opt = OptionPtr(new Option(Option::V4, opt_type,
+ buf.begin()+offset,
+ buf.begin()+offset+opt_len));
}
options.insert(pair<int, boost::shared_ptr<Option> >(opt_type, opt));
offset += opt_len;
}
+ return (offset);
}
-unsigned int
-LibDHCP::packOptions6(boost::shared_array<uint8_t> data,
- unsigned int data_len,
- unsigned int offset,
- const isc::dhcp::Option::OptionCollection& options) {
+void LibDHCP::packOptions6(isc::util::OutputBuffer &buf,
+ const isc::dhcp::Option::OptionCollection& options) {
try {
for (Option::OptionCollection::const_iterator it = options.begin();
- it != options.end();
- ++it) {
- unsigned short opt_len = (*it).second->len();
- if (offset + opt_len > data_len) {
- isc_throw(OutOfRange, "Failed to build option " <<
- (*it).first << ": out of buffer");
- }
- offset = it->second->pack(data, data_len, offset);
+ it != options.end(); ++it) {
+ it->second->pack(buf);
}
}
catch (const Exception&) {
cout << "Packet build failed (Option build failed)." << endl;
throw;
}
- return (offset);
}
void
}
}
-
-bool
-LibDHCP::OptionFactoryRegister(Option::Universe u,
- unsigned short opt_type,
- Option::Factory * factory) {
+void LibDHCP::OptionFactoryRegister(Option::Universe u,
+ uint16_t opt_type,
+ Option::Factory * factory) {
switch (u) {
case Option::V6: {
if (v6factories_.find(opt_type)!=v6factories_.end()) {
<< "for option type " << opt_type);
}
v6factories_[opt_type]=factory;
- return true;
+ return;
}
case Option::V4:
- default:{
- isc_throw(BadValue, "This universe type is not supported yet.");
- return false; // never happens
+ {
+ if (opt_type > 254) {
+ isc_throw(BadValue, "Too big option type for DHCPv4, only 0-254 allowed.");
+ }
+ if (v4factories_.find(opt_type)!=v4factories_.end()) {
+ isc_throw(BadValue, "There is already DHCPv4 factory registered "
+ << "for option type " << opt_type);
+ }
+ v4factories_[opt_type]=factory;
+ return;
}
+ default:
+ isc_throw(BadValue, "Invalid universe type specified.");
}
+ return;
}
///
/// Builds raw (on-wire) data for provided collection of options.
///
- /// @param buf shared pointer to buffer. Data will be stored there.
- /// @param buf_len buffer length. Used for buffer overflow protection.
- /// @param offset Offset from beginning of the buffer, where store options
+ /// @param buf output buffer (assembled options will be stored here)
/// @param options collection of options to store to
- ///
- /// @return offset to the first unused byte in buffer (next one after last
- /// used byte)
- ///
- static unsigned int
- packOptions6(boost::shared_array<uint8_t> buf, unsigned int buf_len,
- unsigned int offset,
- const isc::dhcp::Option::OptionCollection& options);
+ static void packOptions6(isc::util::OutputBuffer& buf,
+ const isc::dhcp::Option::OptionCollection& options);
/// @brief Stores options in a buffer.
/// may be different reasons (option too large, option malformed,
/// too many options etc.)
///
- /// @param buf
- /// @param options
- static void
- packOptions(isc::util::OutputBuffer& buf,
- const isc::dhcp::Option::OptionCollection& options);
+ /// @param buf output buffer (assembled options will be stored here)
+ /// @param options collection of options to store to
+ static void packOptions(isc::util::OutputBuffer& buf,
+ const isc::dhcp::Option::OptionCollection& options);
- static void
- unpackOptions4(const std::vector<uint8_t>& buf,
- isc::dhcp::Option::OptionCollection& options);
- ///
- /// Parses provided buffer and creates Option objects.
+ /// @brief Parses provided buffer as DHCPv4 options and creates Option objects.
///
- /// Parses provided buf array and stores created Option objects
+ /// Parses provided buffer and stores created Option objects
/// in options container.
///
/// @param buf Buffer to be parsed.
- /// @param offset Specifies offset for the first option.
/// @param options Reference to option container. Options will be
/// put here.
+ static uint32_t unpackOptions4(const OptionBuffer& buf,
+ isc::dhcp::Option::OptionCollection& options);
+
+ /// @brief Parses provided buffer as DHCPv6 options and creates Option objects.
///
- /// @return offset to first byte after last parsed option
+ /// Parses provided buffer and stores created Option objects
+ /// in options container.
///
- static unsigned int
- unpackOptions6(const boost::shared_array<uint8_t> buf, unsigned int buf_len,
- unsigned int offset, unsigned int parse_len,
- isc::dhcp::Option::OptionCollection& options_);
+ /// @param buf Buffer to be parsed.
+ /// @param options Reference to option container. Options will be
+ /// put here.
+ static uint32_t unpackOptions6(const OptionBuffer& buf,
+ isc::dhcp::Option::OptionCollection& options);
- ///
/// Registers factory method that produces options of specific option types.
///
+ /// @exception BadValue if provided type is already registered, has too large
+ /// value or invalid universe is specified
+ ///
/// @param u universe of the option (V4 or V6)
/// @param opt_type option-type
/// @param factory function pointer
- ///
- /// @return true, if registration was successful, false otherwise
- ///
- static bool
- OptionFactoryRegister(Option::Universe u,
- unsigned short type,
- Option::Factory * factory);
+ static void OptionFactoryRegister(Option::Universe u,
+ uint16_t type,
+ Option::Factory * factory);
protected:
- // pointers to factories that produce DHCPv6 options
+ /// pointers to factories that produce DHCPv6 options
+ static std::map<unsigned short, Option::Factory*> v4factories_;
+
+ /// pointers to factories that produce DHCPv6 options
static std::map<unsigned short, Option::Factory*> v6factories_;
};
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <arpa/inet.h>
#include <sstream>
#include <iomanip>
-#include <boost/shared_array.hpp>
#include "exceptions/exceptions.h"
#include "util/io_utilities.h"
}
}
-Option::Option(Universe u, unsigned short type,
- const boost::shared_array<uint8_t>& buf,
- unsigned int offset, unsigned int len)
- :universe_(u), type_(type),
- offset_(offset)
-{
- uint8_t* ptr = &buf[offset];
- data_ = std::vector<uint8_t>(ptr, ptr + len);
-
- check();
-}
-
-Option::Option(Universe u, unsigned short type, std::vector<uint8_t>& data)
+Option::Option(Universe u, unsigned short type, const OptionBuffer& data)
:universe_(u), type_(type), data_(data) {
check();
}
-Option::Option(Universe u, uint16_t type, vector<uint8_t>::const_iterator first,
- vector<uint8_t>::const_iterator last)
- :universe_(u), type_(type), data_(std::vector<uint8_t>(first,last)) {
+Option::Option(Universe u, uint16_t type, OptionBufferConstIter first,
+ OptionBufferConstIter last)
+ :universe_(u), type_(type), data_(OptionBuffer(first,last)) {
check();
}
// both types and data size.
}
-unsigned int
-Option::pack(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset) {
- if (universe_ != V6) {
+void Option::pack(isc::util::OutputBuffer& buf) {
+ switch (universe_) {
+ case V6:
+ return pack6(buf);
+ case V4:
+ return pack4(buf);
+ default:
isc_throw(BadValue, "Failed to pack " << type_ << " option. Do not "
<< "use this method for options other than DHCPv6.");
}
- return pack6(buf, buf_len, offset);
}
void
}
}
-unsigned int
-Option::pack6(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset) {
- if (offset+len() > buf_len) {
- isc_throw(OutOfRange, "Failed to pack v6 option=" <<
- type_ << ",len=" << len() << ": too small buffer.");
- }
-
- uint8_t* ptr = &buf[offset];
-
- ptr = writeUint16(type_, ptr);
-
- ptr = writeUint16(len() - getHeaderLen(), ptr);
-
- if (! data_.empty())
- memcpy(ptr, &data_[0], data_.size());
-
- // end of fixed part of this option
- offset += OPTION6_HDR_LEN + data_.size();
-
- return LibDHCP::packOptions6(buf, buf_len, offset, options_);
-}
+void Option::pack6(isc::util::OutputBuffer& buf) {
+ buf.writeUint16(type_);
+ buf.writeUint16(len() - getHeaderLen());
-unsigned int
-Option::unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len) {
- switch (universe_) {
- case V4:
- return unpack4(buf, buf_len, offset, parse_len);
- case V6:
- return unpack6(buf, buf_len, offset, parse_len);
- default:
- isc_throw(BadValue, "Unknown universe defined for Option " << type_);
+ if (! data_.empty()) {
+ buf.writeData(&data_[0], data_.size());
}
- return 0; // should not happen
-}
-
-unsigned int
-Option::unpack4(const boost::shared_array<uint8_t>&,
- unsigned int ,
- unsigned int ,
- unsigned int ) {
- isc_throw(Unexpected, "IPv4 support not implemented yet.");
- return 0;
+ return LibDHCP::packOptions6(buf, options_);
}
-unsigned int
-Option::unpack6(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len) {
-
- if (buf_len < offset+parse_len) {
- isc_throw(OutOfRange, "Failed to unpack DHCPv6 option len="
- << parse_len << " offset=" << offset
- << " from buffer (length=" << buf_len
- << "): too small buffer.");
- }
-
- uint8_t* ptr = &buf[offset];
- data_ = std::vector<uint8_t>(ptr, ptr + parse_len);
-
- offset_ = offset;
-
- return (offset+parse_len);
-
- //return LibDHCP::unpackOptions6(buf, buf_len, offset, parse_len,
- // options_);
+void Option::unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ data_ = OptionBuffer(begin, end);
}
-/// Returns length of the complete option (data length + DHCPv4/DHCPv6
-/// option header)
-uint16_t
-Option::len() {
+uint16_t Option::len() {
+ // Returns length of the complete option (data length + DHCPv4/DHCPv6
+ // option header)
// length of the whole option is header and data stored in this option...
int length = getHeaderLen() + data_.size();
return (true);
}
-boost::shared_ptr<isc::dhcp::Option>
-Option::getOption(unsigned short opt_type) {
+OptionPtr Option::getOption(unsigned short opt_type) {
isc::dhcp::Option::OptionCollection::const_iterator x =
options_.find(opt_type);
if ( x != options_.end() ) {
return (*x).second;
}
- return boost::shared_ptr<isc::dhcp::Option>(); // NULL
+ return OptionPtr(); // NULL
}
-bool
-Option::delOption(unsigned short opt_type) {
+bool Option::delOption(unsigned short opt_type) {
isc::dhcp::Option::OptionCollection::iterator x = options_.find(opt_type);
if ( x != options_.end() ) {
options_.erase(x);
return 0; // should not happen
}
-void
-Option::addOption(boost::shared_ptr<Option> opt) {
+void Option::addOption(OptionPtr opt) {
if (universe_ == V4) {
// check for uniqueness (DHCPv4 options must be unique)
if (getOption(opt->getType())) {
<< " already present in this message.");
}
}
- options_.insert(pair<int, boost::shared_ptr<Option> >(opt->getType(), opt));
+ options_.insert(pair<int, OptionPtr >(opt->getType(), opt));
}
uint8_t Option::getUint8() {
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <map>
#include <vector>
#include <boost/shared_ptr.hpp>
-#include <boost/shared_array.hpp>
#include <util/buffer.h>
namespace isc {
namespace dhcp {
+/// buffer types used in DHCP code
+typedef std::vector<uint8_t> OptionBuffer;
+
+/// iterator for walking over OptionBuffer
+typedef OptionBuffer::iterator OptionBufferIter;
+
+/// const_iterator for walking over OptionBuffer
+typedef OptionBuffer::const_iterator OptionBufferConstIter;
+
+/// pointer to a DHCP buffer
+typedef boost::shared_ptr< OptionBuffer > OptionBufferPtr;
+
+/// shared pointer to Option object
+class Option;
+typedef boost::shared_ptr<Option> OptionPtr;
+
+
class Option {
public:
/// length of the usual DHCPv4 option header (there are exceptions)
enum Universe { V4, V6 };
/// a collection of DHCPv6 options
- typedef std::multimap<unsigned int, boost::shared_ptr<Option> >
+ typedef std::multimap<unsigned int, OptionPtr >
OptionCollection;
/// @brief a factory function prototype
/// @param u option universe (DHCPv4 or DHCPv6)
/// @param type option type
/// @param buf pointer to a buffer
- /// @param offset offset to first data byte in that buffer
- /// @param len data length of this option
///
/// @return a pointer to a created option object
- typedef boost::shared_ptr<Option> Factory(Option::Universe u,
- unsigned short type,
- boost::shared_array<uint8_t>& buf,
- unsigned int offset,
- unsigned int len);
+ typedef OptionPtr Factory(Option::Universe u,
+ uint16_t type,
+ const OptionBuffer& buf);
/// @brief ctor, used for options constructed, usually during transmission
///
/// @param u option universe (DHCPv4 or DHCPv6)
/// @param type option type
- Option(Universe u, unsigned short type);
-
- /// @brief ctor, used for received options
- ///
- /// boost::shared_array allows sharing a buffer, but it requires that
- /// different instances share pointer to the whole array, not point
- /// to different elements in shared array. Therefore we need to share
- /// pointer to the whole array and remember offset where data for
- /// this option begins
- ///
- /// @param u specifies universe (V4 or V6)
- /// @param type option type
- /// @param buf pointer to a buffer
- /// @param offset offset in a buffer pointing to first byte of data
- /// @param len length of the option data
- Option(Universe u, unsigned short type,
- const boost::shared_array<uint8_t>& buf, unsigned int offset,
- unsigned int len);
+ Option(Universe u, uint16_t type);
/// @brief Constructor, used for received options.
///
/// @param u specifies universe (V4 or V6)
/// @param type option type (0-255 for V4 and 0-65535 for V6)
/// @param data content of the option
- Option(Universe u, unsigned short type, std::vector<uint8_t>& data);
+ Option(Universe u, uint16_t type, const OptionBuffer& data);
/// @brief Constructor, used for received options.
///
/// @param first iterator to the first element that should be copied
/// @param last iterator to the next element after the last one
/// to be copied.
- Option(Universe u, uint16_t type,
- std::vector<uint8_t>::const_iterator first,
- std::vector<uint8_t>::const_iterator last);
+ Option(Universe u, uint16_t type, OptionBufferConstIter first,
+ OptionBufferConstIter last);
/// @brief returns option universe (V4 or V6)
///
/// @return universe type
- Universe
- getUniverse() { return universe_; };
+ Universe getUniverse() { return universe_; };
/// @brief Writes option in wire-format to a buffer.
///
/// TODO: Migrate DHCPv6 code to pack(OutputBuffer& buf) version
///
/// @param buf pointer to a buffer
- /// @param buf_len length of the buffer
- /// @param offset offset to place, where option shout be stored
///
/// @return offset to first unused byte after stored option
///
- virtual unsigned int
- pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
- unsigned int offset);
+ virtual void pack(isc::util::OutputBuffer& buf);
/// @brief Writes option in a wire-format to a buffer.
///
/// unify pack4() and pack6() and rename them to just pack().
///
/// @param buf output buffer (option will be stored there)
- virtual void
- pack4(isc::util::OutputBuffer& buf);
-
+ virtual void pack4(isc::util::OutputBuffer& buf);
/// @brief Parses buffer.
///
/// Parses received buffer, returns offset to the first unused byte after
/// parsed option.
///
- /// @param buf pointer to buffer
- /// @param buf_len length of buf
- /// @param offset offset, where start parsing option
- /// @param parse_len how many bytes should be parsed
- ///
- /// @return offset after last parsed octet
- virtual unsigned int
- unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ virtual void unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end);
/// Returns string representation of the option.
///
///
/// @return pointer to actual data (or reference to an empty vector
/// if there is no data)
- virtual const std::vector<uint8_t>& getData() { return (data_); }
+ virtual const OptionBuffer& getData() { return (data_); }
/// Adds a sub-option.
///
/// many places. Requiring casting is not feasible.
///
/// @param opt shared pointer to a suboption that is going to be added.
- void
- addOption(boost::shared_ptr<Option> opt);
+ void addOption(OptionPtr opt);
/// Returns shared_ptr to suboption of specific type
///
/// @param type type of requested suboption
///
/// @return shared_ptr to requested suoption
- boost::shared_ptr<isc::dhcp::Option>
- getOption(unsigned short type);
+ OptionPtr getOption(uint16_t type);
/// Attempts to delete first suboption of requested type
///
/// @param type Type of option to be deleted.
///
/// @return true if option was deleted, false if no such option existed
- bool
- delOption(unsigned short type);
+ bool delOption(uint16_t type);
/// @brief Returns content of first byte.
///
/// defined suboptions. Version for building DHCPv4 options.
///
/// @param buf output buffer (built options will be stored here)
- /// @param buf_len buffer length (used for buffer overflow checks)
- /// @param offset offset from start of the buf buffer
- ///
- /// @return offset to the next byte after last used byte
- virtual unsigned int
- pack6(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset);
-
- /// Parses provided buffer and creates DHCPv4 options.
- ///
- /// @param buf buffer that contains raw buffer to parse (on-wire format)
- /// @param buf_len buffer length (used for buffer overflow checks)
- /// @param offset offset from start of the buf buffer
- ///
- /// @return offset to the next byte after last parsed byte
- virtual unsigned int
- unpack4(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len);
-
- /// Parses provided buffer and creates DHCPv6 options.
- ///
- /// @param buf buffer that contains raw buffer to parse (on-wire format)
- /// @param buf_len buffer length (used for buffer overflow checks)
- /// @param offset offset from start of the buf buffer
- ///
- /// @return offset to the next byte after last parsed byte
- virtual unsigned int
- unpack6(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len);
+ virtual void pack6(isc::util::OutputBuffer& buf);
/// @brief A private method used for option correctness.
///
Universe universe_;
/// option type (0-255 for DHCPv4, 0-65535 for DHCPv6)
- unsigned short type_;
+ uint16_t type_;
/// contains content of this data
- std::vector<uint8_t> data_;
-
- /// TODO: Remove this field. vector<uint8_t> should be used
- /// instead.
- /// data is a shared_pointer that points out to the
- /// whole packet. offset_ specifies where data for
- /// this option begins.
- unsigned int offset_;
+ OptionBuffer data_;
/// collection for storing suboptions
OptionCollection options_;
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
}
-Option4AddrLst::Option4AddrLst(uint8_t type,
- vector<uint8_t>::const_iterator first,
- vector<uint8_t>::const_iterator last)
+Option4AddrLst::Option4AddrLst(uint8_t type, OptionBufferConstIter first,
+ OptionBufferConstIter last)
:Option(V4, type) {
if ( (distance(first, last) % V4ADDRESS_LEN) ) {
isc_throw(OutOfRange, "DHCPv4 Option4AddrLst " << type_
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// @param first iterator to the first element that should be copied
/// @param last iterator to the next element after the last one
/// to be copied.
- Option4AddrLst(uint8_t type, std::vector<uint8_t>::const_iterator first,
- std::vector<uint8_t>::const_iterator last);
+ Option4AddrLst(uint8_t type, OptionBufferConstIter first,
+ OptionBufferConstIter last);
/// @brief Writes option in a wire-format to a buffer.
///
/// unify pack4() and pack6() and rename them to just pack().
///
/// @param buf output buffer (option will be stored there)
- virtual void
- pack4(isc::util::OutputBuffer& buf);
+ virtual void pack4(isc::util::OutputBuffer& buf);
/// Returns string representation of the option.
///
/// @param indent number of spaces before printing text
///
/// @return string with text representation.
- virtual std::string
- toText(int indent = 0);
+ virtual std::string toText(int indent = 0);
/// Returns length of the complete option (data length + DHCPv4/DHCPv6
/// option header)
/// a couple (1-3) addresses, the overhead is not that big.
///
/// @return address container with addresses
- AddressContainer
- getAddresses() { return addrs_; };
+ AddressContainer getAddresses() { return addrs_; };
/// @brief Sets addresses list.
///
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
}
Option6AddrLst::Option6AddrLst(unsigned short type,
- boost::shared_array<uint8_t> buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int option_len)
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end)
:Option(V6, type) {
- unpack(buf, buf_len, offset, option_len);
+ unpack(begin, end);
}
void
addrs_ = addrs;
}
-unsigned int
-Option6AddrLst::pack(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset) {
- if (len() > buf_len) {
- isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
- << ", buffer=" << buf_len << ": too small buffer.");
- }
+void Option6AddrLst::pack(isc::util::OutputBuffer& buf) {
- writeUint16(type_, &buf[offset]);
- offset += sizeof(uint16_t);
+ buf.writeUint16(type_);
// len() returns complete option length.
// len field contains length without 4-byte option header
- writeUint16(len() - OPTION6_HDR_LEN, &buf[offset]);
- offset += sizeof(uint16_t);
+ buf.writeUint16(len() - getHeaderLen());
// this wrapping is *ugly*. I wish there was a a
for (AddressContainer::const_iterator addr=addrs_.begin();
- addr!=addrs_.end();
- ++addr) {
- memcpy(&buf[offset],
- addr->getAddress().to_v6().to_bytes().data(),
- V6ADDRESS_LEN);
- offset += V6ADDRESS_LEN;
+ addr!=addrs_.end(); ++addr) {
+ buf.writeData(addr->getAddress().to_v6().to_bytes().data(), V6ADDRESS_LEN);
}
-
- return offset;
}
-unsigned int
-Option6AddrLst::unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int option_len) {
- if (offset+option_len > buf_len) {
+void Option6AddrLst::unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ if (distance(begin, end) % 16) {
isc_throw(OutOfRange, "Option " << type_
- << " truncated.");
- }
-
- if (option_len%16) {
- isc_throw(OutOfRange, "Option " << type_
- << " malformed: len=" << option_len
+ << " malformed: len=" << distance(begin, end)
<< " is not divisible by 16.");
}
- while (option_len > 0) {
- addrs_.push_back(IOAddress::from_bytes(AF_INET6, &buf[offset]));
- offset += 16;
- option_len -= 16;
+ while (begin != end) {
+ addrs_.push_back(IOAddress::from_bytes(AF_INET6, &(*begin)));
+ begin += V6ADDRESS_LEN;
}
-
- return offset;
}
std::string Option6AddrLst::toText(int indent /* =0 */) {
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
///
/// @param type option type
/// @param addrs vector of addresses to be stored
- ///
- Option6AddrLst(unsigned short type,
- const AddressContainer& addrs);
+ Option6AddrLst(uint16_t type, const AddressContainer& addrs);
/// @brief Simplified constructor for a single address
///
/// @param type option type
/// @param addr a single address to be stored
- ///
- Option6AddrLst(unsigned short type,
- const isc::asiolink::IOAddress& addr);
+ Option6AddrLst(uint16_t type, const isc::asiolink::IOAddress& addr);
/// @brief Constructor used for parsing received option
///
/// @param type option type
- /// @param buf pointer to packet buffer
- /// @param buf_len length of packet buffer
- /// @param offset offset to beginning of option data
- /// @param len length of option data
- ///
- Option6AddrLst(unsigned short type, boost::shared_array<uint8_t> buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ Option6AddrLst(uint16_t type, OptionBufferConstIter begin,
+ OptionBufferConstIter end);
/// @brief Assembles on-wire form of this option
///
/// @param buf pointer to packet buffer
- /// @param buf_len length of packet buffer
- /// @param offset offset to place, where option is to be stored
- ///
- /// @return offset to the next unused char (just after stored option)
- ///
- unsigned int
- pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
- unsigned int offset);
+ void pack(isc::util::OutputBuffer& buf);
/// @brief Parses received data
///
/// @param buf pointer to packet buffer
- /// @param buf_len length of packet buffer
/// @param offset offset to option data
/// @param parse_len specified option data length
///
/// @return offset to the next unparsed char (just after parsed option)
///
- virtual unsigned int
- unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len);
+ virtual void unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end);
virtual std::string toText(int indent = 0);
/// @brief Sets a single address.
///
/// @param addr a single address to be added
- ///
void setAddress(const isc::asiolink::IOAddress& addr);
/// @brief Sets list of addresses.
///
/// @param addrs a vector of addresses to be added
- ///
void setAddresses(const AddressContainer& addrs);
/// @brief Returns vector with addresses.
/// a couple (1-3) addresses, the overhead is not that big.
///
/// @return address container with addresses
- AddressContainer
- getAddresses() { return addrs_; };
+ AddressContainer getAddresses() { return addrs_; };
// returns data length (data length + DHCPv4/DHCPv6 option header)
virtual uint16_t len();
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <stdint.h>
#include <arpa/inet.h>
#include <sstream>
-#include "exceptions/exceptions.h"
-#include "dhcp/libdhcp++.h"
-#include "dhcp/option6_ia.h"
-#include "dhcp/dhcp6.h"
-#include "util/io_utilities.h"
+#include <exceptions/exceptions.h>
+#include <dhcp/libdhcp++.h>
+#include <dhcp/option6_ia.h>
+#include <dhcp/dhcp6.h>
+#include <util/io_utilities.h>
using namespace std;
using namespace isc;
}
Option6IA::Option6IA(unsigned short type,
- const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int option_len)
+ OptionBufferConstIter begin,
+ OptionBufferConstIter end)
:Option(Option::V6, type) {
- unpack(buf, buf_len, offset, option_len);
+ unpack(begin, end);
}
-unsigned int
-Option6IA::pack(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset) {
- if (offset + len() > buf_len) {
- isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
- << ", buffer=" << buf_len << ": too small buffer.");
- }
-
- if (len() < 16 ) {
- isc_throw(OutOfRange, "Attempt to build malformed IA option: len="
- << len() << " is too small (at least 16 is required).");
- }
-
- uint8_t* ptr = &buf[offset];
-
- ptr = writeUint16(type_, ptr);
- ptr = writeUint16(len() - OPTION6_HDR_LEN, ptr);
- offset += OPTION6_HDR_LEN;
+void Option6IA::pack(isc::util::OutputBuffer& buf) {
+ buf.writeUint16(type_);
+ buf.writeUint16(len() - OPTION6_HDR_LEN);
+ buf.writeUint32(iaid_);
+ buf.writeUint32(t1_);
+ buf.writeUint32(t2_);
- ptr = writeUint32(iaid_, ptr);
- ptr = writeUint32(t1_, ptr);
- ptr = writeUint32(t2_, ptr);
- offset += OPTION6_IA_LEN;
-
- offset = LibDHCP::packOptions6(buf, buf_len, offset, options_);
- return offset;
+ LibDHCP::packOptions6(buf, options_);
}
-unsigned int
-Option6IA::unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len) {
- if ( parse_len < OPTION6_IA_LEN || offset + OPTION6_IA_LEN > buf_len) {
+void Option6IA::unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end) {
+ if (distance(begin, end) < 12) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
+ iaid_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
+ t1_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
- iaid_ = readUint32(&buf[offset]);
- offset += sizeof(uint32_t);
-
- t1_ = readUint32(&buf[offset]);
- offset += sizeof(uint32_t);
-
- t2_ = readUint32(&buf[offset]);
- offset += sizeof(uint32_t);
-
- offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
- parse_len - OPTION6_IA_LEN, options_);
+ t2_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
- return (offset);
+ LibDHCP::unpackOptions6(OptionBuffer(begin, end), options_);
}
std::string Option6IA::toText(int indent /* = 0*/) {
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// Length of IA_NA and IA_PD content
const static size_t OPTION6_IA_LEN = 12;
- /// @brief ctor, used for options constructed, usually during transmission
+ /// @brief Ctor, used for constructed options, usually during transmission.
///
/// @param type option type (usually 4 for IA_NA, 25 for IA_PD)
/// @param iaid identity association identifier (id of IA)
- Option6IA(uint16_t type, unsigned int iaid);
+ Option6IA(uint16_t type, uint32_t iaid);
- /// @brief ctor, used for received options
- ///
- /// boost::shared_array allows sharing a buffer, but it requires that
- /// different instances share pointer to the whole array, not point
- /// to different elements in shared array. Therefore we need to share
- /// pointer to the whole array and remember offset where data for
- /// this option begins
+ /// @brief Ctor, used for received options.
///
/// @param type option type (usually 4 for IA_NA, 25 for IA_PD)
- /// @param buf buffer to be parsed
- /// @param buf_len buffer length
- /// @param offset offset in buffer
- /// @param len number of bytes to parse
- Option6IA(uint16_t type, const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len, unsigned int offset, unsigned int len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ Option6IA(uint16_t type, OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end);
/// Writes option in wire-format to buf, returns pointer to first unused
/// byte after stored option.
///
/// @param buf buffer (option will be stored here)
- /// @param buf_len (buffer length)
- /// @param offset offset place where option should be stored
- ///
- /// @return offset to the first unused byte after stored option
- unsigned int
- pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
- unsigned int offset);
+ void pack(isc::util::OutputBuffer& buf);
/// @brief Parses received buffer
///
/// Parses received buffer and returns offset to the first unused byte after
/// parsed option.
///
- /// @param buf pointer to buffer
- /// @param buf_len length of buf
- /// @param offset offset, where start parsing option
- /// @param parse_len how many bytes should be parsed
- ///
- /// @return offset after last parsed octet
- virtual unsigned int
- unpack(const boost::shared_array<uint8_t>& buf, unsigned int buf_len,
- unsigned int offset, unsigned int parse_len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end);
/// Provides human readable text representation
///
/// Sets T1 timer.
///
/// @param t1 t1 value to be set
- void setT1(unsigned int t1) { t1_=t1; }
-
+ void setT1(uint32_t t1) { t1_=t1; }
/// Sets T2 timer.
///
/// @param t2 t2 value to be set
- void setT2(unsigned int t2) { t2_=t2; }
+ void setT2(uint32_t t2) { t2_=t2; }
/// Returns IA identifier.
///
/// @return IAID value.
///
- unsigned int getIAID() const { return iaid_; }
+ uint32_t getIAID() const { return iaid_; }
/// Returns T1 timer.
///
/// @return T1 value.
- unsigned int getT1() const { return t1_; }
+ uint32_t getT1() const { return t1_; }
/// Returns T2 timer.
///
/// @return T2 value.
- unsigned int getT2() const { return t2_; }
+ uint32_t getT2() const { return t2_; }
/// @brief returns complete length of option
///
/// Returns length of this option, including option header and suboptions
///
/// @return length of this option
- virtual uint16_t
- len();
+ virtual uint16_t len();
protected:
/// keeps IA identifier
- unsigned int iaid_;
+ uint32_t iaid_;
/// keeps T1 timer value
- unsigned int t1_;
+ uint32_t t1_;
/// keeps T2 timer value
- unsigned int t2_;
+ uint32_t t2_;
};
} // isc::dhcp namespace
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
valid_(valid) {
}
-Option6IAAddr::Option6IAAddr(unsigned short type,
- boost::shared_array<uint8_t> buf,
- unsigned int buf_len, unsigned int offset,
- unsigned int option_len)
+Option6IAAddr::Option6IAAddr(uint32_t type, OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end)
:Option(V6, type), addr_("::") {
- unpack(buf, buf_len, offset, option_len);
+ unpack(begin, end);
}
-unsigned int
-Option6IAAddr::pack(boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset) {
- if (len() > buf_len) {
- isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
- << ", buffer=" << buf_len << ": too small buffer.");
- }
-
- uint8_t* ptr = &buf[offset];
+void Option6IAAddr::pack(isc::util::OutputBuffer& buf) {
- ptr = writeUint16(type_, ptr);
+ buf.writeUint16(type_);
// len() returns complete option length. len field contains
// length without 4-byte option header
- ptr = writeUint16(len() - OPTION6_HDR_LEN, ptr);
- offset += OPTION6_HDR_LEN;
+ buf.writeUint16(len() - getHeaderLen());
- memcpy(ptr, addr_.getAddress().to_v6().to_bytes().data(), 16);
- ptr += V6ADDRESS_LEN;
- ptr = writeUint32(preferred_, ptr);
+ buf.writeData(addr_.getAddress().to_v6().to_bytes().data(),
+ isc::asiolink::V6ADDRESS_LEN);
- ptr = writeUint32(valid_, ptr);
- offset += OPTION6_IAADDR_LEN;
+ buf.writeUint32(preferred_);
+ buf.writeUint32(valid_);
- // parse suboption (there shouldn't be any)
- offset = LibDHCP::packOptions6(buf, buf_len, offset, options_);
- return offset;
+ // parse suboption (there shouldn't be any for IAADDR)
+ LibDHCP::packOptions6(buf, options_);
}
-unsigned int
-Option6IAAddr::unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len) {
- if ( parse_len < OPTION6_IAADDR_LEN || offset + OPTION6_IAADDR_LEN > buf_len) {
+void Option6IAAddr::unpack(OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end) {
+ if ( distance(begin, end) < OPTION6_IAADDR_LEN) {
isc_throw(OutOfRange, "Option " << type_ << " truncated");
}
// 16 bytes: IPv6 address
- addr_ = IOAddress::from_bytes(AF_INET6, &buf[offset]);
- offset += V6ADDRESS_LEN;
-
- preferred_ = readUint32(&buf[offset]);
- offset += sizeof(uint32_t);
+ addr_ = IOAddress::from_bytes(AF_INET6, &(*begin));
+ begin += V6ADDRESS_LEN;
- valid_ = readUint32(&buf[offset]);
- offset += sizeof(uint32_t);
- offset = LibDHCP::unpackOptions6(buf, buf_len, offset,
- parse_len - 24, options_);
+ preferred_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
- return offset;
+ valid_ = readUint32( &(*begin) );
+ begin += sizeof(uint32_t);
+ LibDHCP::unpackOptions6(OptionBuffer(begin, end), options_);
}
std::string Option6IAAddr::toText(int indent /* =0 */) {
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// length of the fixed part of the IAADDR option
static const size_t OPTION6_IAADDR_LEN = 24;
- /// @brief ctor, used for options constructed (during transmission)
+ /// @brief Ctor, used for options constructed (during transmission).
///
/// @param type option type
/// @param addr reference to an address
/// @param preferred address preferred lifetime (in seconds)
/// @param valid address valid lifetime (in seconds)
- Option6IAAddr(unsigned short type, const isc::asiolink::IOAddress& addr,
- unsigned int preferred, unsigned int valid);
+ Option6IAAddr(uint16_t type, const isc::asiolink::IOAddress& addr,
+ uint32_t preferred, uint32_t valid);
- /// ctor, used for received options
- /// boost::shared_array allows sharing a buffer, but it requires that
- /// different instances share pointer to the whole array, not point
- /// to different elements in shared array. Therefore we need to share
- /// pointer to the whole array and remember offset where data for
- /// this option begins
+ /// @brief ctor, used for received options.
///
/// @param type option type
- /// @param buf pointer to a buffer
- /// @param offset offset to first data byte in that buffer
- /// @param len data length of this option
- Option6IAAddr(unsigned short type, boost::shared_array<uint8_t> buf,
- unsigned int buf_len, unsigned int offset, unsigned int len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ Option6IAAddr(uint32_t type, OptionBuffer::const_iterator begin,
+ OptionBuffer::const_iterator end);
/// @brief Writes option in wire-format.
///
/// byte after stored option.
///
/// @param buf pointer to a buffer
- /// @param buf_len length of the buffer
- /// @param offset offset to place, where option shout be stored
- ///
- /// @return offset to first unused byte after stored option
- unsigned int
- pack(boost::shared_array<uint8_t>& buf, unsigned int buf_len,
- unsigned int offset);
+ void pack(isc::util::OutputBuffer& buf);
/// @brief Parses buffer.
///
/// parsed option.
///
/// @param buf pointer to buffer
- /// @param buf_len length of buf
- /// @param offset offset, where start parsing option
- /// @param parse_len how many bytes should be parsed
- ///
- /// @return offset after last parsed octet
- virtual unsigned int
- unpack(const boost::shared_array<uint8_t>& buf,
- unsigned int buf_len,
- unsigned int offset,
- unsigned int parse_len);
+ /// @param begin iterator to first byte of option data
+ /// @param end iterator to end of option data (first byte after option end)
+ virtual void unpack(OptionBufferConstIter begin,
+ OptionBufferConstIter end);
/// Returns string representation of the option.
///
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
-#include <boost/shared_array.hpp>
#include "asiolink/io_address.h"
#include "util/buffer.h"
#include "dhcp/option.h"
/// This function is useful mainly for debugging.
///
/// @return string with text representation
- std::string
- toText();
+ std::string toText();
/// @brief Returns the size of the required buffer to build the packet.
///
/// the current set of packet options.
///
/// @return number of bytes required to build this packet
- size_t
- len();
+ size_t len();
- /// Sets hops field
+ /// @brief Sets hops field.
///
/// @param hops value to be set
- void
- setHops(uint8_t hops) { hops_ = hops; };
+ void setHops(uint8_t hops) { hops_ = hops; };
- /// Returns hops field
+ /// @brief Returns hops field.
///
/// @return hops field
- uint8_t
- getHops() const { return (hops_); };
+ uint8_t getHops() const { return (hops_); };
// Note: There's no need to manipulate OP field directly,
// thus no setOp() method. See op_ comment.
- /// Returns op field
+ /// @brief Returns op field.
///
/// @return op field
- uint8_t
- getOp() const { return (op_); };
+ uint8_t getOp() const { return (op_); };
- /// Sets secs field
+ /// @brief Sets secs field.
///
/// @param secs value to be set
- void
- setSecs(uint16_t secs) { secs_ = secs; };
+ void setSecs(uint16_t secs) { secs_ = secs; };
- /// Returns secs field
+ /// @brief Returns secs field.
///
/// @return secs field
- uint16_t
- getSecs() const { return (secs_); };
+ uint16_t getSecs() const { return (secs_); };
- /// Sets flags field
+ /// @brief Sets flags field.
///
/// @param flags value to be set
- void
- setFlags(uint16_t flags) { flags_ = flags; };
+ void setFlags(uint16_t flags) { flags_ = flags; };
- /// Returns flags field
+ /// @brief Returns flags field.
///
/// @return flags field
- uint16_t
- getFlags() const { return (flags_); };
+ uint16_t getFlags() const { return (flags_); };
- /// Returns ciaddr field
+ /// @brief Returns ciaddr field.
///
/// @return ciaddr field
const isc::asiolink::IOAddress&
getCiaddr() const { return (ciaddr_); };
- /// Sets ciaddr field
+ /// @brief Sets ciaddr field.
///
/// @param ciaddr value to be set
void
setCiaddr(const isc::asiolink::IOAddress& ciaddr) { ciaddr_ = ciaddr; };
- /// Returns siaddr field
+ /// @brief Returns siaddr field.
///
/// @return siaddr field
const isc::asiolink::IOAddress&
getSiaddr() const { return (siaddr_); };
- /// Sets siaddr field
+ /// @brief Sets siaddr field.
///
/// @param siaddr value to be set
void
setSiaddr(const isc::asiolink::IOAddress& siaddr) { siaddr_ = siaddr; };
- /// Returns yiaddr field
+ /// @brief Returns yiaddr field.
///
/// @return yiaddr field
const isc::asiolink::IOAddress&
getYiaddr() const { return (yiaddr_); };
- /// Sets yiaddr field
+ /// @brief Sets yiaddr field.
///
/// @param yiaddr value to be set
void
setYiaddr(const isc::asiolink::IOAddress& yiaddr) { yiaddr_ = yiaddr; };
- /// Returns giaddr field
+ /// @brief Returns giaddr field.
///
/// @return giaddr field
const isc::asiolink::IOAddress&
getGiaddr() const { return (giaddr_); };
- /// Sets giaddr field
+ /// @brief Sets giaddr field.
///
/// @param giaddr value to be set
void
setGiaddr(const isc::asiolink::IOAddress& giaddr) { giaddr_ = giaddr; };
- /// Returns value of transaction-id field
+ /// @brief Returns value of transaction-id field.
///
/// @return transaction-id
uint32_t getTransid() const { return (transid_); };
- /// Returns message type (e.g. 1 = DHCPDISCOVER)
+ /// @brief Returns message type (e.g. 1 = DHCPDISCOVER).
///
/// @return message type
uint8_t
getType() const { return (msg_type_); }
- /// Sets message type (e.g. 1 = DHCPDISCOVER)
+ /// @brief Sets message type (e.g. 1 = DHCPDISCOVER).
///
/// @param type message type to be set
void setType(uint8_t type) { msg_type_=type; };
/// null-terminated. Do not use strlen() or similar on it.
///
/// @return sname field
- const std::vector<uint8_t>
+ const OptionBuffer
getSname() const { return (std::vector<uint8_t>(sname_, &sname_[MAX_SNAME_LEN])); };
- /// Sets sname field
+ /// @brief Sets sname field.
///
/// @param sname value to be set
- void
- setSname(const uint8_t* sname, size_t snameLen = MAX_SNAME_LEN);
+ void setSname(const uint8_t* sname, size_t snameLen = MAX_SNAME_LEN);
/// @brief Returns file field
///
/// null-terminated. Do not use strlen() or similar on it.
///
/// @return pointer to file field
- const std::vector<uint8_t>
+ const OptionBuffer
getFile() const { return (std::vector<uint8_t>(file_, &file_[MAX_FILE_LEN])); };
/// Sets file field
// end of real DHCPv4 fields
- /// output buffer (used during message
+ /// output buffer (used during message transmission)
isc::util::OutputBuffer bufferOut_;
// that's the data of input buffer used in RX packet. Note that
isc::dhcp::Option::OptionCollection options_;
}; // Pkt4 class
+typedef boost::shared_ptr<Pkt4> Pkt4Ptr;
+
} // isc::dhcp namespace
} // isc namespace
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
namespace isc {
-Pkt6::Pkt6(unsigned int dataLen, DHCPv6Proto proto /* = UDP */)
- :data_len_(dataLen),
- local_addr_("::"),
- remote_addr_("::"),
- iface_(""),
- ifindex_(-1),
- local_port_(-1),
- remote_port_(-1),
- proto_(proto),
- msg_type_(-1),
- transid_(rand()%0xffffff)
-{
-
- data_ = boost::shared_array<uint8_t>(new uint8_t[dataLen]);
- data_len_ = dataLen;
+Pkt6::Pkt6(const uint8_t* buf, uint32_t buf_len, DHCPv6Proto proto /* = UDP */) :
+ proto_(proto),
+ msg_type_(-1),
+ transid_(rand()%0xffffff),
+ iface_(""),
+ ifindex_(-1),
+ local_addr_("::"),
+ remote_addr_("::"),
+ local_port_(-1),
+ remote_port_(-1),
+ bufferOut_(0) {
+ data_.resize(buf_len);
+ memcpy(&data_[0], buf, buf_len);
}
-Pkt6::Pkt6(uint8_t msg_type,
- unsigned int transid,
- DHCPv6Proto proto /*= UDP*/)
- :local_addr_("::"),
- remote_addr_("::"),
- iface_(""),
- ifindex_(-1),
- local_port_(-1),
- remote_port_(-1),
- proto_(proto),
- msg_type_(msg_type),
- transid_(transid) {
-
- data_ = boost::shared_array<uint8_t>(new uint8_t[4]);
- data_len_ = 4;
+Pkt6::Pkt6(uint8_t msg_type, unsigned int transid, DHCPv6Proto proto /*= UDP*/) :
+ proto_(proto),
+ msg_type_(msg_type),
+ transid_(transid),
+ iface_(""),
+ ifindex_(-1),
+ local_addr_("::"),
+ remote_addr_("::"),
+ local_port_(-1),
+ remote_port_(-1),
+ bufferOut_(0) {
}
-unsigned short
-Pkt6::len() {
- unsigned int length = DHCPV6_PKT_HDR_LEN; // DHCPv6 header
+uint16_t Pkt6::len() {
+ uint16_t length = DHCPV6_PKT_HDR_LEN; // DHCPv6 header
for (Option::OptionCollection::iterator it = options_.begin();
it != options_.end();
// It is better to implement a method in IOAddress that extracts
// vector<uint8_t>
- unsigned short length = len();
- if (data_len_ < length) {
- cout << "Previous len=" << data_len_ << ", allocating new buffer: len="
- << length << endl;
-
- // May throw exception if out of memory. That is rather fatal,
- // so we don't catch this
- data_ = boost::shared_array<uint8_t>(new uint8_t[length]);
- data_len_ = length;
- }
-
- data_len_ = length;
try {
// DHCPv6 header: message-type (1 octect) + transaction id (3 octets)
- data_[0] = msg_type_;
-
+ bufferOut_.writeUint8(msg_type_);
// store 3-octet transaction-id
- data_[1] = (transid_ >> 16) & 0xff;
- data_[2] = (transid_ >> 8) & 0xff;
- data_[3] = (transid_) & 0xff;
+ bufferOut_.writeUint8( (transid_ >> 16) & 0xff );
+ bufferOut_.writeUint8( (transid_ >> 8) & 0xff );
+ bufferOut_.writeUint8( (transid_) & 0xff );
// the rest are options
- unsigned short offset = LibDHCP::packOptions6(data_, length,
- 4/*offset*/,
- options_);
-
- // sanity check
- if (offset != length) {
- isc_throw(OutOfRange, "Packet build failed: expected size="
- << length << ", actual len=" << offset);
- }
+ LibDHCP::packOptions6(bufferOut_, options_);
}
catch (const Exception& e) {
cout << "Packet build failed:" << e.what() << endl;
return (false);
}
- // Limited verbosity of this method
- // cout << "Packet built, len=" << len() << endl;
return (true);
}
bool
Pkt6::unpackUDP() {
- if (data_len_ < 4) {
- std::cout << "DHCPv6 packet truncated. Only " << data_len_
+ if (data_.size() < 4) {
+ std::cout << "DHCPv6 packet truncated. Only " << data_.size()
<< " bytes. Need at least 4." << std::endl;
return (false);
}
((data_[2]) << 8) + (data_[3]);
transid_ = transid_ & 0xffffff;
- unsigned int offset = LibDHCP::unpackOptions6(data_,
- data_len_,
- 4, //offset
- data_len_ - 4,
- options_);
- if (offset != data_len_) {
- cout << "DHCPv6 packet contains trailing garbage. Parsed "
- << offset << " bytes, packet is " << data_len_ << " bytes."
- << endl;
- // just a warning. Ignore trailing garbage and continue
+ try {
+ OptionBuffer opt_buffer(data_.begin() + 4, data_.end());
+
+ LibDHCP::unpackOptions6(opt_buffer, options_);
+ } catch (const Exception& e) {
+ cout << "Packet parsing failed:" << e.what() << endl;
+ return (false);
}
return (true);
}
return (false); // can't find option to be deleted
}
+void Pkt6::repack() {
+ cout << "Convering RX packet to TX packet: " << data_.size() << " bytes." << endl;
+
+ bufferOut_.writeData(&data_[0], data_.size());
+}
+
+
};
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
/// @param msg_type type of message (SOLICIT=1, ADVERTISE=2, ...)
/// @param transid transaction-id
/// @param proto protocol (TCP or UDP)
- Pkt6(unsigned char msg_type,
- unsigned int transid,
+ Pkt6(uint8_t msg_type,
+ uint32_t transid,
DHCPv6Proto proto = UDP);
/// Constructor, used in message transmission
///
/// Creates new message. Transaction-id will randomized.
///
- /// @param len size of buffer to be allocated for this packet.
+ /// @param buf pointer to a buffer of received packet content
+ /// @param len size of buffer of received packet content
/// @param proto protocol (usually UDP, but TCP will be supported eventually)
- Pkt6(unsigned int len, DHCPv6Proto proto = UDP);
+ Pkt6(const uint8_t* buf, uint32_t len, DHCPv6Proto proto = UDP);
/// @brief Prepares on-wire format.
///
/// will be set in data_len_.
///
/// @return true if packing procedure was successful
- bool
- pack();
+ bool pack();
/// @brief Dispatch method that handles binary packet parsing.
///
/// unpackTCP).
///
/// @return true if parsing was successful
- bool
- unpack();
+ bool unpack();
- /// Returns protocol of this packet (UDP or TCP)
+ /// @brief Returns reference to output buffer.
+ ///
+ /// Returned buffer will contain reasonable data only for
+ /// output (TX) packet and after pack() was called. This buffer
+ /// is only valid till Pkt4 object is valid.
+ ///
+ /// RX packet or TX packet before pack() will return buffer with
+ /// zero length
+ ///
+ /// @return reference to output buffer
+ const isc::util::OutputBuffer& getBuffer() const { return (bufferOut_); };
+
+
+ /// @brief Returns reference to input buffer.
+ ///
+ /// @return reference to input buffer
+ const OptionBuffer& getData() const { return(data_); }
+
+ /// @brief Returns protocol of this packet (UDP or TCP).
///
/// @return protocol type
- DHCPv6Proto
- getProto();
+ DHCPv6Proto getProto();
/// Sets protocol of this packet.
///
/// @param proto protocol (UDP or TCP)
- ///
- void
- setProto(DHCPv6Proto proto = UDP) { proto_ = proto; }
+ void setProto(DHCPv6Proto proto = UDP) { proto_ = proto; }
/// @brief Returns text representation of the packet.
///
/// This function is useful mainly for debugging.
///
/// @return string with text representation
- std::string
- toText();
+ std::string toText();
/// @brief Returns calculated length of the packet.
///
- /// This function returns size of required buffer to buld this packet.
- /// To use that function, options_ field must be set.
+ /// This function returns size of all options including DHCPv6
+ /// header. To use that function, options_ field must be set.
///
/// @return number of bytes required to build this packet
- unsigned short
- len();
+ uint16_t len();
/// Returns message type (e.g. 1 = SOLICIT)
///
/// @return message type
- unsigned char
- getType() { return (msg_type_); }
+ uint8_t getType() { return (msg_type_); }
/// Sets message type (e.g. 1 = SOLICIT)
///
/// @param type message type to be set
- void setType(unsigned char type) { msg_type_=type; };
+ void setType(uint8_t type) { msg_type_=type; };
/// Returns value of transaction-id field
///
/// @return transaction-id
- unsigned int getTransid() { return (transid_); };
+ uint32_t getTransid() { return (transid_); };
/// Adds an option to this packet.
///
/// @param opt option to be added.
- void addOption(boost::shared_ptr<isc::dhcp::Option> opt);
+ void addOption(OptionPtr opt);
/// @brief Returns the first option of specified type.
///
/// @param opt_type option type we are looking for
///
/// @return pointer to found option (or NULL)
- boost::shared_ptr<isc::dhcp::Option>
- getOption(unsigned short type);
+ OptionPtr getOption(uint16_t type);
/// Attempts to delete first suboption of requested type
///
/// @param type Type of option to be deleted.
///
/// @return true if option was deleted, false if no such option existed
- bool
- delOption(unsigned short type);
+ bool delOption(uint16_t type);
- /// TODO need getter/setter wrappers
- /// and hide following fields as protected
+ /// @brief This method copies data from output buffer to input buffer
+ ///
+ /// This is useful only in testing
+ void repack();
- /// buffer that holds memory. It is shared_array as options may
- /// share pointer to this buffer
- boost::shared_array<uint8_t> data_;
+ /// @brief Sets remote address.
+ ///
+ /// @params remote specifies remote address
+ void setRemoteAddr(const isc::asiolink::IOAddress& remote) {
+ remote_addr_ = remote;
+ }
- /// length of the data
- unsigned int data_len_;
+ /// @brief Returns remote address
+ ///
+ /// @return remote address
+ const isc::asiolink::IOAddress& getRemoteAddr() {
+ return (remote_addr_);
+ }
- /// local address (dst if receiving packet, src if sending packet)
- isc::asiolink::IOAddress local_addr_;
+ /// @brief Sets local address.
+ ///
+ /// @params local specifies local address
+ void setLocalAddr(const isc::asiolink::IOAddress& local) {
+ local_addr_ = local;
+ }
- /// remote address (src if receiving packet, dst if sending packet)
- isc::asiolink::IOAddress remote_addr_;
+ /// @brief Returns local address.
+ ///
+ /// @return local address
+ const isc::asiolink::IOAddress& getLocalAddr() {
+ return (local_addr_);
+ }
- /// name of the network interface the packet was received/to be sent over
- std::string iface_;
+ /// @brief Sets local port.
+ ///
+ /// @params local specifies local port
+ void setLocalPort(uint16_t local) { local_port_ = local; }
- /// @brief interface index
+ /// @brief Returns local port.
///
- /// interface index (each network interface has assigned unique ifindex
- /// it is functional equvalent of name, but sometimes more useful, e.g.
- /// when using crazy systems that allow spaces in interface names
- /// e.g. windows
- int ifindex_;
+ /// @return local port
+ uint16_t getLocalPort() { return (local_port_); }
- /// local TDP or UDP port
- int local_port_;
+ /// @brief Sets remote port.
+ ///
+ /// @params remote specifies remote port
+ void setRemotePort(uint16_t remote) { remote_port_ = remote; }
- /// remote TCP or UDP port
- int remote_port_;
+ /// @brief Returns remote port.
+ ///
+ /// @return remote port
+ uint16_t getRemotePort() { return (remote_port_); }
+
+ /// @brief Sets interface index.
+ ///
+ /// @param ifindex specifies interface index.
+ void setIndex(uint32_t ifindex) { ifindex_ = ifindex; };
+
+ /// @brief Returns interface index.
+ ///
+ /// @return interface index
+ uint32_t getIndex() const { return (ifindex_); };
+
+ /// @brief Returns interface name.
+ ///
+ /// Returns interface name over which packet was received or is
+ /// going to be transmitted.
+ ///
+ /// @return interface name
+ std::string getIface() const { return iface_; };
+
+ /// @brief Sets interface name.
+ ///
+ /// Sets interface name over which packet was received or is
+ /// going to be transmitted.
+ ///
+ /// @return interface name
+ void setIface(const std::string& iface ) { iface_ = iface; };
/// TODO Need to implement getOptions() as well
/// DHCPv6 transaction-id
unsigned int transid_;
+
+ /// unparsed data (in received packets)
+ OptionBuffer data_;
+
+ /// name of the network interface the packet was received/to be sent over
+ std::string iface_;
+
+ /// @brief interface index
+ ///
+ /// interface index (each network interface has assigned unique ifindex
+ /// it is functional equvalent of name, but sometimes more useful, e.g.
+ /// when using crazy systems that allow spaces in interface names
+ /// e.g. windows
+ int ifindex_;
+
+ /// local address (dst if receiving packet, src if sending packet)
+ isc::asiolink::IOAddress local_addr_;
+
+ /// remote address (src if receiving packet, dst if sending packet)
+ isc::asiolink::IOAddress remote_addr_;
+
+ /// local TDP or UDP port
+ int local_port_;
+
+ /// remote TCP or UDP port
+ int remote_port_;
+
+ /// output buffer (used during message transmission)
+ isc::util::OutputBuffer bufferOut_;
+
}; // Pkt6 class
+typedef boost::shared_ptr<Pkt6> Pkt6Ptr;
+
} // isc::dhcp namespace
} // isc namespace
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
IOAddress loAddr("::1");
- Pkt6 pkt6(128);
- pkt6.iface_ = LOOPBACK;
+ Pkt6 pkt6(DHCPV6_SOLICIT, 123);
+ pkt6.setIface(LOOPBACK);
// bind multicast socket to port 10547
int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
EXPECT_GT(socket1, 0);
EXPECT_GT(socket2, 0);
- boost::shared_ptr<Pkt6> sendPkt(new Pkt6(128) );
// prepare dummy payload
+ uint8_t data[128];
for (int i=0;i<128; i++) {
- sendPkt->data_[i] = i;
+ data[i] = i;
}
+ Pkt6Ptr sendPkt = Pkt6Ptr(new Pkt6(data, 128));
- sendPkt->remote_port_ = 10547;
- sendPkt->remote_addr_ = IOAddress("::1");
- sendPkt->ifindex_ = 1;
- sendPkt->iface_ = LOOPBACK;
+ sendPkt->repack();
- boost::shared_ptr<Pkt6> rcvPkt;
+ sendPkt->setRemotePort(10547);
+ sendPkt->setRemoteAddr(IOAddress("::1"));
+ sendPkt->setIndex(1);
+ sendPkt->setIface(LOOPBACK);
+
+ Pkt6Ptr rcvPkt;
EXPECT_EQ(true, ifacemgr->send(sendPkt));
ASSERT_TRUE( rcvPkt ); // received our own packet
// let's check that we received what was sent
- EXPECT_EQ(sendPkt->data_len_, rcvPkt->data_len_);
- EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
- rcvPkt->data_len_) );
+ ASSERT_EQ(sendPkt->getData().size(), rcvPkt->getData().size());
+ EXPECT_EQ(0, memcmp(&sendPkt->getData()[0], &rcvPkt->getData()[0],
+ rcvPkt->getData().size()));
- EXPECT_EQ(sendPkt->remote_addr_.toText(), rcvPkt->remote_addr_.toText());
+ EXPECT_EQ(sendPkt->getRemoteAddr().toText(), rcvPkt->getRemoteAddr().toText());
// since we opened 2 sockets on the same interface and none of them is multicast,
// none is preferred over the other for sending data, so we really should not
// assume the one or the other will always be choosen for sending data. Therefore
// we should accept both values as source ports.
- EXPECT_TRUE( (rcvPkt->remote_port_ == 10546) || (rcvPkt->remote_port_ == 10547) );
+ EXPECT_TRUE( (rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547) );
delete ifacemgr;
}
loopback->addSocket(sock1);
loopback->addSocket(sock2);
- Pkt6 pkt6(100);
+ Pkt6 pkt6(DHCPV6_REPLY, 123456);
// pkt6 dos not have interface set yet
EXPECT_THROW(
);
// try to send over non-existing interface
- pkt6.iface_ = "nosuchinterface45";
+ pkt6.setIface("nosuchinterface45");
EXPECT_THROW(
ifacemgr->getSocket(pkt6),
BadValue
);
// this will work
- pkt6.iface_ = LOOPBACK;
+ pkt6.setIface(LOOPBACK);
EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
bool deleted = false;
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
};
TEST(LibDhcpTest, packOptions6) {
- boost::shared_array<uint8_t> buf(new uint8_t[512]);
+ OptionBuffer buf(512);
isc::dhcp::Option::OptionCollection opts; // list of options
// generate content for options
buf[i]=i+100;
}
- boost::shared_ptr<Option> opt1(new Option(Option::V6, 12, buf, 0, 5));
- boost::shared_ptr<Option> opt2(new Option(Option::V6, 13, buf, 5, 3));
- boost::shared_ptr<Option> opt3(new Option(Option::V6, 14, buf, 8, 2));
- boost::shared_ptr<Option> opt4(new Option(Option::V6,256, buf,10, 4));
- boost::shared_ptr<Option> opt5(new Option(Option::V6,257, buf,14, 1));
+ OptionPtr opt1(new Option(Option::V6, 12, buf.begin() + 0, buf.begin() + 5));
+ OptionPtr opt2(new Option(Option::V6, 13, buf.begin() + 5, buf.begin() + 8));
+ OptionPtr opt3(new Option(Option::V6, 14, buf.begin() + 8, buf.begin() + 10));
+ OptionPtr opt4(new Option(Option::V6,256, buf.begin() + 10,buf.begin() + 14));
+ OptionPtr opt5(new Option(Option::V6,257, buf.begin() + 14,buf.begin() + 15));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt1));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt2));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt3));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt4));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt5));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt1));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt2));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt3));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt4));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt5));
+
+ OutputBuffer assembled(512);
- unsigned int offset;
EXPECT_NO_THROW ({
- offset = LibDHCP::packOptions6(buf, 512, 100, opts);
+ LibDHCP::packOptions6(assembled, opts);
});
- EXPECT_EQ(135, offset); // options should take 35 bytes
- EXPECT_EQ(0, memcmp(&buf[100], packed, 35) );
+ EXPECT_EQ(35, assembled.getLength()); // options should take 35 bytes
+ EXPECT_EQ(0, memcmp(assembled.getData(), packed, 35) );
}
TEST(LibDhcpTest, unpackOptions6) {
// specific derived classes.
isc::dhcp::Option::OptionCollection options; // list of options
- // we can't use packed directly, as shared_array would try to
- // free it eventually
- boost::shared_array<uint8_t> buf(new uint8_t[512]);
+ OptionBuffer buf(512);
memcpy(&buf[0], packed, 35);
- unsigned int offset;
EXPECT_NO_THROW ({
- offset = LibDHCP::unpackOptions6(buf, 512, 0, 35, options);
+ LibDHCP::unpackOptions6(OptionBuffer(buf.begin(), buf.begin()+35), options);
});
- EXPECT_EQ(35, offset); // parsed first 35 bytes (offset 0..34)
EXPECT_EQ(options.size(), 5); // there should be 5 options
isc::dhcp::Option::OptionCollection::const_iterator x = options.find(12);
payload[i][2] = i*10+2;
}
- boost::shared_ptr<Option> opt1(new Option(Option::V4, 12, payload[0]));
- boost::shared_ptr<Option> opt2(new Option(Option::V4, 13, payload[1]));
- boost::shared_ptr<Option> opt3(new Option(Option::V4, 14, payload[2]));
- boost::shared_ptr<Option> opt4(new Option(Option::V4,254, payload[3]));
- boost::shared_ptr<Option> opt5(new Option(Option::V4,128, payload[4]));
+ OptionPtr opt1(new Option(Option::V4, 12, payload[0]));
+ OptionPtr opt2(new Option(Option::V4, 13, payload[1]));
+ OptionPtr opt3(new Option(Option::V4, 14, payload[2]));
+ OptionPtr opt4(new Option(Option::V4,254, payload[3]));
+ OptionPtr opt5(new Option(Option::V4,128, payload[4]));
isc::dhcp::Option::OptionCollection opts; // list of options
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt1));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt2));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt3));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt4));
- opts.insert(pair<int, boost::shared_ptr<Option> >(opt1->getType(), opt5));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt1));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt2));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt3));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt4));
+ opts.insert(pair<int, OptionPtr >(opt1->getType(), opt5));
vector<uint8_t> expVect(v4Opts, v4Opts + sizeof(v4Opts));
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <dhcp/dhcp6.h>
#include <dhcp/option.h>
#include <dhcp/option6_addrlst.h>
+#include <util/buffer.h>
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
+using namespace isc::util;
namespace {
class Option6AddrLstTest : public ::testing::Test {
public:
- Option6AddrLstTest() {
+ Option6AddrLstTest(): buf_(255), outBuf_(255) {
+ for (int i = 0; i < 255; i++) {
+ buf_[i] = 255 - i;
+ }
}
+ OptionBuffer buf_;
+ OutputBuffer outBuf_;
};
TEST_F(Option6AddrLstTest, basic) {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
- boost::shared_array<uint8_t> buf(new uint8_t[300]);
- for (int i = 0; i < 300; i++)
- buf[i] = 0;
-
- memcpy(&buf[0], sampledata, 48);
+ memcpy(&buf_[0], sampledata, 48);
// just a single address
Option6AddrLst* opt1 = 0;
EXPECT_NO_THROW(
- opt1 = new Option6AddrLst(D6O_NAME_SERVERS, buf, 128, 0, 16);
+ opt1 = new Option6AddrLst(D6O_NAME_SERVERS, buf_.begin(), buf_.begin() + 16 );
);
EXPECT_EQ(Option::V6, opt1->getUniverse());
IOAddress addr = addrs[0];
EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
- // pack this option again in the same buffer, but in
- // different place
- int offset = opt1->pack(buf,300, 100);
+ // pack this option
+ opt1->pack(outBuf_);
- EXPECT_EQ(120, offset);
- EXPECT_EQ( 0, memcmp(expected1, &buf[100], 20) );
+ EXPECT_EQ(20, outBuf_.getLength());
+ EXPECT_EQ( 0, memcmp(expected1, outBuf_.getData(), 20) );
// two addresses
Option6AddrLst* opt2 = 0;
EXPECT_NO_THROW(
- opt2 = new Option6AddrLst(D6O_SIP_SERVERS_ADDR, buf, 128, 0, 32);
+ opt2 = new Option6AddrLst(D6O_SIP_SERVERS_ADDR, buf_.begin(), buf_.begin() + 32);
);
EXPECT_EQ(D6O_SIP_SERVERS_ADDR, opt2->getType());
EXPECT_EQ(36, opt2->len());
EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
- // pack this option again in the same buffer, but in
- // different place
- offset = opt2->pack(buf,300, 150);
+ // pack this option
+ outBuf_.clear();
+ opt2->pack(outBuf_);
- EXPECT_EQ(150+36, offset);
- EXPECT_EQ( 0, memcmp(expected2, &buf[150], 36));
+ EXPECT_EQ(36, outBuf_.getLength() );
+ EXPECT_EQ( 0, memcmp(expected2, outBuf_.getData(), 36));
// three addresses
Option6AddrLst* opt3 = 0;
EXPECT_NO_THROW(
- opt3 = new Option6AddrLst(D6O_NIS_SERVERS, buf, 128, 0, 48);
+ opt3 = new Option6AddrLst(D6O_NIS_SERVERS, buf_.begin(), buf_.begin() + 48);
);
EXPECT_EQ(D6O_NIS_SERVERS, opt3->getType());
EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addrs[2].toText());
- // pack this option again in the same buffer, but in
- // different place
- offset = opt3->pack(buf,300, 200);
+ // pack this option
+ outBuf_.clear();
+ opt3->pack(outBuf_);
- EXPECT_EQ(252, offset);
- EXPECT_EQ( 0, memcmp(expected3, &buf[200], 52) );
+ EXPECT_EQ(52, outBuf_.getLength());
+ EXPECT_EQ( 0, memcmp(expected3, outBuf_.getData(), 52) );
EXPECT_NO_THROW(
delete opt1;
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <arpa/inet.h>
#include <gtest/gtest.h>
-#include <boost/shared_array.hpp>
-#include <boost/shared_ptr.hpp>
-
-#include "dhcp/dhcp6.h"
-#include "dhcp/option.h"
-#include "dhcp/option6_ia.h"
-#include "dhcp/option6_iaaddr.h"
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/option6_ia.h>
+#include <dhcp/option6_iaaddr.h>
+#include <util/buffer.h>
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::asiolink;
+using namespace isc::util;
namespace {
class Option6IATest : public ::testing::Test {
public:
- Option6IATest() {
+ Option6IATest(): buf_(255), outBuf_(255) {
+ for (int i = 0; i < 255; i++) {
+ buf_[i] = 255 - i;
+ }
}
+ OptionBuffer buf_;
+ OutputBuffer outBuf_;
};
TEST_F(Option6IATest, basic) {
+ buf_[0] = 0xa1; // iaid
+ buf_[1] = 0xa2;
+ buf_[2] = 0xa3;
+ buf_[3] = 0xa4;
- boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
- for (int i = 0; i < 128; i++)
- simple_buf[i] = 0;
- simple_buf[0] = 0xa1; // iaid
- simple_buf[1] = 0xa2;
- simple_buf[2] = 0xa3;
- simple_buf[3] = 0xa4;
-
- simple_buf[4] = 0x81; // T1
- simple_buf[5] = 0x02;
- simple_buf[6] = 0x03;
- simple_buf[7] = 0x04;
+ buf_[4] = 0x81; // T1
+ buf_[5] = 0x02;
+ buf_[6] = 0x03;
+ buf_[7] = 0x04;
- simple_buf[8] = 0x84; // T2
- simple_buf[9] = 0x03;
- simple_buf[10] = 0x02;
- simple_buf[11] = 0x01;
+ buf_[8] = 0x84; // T2
+ buf_[9] = 0x03;
+ buf_[10] = 0x02;
+ buf_[11] = 0x01;
// create an option
// unpack() is called from constructor
Option6IA* opt = new Option6IA(D6O_IA_NA,
- simple_buf,
- 128,
- 0,
- 12);
+ buf_.begin(),
+ buf_.begin() + 12);
EXPECT_EQ(Option::V6, opt->getUniverse());
EXPECT_EQ(D6O_IA_NA, opt->getType());
// different place
// test for pack()
- int offset = opt->pack(simple_buf, 128, 60);
+ opt->pack(outBuf_);
- // 4 bytes header + 4 bytes content
- EXPECT_EQ(12, opt->len() - 4);
+ // 12 bytes header + 4 bytes content
+ EXPECT_EQ(12, opt->len() - opt->getHeaderLen());
EXPECT_EQ(D6O_IA_NA, opt->getType());
- EXPECT_EQ(offset, 76); // 60 + lenght(IA_NA) = 76
+ EXPECT_EQ(16, outBuf_.getLength()); // lenght(IA_NA) = 16
// check if pack worked properly:
+ InputBuffer out(outBuf_.getData(), outBuf_.getLength());
+
// if option type is correct
- EXPECT_EQ(D6O_IA_NA, simple_buf[60]*256 + simple_buf[61]);
+ EXPECT_EQ(D6O_IA_NA, out.readUint16());
// if option length is correct
- EXPECT_EQ(12, simple_buf[62]*256 + simple_buf[63]);
+ EXPECT_EQ(12, out.readUint16());
// if iaid is correct
- unsigned int iaid = htonl(*(unsigned int*)&simple_buf[64]);
- EXPECT_EQ(0xa1a2a3a4, iaid );
+ EXPECT_EQ(0xa1a2a3a4, out.readUint32() );
// if T1 is correct
- EXPECT_EQ(0x81020304, (simple_buf[68] << 24) +
- (simple_buf[69] << 16) +
- (simple_buf[70] << 8) +
- (simple_buf[71]) );
+ EXPECT_EQ(0x81020304, out.readUint32() );
// if T1 is correct
- EXPECT_EQ(0x84030201, (simple_buf[72] << 24) +
- (simple_buf[73] << 16) +
- (simple_buf[74] << 8) +
- (simple_buf[75]) );
+ EXPECT_EQ(0x84030201, out.readUint32() );
EXPECT_NO_THROW(
delete opt;
}
TEST_F(Option6IATest, simple) {
- boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
- for (int i = 0; i < 128; i++)
- simple_buf[i] = 0;
-
Option6IA * ia = new Option6IA(D6O_IA_NA, 1234);
ia->setT1(2345);
ia->setT2(3456);
);
}
+
// test if option can build suboptions
TEST_F(Option6IATest, suboptions_pack) {
- boost::shared_array<uint8_t> buf(new uint8_t[128]);
- for (int i=0; i<128; i++)
- buf[i] = 0;
- buf[0] = 0xff;
- buf[1] = 0xfe;
- buf[2] = 0xfc;
+ buf_[0] = 0xff;
+ buf_[1] = 0xfe;
+ buf_[2] = 0xfc;
Option6IA * ia = new Option6IA(D6O_IA_NA, 0x13579ace);
ia->setT1(0x2345);
ia->setT2(0x3456);
- boost::shared_ptr<Option> sub1(new Option(Option::V6,
+ OptionPtr sub1(new Option(Option::V6,
0xcafe));
boost::shared_ptr<Option6IAAddr> addr1(
0, 0 // len
};
- int offset = ia->pack(buf, 128, 10);
- ASSERT_EQ(offset, 10 + 48);
+ ia->pack(outBuf_);
+ ASSERT_EQ(48, outBuf_.getLength());
- EXPECT_EQ(0, memcmp(&buf[10], expected, 48));
+ EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 48));
EXPECT_NO_THROW(
delete ia;
);
}
+
// test if option can parse suboptions
TEST_F(Option6IATest, suboptions_unpack) {
-
-
+ // 48 bytes
uint8_t expected[] = {
D6O_IA_NA/256, D6O_IA_NA%256, // type
0, 28, // length
0, 0 // len
};
- boost::shared_array<uint8_t> buf(new uint8_t[128]);
- for (int i = 0; i < 128; i++)
- buf[i] = 0;
- memcpy(&buf[0], expected, 48);
+ memcpy(&buf_[0], expected, sizeof(expected));
Option6IA* ia = 0;
EXPECT_NO_THROW({
- ia = new Option6IA(D6O_IA_NA, buf, 128, 4, 44);
-
- // let's limit verbosity of this test
- // cout << "Parsed option:" << endl << ia->toText() << endl;
+ ia = new Option6IA(D6O_IA_NA, buf_.begin() + 4, buf_.begin() + sizeof(expected));
});
ASSERT_TRUE(ia);
EXPECT_EQ(0x2345, ia->getT1());
EXPECT_EQ(0x3456, ia->getT2());
- boost::shared_ptr<Option> subopt = ia->getOption(D6O_IAADDR);
- ASSERT_NE(boost::shared_ptr<Option>(), subopt); // non-NULL
+ OptionPtr subopt = ia->getOption(D6O_IAADDR);
+ ASSERT_NE(OptionPtr(), subopt); // non-NULL
// checks for address option
Option6IAAddr * addr = dynamic_cast<Option6IAAddr*>(subopt.get());
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
#include <arpa/inet.h>
#include <gtest/gtest.h>
-#include "dhcp/dhcp6.h"
-#include "dhcp/option.h"
-#include "dhcp/option6_iaaddr.h"
+#include <dhcp/dhcp6.h>
+#include <dhcp/option.h>
+#include <dhcp/option6_iaaddr.h>
+#include <util/buffer.h>
using namespace std;
using namespace isc;
using namespace isc::dhcp;
+using namespace isc::util;
namespace {
class Option6IAAddrTest : public ::testing::Test {
public:
- Option6IAAddrTest() {
+ Option6IAAddrTest() : buf_(255), outBuf_(255) {
+ for (int i = 0; i < 255; i++) {
+ buf_[i] = 255 - i;
+ }
}
+ OptionBuffer buf_;
+ OutputBuffer outBuf_;
};
-/// TODO reenable this once ticket #1313 is implemented.
TEST_F(Option6IAAddrTest, basic) {
-
- boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
- for (int i = 0; i < 128; i++)
- simple_buf[i] = 0;
-
- simple_buf[0] = 0x20;
- simple_buf[1] = 0x01;
- simple_buf[2] = 0x0d;
- simple_buf[3] = 0xb8;
- simple_buf[4] = 0x00;
- simple_buf[5] = 0x01;
- simple_buf[12] = 0xde;
- simple_buf[13] = 0xad;
- simple_buf[14] = 0xbe;
- simple_buf[15] = 0xef; // 2001:db8:1::dead:beef
-
- simple_buf[16] = 0x00;
- simple_buf[17] = 0x00;
- simple_buf[18] = 0x03;
- simple_buf[19] = 0xe8; // 1000
-
- simple_buf[20] = 0xb2;
- simple_buf[21] = 0xd0;
- simple_buf[22] = 0x5e;
- simple_buf[23] = 0x00; // 3,000,000,000
+ for (int i=0; i<255; i++) {
+ buf_[i]=0;
+ }
+ buf_[0] = 0x20;
+ buf_[1] = 0x01;
+ buf_[2] = 0x0d;
+ buf_[3] = 0xb8;
+ buf_[4] = 0x00;
+ buf_[5] = 0x01;
+ buf_[12] = 0xde;
+ buf_[13] = 0xad;
+ buf_[14] = 0xbe;
+ buf_[15] = 0xef; // 2001:db8:1::dead:beef
+
+ buf_[16] = 0x00;
+ buf_[17] = 0x00;
+ buf_[18] = 0x03;
+ buf_[19] = 0xe8; // 1000
+
+ buf_[20] = 0xb2;
+ buf_[21] = 0xd0;
+ buf_[22] = 0x5e;
+ buf_[23] = 0x00; // 3,000,000,000
// create an option (unpack content)
Option6IAAddr* opt = new Option6IAAddr(D6O_IAADDR,
- simple_buf,
- 128,
- 0,
- 24);
+ buf_.begin(),
+ buf_.begin() + 24);
- // pack this option again in the same buffer, but in
- // different place
- int offset = opt->pack(simple_buf, 128, 50);
+ // pack this option
+ opt->pack(outBuf_);
- EXPECT_EQ(78, offset);
+ EXPECT_EQ(28, outBuf_.getLength());
EXPECT_EQ(Option::V6, opt->getUniverse());
opt->len());
// check if pack worked properly:
+ const uint8_t* out = (const uint8_t*)outBuf_.getData();
+
// if option type is correct
- EXPECT_EQ(D6O_IAADDR, simple_buf[50]*256 + simple_buf[51]);
+ EXPECT_EQ(D6O_IAADDR, out[0]*256 + out[1]);
// if option length is correct
- EXPECT_EQ(24, simple_buf[52]*256 + simple_buf[53]);
+ EXPECT_EQ(24, out[2]*256 + out[3]);
// if option content is correct
- EXPECT_EQ(0, memcmp(&simple_buf[0], &simple_buf[54],24));
+ EXPECT_EQ(0, memcmp(out + 4, &buf_[0], 24));
EXPECT_NO_THROW(
delete opt;
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
namespace {
class OptionTest : public ::testing::Test {
public:
- OptionTest(): outBuffer_(255) {
- buf_ = boost::shared_array<uint8_t>(new uint8_t[255]);
+ OptionTest(): buf_(255), outBuf_(255) {
for (int i = 0; i < 255; i++) {
buf_[i] = 255 - i;
}
}
- boost::shared_array<uint8_t> buf_;
- OutputBuffer outBuffer_;
+ OptionBuffer buf_;
+ OutputBuffer outBuf_;
};
// v4 is not really implemented yet. A simple test will do for now
// create DHCPv4 option of type 123
// that contains 4 bytes of data
ASSERT_NO_THROW(
- opt= new Option(Option::V4,
- 123, // type
- data);
+ opt= new Option(Option::V4, 123, data);
);
// check that content is reported properly
// Create DHCPv4 option of type 123 that contains
// 4 bytes (sizeof(dummyPayload).
ASSERT_NO_THROW(
- opt= new Option(Option::V4,
- 123, // type
- data.begin() + 1,
- data.end() - 1);
+ opt= new Option(Option::V4, 123, data.begin() + 1, data.end() - 1);
);
// check that content is reported properly
// tests contructor used in pkt reception
// option contains actual data
TEST_F(OptionTest, v6_data1) {
- boost::shared_array<uint8_t> buf(new uint8_t[32]);
for (int i = 0; i < 32; i++)
- buf[i] = 100+i;
- Option* opt = new Option(Option::V6, 333, //type
- buf,
- 3, // offset
- 7); // 7 bytes of data
+ buf_[i] = 100+i;
+ Option* opt = new Option(Option::V6, 333, //type
+ buf_.begin() + 3, // begin offset
+ buf_.begin() + 10); // end offset (7 bytes of data)
EXPECT_EQ(333, opt->getType());
ASSERT_EQ(11, opt->len());
ASSERT_EQ(7, opt->getData().size());
- EXPECT_EQ(0, memcmp(&buf[3], &opt->getData()[0], 7) );
+ EXPECT_EQ(0, memcmp(&buf_[3], &opt->getData()[0], 7) );
- int offset = opt->pack(buf, 32, 20);
- EXPECT_EQ(31, offset);
+ opt->pack(outBuf_);
+ EXPECT_EQ(11, outBuf_.getLength());
- EXPECT_EQ(buf[20], 333/256); // type
- EXPECT_EQ(buf[21], 333%256);
+ const uint8_t* out = (const uint8_t*)outBuf_.getData();
+ EXPECT_EQ(out[0], 333/256); // type
+ EXPECT_EQ(out[1], 333%256);
- EXPECT_EQ(buf[22], 0); // len
- EXPECT_EQ(buf[23], 7);
+ EXPECT_EQ(out[2], 0); // len
+ EXPECT_EQ(out[3], 7);
// payload
- EXPECT_EQ(0, memcmp(&buf[3], &buf[24], 7) );
+ EXPECT_EQ(0, memcmp(&buf_[3], out+4, 7) );
EXPECT_NO_THROW(
delete opt;
// with different input parameters
TEST_F(OptionTest, v6_data2) {
- boost::shared_array<uint8_t> simple_buf(new uint8_t[128]);
- for (int i = 0; i < 128; i++)
- simple_buf[i] = 0;
- simple_buf[0] = 0xa1;
- simple_buf[1] = 0xa2;
- simple_buf[2] = 0xa3;
- simple_buf[3] = 0xa4;
+ buf_[0] = 0xa1;
+ buf_[1] = 0xa2;
+ buf_[2] = 0xa3;
+ buf_[3] = 0xa4;
// create an option (unpack content)
Option* opt = new Option(Option::V6,
D6O_CLIENTID,
- simple_buf,
- 0,
- 4);
+ buf_.begin(),
+ buf_.begin() + 4);
- // pack this option again in the same buffer, but in
- // different place
- int offset18 = opt->pack(simple_buf, 128, 10);
+ // pack this option
+ opt->pack(outBuf_);
// 4 bytes header + 4 bytes content
EXPECT_EQ(8, opt->len());
EXPECT_EQ(D6O_CLIENTID, opt->getType());
- EXPECT_EQ(offset18, 18);
+ EXPECT_EQ(8, outBuf_.getLength());
// check if pack worked properly:
// if option type is correct
- EXPECT_EQ(D6O_CLIENTID, simple_buf[10]*256 + simple_buf[11]);
+ const uint8_t* out = (const uint8_t*)outBuf_.getData();
+
+ EXPECT_EQ(D6O_CLIENTID, out[0]*256 + out[1]);
// if option length is correct
- EXPECT_EQ(4, simple_buf[12]*256 + simple_buf[13]);
+ EXPECT_EQ(4, out[2]*256 + out[3]);
// if option content is correct
- EXPECT_EQ(0, memcmp(&simple_buf[0], &simple_buf[14],4));
+ EXPECT_EQ(0, memcmp(&buf_[0], out + 4, 4));
EXPECT_NO_THROW(
delete opt;
// +----opt3
//
TEST_F(OptionTest, v6_suboptions1) {
- boost::shared_array<uint8_t> buf(new uint8_t[128]);
for (int i=0; i<128; i++)
- buf[i] = 100+i;
+ buf_[i] = 100+i;
Option* opt1 = new Option(Option::V6, 65535, //type
- buf,
- 0, // offset
- 3); // 3 bytes of data
- boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
- boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
- buf,
- 3, // offset
- 5)); // 5 bytes of data
+ buf_.begin(), // 3 bytes of data
+ buf_.begin() + 3);
+ OptionPtr opt2(new Option(Option::V6, 13));
+ OptionPtr opt3(new Option(Option::V6, 7,
+ buf_.begin() + 3,
+ buf_.begin() + 8)); // 5 bytes of data
opt1->addOption(opt2);
opt1->addOption(opt3);
// opt2 len = 4 (just header)
0, 13, 0, 0 // no data at all
};
- int offset = opt1->pack(buf, 128, 20);
- EXPECT_EQ(40, offset);
+ opt1->pack(outBuf_);
+ EXPECT_EQ(20, outBuf_.getLength());
// payload
- EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
+ EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 20) );
EXPECT_NO_THROW(
delete opt1;
// +----opt3
//
TEST_F(OptionTest, v6_suboptions2) {
- boost::shared_array<uint8_t> buf(new uint8_t[128]);
for (int i=0; i<128; i++)
- buf[i] = 100+i;
+ buf_[i] = 100+i;
Option* opt1 = new Option(Option::V6, 65535, //type
- buf,
- 0, // offset
- 3); // 3 bytes of data
- boost::shared_ptr<Option> opt2(new Option(Option::V6, 13));
- boost::shared_ptr<Option> opt3(new Option(Option::V6, 7,
- buf,
- 3, // offset
- 5)); // 5 bytes of data
+ buf_.begin(),
+ buf_.begin() + 3);
+ OptionPtr opt2(new Option(Option::V6, 13));
+ OptionPtr opt3(new Option(Option::V6, 7,
+ buf_.begin() + 3,
+ buf_.begin() + 8));
opt1->addOption(opt2);
opt2->addOption(opt3);
// opt3 len = 9 4(header)+5(data)
0, 7, 0, 5, 103, 104, 105, 106, 107,
};
- int offset = opt1->pack(buf, 128, 20);
- EXPECT_EQ(40, offset);
+ opt1->pack(outBuf_);
+ EXPECT_EQ(20, outBuf_.getLength());
// payload
- EXPECT_EQ(0, memcmp(&buf[20], expected, 20) );
+ EXPECT_EQ(0, memcmp(outBuf_.getData(), expected, 20) );
EXPECT_NO_THROW(
delete opt1;
}
TEST_F(OptionTest, v6_addgetdel) {
- boost::shared_array<uint8_t> buf(new uint8_t[128]);
for (int i=0; i<128; i++)
- buf[i] = 100+i;
+ buf_[i] = 100+i;
Option* parent = new Option(Option::V6, 65535); //type
- boost::shared_ptr<Option> opt1(new Option(Option::V6, 1));
- boost::shared_ptr<Option> opt2(new Option(Option::V6, 2));
- boost::shared_ptr<Option> opt3(new Option(Option::V6, 2));
+ OptionPtr opt1(new Option(Option::V6, 1));
+ OptionPtr opt2(new Option(Option::V6, 2));
+ OptionPtr opt3(new Option(Option::V6, 2));
parent->addOption(opt1);
parent->addOption(opt2);
EXPECT_EQ(opt2, parent->getOption(2));
// expect NULL
- EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(4));
+ EXPECT_EQ(OptionPtr(), parent->getOption(4));
// now there are 2 options of type 2
parent->addOption(opt3);
EXPECT_EQ(true, parent->delOption(2));
// there still should be the other option 2
- EXPECT_NE(boost::shared_ptr<Option>(), parent->getOption(2));
+ EXPECT_NE(OptionPtr(), parent->getOption(2));
// let's delete the other option 2
EXPECT_EQ(true, parent->delOption(2));
// no more options with type=2
- EXPECT_EQ(boost::shared_ptr<Option>(), parent->getOption(2));
+ EXPECT_EQ(OptionPtr(), parent->getOption(2));
// let's try to delete - should fail
EXPECT_TRUE(false == parent->delOption(2));
delete parent;
}
-}
-
TEST_F(OptionTest, v6_toText) {
- boost::shared_array<uint8_t> buf(new uint8_t[3]);
- buf[0] = 0;
- buf[1] = 0xf;
- buf[2] = 0xff;
+ buf_[0] = 0;
+ buf_[1] = 0xf;
+ buf_[2] = 0xff;
- boost::shared_ptr<Option> opt(new Option(Option::V6, 258,
- buf, 0, 3));
+ OptionPtr opt(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 3 ));
EXPECT_EQ("type=258, len=3: 00:0f:ff", opt->toText());
}
+
TEST_F(OptionTest, getUintX) {
- // TODO: Update this test to use buf_ instead of buf
- boost::shared_array<uint8_t> buf(new uint8_t[5]);
- buf[0] = 0x5;
- buf[1] = 0x4;
- buf[2] = 0x3;
- buf[3] = 0x2;
- buf[4] = 0x1;
+ buf_[0] = 0x5;
+ buf_[1] = 0x4;
+ buf_[2] = 0x3;
+ buf_[3] = 0x2;
+ buf_[4] = 0x1;
// five options with varying lengths
- boost::shared_ptr<Option> opt1(new Option(Option::V6, 258, buf, 0, 1));
- boost::shared_ptr<Option> opt2(new Option(Option::V6, 258, buf, 0, 2));
- boost::shared_ptr<Option> opt3(new Option(Option::V6, 258, buf, 0, 3));
- boost::shared_ptr<Option> opt4(new Option(Option::V6, 258, buf, 0, 4));
- boost::shared_ptr<Option> opt5(new Option(Option::V6, 258, buf, 0, 5));
+ OptionPtr opt1(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 1));
+ OptionPtr opt2(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 2));
+ OptionPtr opt3(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 3));
+ OptionPtr opt4(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 4));
+ OptionPtr opt5(new Option(Option::V6, 258, buf_.begin(), buf_.begin() + 5));
EXPECT_EQ(5, opt1->getUint8());
EXPECT_THROW(opt1->getUint16(), OutOfRange);
}
TEST_F(OptionTest, setUintX) {
- boost::shared_ptr<Option> opt1(new Option(Option::V4, 125));
- boost::shared_ptr<Option> opt2(new Option(Option::V4, 125));
- boost::shared_ptr<Option> opt4(new Option(Option::V4, 125));
+ OptionPtr opt1(new Option(Option::V4, 125));
+ OptionPtr opt2(new Option(Option::V4, 125));
+ OptionPtr opt4(new Option(Option::V4, 125));
// verify setUint8
opt1->setUint8(255);
EXPECT_EQ(255, opt1->getUint8());
- opt1->pack4(outBuffer_);
+ opt1->pack4(outBuf_);
EXPECT_EQ(3, opt1->len());
- EXPECT_EQ(3, outBuffer_.getLength());
+ EXPECT_EQ(3, outBuf_.getLength());
uint8_t exp1[] = {125, 1, 255};
- EXPECT_TRUE(0 == memcmp(exp1, outBuffer_.getData(), 3));
+ EXPECT_TRUE(0 == memcmp(exp1, outBuf_.getData(), 3));
// verify getUint16
- outBuffer_.clear();
+ outBuf_.clear();
opt2->setUint16(12345);
- opt2->pack4(outBuffer_);
+ opt2->pack4(outBuf_);
EXPECT_EQ(12345, opt2->getUint16());
EXPECT_EQ(4, opt2->len());
- EXPECT_EQ(4, outBuffer_.getLength());
+ EXPECT_EQ(4, outBuf_.getLength());
uint8_t exp2[] = {125, 2, 12345/256, 12345%256};
- EXPECT_TRUE(0 == memcmp(exp2, outBuffer_.getData(), 4));
+ EXPECT_TRUE(0 == memcmp(exp2, outBuf_.getData(), 4));
// verity getUint32
- outBuffer_.clear();
+ outBuf_.clear();
opt4->setUint32(0x12345678);
- opt4->pack4(outBuffer_);
+ opt4->pack4(outBuf_);
EXPECT_EQ(0x12345678, opt4->getUint32());
EXPECT_EQ(6, opt4->len());
- EXPECT_EQ(6, outBuffer_.getLength());
+ EXPECT_EQ(6, outBuf_.getLength());
uint8_t exp4[] = {125, 4, 0x12, 0x34, 0x56, 0x78};
- EXPECT_TRUE(0 == memcmp(exp4, outBuffer_.getData(), 6));
+ EXPECT_TRUE(0 == memcmp(exp4, outBuf_.getData(), 6));
+}
}
-// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
};
TEST_F(Pkt6Test, constructor) {
- Pkt6 * pkt1 = new Pkt6(17);
+ uint8_t data[] = { 0, 1, 2, 3, 4, 5 };
+ Pkt6 * pkt1 = new Pkt6(data, sizeof(data) );
- EXPECT_EQ(pkt1->data_len_, 17);
+ EXPECT_EQ(6, pkt1->getData().size());
+ EXPECT_EQ(0, memcmp( &pkt1->getData()[0], data, sizeof(data)) );
delete pkt1;
}
// this code is autogenerated (see src/bin/dhcp6/tests/iface_mgr_unittest.c)
Pkt6 *capture1() {
Pkt6* pkt;
- pkt = new Pkt6(98);
- pkt->remote_port_ = 546;
- pkt->remote_addr_ = IOAddress("fe80::21e:8cff:fe9b:7349");
- pkt->local_port_ = 0;
- pkt->local_addr_ = IOAddress("ff02::1:2");
- pkt->ifindex_ = 2;
- pkt->iface_ = "eth0";
- pkt->data_[0]=1;
- pkt->data_[1]=01; pkt->data_[2]=02; pkt->data_[3]=03; pkt->data_[4]=0;
- pkt->data_[5]=1; pkt->data_[6]=0; pkt->data_[7]=14; pkt->data_[8]=0;
- pkt->data_[9]=1; pkt->data_[10]=0; pkt->data_[11]=1; pkt->data_[12]=21;
- pkt->data_[13]=158; pkt->data_[14]=60; pkt->data_[15]=22; pkt->data_[16]=0;
- pkt->data_[17]=30; pkt->data_[18]=140; pkt->data_[19]=155; pkt->data_[20]=115;
- pkt->data_[21]=73; pkt->data_[22]=0; pkt->data_[23]=3; pkt->data_[24]=0;
- pkt->data_[25]=40; pkt->data_[26]=0; pkt->data_[27]=0; pkt->data_[28]=0;
- pkt->data_[29]=1; pkt->data_[30]=255; pkt->data_[31]=255; pkt->data_[32]=255;
- pkt->data_[33]=255; pkt->data_[34]=255; pkt->data_[35]=255; pkt->data_[36]=255;
- pkt->data_[37]=255; pkt->data_[38]=0; pkt->data_[39]=5; pkt->data_[40]=0;
- pkt->data_[41]=24; pkt->data_[42]=32; pkt->data_[43]=1; pkt->data_[44]=13;
- pkt->data_[45]=184; pkt->data_[46]=0; pkt->data_[47]=1; pkt->data_[48]=0;
- pkt->data_[49]=0; pkt->data_[50]=0; pkt->data_[51]=0; pkt->data_[52]=0;
- pkt->data_[53]=0; pkt->data_[54]=0; pkt->data_[55]=0; pkt->data_[56]=18;
- pkt->data_[57]=52; pkt->data_[58]=255; pkt->data_[59]=255; pkt->data_[60]=255;
- pkt->data_[61]=255; pkt->data_[62]=255; pkt->data_[63]=255; pkt->data_[64]=255;
- pkt->data_[65]=255; pkt->data_[66]=0; pkt->data_[67]=23; pkt->data_[68]=0;
- pkt->data_[69]=16; pkt->data_[70]=32; pkt->data_[71]=1; pkt->data_[72]=13;
- pkt->data_[73]=184; pkt->data_[74]=0; pkt->data_[75]=1; pkt->data_[76]=0;
- pkt->data_[77]=0; pkt->data_[78]=0; pkt->data_[79]=0; pkt->data_[80]=0;
- pkt->data_[81]=0; pkt->data_[82]=0; pkt->data_[83]=0; pkt->data_[84]=221;
- pkt->data_[85]=221; pkt->data_[86]=0; pkt->data_[87]=8; pkt->data_[88]=0;
- pkt->data_[89]=2; pkt->data_[90]=0; pkt->data_[91]=100; pkt->data_[92]=0;
- pkt->data_[93]=6; pkt->data_[94]=0; pkt->data_[95]=2; pkt->data_[96]=0;
- pkt->data_[97]=23;
+ uint8_t data[98];
+ data[0]=1;
+ data[1]=01; data[2]=02; data[3]=03; data[4]=0;
+ data[5]=1; data[6]=0; data[7]=14; data[8]=0;
+ data[9]=1; data[10]=0; data[11]=1; data[12]=21;
+ data[13]=158; data[14]=60; data[15]=22; data[16]=0;
+ data[17]=30; data[18]=140; data[19]=155; data[20]=115;
+ data[21]=73; data[22]=0; data[23]=3; data[24]=0;
+ data[25]=40; data[26]=0; data[27]=0; data[28]=0;
+ data[29]=1; data[30]=255; data[31]=255; data[32]=255;
+ data[33]=255; data[34]=255; data[35]=255; data[36]=255;
+ data[37]=255; data[38]=0; data[39]=5; data[40]=0;
+ data[41]=24; data[42]=32; data[43]=1; data[44]=13;
+ data[45]=184; data[46]=0; data[47]=1; data[48]=0;
+ data[49]=0; data[50]=0; data[51]=0; data[52]=0;
+ data[53]=0; data[54]=0; data[55]=0; data[56]=18;
+ data[57]=52; data[58]=255; data[59]=255; data[60]=255;
+ data[61]=255; data[62]=255; data[63]=255; data[64]=255;
+ data[65]=255; data[66]=0; data[67]=23; data[68]=0;
+ data[69]=16; data[70]=32; data[71]=1; data[72]=13;
+ data[73]=184; data[74]=0; data[75]=1; data[76]=0;
+ data[77]=0; data[78]=0; data[79]=0; data[80]=0;
+ data[81]=0; data[82]=0; data[83]=0; data[84]=221;
+ data[85]=221; data[86]=0; data[87]=8; data[88]=0;
+ data[89]=2; data[90]=0; data[91]=100; data[92]=0;
+ data[93]=6; data[94]=0; data[95]=2; data[96]=0;
+ data[97]=23;
+
+ pkt = new Pkt6(data, sizeof(data));
+ pkt->setRemotePort(546);
+ pkt->setRemoteAddr(IOAddress("fe80::21e:8cff:fe9b:7349"));
+ pkt->setLocalPort(0);
+ pkt->setLocalAddr(IOAddress("ff02::1:2"));
+ pkt->setIndex(2);
+ pkt->setIface("eth0");
+
return (pkt);
}
+
TEST_F(Pkt6Test, unpack_solicit1) {
Pkt6 * sol = capture1();
EXPECT_FALSE(sol->getOption(D6O_IA_TA));
EXPECT_FALSE(sol->getOption(D6O_IAADDR));
- // let's limit verbosity of this test
- // std::cout << sol->toText();
-
delete sol;
}
TEST_F(Pkt6Test, packUnpack) {
- Pkt6 * parent = new Pkt6(100);
-
- parent->setType(DHCPV6_SOLICIT);
+ Pkt6* parent = new Pkt6(DHCPV6_SOLICIT, 0x020304);
boost::shared_ptr<Option> opt1(new Option(Option::V6, 1));
boost::shared_ptr<Option> opt2(new Option(Option::V6, 2));
parent->addOption(opt3);
EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());
- int transid = parent->getTransid();
- // transaction-id was randomized, let's remember it
// calculated length should be 16
- EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN,
+ EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN,
parent->len() );
EXPECT_TRUE( parent->pack() );
- //
- EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN,
+ EXPECT_EQ( Pkt6::DHCPV6_PKT_HDR_LEN + 3*Option::OPTION6_HDR_LEN,
parent->len() );
- // let's delete options from options_ collection
- // they still be defined in packed
- parent->options_.clear();
-
- // that that removed options are indeed are gone
- EXPECT_EQ( 4, parent->len() );
+ // create second packet,based on assembled data from the first one
+ Pkt6* clone = new Pkt6((const uint8_t*)parent->getBuffer().getData(), parent->getBuffer().getLength());
// now recreate options list
- EXPECT_TRUE( parent->unpack() );
+ EXPECT_TRUE( clone->unpack() );
// transid, message-type should be the same as before
- EXPECT_EQ(transid, parent->getTransid());
- EXPECT_EQ(DHCPV6_SOLICIT, parent->getType());
-
- EXPECT_TRUE( parent->getOption(1));
- EXPECT_TRUE( parent->getOption(2));
- EXPECT_TRUE( parent->getOption(100));
- EXPECT_FALSE( parent->getOption(4));
-
+ EXPECT_EQ(parent->getTransid(), parent->getTransid());
+ EXPECT_EQ(DHCPV6_SOLICIT, clone->getType());
+
+ EXPECT_TRUE( clone->getOption(1));
+ EXPECT_TRUE( clone->getOption(2));
+ EXPECT_TRUE( clone->getOption(100));
+ EXPECT_FALSE( clone->getOption(4));
+
delete parent;
+ delete clone;
}
TEST_F(Pkt6Test, addGetDelOptions) {
- Pkt6 * parent = new Pkt6(100);
+ Pkt6 * parent = new Pkt6(DHCPV6_SOLICIT, random() );
boost::shared_ptr<Option> opt1(new Option(Option::V6, 1));
boost::shared_ptr<Option> opt2(new Option(Option::V6, 2));
delete parent;
}
-
}
/// \param len The length of the data in bytes.
InputBuffer(const void* data, size_t len) :
position_(0), data_(static_cast<const uint8_t*>(data)), len_(len) {}
+
+ /// @brief Constructor from vector<uint8_t>
+ ///
+ /// It is caller's responsibility to ensure that the data is valid as long
+ /// as the buffer exists.
+ ///
+ /// @param begin iterator to beginning of the vector
+ /// @param end iterator to end of the vector
+ InputBuffer(std::vector<uint8_t>::const_iterator begin,
+ std::vector<uint8_t>::const_iterator end) :
+ data_(&(*begin)), len_(distance(begin, end)) {}
//@}
///