Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Basic IPv6 support added.

  • Loading branch information...
commit 9c6ba50ec4d27e44920561d68bd049d0d233befb 1 parent ea100e9
unknown authored
View
420 Beacon.cpp
@@ -20,7 +20,6 @@ namespace openbfdd
{
Beacon::Beacon() :
m_scheduler(NULL),
- m_packetBuffer(bfd::MaxPacketSize),
m_discMap(32),
m_IdMap(32),
m_sourceMap(32),
@@ -31,25 +30,34 @@ namespace openbfdd
m_paramsLock(true),
m_shutownRequested (false)
{
- // Do as little as possible. Logging not even initialized.
-
- // This must be big enough to include ttl and dest address
- m_messageBuffer.resize(CMSG_SPACE(sizeof(uint32_t))
- + CMSG_SPACE(sizeof(struct in_addr))
- + 8 /*just in case*/
- );
+ // Do as little as possible. Logging not even initialized.
}
Beacon::~Beacon()
{
}
+ void Beacon::handleListenSocketCallback(int ATTR_UNUSED(socket), void *userdata)
+ {
+ Beacon::listenCallbackData *data;
+ data = reinterpret_cast<Beacon::listenCallbackData *>(userdata);
+ data->beacon->handleListenSocket(data->socket);
+ }
+
int Beacon::Run()
{
- RiaaClass<CommandProcessor> commandProcessor(MakeCommandProcessor(*this));
- RiaaClass<CommandProcessor> altCommandProcessor(MakeCommandProcessor(*this));
+ Riaa<CommandProcessor>::Delete commandProcessor(MakeCommandProcessor(*this));
+ Riaa<CommandProcessor>::Delete altCommandProcessor(MakeCommandProcessor(*this));
int returnVal = 1;
+ #warning test
+ SockAddr addr("fd0f:1::1", 10);
+ gLog.LogError ("%s", addr.ToString());
+
+
+ Socket socketIPv4, socketIPv6;
+ listenCallbackData socketIPv4data, socketIPv6data;
+
if (m_scheduler != NULL)
{
gLog.LogError("Can not call Beacon::Run twice. Aborting.");
@@ -74,14 +82,26 @@ namespace openbfdd
m_scheduler = new SelectScheduler();
#endif
- int socket = makeListenSocket();
- if (socket < 0)
+ makeListenSocket(Addr::IPv4, socketIPv4);
+ if (socketIPv4.empty())
{
- gLog.LogError("Failed to start create listen socket on BFD port %hd.", bfd::ListenPort);
+ gLog.LogError("Failed to start create IPv4 listen socket on BFD port %hd.", bfd::ListenPort);
return 1;
+ }
+ makeListenSocket(Addr::IPv6, socketIPv6);
+ if (socketIPv6.empty())
+ {
+ gLog.LogError("Failed to start create IPv6 listen socket on BFD port %hd.", bfd::ListenPort);
+ return 1;
}
+ m_packet.AllocBuffers(bfd::MaxPacketSize,
+ Socket::GetMaxControlSizeReceiveDestinationAddress() +
+ Socket::GetMaxControlSizeRecieveTTLOrHops() +
+ + 8 /*just in case*/ );
+
+
// We use this "signal channel" to communicate back to ourself in the Scheduler
// thread.
if (!m_scheduler->CreateSignalChannel(&m_selfSignalId, handleSelfMessageCallback, this))
@@ -90,12 +110,23 @@ namespace openbfdd
return 1;
}
- if (!m_scheduler->SetSocketCallback(socket, handleListenSocketCallback, this))
+ socketIPv4data.beacon = this;
+ socketIPv4data.socket = &socketIPv4;
+ if (!m_scheduler->SetSocketCallback(*socketIPv4data.socket, handleListenSocketCallback, &socketIPv4data))
+ {
+ gLog.LogError("Failed to set m_scheduler IPv4 socket processing thread. Aborting.");
+ return 1;
+ }
+
+ socketIPv6data.beacon = this;
+ socketIPv6data.socket = &socketIPv6;
+ if (!m_scheduler->SetSocketCallback(*socketIPv6data.socket, handleListenSocketCallback, &socketIPv6data))
{
- gLog.LogError("Failed to set m_scheduler socket processing thread. Aborting.");
+ gLog.LogError("Failed to set m_scheduler IPv6 socket processing thread. Aborting.");
return 1;
}
+
if (!m_scheduler->Run())
gLog.LogError("Failed to start m_scheduler. Aborting.");
else
@@ -113,51 +144,77 @@ namespace openbfdd
m_scheduler = NULL;
delete oldScheduler;
- ::close(socket);
-
return returnVal;
}
- bool Beacon::StartActiveSession(in_addr_t remoteAddr, in_addr_t localAddr)
+ bool Beacon::StartActiveSession(const IpAddr &remoteAddr, const IpAddr &localAddr)
{
Session *session = NULL;
LogAssert(m_scheduler->IsMainThread());
session = findInSourceMap(remoteAddr, localAddr);
- if (NULL == session)
+ if (session)
+ {
+ if (session->IsActiveSession())
+ return true;
+ if (!session->UpgradeToActiveSession())
+ {
+ LogOptional(Log::Session, "Failed to upgrade Session id=%u for %s to %s is to an active session.",
+ session->GetId(),
+ localAddr.ToString(),
+ remoteAddr.ToString()
+ );
+ return false;
+ }
+
+
+ LogOptional(Log::Session, "Session id=%u for %s to %s is now an active session.",
+ session->GetId(),
+ localAddr.ToString(),
+ remoteAddr.ToString()
+ );
+ return true;
+ }
+ else
{
session = addSession(remoteAddr, localAddr);
if (!session)
return false;
LogOptional(Log::Session, "Manually added new session for %s to %s id=%u.",
- Ip4ToString(localAddr),
- Ip4ToString(remoteAddr),
+ localAddr.ToString(),
+ remoteAddr.ToString(),
session->GetId());
- }
- if (session->IsActiveSession())
- return true;
- session->StartActiveSession(remoteAddr, localAddr);
+ if (!session->StartActiveSession(remoteAddr, localAddr))
+ {
+ LogOptional(Log::Session, "Failed to start active session id=%u for %s to %s.",
+ session->GetId(),
+ localAddr.ToString(),
+ remoteAddr.ToString()
+ );
+ return false;
+ }
- LogOptional(Log::Session, "Session id=%u for %s to %s is now an active session.",
- session->GetId(),
- Ip4ToString(localAddr),
- Ip4ToString(remoteAddr)
- );
- return true;
+ LogOptional(Log::Session, "Session id=%u for %s to %s is started as an active session.",
+ session->GetId(),
+ localAddr.ToString(),
+ remoteAddr.ToString()
+ );
+ return true;
+ }
}
- void Beacon::AllowPassiveIP(in_addr_t addr)
+ void Beacon::AllowPassiveIP(const IpAddr &addr)
{
LogAssert(m_scheduler->IsMainThread());
m_allowedPassiveIP.insert(addr);
}
- void Beacon::BlockPassiveIP(in_addr_t addr)
+ void Beacon::BlockPassiveIP(const IpAddr &addr)
{
LogAssert(m_scheduler->IsMainThread());
@@ -198,29 +255,23 @@ namespace openbfdd
}
- Session *Beacon::FindSessionIp(in_addr_t remoteAddr, in_addr_t localAddr)
+ Session *Beacon::FindSessionIp(const IpAddr &remoteAddr, const IpAddr &localAddr)
{
LogAssert(m_scheduler->IsMainThread());
return findInSourceMap(remoteAddr, localAddr);
}
- static inline uint64_t makeSourceMapKey(in_addr_t remoteAddr, in_addr_t localAddr)
- {
- return(static_cast<uint64_t>(remoteAddr) << 32) + localAddr;
- }
-
/**
*
- *
- * @param remoteAddr
- * @param localAddr
+ * @param remoteAddr [in] - Port ignored
+ * @param localAddr [in] - Port ignored
*
* @return Session* - NULL on failure
*/
- Session *Beacon::findInSourceMap(in_addr_t remoteAddr, in_addr_t localAddr)
+ Session *Beacon::findInSourceMap(const IpAddr &remoteAddr, const IpAddr &localAddr)
{
LogAssert(m_scheduler->IsMainThread());
- SourceMapIt found = m_sourceMap.find(makeSourceMapKey(remoteAddr, localAddr));
+ SourceMapIt found = m_sourceMap.find(SourceMapKey(remoteAddr, localAddr));
if (found == m_sourceMap.end())
return NULL;
return found->second;
@@ -251,11 +302,11 @@ namespace openbfdd
LogVerify(1==m_discMap.erase(session->GetLocalDiscriminator()));
LogVerify(1==m_IdMap.erase(session->GetId()));
- LogVerify(1==m_sourceMap.erase(makeSourceMapKey(session->GetRemoteAddress(), session->GetLocalAddress())));
+ LogVerify(1==m_sourceMap.erase(SourceMapKey(session->GetRemoteAddress(), session->GetLocalAddress())));
LogOptional(Log::Session, "Removed session %s to %s id=%d.",
- Ip4ToString(session->GetLocalAddress()),
- Ip4ToString(session->GetRemoteAddress()),
+ session->GetLocalAddress().ToString(),
+ session->GetRemoteAddress().ToString(),
session->GetId());
delete session;
@@ -268,7 +319,7 @@ namespace openbfdd
WaitCondition condition(false);
PendingOperation operation;
PendingOperation *useOperation;
- RiaaClass<PendingOperation> allocOperation;
+ Riaa<PendingOperation>::Delete allocOperation;
if (!callback)
@@ -330,209 +381,93 @@ namespace openbfdd
}
/**
- * Creates the one and only listen socket on the bfd listen port.
- *
- *
- * @return int
+ * Creates the a listen socket on the bfd listen port.
+ *
+ * outSocket will be empty on failure.
+ *
*/
- int Beacon::makeListenSocket ()
+ void Beacon::makeListenSocket(Addr::Type family, Socket &outSocket)
{
- int val;
- FileDescriptor listenSocket;
- struct ::sockaddr_in sin;
+ Socket listenSocket;
- /* Make UDP listenSocket to receive control packets */
- listenSocket = ::socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (!listenSocket.IsValid())
+ outSocket.Close();
+ listenSocket.OpenUDP(family);
+ if (listenSocket.empty())
{
- gLog.ErrnoError(errno, "Failed to create BFD listen listenSocket");
- return -1;
+ gLog.LogError("Failed to create BFD %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
- val = bfd::TTLValue;
- if (::setsockopt(listenSocket, IPPROTO_IP, IP_TTL, &val, sizeof(val)) < 0)
- {
- gLog.ErrnoError(errno, "Can't set TTL for outgoing packets");
- return -1;
- }
- val = 1;
- if (::setsockopt(listenSocket, IPPROTO_IP, IP_RECVTTL, &val, sizeof(val)) < 0)
+ if (!listenSocket.SetTTLOrHops(bfd::TTLValue))
{
- gLog.ErrnoError(errno, "Can't set receive TTL for incoming packets");
- return -1;
+ gLog.LogError("Failed to set ttl/hops on %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
-
- val = 1;
-#ifdef IP_RECVDSTADDR
- if (::setsockopt(listenSocket, IPPROTO_IP, IP_RECVDSTADDR, &val, sizeof(val)) < 0)
+ if (!listenSocket.SetRecieveTTLOrHops(true))
{
- gLog.ErrnoError(errno, "Can't set IP_RECVDSTADDR option to get destination address for incoming packets");
- return -1;
+ gLog.LogError("Failed to set receive for ttl/hops on %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
-#elif defined IP_PKTINFO
- if (::setsockopt(listenSocket, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val)) < 0)
+ if (!listenSocket.SetReceiveDestinationAddress(true))
{
- gLog.ErrnoError(errno, "Can't set IP_PKTINFO option to get destination address for incoming packets");
- return -1;
+ gLog.LogError("Failed to set receive for dest address on %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
-#endif
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons(bfd::ListenPort);
- if (::bind(listenSocket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ if (family == Addr::IPv6)
{
- gLog.ErrnoError(errno, "Can't bind listenSocket to default port for bfd listen listenSocket.");
- return -1;
- }
-
- return listenSocket.Detach();
- }
-
- /**
- * Gets the tll.
- *
- *
- * @param msg
- * @param outTTL [out] - Set to the ttl on success. May not be null.
- *
- * @return bool - false on failure.
- */
- static bool getTTL(struct msghdr *msg, uint8_t *outTTL)
- {
- struct cmsghdr* cmsg;
-
- for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
- {
- // It appears that some systems use IP_TTL and some use IP_RECVTTL to
- // return the ttl. Specifically, FreeBSD uses IP_RECVTTL and Debian uses
- // IP_TTL. We work around this by checking both (until that breaks some system.)
- if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TTL)
- {
- if (LogVerify(cmsg->cmsg_len >= CMSG_LEN(sizeof(uint32_t))))
- {
- *outTTL = (uint8_t)*(uint32_t *)CMSG_DATA(cmsg);
- return true;
- }
- }
- else if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVTTL)
+ if (!listenSocket.SetIPv6Only(true))
{
- *outTTL = *(uint8_t *)CMSG_DATA(cmsg);
- return true;
+ gLog.LogError("Failed to set IPv6 only on %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
- }
-
- return false;
- }
-
- static bool getDstAddr(struct msghdr *msg, in_addr_t *outDstAddress)
- {
- struct cmsghdr* cmsg;
-
- for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg))
+ }
+
+ if (!listenSocket.Bind(SockAddr(family, bfd::ListenPort)))
{
-#ifdef IP_RECVDSTADDR
- if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR)
- {
- if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in_addr)))
- return false;
-
- *outDstAddress = reinterpret_cast<struct in_addr *>(CMSG_DATA(cmsg))->s_addr;
- return true;
- }
-#endif
-#ifdef IP_PKTINFO
- if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO)
- {
- if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in_pktinfo)))
- return false;
-
- *outDstAddress = reinterpret_cast<struct in_pktinfo *>(CMSG_DATA(cmsg))->ipi_addr.s_addr;
- return true;
- }
-#endif
+ gLog.LogError("Can't bind listenSocket to default port on %s listen Socket: %s", Addr::TypeToString(family), strerror(errno));
+ return;
}
- return false;
+ // Take ownership
+ outSocket.Transfer(listenSocket);
}
-
- /**
- * @param listenSocket
- * @param outSourceAddress
- * @param outDstAddress
- * @param outTTL
- *
- * @return size_t - 0 on failure. Otherwise the number of bytes read.
- */
- size_t Beacon::readSocketPacket(int listenSocket, struct sockaddr_in *outSourceAddress, in_addr_t *outDstAddress, uint8_t *outTTL)
+ void Beacon::handleListenSocket(Socket *socket)
{
- int msgLength;
- struct sockaddr_in *sin;
- struct iovec msgiov;
- msgiov.iov_base = &m_packetBuffer.front();
- msgiov.iov_len = m_packetBuffer.size();
-
- struct sockaddr_in msgaddr;
- struct msghdr message;
- message.msg_name =&msgaddr;
- message.msg_namelen = sizeof(msgaddr);
- message.msg_iov = &msgiov;
- message.msg_iovlen = 1; // ??
- message.msg_control = &m_messageBuffer.front();
- message.msg_controllen = m_messageBuffer.size();
- message.msg_flags = 0;
-
- // Get packet
- msgLength = recvmsg(listenSocket, &message, 0);
- if (msgLength < 0)
- {
- gLog.ErrnoError(errno, "Error receiving on BFD listen listenSocket");
- return 0;
- }
+ SockAddr sourceAddr;
+ IpAddr destIpAddr, sourceIpAddr;
+ uint8_t ttl;
+ BfdPacket packet;
+ bool found;
+ Session *session = NULL;
- // Get source address
- if (message.msg_namelen < sizeof(struct sockaddr_in))
+ if (!m_packet.DoRecvMsg(*socket))
{
- gLog.ErrnoError(errno, "Malformed source address on BFD packet.");
- return 0;
+ gLog.ErrnoError(m_packet.GetLastError(), "Error receiving on BFD listen socket");
+ return;
}
- sin = reinterpret_cast<struct sockaddr_in *>(message.msg_name);;
- memcpy(outSourceAddress, sin, sizeof(struct sockaddr_in));
- outSourceAddress->sin_port = ntohs(outSourceAddress->sin_port );
-
- if (!getTTL(&message, outTTL))
- {
- gLog.LogError("Could not get ttl for packet from %s:%hu.", Ip4ToString(sin->sin_addr), outSourceAddress->sin_port);
- return 0;
- }
+ sourceAddr = m_packet.GetSrcAddress();
+ if (!LogVerify(sourceAddr.IsValid()))
+ return;
+ sourceIpAddr = IpAddr(sourceAddr);
- if (!getDstAddr(&message, outDstAddress))
+ destIpAddr = m_packet.GetDestAddress();
+ if (!destIpAddr.IsValid())
{
- gLog.LogError("Could not get destination address for packet from %s:%hu.", Ip4ToString(sin->sin_addr), outSourceAddress->sin_port);
- return 0;
+ gLog.LogError("Could not get destination address for packet from %s.", sourceAddr.ToString());
+ return;
}
- return msgLength;
- }
-
-
- void Beacon::handleListenSocket(int listenSocket)
- {
- struct sockaddr_in sourceAddr;
- in_addr_t destAddr;
- size_t messageLength;
- uint8_t ttl;
- BfdPacket packet;
- Session *session = NULL;
-
-
- messageLength = readSocketPacket(listenSocket, &sourceAddr, &destAddr, &ttl);
- if (messageLength == 0)
+ ttl = m_packet.GetTTLorHops(&found);
+ if (!found)
+ {
+ gLog.LogError("Could not get ttl for packet from %s.", sourceAddr.ToString());
return;
+ }
- LogOptional(Log::Packet, "Received bfd packet %zu bytes from %s:%hu to %s", messageLength, Ip4ToString(sourceAddr.sin_addr), sourceAddr.sin_port, Ip4ToString(destAddr));
+ LogOptional(Log::Packet, "Received bfd packet %zu bytes from %s to %s", m_packet.GetDataSize(), sourceAddr.ToString(), destIpAddr.ToString());
//
// Check ip specific stuff. See draft-ietf-bfd-v4v6-1hop-11.txt
@@ -541,9 +476,9 @@ namespace openbfdd
// Port
if (m_strictPorts)
{
- if (sourceAddr.sin_port < bfd::MinSourcePort) // max port is max value, so no need to check
+ if (sourceAddr.Port() < bfd::MinSourcePort) // max port is max value, so no need to check
{
- LogOptional(Log::Discard, "Discard packet: bad source port %s:%hu to %s", Ip4ToString(sourceAddr.sin_addr), sourceAddr.sin_port, Ip4ToString(destAddr));
+ LogOptional(Log::Discard, "Discard packet: bad source port %s to %s", sourceAddr.ToString(), destIpAddr.ToString());
return;
}
}
@@ -551,11 +486,11 @@ namespace openbfdd
// TTL assumes that all control packets are from neighbors.
if (ttl != 255)
{
- gLog.Optional(Log::Discard, "Discard packet: bad ttl %hhu", ttl);
+ gLog.Optional(Log::Discard, "Discard packet: bad ttl/hops %hhu", ttl);
return;
}
- if (!Session::InitialProcessControlPacket(&m_packetBuffer.front(), messageLength, packet))
+ if (!Session::InitialProcessControlPacket(m_packet.GetData(), m_packet.GetDataSize(), packet))
{
gLog.Optional(Log::Discard, "Discard packet");
return;
@@ -568,63 +503,64 @@ namespace openbfdd
if (found == m_discMap.end())
{
if (gLog.LogTypeEnabled(Log::DiscardDetail))
- Session::LogPacketContents(packet, false, true, sourceAddr.sin_addr.s_addr, sourceAddr.sin_port, destAddr, 0);
+ Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr);
gLog.Optional(Log::Discard, "Discard packet: no session found for yourDisc <%u>.", packet.header.yourDisc);
return;
}
session = found->second;
- if (session->GetRemoteAddress() != sourceAddr.sin_addr.s_addr)
+ if (session->GetRemoteAddress() != sourceIpAddr)
{
if (gLog.LogTypeEnabled(Log::DiscardDetail))
- Session::LogPacketContents(packet, false, true, sourceAddr.sin_addr.s_addr, sourceAddr.sin_port, destAddr, 0);
+ Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr);
- LogOptional(Log::Discard, "Discard packet: mismatched yourDisc <%u> and ip <from %s to %s>.", packet.header.yourDisc, Ip4ToString(sourceAddr.sin_addr), Ip4ToString(destAddr));
+ LogOptional(Log::Discard, "Discard packet: mismatched yourDisc <%u> and ip <from %s to %s>.", packet.header.yourDisc, sourceAddr.ToString(), destIpAddr.ToString());
return;
}
}
else
{
// No discriminator
- session = findInSourceMap(sourceAddr.sin_addr.s_addr, destAddr);
+ session = findInSourceMap(sourceIpAddr, destIpAddr);
if (NULL == session)
{
// No session yet .. create one !?
- if (!m_allowAnyPassiveIP && m_allowedPassiveIP.find(sourceAddr.sin_addr.s_addr) == m_allowedPassiveIP.end())
+ if (!m_allowAnyPassiveIP && m_allowedPassiveIP.find(sourceIpAddr) == m_allowedPassiveIP.end())
{
if (gLog.LogTypeEnabled(Log::DiscardDetail))
- Session::LogPacketContents(packet, false, true, sourceAddr.sin_addr.s_addr, sourceAddr.sin_port, destAddr, 0);
+ Session::LogPacketContents(packet, false, true, sourceAddr, destIpAddr);
- LogOptional(Log::Discard, "Ignoring unauthorized bfd packets from %s", Ip4ToString(sourceAddr.sin_addr));
+ LogOptional(Log::Discard, "Ignoring unauthorized bfd packets from %s", sourceAddr.ToString());
return;
}
- session = addSession(sourceAddr.sin_addr.s_addr,destAddr);
+ session = addSession(sourceIpAddr, destIpAddr);
if (!session)
return;
- session->StartPassiveSession(sourceAddr.sin_addr.s_addr, sourceAddr.sin_port, destAddr);
- LogOptional(Log::Session, "Added new session for local %s to remote %s:%hu id=%d.", Ip4ToString(destAddr), Ip4ToString(sourceAddr.sin_addr), sourceAddr.sin_port, session->GetId());
+ if (!session->StartPassiveSession(sourceAddr, destIpAddr))
+ {
+ gLog.LogError("Failed to add new session for local %s to remote %s id=%d.", destIpAddr.ToString(), sourceAddr.ToString(), session->GetId());
+ KillSession(session);
+ }
+ LogOptional(Log::Session, "Added new session for local %s to remote %s id=%d.", destIpAddr.ToString(), sourceAddr.ToString(), session->GetId());
}
}
//
// We have a session that can handle the rest.
//
- session->ProcessControlPacket(packet, sourceAddr.sin_port);
+ session->ProcessControlPacket(packet, sourceAddr.Port());
}
/**
* Adds a session
*
- * @param remoteAddr
- * @param localAddr
- *
* @return Session* - NULL on failure
*/
- Session *Beacon::addSession(in_addr_t remoteAddr, in_addr_t localAddr)
+ Session *Beacon::addSession(const IpAddr &remoteAddr, const IpAddr &localAddr)
{
uint32_t newDisc = makeUniqueDiscriminator();
- RiaaClass<Session> session;
+ Riaa<Session>::Delete session;
try
{
@@ -633,7 +569,7 @@ namespace openbfdd
if (0 == session->GetId())
return NULL;
- m_sourceMap[makeSourceMapKey(remoteAddr, localAddr)] = session;
+ m_sourceMap[SourceMapKey(remoteAddr, localAddr)] = session;
m_discMap[newDisc] = session;
m_IdMap[session->GetId()] = session;
}
@@ -641,7 +577,7 @@ namespace openbfdd
{
if (session.IsValid())
{
- m_sourceMap.erase(makeSourceMapKey(remoteAddr, localAddr));
+ m_sourceMap.erase(SourceMapKey(remoteAddr, localAddr));
m_IdMap.erase(session->GetId());
}
View
68 Beacon.h
@@ -12,6 +12,8 @@
#include "Session.h"
#include "threads.h"
#include "hash_map.h"
+#include "Socket.h"
+#include "SockAddr.h"
#include <deque>
#include <vector>
#include <set>
@@ -76,14 +78,13 @@ namespace openbfdd
*
* @Note can only on the main thread.
*
- * @param remoteAddr [in] - remote address.
- * @param localAddr [in]- address on which to receive and send packets.
+ * @param remoteAddr [in] - remote address.
+ * @param localAddr [in]- address on which to receive and send packets. .
*
* @return bool - false on failure. If there is already a session, then this
* returns true.
*/
- bool StartActiveSession(in_addr_t remoteAddr, in_addr_t localAddr);
-
+ bool StartActiveSession(const IpAddr &remoteAddr, const IpAddr &localAddr);
/**
* Allows us to accept connections from the given ip address.
@@ -92,9 +93,8 @@ namespace openbfdd
*
* @throw - yes.
*
- * @param addr
*/
- void AllowPassiveIP(in_addr_t addr);
+ void AllowPassiveIP(const IpAddr &addr);
/**
* Stops us from accepting new connections from the given ip address.
@@ -104,10 +104,8 @@ namespace openbfdd
*
* @Note can be called only on the main thread.
*
- * @param addr
*/
- void BlockPassiveIP(in_addr_t addr);
-
+ void BlockPassiveIP(const IpAddr &addr);
/**
* Allow or disallow accepting every invitation.
@@ -119,14 +117,25 @@ namespace openbfdd
void AllowAllPassiveConnections(bool allow);
/**
- * Find Session by discriminator or remote and local ip.
+ * Find Session by discriminator.
*
* @Note can be called only on the main thread.
*
- * @return Session* - NULL if none found
+ * @return Session* - NULL on failure
*/
Session *FindSessionId(uint32_t id);
- Session *FindSessionIp(in_addr_t remoteAddr, in_addr_t localAddr);
+
+ /**
+ * Find Session by remote and local ip.
+ *
+ * @Note can be called only on the main thread.
+ *
+ * @param remoteAddr [in] - Port ignored
+ * @param localAddr [in] - Port ignored
+ *
+ * @return Session* - NULL on failure
+ */
+ Session *FindSessionIp(const IpAddr &remoteAddr, const IpAddr &localAddr);
/**
* Clears and fill the vector with all the sessions.
@@ -188,24 +197,38 @@ namespace openbfdd
private:
- int makeListenSocket();
- static void handleListenSocketCallback(int socket, void *userdata) {reinterpret_cast<Beacon *>(userdata)->handleListenSocket(socket);}
- void handleListenSocket(int socket);
- size_t readSocketPacket(int listenSocket, struct sockaddr_in *outSourceAddress, in_addr_t *outDstAddress, uint8_t *outTTL);
+ void makeListenSocket(Addr::Type type, Socket &outSocket);
+ static void handleListenSocketCallback(int socket, void *userdata);
+ void handleListenSocket(Socket *socket);
static void handleSelfMessageCallback(int sigId, void *userdata) {reinterpret_cast<Beacon *>(userdata)->handleSelfMessage(sigId);}
void handleSelfMessage(int sigId);
uint32_t makeUniqueDiscriminator();
bool triggerSelfMessage();
- Session *addSession(in_addr_t remoteAddr, in_addr_t localAddr);
+ Session *addSession(const IpAddr &remoteAddr, const IpAddr &localAddr);
- Session *findInSourceMap(in_addr_t remoteAddr, in_addr_t localAddr);
+ Session *findInSourceMap(const IpAddr &remoteAddr, const IpAddr &localAddr);
private:
+ struct listenCallbackData
+ {
+ Beacon *beacon;
+ Socket *socket;
+ };
+
+ struct SourceMapKey
+ {
+ SourceMapKey(IpAddr remoteAddr, IpAddr localAddr) : remoteAddr(remoteAddr), localAddr(localAddr) {}
+ IpAddr remoteAddr;
+ IpAddr localAddr;
+ bool operator==(const SourceMapKey &other) const {return remoteAddr == other.remoteAddr && localAddr == other.localAddr;}
+ struct hasher {size_t operator()(const SourceMapKey &me) const {return me.remoteAddr.hash() + me.localAddr.hash();}};
+ };
+
typedef hash_map<uint32_t, class Session *>::Type DiscMap;
typedef DiscMap::iterator DiscMapIt;
- typedef hash_map<uint64_t, class Session *>::Type SourceMap;
+ typedef hash_map<SourceMapKey, class Session *, SourceMapKey::hasher>::Type SourceMap;
typedef SourceMap::iterator SourceMapIt;
typedef hash_map<uint32_t, class Session *>::Type IdMap;
typedef IdMap::iterator IdMapIt;
@@ -227,13 +250,12 @@ namespace openbfdd
// locking needed
//
Scheduler *m_scheduler; // This is only valid after Run() is called.
- std::vector<uint8_t> m_packetBuffer; // main message buffer.
- std::vector<uint8_t> m_messageBuffer; // for iovec buffer.
- uint8_t m_msgbuf[bfd::MaxPacketSize];
+ Socket::RecvMsg m_packet;
+
DiscMap m_discMap; // Your Discriminator -> Session
IdMap m_IdMap; // Human readable session id -> Session
SourceMap m_sourceMap; // ip/ip -> Session
- std::set<in_addr_t> m_allowedPassiveIP;
+ std::set<IpAddr, IpAddr::LessClass> m_allowedPassiveIP;
bool m_allowAnyPassiveIP;
bool m_strictPorts; // Should incoming ports be limited as described in draft-ietf-bfd-v4v6-1hop-11.txt
Session::InitialParams m_initialSessionParams;
View
178 CommandProcessor.cpp
@@ -7,6 +7,8 @@
#include "CommandProcessor.h"
#include "utils.h"
#include "Beacon.h"
+#include "SockAddr.h"
+#include "Socket.h"
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
@@ -28,9 +30,9 @@ namespace openbfdd
//
// These are only accessed from thread.
//
- FileDescriptor m_listenSocket;
- int m_replySocket;
- vector<char> m_inCommandBuffer;
+ Socket m_listenSocket;
+ Socket m_replySocket;
+ Socket::RecvMsg m_inCommand;
vector<char> m_inReplyBuffer; // only use messageReply and friends.
string m_inCommandLogStr;
@@ -51,8 +53,8 @@ namespace openbfdd
public:
CommandProcessorImp(Beacon &beacon) : CommandProcessor(beacon),
m_beacon(&beacon),
- m_replySocket(-1),
- m_inCommandBuffer(MaxCommandSize),
+ m_replySocket(),
+ m_inCommand(MaxCommandSize, 0),
m_inReplyBuffer(MaxReplyLineSize + 1),
m_mainLock(true),
m_isThreadRunning(false),
@@ -183,10 +185,6 @@ namespace openbfdd
*/
bool initListening()
{
- struct sockaddr_in saddr;
- int flags;
- int on = 1;
-
// Do this so low memory will not cause distorted messages
if (!UtilsInitThread())
{
@@ -194,47 +192,23 @@ namespace openbfdd
return false;
}
- m_listenSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (!m_listenSocket.IsValid())
- {
- gLog.ErrnoError(errno, "Error opening listen socket: ");
+ if (!m_listenSocket.OpenTCP(Addr::IPv4))
return false;
- }
- // We do not want to get blocked up ever, so make this a non-blocking socket
- flags = fcntl(m_listenSocket, F_GETFL);
- flags = flags | O_NONBLOCK;
- if (-1 == fcntl(m_listenSocket, F_SETFL, flags))
- {
- gLog.LogError("Failed to set socket to non-blocking.");
+ if (!m_listenSocket.SetBlocking(false))
return false;
- }
- // In case we had to restart ... reuse port
- if (0 > setsockopt(m_listenSocket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
- {
- gLog.LogError("Failed to configure socket to SO_REUSEADDR.");
+ if (!m_listenSocket.SetReusePort(true))
return false;
- }
// TODO: listen address should be settable.
- memset(&saddr, 0, sizeof(saddr));
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
- saddr.sin_port = htons(m_port);
-
+ SockAddr addr("127.0.0.1", m_port);
- if (bind(m_listenSocket, (sockaddr*)&saddr, sizeof(saddr)) < 0)
- {
- gLog.ErrnoError(errno, "Error binding listen socket: ");
+ if (!m_listenSocket.Bind(addr))
return false;
- }
- if (listen(m_listenSocket, 3) < 0)
- {
- gLog.ErrnoError(errno, "Error listening on listen socket: ");
+ if (!m_listenSocket.Listen(3))
return false;
- }
return true;
}
@@ -319,7 +293,7 @@ namespace openbfdd
static void closeSyncReplySocket(CommandProcessorImp *me)
{
if (me)
- me->m_replySocket = -1;
+ me->m_replySocket.Close();
}
/**
@@ -338,10 +312,8 @@ namespace openbfdd
bool processMessage()
{
- socklen_t fromlen;
- struct sockaddr_in faddr ;
Result::Type waitResult;
- FileDescriptor connectedSocket;
+ Socket connectedSocket;
RiaaNullBase<CommandProcessorImp, closeSyncReplySocket> syncConnectedSocket(this);
@@ -351,22 +323,12 @@ namespace openbfdd
return false;
// accept a connection
- fromlen = sizeof(faddr);
- connectedSocket = accept(m_listenSocket, (sockaddr*)&faddr, &fromlen);
- if (!connectedSocket.IsValid())
- {
- // No command
- if (errno == EWOULDBLOCK)
- gLog.LogError("Unable to accept listening socket");
- else if (errno == ECONNABORTED)
- gLog.LogError("Unable to accept listening socket due to abort");
- else
- gLog.ErrnoError(errno, "Unable to accept listening socket: ");
-
- // We do not quit on any of these?
+ if (!m_listenSocket.Accept(connectedSocket))
+ {
+ // We do not quit on error?
return true;
}
- m_replySocket = connectedSocket;
+ m_replySocket = connectedSocket; // note connectedSocket still 'owns' the socket.
// Got a connection for the command. Now wait for a command. Since we are
// non-blocking, we use select again.
@@ -380,21 +342,20 @@ namespace openbfdd
if (isStopListeningRequested())
return false;
- ssize_t size = recv(connectedSocket, &m_inCommandBuffer.front(), (int)m_inCommandBuffer.size(), MSG_DONTWAIT);
- if (size < 0)
+ if (!m_inCommand.DoRecv(connectedSocket, MSG_DONTWAIT))
{
// Errors
- if (errno == EAGAIN)
+ if (m_inCommand.GetLastError() == EAGAIN)
gLog.Optional(Log::Command, "Incomplete message ... waiting."); // Must not have the full message. Wait for it?
- else if (errno == EINTR)
+ else if (m_inCommand.GetLastError() == EINTR)
gLog.Optional(Log::Command, "Interrupted message ... trying again.");
- else if (errno== ECONNRESET)
+ else if (m_inCommand.GetLastError()== ECONNRESET)
{
gLog.Message(Log::Command, "Communication connection reset.");
return true;
}
}
- else if (size == 0)
+ else if (m_inCommand.GetDataSize() == 0)
{
gLog.LogError("Empty communication message.");
return true;
@@ -402,10 +363,10 @@ namespace openbfdd
else
{
// Got a message
- gLog.Optional(Log::Command, "Message size %zu.", size);
+ gLog.Optional(Log::Command, "Message size %zu.", m_inCommand.GetDataSize() );
try
{
- dispatchMessage(&m_inCommandBuffer.front(), size);
+ dispatchMessage((char *)m_inCommand.GetData(), m_inCommand.GetDataSize() );
}
catch (std::exception &e)
{
@@ -633,20 +594,19 @@ namespace openbfdd
*/
struct SessionID
{
- SessionID() : allSessions(false), whichId(0), whichRemoteAddr(INADDR_NONE), whichLocalAddr(INADDR_NONE) {}
- void Clear() {allSessions =false; whichId = 0; whichRemoteAddr = whichLocalAddr = INADDR_NONE;}
+ SessionID() : allSessions(false), whichId(0), whichRemoteAddr(), whichLocalAddr() {}
+ void Clear() {allSessions =false; whichId = 0; whichRemoteAddr.clear(); whichLocalAddr.clear();}
bool IsValid() const {return allSessions || whichId != 0 || HasIpAddresses();}
- bool HasIpAddresses() const {return whichRemoteAddr != INADDR_NONE && whichLocalAddr != INADDR_NONE;}
- void SetAddress(bool local, in_addr_t addr) {if (local) whichLocalAddr = addr; else whichRemoteAddr = addr;}
+ bool HasIpAddresses() const {return whichRemoteAddr.IsValid() && whichLocalAddr.IsValid();}
+ void SetAddress(bool local, const IpAddr &addr) {if (local) whichLocalAddr = addr; else whichRemoteAddr = addr;}
bool allSessions;
uint32_t whichId;
- in_addr_t whichRemoteAddr;
- in_addr_t whichLocalAddr;
+ IpAddr whichRemoteAddr;
+ IpAddr whichLocalAddr;
};
/**
- *
* Converts a set of parameters to a local/remote ip address pair.
*
* @param inOutParam [in/out] - The first parameter to examine. On success this
@@ -664,7 +624,7 @@ namespace openbfdd
const char *str = *inOutParam;
bool local;
SessionID temp;
- in_addr_t addrVal;
+ IpAddr addrVal;
sessionId.Clear();
@@ -681,14 +641,13 @@ namespace openbfdd
str = getNextParam(str);
if(!str)
{
- errorMsg = FormatBigStr("Error: '%s' should be followed by an ip address.", command);
+ errorMsg = FormatBigStr("Error: '%s' should be followed by an Pv4 or IPv6 address.", command);
return false;
}
- addrVal = inet_addr (str);
- if(addrVal == INADDR_NONE)
+ if (!addrVal.FromString(str))
{
- errorMsg = FormatBigStr("Error: <%s> is not an ip address.", str);
+ errorMsg = FormatBigStr("Error: <%s> is not an IPv4 or IPv6 address.", str);
return false;
}
@@ -716,10 +675,9 @@ namespace openbfdd
return false;
}
- addrVal = inet_addr (str);
- if(addrVal == INADDR_NONE)
+ if (!addrVal.FromString(str))
{
- errorMsg = FormatBigStr("Error: <%s> is not an ip address.", str);
+ errorMsg = FormatBigStr("Error: <%s> is not an IPv4 or IPv6 address.", str);
return false;
}
@@ -842,7 +800,7 @@ namespace openbfdd
if(sessionId.whichId != 0)
messageReplyF("No session with id=%u.\n", sessionId.whichId);
else if (sessionId.HasIpAddresses())
- messageReplyF("No session with local ip=%s and remote ip=%s.\n", Ip4ToString(sessionId.whichLocalAddr), Ip4ToString(sessionId.whichRemoteAddr));
+ messageReplyF("No session with local ip=%s and remote ip=%s.\n", sessionId.whichLocalAddr.ToString(), sessionId.whichRemoteAddr.ToString());
else
messageReply("Unknown session specifier.\n");
}
@@ -1030,9 +988,9 @@ namespace openbfdd
if(doBeaconOperation(&CommandProcessorImp::doHandleConnect, &address, &result))
{
if (result)
- messageReplyF("Opened connection from local %s to remote %s\n", Ip4ToString(address.whichLocalAddr), Ip4ToString(address.whichRemoteAddr));
+ messageReplyF("Opened connection from local %s to remote %s\n", address.whichLocalAddr.ToString(), address.whichRemoteAddr.ToString());
else
- messageReplyF("Failed to open connection from local %s to remote %s\n", Ip4ToString(address.whichLocalAddr), Ip4ToString(address.whichRemoteAddr));
+ messageReplyF("Failed to open connection from local %s to remote %s\n", address.whichLocalAddr.ToString(), address.whichRemoteAddr.ToString());
}
}
@@ -1052,7 +1010,7 @@ namespace openbfdd
*/
void handle_Allow( const char *message)
{
- in_addr address;
+ IpAddr address;
const char *addressString;
addressString = getNextParam(message);
@@ -1062,20 +1020,19 @@ namespace openbfdd
return;
}
- address.s_addr = inet_addr (addressString);
- if(address.s_addr == INADDR_NONE)
+ if(!address.FromString(addressString))
{
- messageReplyF("Invalid ip address <%s>.\n", addressString);
+ messageReplyF("Invalid IPv4 or IPv6 address <%s>.\n", addressString);
return;
}
- if(doBeaconOperation(&CommandProcessorImp::doHandleAllow, &address.s_addr))
- messageReplyF("Allowing connections from %s\n", Ip4ToString(address));
+ if(doBeaconOperation(&CommandProcessorImp::doHandleAllow, &address))
+ messageReplyF("Allowing connections from %s\n", address.ToString());
}
intptr_t doHandleAllow(Beacon *beacon, void *userdata)
{
- in_addr_t *addr = (in_addr_t *)userdata;
+ IpAddr *addr = reinterpret_cast<IpAddr *>(userdata);
beacon->AllowPassiveIP(*addr);
return 0;
}
@@ -1087,30 +1044,29 @@ namespace openbfdd
*/
void handle_Block( const char *message)
{
- in_addr address;
+ IpAddr address;
const char *addressString;
addressString = getNextParam(message);
if(!addressString)
{
- messageReply("Must supply ip address.\n");
+ messageReply("Must supply an IPv4 or IPv6 address.\n");
return;
}
- address.s_addr = inet_addr (addressString);
- if(address.s_addr == INADDR_NONE)
+ if (!address.FromString(addressString))
{
- messageReplyF("Invalid ip address <%s>.\n", addressString);
+ messageReplyF("Invalid IPv4 or IPv6 address <%s>.\n", addressString);
return;
}
- if(doBeaconOperation(&CommandProcessorImp::doHandleBlock, &address.s_addr))
- messageReplyF("Blocking connections from %s. This will not terminate any ongoing session.\n", Ip4ToString(address));
+ if(doBeaconOperation(&CommandProcessorImp::doHandleBlock, &address))
+ messageReplyF("Blocking connections from %s. This will not terminate any ongoing session.\n", address.ToString());
}
intptr_t doHandleBlock(Beacon *beacon, void *userdata)
{
- in_addr_t *addr = (in_addr_t *)userdata;
+ IpAddr *addr = reinterpret_cast<IpAddr *>(userdata);
beacon->BlockPassiveIP(*addr);
return 0;
}
@@ -1120,8 +1076,8 @@ namespace openbfdd
uint32_t id;
uint32_t localDisc;
uint32_t remoteDisc;
- in_addr_t remoteAddress;
- in_addr_t localAddress;
+ IpAddr remoteAddress;
+ IpAddr localAddress;
bool isActiveSession; //active or passive role.
Session::ExtendedStateInfo extState;
};
@@ -1164,9 +1120,9 @@ namespace openbfdd
messageReplyF(" id=%u %slocal=%s %sremote=%s %sstate=%s\n",
info.id,
sep,
- Ip4ToString(info.localAddress),
+ info.localAddress.ToString(),
sep,
- Ip4ToString(info.remoteAddress),
+ info.remoteAddress.ToString(),
sep,
bfd::StateName(info.extState.localState));
}
@@ -1175,10 +1131,10 @@ namespace openbfdd
messageReplyF(" id=%u %slocal=%s %s %sremote=%s %sstate=%s%s %s\n",
info.id,
sep,
- Ip4ToString(info.localAddress),
+ info.localAddress.ToString(),
info.isActiveSession ? "(a)":"(p)",
sep,
- Ip4ToString(info.remoteAddress),
+ info.remoteAddress.ToString(),
sep,
bfd::StateName(info.extState.localState),
info.extState.isHoldingState ? "<Forced>":"",
@@ -1191,10 +1147,10 @@ namespace openbfdd
messageReplyF(" id=%u %slocal=%s %s %sremote=%s %sLocalState=%s<%s%s%s> %sRemoteState=%s<%s> %sLocalId=%u %sRemoteId=%u %s",
info.id,
sep,
- Ip4ToString(info.localAddress),
+ info.localAddress.ToString(),
info.isActiveSession ? (brief ? "(a)":"(active)"): (brief ? "(p)":"(passive)"),
sep,
- Ip4ToString(info.remoteAddress),
+ info.remoteAddress.ToString(),
sep,
bfd::StateName(info.extState.localState),
info.extState.isHoldingState ? "Forced: ":"",
@@ -1565,12 +1521,12 @@ namespace openbfdd
else if (info->action == SessionCallbackInfo::Reset)
{
bool active = session->IsActiveSession();
- in_addr_t remoteAddr = session->GetRemoteAddress();
- in_addr_t localAddr = session->GetLocalAddress();
+ IpAddr remoteAddr = session->GetRemoteAddress();
+ IpAddr localAddr = session->GetLocalAddress();
beacon->KillSession(session);
session = NULL; // warning session now invalid
- gLog.Optional(Log::SessionDetail, "Reset session id=%u for local %s to remote %s.", *idIt, Ip4ToString(localAddr), Ip4ToString(remoteAddr));
+ gLog.Optional(Log::SessionDetail, "Reset session id=%u for local %s to remote %s.", *idIt, localAddr.ToString(), remoteAddr.ToString());
if(active)
beacon->StartActiveSession(remoteAddr, localAddr);
}
@@ -2088,10 +2044,8 @@ namespace openbfdd
void doMessageReply(const char *reply, size_t length)
{
// TODO timeout? Check for shutdown?
- if (send(m_replySocket, reply, length, 0) < 0)
- {
+ if (!m_replySocket.Send(reply, length))
gLog.ErrnoError(errno, "Failed to complete message reply.");
- }
}
View
8 Makefile.am
@@ -3,14 +3,14 @@ bin_PROGRAMS = bfdd-beacon bfdd-control
AM_CXXFLAGS = $(INTI_CFLAGS) $(WARNINGCXXFLAGS) $(OTHERCXXFLAGS)
COMMON_INC = common.h utils.h log.h SmartPointer.h threads.h bfd.h standard.h \
- TimeSpec.h Socket.h
+ TimeSpec.h Socket.h IpAddr.h lookup3.h
COMMON_SRC = $(COMMON_INC) common.cpp utils.cpp log.cpp SmartPointer.cpp threads.cpp bfd.cpp \
- TimeSpec.cpp Socket.cpp
+ TimeSpec.cpp Socket.cpp SockAddr.cpp lookup3.cpp
CONTROL_SRC = bfdd-control.cpp
BEACON_INC = Beacon.h CommandProcessor.h Scheduler.h SchedulerBase.h KeventScheduler.h SelectScheduler.h \
- Session.h hash_map.h
+ Session.h hash_map.h
BEACON_SRC = $(BEACON_INC) BeaconMain.cpp Beacon.cpp CommandProcessor.cpp SchedulerBase.cpp KeventScheduler.cpp \
- SelectScheduler.cpp Session.cpp
+ SelectScheduler.cpp Session.cpp
bfdd_beacon_SOURCES = $(COMMON_SRC) $(BEACON_SRC)
bfdd_beacon_LDADD = $(INTI_LIBS)
View
290 Session.cpp
@@ -43,9 +43,9 @@ namespace openbfdd
Session::Session(Scheduler &scheduler, Beacon *beacon, uint32_t descriminator, const InitialParams &params) :
m_beacon(beacon),
m_scheduler(&scheduler),
- m_remoteAddr(INADDR_NONE),
+ m_remoteAddr(),
m_remoteSourcePort(0),
- m_localAddr(INADDR_NONE),
+ m_localAddr(),
m_sendPort(0),
m_isActive(false),
m_sessionState(bfd::State::Down),
@@ -81,7 +81,7 @@ namespace openbfdd
m_defaultDesiredMinTxInterval(params.desiredMinTx), // this will not take effect until we are up ... see m_useDesiredMinTxInterva
m_wantsPollForNewRequiredMinRxInterval(false),
_useRequiredMinRxInterval(m_requiredMinRxInterval),
- m_recieveTimeoutTimer(this),
+ m_receiveTimeoutTimer(this),
m_transmitNextTimer(this)
{
LogAssert(m_scheduler->IsMainThread());
@@ -97,12 +97,12 @@ namespace openbfdd
// It may be more efficient to wait until we need these?
char name[32];
snprintf(name, sizeof(name), "<Rcv %u>", m_id);
- m_recieveTimeoutTimer = m_scheduler->MakeTimer(name);
+ m_receiveTimeoutTimer = m_scheduler->MakeTimer(name);
snprintf(name, sizeof(name), "<Tx %u>", m_id);
m_transmitNextTimer = m_scheduler->MakeTimer(name);
- m_recieveTimeoutTimer->SetCallback(handleRecieveTimeoutTimerCallback, this);
- m_recieveTimeoutTimer->SetPriority(Timer::Priority::Low);
+ m_receiveTimeoutTimer->SetCallback(handleRecieveTimeoutTimerCallback, this);
+ m_receiveTimeoutTimer->SetPriority(Timer::Priority::Low);
m_transmitNextTimer->SetCallback(handletTransmitNextTimerCallback, this);
m_transmitNextTimer->SetPriority(Timer::Priority::Hi);
@@ -128,43 +128,79 @@ namespace openbfdd
}
}
- void Session::StartPassiveSession(in_addr_t remoteAddr, in_port_t remotePort, in_addr_t localAddr)
+ bool Session::StartPassiveSession(const SockAddr &remoteAddr, const IpAddr &localAddr)
{
LogAssert(m_scheduler->IsMainThread());
// this should only be called once.
- LogAssert(m_remoteAddr==INADDR_NONE);
- LogAssert(m_localAddr==INADDR_NONE);
- m_remoteAddr = remoteAddr;
- m_remoteSourcePort = remotePort;
+ LogAssert(!m_remoteAddr.IsValid());
+ LogAssert(!m_localAddr.IsValid());
+ if (!LogVerify(remoteAddr.HasPort()))
+ return false;
+ if (!LogVerify(!localAddr.IsAny()))
+ return false;
+
+ m_remoteAddr = IpAddr(remoteAddr);
+ m_remoteSourcePort = remoteAddr.Port();
+
m_localAddr = localAddr;
m_isActive = false;
-
+ return true;
}
- void Session::StartActiveSession(in_addr_t remoteAddr, in_addr_t localAddr)
+
+
+ bool Session::StartActiveSession(const IpAddr &remoteAddr, const IpAddr &localAddr)
{
LogAssert(m_scheduler->IsMainThread());
// this should only be called once.
- LogAssert(m_remoteAddr==INADDR_NONE);
- LogAssert(m_localAddr==INADDR_NONE);
+ if (!LogVerify(!m_remoteAddr.IsValid()))
+ return false;
+ if (!LogVerify(!m_localAddr.IsValid()))
+ return false;
+ // Any is not valid send address
+ if (!LogVerify(!localAddr.IsAny()))
+ return false;
+
m_remoteAddr = remoteAddr;
m_remoteSourcePort = 0;
+
m_localAddr = localAddr;
m_isActive = true;
// Start the timers now, and begin sending connection packets
scheduleTransmit();
+ return true;
+ }
+
+ bool Session::UpgradeToActiveSession()
+ {
+ LogAssert(m_scheduler->IsMainThread());
+
+ // Must already have a passive session.
+ if (!LogVerify(m_remoteAddr.IsValid()))
+ return false;
+ if (!LogVerify(m_localAddr.IsValid()))
+ return false;
+ if (!LogVerify(!IsActiveSession()))
+ return false;
+
+ m_isActive = true;
+
+ // Start the timers now, and begin sending connection packets
+ scheduleTransmit();
+ return true;
}
- in_addr_t Session::GetRemoteAddress()
+
+ const IpAddr &Session::GetRemoteAddress()
{
LogAssert(m_scheduler->IsMainThread());
return m_remoteAddr;
}
- in_addr_t Session::GetLocalAddress()
+ const IpAddr & Session::GetLocalAddress()
{
LogAssert(m_scheduler->IsMainThread());
return m_localAddr;
@@ -263,7 +299,7 @@ namespace openbfdd
LogAssert(m_scheduler->IsMainThread());
- LogPacketContents(packet, false, true, m_remoteAddr, port, m_localAddr, 0);
+ logPacketContents(packet, false, true, m_remoteAddr, port, m_localAddr, 0);
if(gDropFinalPercent != 0)
{
@@ -454,9 +490,9 @@ namespace openbfdd
uint64_t timeout = getDetectionTimeout();
if(timeout == 0)
- m_recieveTimeoutTimer->Stop();
+ m_receiveTimeoutTimer->Stop();
else
- m_recieveTimeoutTimer->SetMicroTimer(timeout);
+ m_receiveTimeoutTimer->SetMicroTimer(timeout);
}
/**
@@ -473,9 +509,9 @@ namespace openbfdd
uint64_t timeout = getDetectionTimeout();
if(timeout == 0)
- m_recieveTimeoutTimer->Stop();
+ m_receiveTimeoutTimer->Stop();
else
- m_recieveTimeoutTimer->UpdateMicroTimer(timeout);
+ m_receiveTimeoutTimer->UpdateMicroTimer(timeout);
}
@@ -869,15 +905,13 @@ namespace openbfdd
/**
* Sends the given packet.
+ *
* @note Must be called from main thread.
*
- *
* @param packet
*/
void Session::send(const BfdPacket &packet)
{
- struct sockaddr_in sin;
-
if (!ensureSendSocket())
return;
@@ -887,107 +921,84 @@ namespace openbfdd
return;
}
- LogPacketContents(packet, true, false, m_remoteAddr, 0, m_localAddr, m_sendPort);
-
- // Send the packet
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = m_remoteAddr;
- sin.sin_port = htons(bfd::ListenPort);
+ logPacketContents(packet, true, false, m_remoteAddr, 0, m_localAddr, m_sendPort);
- if (sendto(m_sendSocket, &packet, packet.header.length, MSG_NOSIGNAL, (struct sockaddr *)&sin, sizeof(sin)) < 0)
- {
- gLog.LogError("Error sending control packet for session %u : %s", m_id, strerror(errno));
- return;
- }
-
- gLog.Optional(Log::Packet, "Sent control packet for session %u.", m_id);
- return;
+ if (m_sendSocket.SendTo(&packet, packet.header.length,
+ SockAddr(m_remoteAddr, bfd::ListenPort),
+ MSG_NOSIGNAL))
+ gLog.Optional(Log::Packet, "Sent control packet for session %u.", m_id);
+ else
+ gLog.LogError("Error sending control packet for session %u", m_id);
}
/**
- * Attempts to connect the send socket, if there is not one already.
+ * Attempts to connect the m_sendSocket send socket, if there is not one
+ * already.
*
* @return bool - false if the socket could not be opened.
*/
bool Session::ensureSendSocket()
{
- int ttlval = bfd::TTLValue;
- struct sockaddr_in sin;
- uint16_t port, startPort;
- FileDescriptor sendSocket;
+ uint16_t startPort;
+ Socket sendSocket;
+ SockAddr sendAddr;
- if (m_sendSocket.IsValid())
+ if (!m_sendSocket.empty())
return true;
- if (m_localAddr == INADDR_NONE)
- {
- gLog.ErrnoError(errno, "No source address for send socket");
+ if (!LogVerify(m_localAddr.IsValid()))
return false;
- }
-
- if (m_localAddr == INADDR_ANY)
- {
- gLog.ErrnoError(errno, "'INADDR_ANY' is not a valid source address for send socket");
+ if (!LogVerify(!m_localAddr.IsAny()))
return false;
- }
- sendSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (!sendSocket.IsValid())
- {
- gLog.ErrnoError(errno, "Failed to create socket for send");
+ // Not that all sockets will log errors, so we do not have to.
+ if (!sendSocket.OpenUDP(m_localAddr.Type()))
return false;
- }
-
- /* Set TTL to 255 for all transmitted packets */
- if (setsockopt(sendSocket, IPPROTO_IP, IP_TTL, &ttlval, sizeof(ttlval)) < 0)
- {
- gLog.ErrnoError(errno, "Can't set TTL for send socket" );
+
+ if (!sendSocket.SetTTLOrHops(bfd::TTLValue))
return false;
- }
/* Find an available port in the proper range */
if (m_sendPort != 0)
- port = startPort = m_sendPort;
+ startPort = m_sendPort;
else
- port = startPort = bfd::MinSourcePort + rand()%(bfd::MaxSourcePort-bfd::MinSourcePort);
+ startPort = bfd::MinSourcePort + rand()%(bfd::MaxSourcePort-bfd::MinSourcePort);
+
+ sendAddr = SockAddr(m_localAddr, startPort);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = m_localAddr;
- sin.sin_port = htons(port);
- while (bind(sendSocket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ #warning need to be able to quiet socket
+ while (!sendSocket.Bind(sendAddr))
{
- if (port == bfd::MaxSourcePort)
- port = bfd::MinSourcePort;
+ if (sendAddr.Port() == bfd::MaxSourcePort)
+ sendAddr.SetPort(bfd::MinSourcePort);
else
- port++;
+ sendAddr.SetPort(sendAddr.Port() + 1);
- if (port == startPort)
+ if (sendAddr.Port() == startPort)
{
gLog.LogError("Cant find valid send port." );
return false;
}
-
- sin.sin_port = htons(port);
}
- if (m_sendPort != 0 && port != m_sendPort)
+ if (m_sendPort != 0 && sendAddr.Port() != m_sendPort)
{
- gLog.Message(Log::Session, "Source port for session %u at address %s changed from %hu to %hu.", m_id, Ip4ToString(m_localAddr), m_sendPort, port);
+ gLog.Message(Log::Session, "Source port for session %u at address %s changed from %hu to %hu.", m_id, m_localAddr.ToString(), m_sendPort, (uint16_t)sendAddr.Port());
}
else
{
- gLog.Optional(Log::Session, "Source socket %s:%hu for session %u opened.", Ip4ToString(m_localAddr), port, m_id);
+ gLog.Optional(Log::Session, "Source socket %s for session %u opened.", sendAddr.ToString(), m_id);
}
- m_sendPort = port;
- m_sendSocket = sendSocket.Detach();
+ m_sendPort = sendAddr.Port();
+ m_sendSocket.Transfer(sendSocket);
return true;
}
/**
- * Called when m_recieveTimeoutTimer expires.
+ * Called when m_receiveTimeoutTimer expires.
* This may call "delete this" so the object should not be used again.
*
* @param timer
@@ -1023,7 +1034,7 @@ namespace openbfdd
uint64_t initialTimeout = getDetectionTimeout()*(m_destroyAfterTimeouts - 1);
gLog.Optional(Log::SessionDetail, "Session (id=%u) setting initial timeout based on local system timeout multiplier.", m_id);
- m_recieveTimeoutTimer->SetMicroTimer(initialTimeout);
+ m_receiveTimeoutTimer->SetMicroTimer(initialTimeout);
}
else if ( m_timeoutStatus == TimeoutStatus::TimedOut)
{
@@ -1053,7 +1064,7 @@ namespace openbfdd
gLog.Optional(Log::SessionDetail, "Session (id=%u) setting deadly timeout based on remote system Detection interval.", m_id);
- m_recieveTimeoutTimer->SetMicroTimer(remoteDeadlyTimeout);
+ m_receiveTimeoutTimer->SetMicroTimer(remoteDeadlyTimeout);
}
else if ( m_timeoutStatus == TimeoutStatus::TxSuspeded)
{
@@ -1213,51 +1224,82 @@ namespace openbfdd
gLog.Optional(Log::Session, "(id=%u) set from %s to %s.", m_id, wasSuspened ? "suspended":"responsive", m_isSuspended ? "suspended":"responsive");
}
-
- void Session::LogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, in_addr_t remoteAddr, in_port_t remotePort, in_addr_t localAddr, in_port_t localPort)
+ /**
+ * Logs packet contents if PacketContents is enabled.
+ * This version allows the ports to be specified.
+ *
+ * @param packet
+ * @param outPacket
+ * @param inHostOrder
+ * @param remoteAddr
+ * @param remotePort - 0 for no port specified.
+ * @param localAddr
+ * @param localPort - 0 for no port specified.
+ */
+ void Session::logPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const IpAddr &remoteAddr, in_port_t remotePort, const IpAddr &localAddr, in_port_t localPort)
{
if(gLog.LogTypeEnabled(Log::PacketContents))
{
- TimeSpec time;
- const BfdPacketHeader &header = packet.header;
-
- // Since we use multiple log lines, this is inefficient, and could get
- // "confused" if more than one session was running??
- time = TimeSpec::MonoNow();
-
- gLog.Message(Log::PacketContents, "%s [%jd:%09ld] from %s to %s, myDisc=%u yourDisc=%u",
- outPacket ?"Send":"Receive",
- (intmax_t)time.tv_sec,
- time.tv_nsec,
- localPort ? Ip4ToString(localAddr, localPort) : Ip4ToString(localAddr),
- remotePort ? Ip4ToString(remoteAddr, remotePort) : Ip4ToString(remoteAddr),
- inHostOrder ? header.myDisc : ntohl(header.myDisc),
- inHostOrder ? header.yourDisc : ntohl(header.yourDisc)
- );
-
- gLog.Message(Log::PacketContents, " v=%hhd state=<%s> flags=[%s%s%s%s%s%s] diag=<%s> len=%hhd",
- header.GetVersion(),
- bfd::StateName(header.GetState()),
- header.GetPoll() ? "P":"",
- header.GetFinal() ? "F":"",
- header.GetControlPlaneIndependent() ? "C":"",
- header.GetAuth() ? "A":"",
- header.GetDemand() ? "D":"",
- header.GetMultipoint() ? "M":"",
- bfd::DiagShortString(header.GetDiag()),
- header.length
- );
-
-
- gLog.Message(Log::PacketContents, " Multi=%hhu MinTx=%u MinRx=%u MinEchoRx=%u",
- header.detectMult,
- inHostOrder ? header.txDesiredMinInt : htonl(header.txDesiredMinInt),
- inHostOrder ? header.rxRequiredMinInt : htonl(header.rxRequiredMinInt),
- inHostOrder ? header.rxRequiredMinEchoInt : htonl(header.rxRequiredMinEchoInt)
- );
+ // Not super efficient ... but we are logging packet contents, so this is a
+ // debug situation
+ SockAddr useRemoteAddr(remoteAddr);
+ SockAddr useLocalAddr(localAddr);
+ useRemoteAddr.SetPort(remotePort);
+ useLocalAddr.SetPort(localPort);
+ doLogPacketContents(packet, outPacket, inHostOrder, useRemoteAddr, useLocalAddr);
}
}
+ void Session::LogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const SockAddr &remoteAddr, const IpAddr &localAddr)
+ {
+ if(gLog.LogTypeEnabled(Log::PacketContents))
+ doLogPacketContents(packet, outPacket, inHostOrder, remoteAddr, SockAddr(localAddr));
+ }
+
+ /**
+ * Same as LogPacketContents, but always does the work.
+ */
+ void Session::doLogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const SockAddr &remoteAddr, const SockAddr &localAddr)
+ {
+ TimeSpec time;
+ const BfdPacketHeader &header = packet.header;
+
+ // Since we use multiple log lines, this is inefficient, and could get
+ // "confused" if more than one session was running??
+ time = TimeSpec::MonoNow();
+
+ gLog.Message(Log::PacketContents, "%s [%jd:%09ld] from %s to %s, myDisc=%u yourDisc=%u",
+ outPacket ?"Send":"Receive",
+ (intmax_t)time.tv_sec,
+ time.tv_nsec,
+ localAddr.ToString(),
+ remoteAddr.ToString(),
+ inHostOrder ? header.myDisc : ntohl(header.myDisc),
+ inHostOrder ? header.yourDisc : ntohl(header.yourDisc)
+ );
+
+ gLog.Message(Log::PacketContents, " v=%hhd state=<%s> flags=[%s%s%s%s%s%s] diag=<%s> len=%hhd",
+ header.GetVersion(),
+ bfd::StateName(header.GetState()),
+ header.GetPoll() ? "P":"",
+ header.GetFinal() ? "F":"",
+ header.GetControlPlaneIndependent() ? "C":"",
+ header.GetAuth() ? "A":"",
+ header.GetDemand() ? "D":"",
+ header.GetMultipoint() ? "M":"",
+ bfd::DiagShortString(header.GetDiag()),
+ header.length
+ );
+
+
+ gLog.Message(Log::PacketContents, " Multi=%hhu MinTx=%u MinRx=%u MinEchoRx=%u",
+ header.detectMult,
+ inHostOrder ? header.txDesiredMinInt : htonl(header.txDesiredMinInt),
+ inHostOrder ? header.rxRequiredMinInt : htonl(header.rxRequiredMinInt),
+ inHostOrder ? header.rxRequiredMinEchoInt : htonl(header.rxRequiredMinEchoInt)
+ );
+ }
+
void Session::SetMulti(uint8_t val)
{
LogAssert(m_scheduler->IsMainThread());
View
62 Session.h
@@ -13,6 +13,8 @@
#include "bfd.h"
#include "SmartPointer.h"
#include "TimeSpec.h"
+#include "SockAddr.h"
+#include "Socket.h"
#include <list>
#include <arpa/inet.h>
@@ -23,7 +25,6 @@ namespace openbfdd
class Timer;
struct BfdPacket;
-
/**
* Session class, handles a single BFD session.
* Unless otherwise specified, all calls must be made on the scheduler's main
@@ -63,35 +64,56 @@ namespace openbfdd
* Starts a passive session receiving packets from the given address and
* port.
*
- * @param remoteAddr [in] - remote address.
- * @param remotePort [in]- remote port.
- * @param localAddr [in]- address on which to receive and send packets.
+ * @param remoteAddr [in] - remote address. Must include a port, that will be
+ * the source port used by the remote machine for sending us
+ * packets.
+ * @param localAddr [in]- address on which to receive and send packets. May not
+ * be 'any'
+ *
+ * @return - False on failure.
*/
- void StartPassiveSession(in_addr_t remoteAddr, in_port_t remotePort, in_addr_t localAddr);
+ bool StartPassiveSession(const SockAddr &remoteAddr, const IpAddr &localAddr);
/**
* Starts an active session for the given address.
+ *
+ * This must not already be a working session.
*
- * @param remoteAddr [in] - remote address.
- * @param localAddr [in]- address on which to receive and send packets.
- */
- void StartActiveSession(in_addr_t remoteAddr, in_addr_t localAddr);
+ * @param remoteAddr [in] - remote address.
+ * @param localAddr [in]- address on which to receive and send packets. May not
+ * be 'any'
+ *
+ * @return - False on failure.
+ **/
+ bool StartActiveSession(const IpAddr &remoteAddr, const IpAddr &localAddr);
+
+ /**
+ * Upgrades a passive to active session.
+ *
+ * The session must be a passive session. It is converted to an active one. If
+ * the session is passive, and this returns false, then it is still a valid
+ * passive session.
+ *
+ * @return - False on failure.
+ **/
+ bool UpgradeToActiveSession();
+
/**
* Gets the last remote address set with StartActiveSession() or
* StartPassiveSession()
*
- * @return in_addr_t - or INADDR_NONE if never set.
+ * @return - The address, or an Invalid address if never set.
*/
- in_addr_t GetRemoteAddress();
+ const IpAddr &GetRemoteAddress();
/**
* Gets the last local address set with StartActiveSession() or
* StartPassiveSession()
*
- * @return in_addr_t - or INADDR_NONE if never set.
+ * @return - The address, or an Invalid address if never set.
*/
- in_addr_t GetLocalAddress();
+ const IpAddr &GetLocalAddress();
/**
* Checks if the session is active (StartActiveSession)
@@ -277,11 +299,9 @@ namespace openbfdd
* @param outPacket
* @param inHostOrder
* @param remoteAddr
- * @param remotePort - 0 for no port specified.
* @param localAddr
- * @param localPort - 0 for no port specified.
*/
- static void LogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, in_addr_t remoteAddr, in_port_t remotePort, in_addr_t localAddr, in_port_t localPort);
+ static void LogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const SockAddr &remoteAddr, const IpAddr &localAddr);
struct SetValueFlags {enum Flag{None=0x0000, PreventTxReschedule = 0x0001, TryPoll = 0x0002};};
@@ -324,6 +344,8 @@ namespace openbfdd
void setDesiredMinTxInterval(uint32_t newValue, SetValueFlags::Flag flags = SetValueFlags::None);
void setRequiredMinRxInterval(uint32_t newValue, SetValueFlags::Flag flags = SetValueFlags::None);
+ static void logPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const IpAddr &remoteAddr, in_port_t remotePort, const IpAddr &localAddr, in_port_t localPort);
+ static void doLogPacketContents(const BfdPacket &packet, bool outPacket, bool inHostOrder, const SockAddr &remoteAddr, const SockAddr &localAddr);
private:
@@ -334,16 +356,16 @@ namespace openbfdd
Beacon *m_beacon; //For lifetime management only.
Scheduler *m_scheduler;
- in_addr_t m_remoteAddr;
+ IpAddr m_remoteAddr;
in_port_t m_remoteSourcePort;
- in_addr_t m_localAddr; // The ip local address for the session, from which packets are sent.
+ IpAddr m_localAddr; // The ip local address for the session, from which packets are sent.
in_port_t m_sendPort; // The port we are using to send to the remote machine for this session.
bool m_isActive; // are we taking an active role ... that is, we start sending periodic packets until session comes up.
uint32_t m_id; //Human readable id.
// For sending data back to the source
- FileDescriptor m_sendSocket;
+ Socket m_sendSocket;
// State variables from spec
bfd::State::Value m_sessionState;
@@ -413,7 +435,7 @@ namespace openbfdd
// Timers
void deleteTimer(Timer *timer);
- RiaaClassCall<Timer, Session, &Session::deleteTimer> m_recieveTimeoutTimer; // Timer for the receive packet timeout.
+ RiaaClassCall<Timer, Session, &Session::deleteTimer> m_receiveTimeoutTimer; // Timer for the receive packet timeout.
RiaaClassCall<Timer, Session, &Session::deleteTimer> m_transmitNextTimer; // Timer for the next control packet.
};
View
77 SmartPointer.h
@@ -28,9 +28,9 @@ namespace openbfdd
bool operator==(T cmp) const {return val == cmp;}
T Detach() {T old = val; val = nullval;return old;} // detach without freeing
void Dispose() {if (!isNull()) freeFn(val);val=nullval;}
- bool IsValid() {return !isNull();}
+ bool IsValid() const {return !isNull();}
protected:
- bool isNull() {return val==nullval;}
+ bool isNull() const {return val==nullval;}
private:
RiaaBase& operator=(RiaaBase<T, nullval, freeFn> &src) {fprintf(stderr, "Bad operator=\n"); return *this;} // don't want two RiaaBase freeing the same object
RiaaBase(const RiaaBase<T, nullval, freeFn> &src) {fprintf(stderr, "Bad constructor\n");}; // never use this.
@@ -49,17 +49,17 @@ namespace openbfdd
public:
T* val;
RiaaNullBase() : val(NULL) {}
- RiaaNullBase(T* val) : val(val) {}
+ RiaaNullBase( T *val) : val(val) {}
~RiaaNullBase() {Dispose();}
operator T*() const { return val;}
T* operator=(T* newval) {Dispose();val = newval; return newval;}
bool operator==(T* cmp) const {return val == cmp;}
T* Detach() {T* old = val; val = NULL;return old;} // detach without freeing
void Dispose() {if (!isNull()) freeFn(val);val=NULL;}
- bool IsValid() {return !isNull();}
- T* operator->() { return val; }
+ bool IsValid() const {return !isNull();}
+ T* operator->() { return val;}
protected:
- bool isNull() {return val==NULL;}
+ bool isNull() const {return val==NULL;}
private:
RiaaNullBase& operator=(RiaaNullBase<T, freeFn> &src) {fprintf(stderr, "Bad operator=\n"); return *this;} // don't want two RiaaNullBase freeing the same object
RiaaNullBase(const RiaaNullBase<T, freeFn> &src) {fprintf(stderr, "Bad constructor\n");}; // never use this.
@@ -79,29 +79,18 @@ namespace openbfdd
void CloseFileHandle(FILE *val);
typedef RiaaNullBase<FILE, CloseFileHandle> FileHandle;
+
/**
- * RIAA base class for class pointers that use delete.
+ * RIAA class for simple array allocated with new or new[]
*/
- template <typename T> class RiaaClass
+ template <typename T> void FreeFree(T *val) {free(val);}
+ template <typename T> void FreeArray(T *val) {delete[] val;}
+ template <typename T> void FreeDelete(T *val) {delete val;}
+ template <typename T> struct Riaa
{
- public:
- T* val;
- RiaaClass() : val(NULL) {}
- RiaaClass(T* val) : val(val) {}
- ~RiaaClass() {Dispose();}
- operator T*() const { return val;}
- T* operator=(T* newval) {Dispose();val = newval; return newval;}
- bool operator==(T* cmp) const {return val == cmp;}
- T* Detach() {T* old = val; val = NULL;return old;} // detach without freeing
- void Dispose() {if (!isNull()) delete val;val=NULL;}
- bool IsValid() {return !isNull();}
- T* operator->() { return val; }
- protected:
- bool isNull() {return val==NULL;}
-
- private:
- RiaaClass& operator=(RiaaClass<T> &src) {fprintf(stderr, "Bad operator=\n"); return *this;} // don't want two RiaaClass freeing the same object
- RiaaClass(const RiaaClass<T> &src) {fprintf(stderr, "Bad constructor\n");}; // never use this.
+ typedef RiaaNullBase<T, FreeArray<T> > DeleteArray;
+ typedef RiaaNullBase<T, FreeDelete<T> > Delete;
+ typedef RiaaNullBase<T, FreeFree<T> > Free;
};
@@ -119,22 +108,50 @@ namespace openbfdd
T* val;
C* myClass;
RiaaClassCall(C* myClass) : val(NULL), myClass(myClass) {}
- RiaaClassCall(T* val, C* myClass) : val(val), myClass(myClass) {}
+ RiaaClassCall(const T* val, C* myClass) : val(val), myClass(myClass) {}
~RiaaClassCall() {Dispose();}
operator T*() const { return val;}
T* operator=(T* newval) {Dispose();val = newval; return newval;}
bool operator==(T* cmp) const {return val == cmp;}
T* Detach() {T* old = val; val = NULL;return old;} // detach without freeing
void Dispose() {if (!isNull()) (myClass->*freeFn)(val);val=NULL;}
- bool IsValid() {return !isNull();}
- T* operator->() { return val; }
+ bool IsValid() const {return !isNull();}
+ T* operator->() { return val;}
protected:
- bool isNull() {return val==NULL;}
+ bool isNull() const {return val==NULL;}
private:
RiaaClassCall& operator=(RiaaClassCall<T, C, freeFn> &src) {fprintf(stderr, "Bad operator=\n"); return *this;} // don't want two RiaaClassCall freeing the same object
RiaaClassCall(const RiaaClassCall<T, C, freeFn> &src) {fprintf(stderr, "Bad constructor\n");}; // never use this.
};
+ /**
+ * RIAA class for self deleting NON pointer type, that calls a function on a
+ * class. T Must have simple copy semantics & compare semantics.
+ *
+ * (We need a separate template class, because NULL is not allowed as a template
+ * parameter.)
+ */
+ template <typename T, typename C, void (C::*freeFn)(T)> class RiaaObjCall
+ {
+ public:
+ T val;
+ bool valid;
+ C* myClass;
+ //RiaaObjCall(C* myClass) : valid(false), myClass(myClass) { /*for warning ... hopefully not damaging*/}
+ RiaaObjCall(T val, C* myClass) : val(val), valid(true), myClass(myClass) {}
+ ~RiaaObjCall() {Dispose();}
+ operator T&() { return val;}
+ T& operator=(T newval) {Dispose();val = newval; valid=true; return val;}
+ bool operator==(T cmp) const {return val == cmp;}
+ T& Detach() {valid = false; return val;} // detach without freeing
+ void Dispose() {if (valid) (myClass->*freeFn)(val);valid=false;}
+ bool IsValid() const {return valid;}
+ //T& operator->() { return val; } //??
+ protected:
+ private:
+ RiaaObjCall& operator=(RiaaObjCall<T, C, freeFn> &src) {fprintf(stderr, "Bad operator=\n"); return *this;} // don't want two RiaaObjCall freeing the same object
+ RiaaObjCall(const RiaaObjCall<T, C, freeFn> &src) {fprintf(stderr, "Bad constructor\n");}; // never use this.
+ };
};
View
640 SockAddr.cpp
@@ -0,0 +1,640 @@
+/**************************************************************
+* Copyright (c) 2011, Dynamic Network Services, Inc.
+* Jake Montgomery (jmontgomery@dyn.com) & Tom Daly (tom@dyn.com)
+* Distributed under the FreeBSD License - see LICENSE
+***************************************************************/
+#include "common.h"
+#include "SockAddr.h"
+#include "utils.h"
+#include "lookup3.h"
+#include <cstring>
+
+using namespace std;
+namespace openbfdd
+{
+
+ Addr::Type Addr::FamilyToType(int af)
+ {
+ if (af == AF_INET)
+ return Addr::IPv4;
+ else if (af == AF_INET6)
+ return Addr::IPv6;
+ else
+ return Addr::Invalid;
+ }
+
+ int Addr::TypeToFamily(Addr::Type type)
+ {
+ if (type == Addr::IPv4)
+ return AF_INET;
+ else if (Addr::IPv6)
+ return AF_INET6;
+ else
+ return AF_UNSPEC;
+ }
+
+ const char *Addr::TypeToString(Addr::Type type)
+ {
+ if (type == Addr::IPv4)
+ return "IPv4";
+ else if (Addr::IPv6)
+ return "IPv6";
+ else
+ return "<unknown>";
+ }
+
+ /**
+ * Sets the address to invalid, and m_addr to the default for the given type.
+ *
+ * @param type
+ */
+ void sockAddrBase::init(Addr::Type type)
+ {
+ m_isValid = false;
+ switch (type)
+ {
+ default:
+ case Addr::IPv4:
+ {
+ struct sockaddr_in *storage = getIPv4Storage();
+ storage->sin_family = AF_INET;
+ storage->sin_port = 0;
+ storage->sin_addr.s_addr = INADDR_ANY;
+ }
+ break;
+ case Addr::IPv6:
+ {
+ struct sockaddr_in6 *storage = getIPv6Storage();
+ memset(storage, 0, sizeof(struct sockaddr_in6));
+ storage->sin6_family = AF_INET6;
+ storage->sin6_addr = in6addr_any; /** Probably not necessary. Is in6addr_any _guaranteed_ to be 0?*/
+ }
+ break;
+ }
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort) : m_allowPort(allowPort)
+ {
+ init(Addr::Invalid);
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort, const struct sockaddr_in6 *addr) : m_allowPort(allowPort)
+ {
+ struct sockaddr_in6 *storage = getIPv6Storage();
+
+ if (!addr || addr->sin6_family != AF_INET6)
+ {
+ init(Addr::IPv6);
+ return;
+ }
+
+ memcpy(storage, addr, sizeof(struct sockaddr_in6));
+ if (!m_allowPort)
+ clearPort();
+ m_isValid = true;
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort, const struct sockaddr_in *addr) : m_allowPort(allowPort)
+ {
+ struct sockaddr_in *storage = getIPv4Storage();
+
+ if (!addr || addr->sin_family != AF_INET)
+ {
+ init(Addr::IPv4);
+ return;
+ }
+
+ memcpy(storage, addr, sizeof(struct sockaddr_in));
+ if (!m_allowPort)
+ clearPort();
+ m_isValid = true;
+ }
+
+
+ sockAddrBase::sockAddrBase(bool allowPort, const struct in6_addr *addr) : m_allowPort(allowPort)
+ {
+ init(Addr::IPv6);
+
+ if (!addr)
+ return;
+
+ struct sockaddr_in6 *storage = getIPv6Storage();
+
+ storage->sin6_addr = *addr;
+ m_isValid = true;
+ }
+
+
+ sockAddrBase::sockAddrBase(bool allowPort, const struct in_addr *addr) : m_allowPort(allowPort)
+ {
+ init(Addr::IPv4);
+
+ if (!addr)
+ return;
+
+ struct sockaddr_in *storage = getIPv4Storage();
+
+ storage->sin_addr.s_addr = addr->s_addr;
+ m_isValid = true;
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort, Addr::Type type, in_port_t port) : m_allowPort(allowPort)
+ {
+ init(Addr::Invalid);
+ if (type != Addr::Invalid)
+ SetAny(type, port);
+ }
+
+
+ sockAddrBase::sockAddrBase(bool allowPort, const struct sockaddr *addr, socklen_t addrlen) : m_allowPort(allowPort)
+ {
+ if (!addr || (addrlen < sizeof(struct sockaddr_in) && addrlen < sizeof(struct sockaddr_in6)))
+ {
+ init(Addr::Invalid);
+ return;
+ }
+
+ int family = ((struct sockaddr_in *)addr)->sin_family;
+
+ if (family == AF_INET)
+ init(Addr::IPv4);
+ else if (family == AF_INET6)
+ init(Addr::IPv6);
+ else
+ {
+ init(Addr::Invalid);
+ return;
+ }
+
+ if (addrlen < GetSize())
+ return;
+ memcpy(&m_addr, addr, GetSize());
+ if (!m_allowPort)
+ clearPort();
+ m_isValid = true;
+
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort, const sockAddrBase &src) : m_allowPort(allowPort)
+ {
+ copy(src);
+ }
+
+ sockAddrBase::sockAddrBase(bool allowPort, const char *str) : m_allowPort(allowPort)
+ {
+ FromString(str);
+ }
+
+
+ sockAddrBase::sockAddrBase(bool allowPort, const char *str, in_port_t port) : m_allowPort(allowPort)
+ {
+ FromString(str, port);
+ }
+
+
+ void sockAddrBase::copy(const sockAddrBase& src)
+ {
+ if (!src.IsValid())
+ {
+ init(Addr::Invalid);
+ return;