From: dw6 Date: Wed, 5 Dec 2007 10:42:18 +0000 (+0000) Subject: adding PF_INET[6], SOCK_RAW sockets called RawV[4|6]ClientSocketHandle while naming... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=52d44a2033ffdac443e52f5dd1f075c5fe2774ef;p=senf.git adding PF_INET[6], SOCK_RAW sockets called RawV[4|6]ClientSocketHandle while naming the files RawInet... to distinguish them from PF_PACKET SOCK_RAW sockets. see Wiki for more information git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@542 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Protocols/INet/RawInetProtocol.cc b/Socket/Protocols/INet/RawInetProtocol.cc new file mode 100644 index 0000000..1603bf4 --- /dev/null +++ b/Socket/Protocols/INet/RawInetProtocol.cc @@ -0,0 +1,50 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum NETwork research (NET) +// David Wagner +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#include "RawInetProtocol.hh" + +// Custom includes +#include +#include +#include +#include // for SIOCINQ / SIOCOUTQ +#include // for if_nametoindex +#include "../../../Socket/SocketHandle.hh" + +//#include "UDPProtocol.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ unsigned senf::RawInetProtocol::available() + const +{ + int n; + if (::ioctl(body().fd(),SIOCINQ,&n) < 0) + throwErrno(); + return n; +} + +prefix_ bool senf::RawInetProtocol::eof() + const +{ + return false; +} +#undef prefix_ diff --git a/Socket/Protocols/INet/RawInetProtocol.hh b/Socket/Protocols/INet/RawInetProtocol.hh new file mode 100644 index 0000000..8970955 --- /dev/null +++ b/Socket/Protocols/INet/RawInetProtocol.hh @@ -0,0 +1,60 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum NETwork research (NET) +// David Wagner +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +#ifndef RAWINETPROTOCOL_HH_ +#define RAWINETPROTOCOL_HH_ + +// Custom includes +#include "INetAddressing.hh" +#include "INetProtocol.hh" +#include "../../../Socket/Protocols/BSDSocketProtocol.hh" +#include "../../../Socket/FramingPolicy.hh" +#include "../../../Socket/CommunicationPolicy.hh" +#include "../../../Socket/ReadWritePolicy.hh" +#include "../../../Socket/BufferingPolicy.hh" +#include "../../../Socket/ProtocolClientSocketHandle.hh" + +namespace senf { + + /// \addtogroup protocol_facets_group + /// @{ + + /** \brief Protocol facat to support RAW operations upon IPv4/6 + + This protocol facet provides all those protocol functions, + which are available on a PF_INET[6]/RAW socket. + + */ + class RawInetProtocol + : public virtual SocketProtocol + { + public: + ///\name Abstract Interface Implementation + ///@{ + + unsigned available() const; + bool eof() const; + + ///@} + }; + + /// @} +} + +#endif /*RAWINETPROTOCOL_HH_*/ diff --git a/Socket/Protocols/INet/RawInetSocketHandle.cc b/Socket/Protocols/INet/RawInetSocketHandle.cc new file mode 100644 index 0000000..1e16bf5 --- /dev/null +++ b/Socket/Protocols/INet/RawInetSocketHandle.cc @@ -0,0 +1,100 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum NETwork research (NET) +// David Wagner +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "RawInetSocketHandle.hh" + +// Custom includes +#include +#include +#include + +#include "../../../Utils/Exception.hh" + +//#include "UDPSocketHandle.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::UDPv4SocketProtocol + +prefix_ void senf::RawV4SocketProtocol::init_client() + const +{ + init_client(IPPROTO_RAW); +} + +prefix_ void +senf::RawV4SocketProtocol::init_client(int const & protocol) + const +{ + int sock = ::socket(PF_INET, SOCK_RAW, protocol); + if (sock < 0) + throwErrno(); + body().fd(sock); +} + +prefix_ void +senf::RawV4SocketProtocol::init_client(int const & protocol, INet4SocketAddress const & address) + const +{ + init_client(protocol); + bind(address); +} + +prefix_ std::auto_ptr senf::RawV4SocketProtocol::clone() + const +{ + return std::auto_ptr(new RawV4SocketProtocol()); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::UDPv6SocketProtocol:: + +prefix_ void senf::RawV6SocketProtocol::init_client() + const +{ + init_client(IPPROTO_RAW); +} + +prefix_ void senf::RawV6SocketProtocol::init_client(int const & protocol) + const +{ + int sock = ::socket(PF_INET6,SOCK_RAW,protocol); + if (sock < 0) + throwErrno(); + body().fd(sock); +} + +prefix_ void +senf::RawV6SocketProtocol::init_client(int const & protocol, INet6SocketAddress const & address) + const +{ + init_client(protocol); + bind(address); +} + +prefix_ std::auto_ptr senf::RawV6SocketProtocol::clone() + const +{ + return std::auto_ptr(new RawV6SocketProtocol()); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ diff --git a/Socket/Protocols/INet/RawInetSocketHandle.hh b/Socket/Protocols/INet/RawInetSocketHandle.hh new file mode 100644 index 0000000..86095e5 --- /dev/null +++ b/Socket/Protocols/INet/RawInetSocketHandle.hh @@ -0,0 +1,189 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum NETwork research (NET) +// David Wagner +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef RAWINETSOCKETHANDLE_HH_ +#define RAWINETSOCKETHANDLE_HH_ + + +// Custom includes +#include "INetProtocol.hh" +#include "RawInetProtocol.hh" +#include "../../../Socket/Protocols/BSDSocketProtocol.hh" +#include "../../../Socket/FramingPolicy.hh" +#include "../../../Socket/CommunicationPolicy.hh" +#include "../../../Socket/ReadWritePolicy.hh" +#include "../../../Socket/BufferingPolicy.hh" +#include "../../../Socket/ProtocolClientSocketHandle.hh" + +//#include "UDPSocketHandle.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { + + /// \addtogroup concrete_protocol_group + /// @{ + + typedef MakeSocketPolicy< + INet4AddressingPolicy, + DatagramFramingPolicy, + UnconnectedCommunicationPolicy, + ReadablePolicy, + WriteablePolicy, + SocketBufferingPolicy + >::policy RawV4Socket_Policy; ///< Socket Policy of the RawV4 Protocol + + /** \brief IPv4 RAW Socket Protocol + + \par Socket Handle typedefs: + \ref RawV4ClientSocketHandle (ProtocolClientSocketHandle) + + \par Policy Interface: + ClientSocketHandle::read(), ClientSocketHandle::readfrom(), + ClientSocketHandle::writeto(), ClientSocketHandle::bind(), ClientSocketHandle::local(), + ClientSocketHandle::rcvbuf(), ClientSocketHandle::sndbuf() + + \par Address Type: + INet4Address + + RawV4SocketProtocol provides an internet protocol raw socket based on IPv4 addressing. + + This class is utilized as the protocol class of the ProtocolClientSocketHandle + via the Socket Handle typedefs above. + + \see RawV6SocketProtocol + */ + class RawV4SocketProtocol + : public ConcreteSocketProtocol, + public IPv4Protocol, + public RawInetProtocol, + public BSDSocketProtocol, + public AddressableBSDSocketProtocol//, +// public senf::pool_alloc_mixin + { + public: + /////////////////////////////////////////////////////////////////////////// + // internal interface + + ///\name Constructors + ///@{ + + void init_client() const; ///< Create unconnected client socket for IPPROTO_RAW + /**< \note This member is implicitly called from the + ProtocolClientSocketHandle::ProtocolClientSocketHandle() + constructor */ + void init_client(int const & protocol) const; ///< Create unconnected client socket for protocol + + void init_client(int const & protocol, INet4SocketAddress const & address) const; + ///< Create client socket and bind + /**< Creates a new client socket for the given protocol and binds to the given + address. + \param[in] protocol Layer 4 protocol to filter for / to send + \param[in] address local address to bind to */ + + ///@} + ///\name Abstract Interface Implementation + + std::auto_ptr clone() const; + + ///@} + }; + + typedef ProtocolClientSocketHandle RawV4ClientSocketHandle; + + + + +//////////////////////////////////////////////////////////////////// Raw IPv6 Socket ////////////////////////////////////// + typedef MakeSocketPolicy< + INet6AddressingPolicy, + DatagramFramingPolicy, + UnconnectedCommunicationPolicy, + ReadablePolicy, + WriteablePolicy, + SocketBufferingPolicy + >::policy RawV6Socket_Policy; ///< Socket Policy of the RawV6 Protocol + + /** \brief IPv6 RAW Socket Protocol + + \par Socket Handle typedefs: + \ref RawV6ClientSocketHandle (ProtocolClientSocketHandle) + + \par Policy Interface: + ClientSocketHandle::read(), ClientSocketHandle::readfrom(), + ClientSocketHandle::writeto(), ClientSocketHandle::bind(), ClientSocketHandle::local(), + ClientSocketHandle::rcvbuf(), ClientSocketHandle::sndbuf() + + \par Address Type: + INet6Address + + RawV6SocketProtocol provides an internet protocol stream socket based on IPv6 addressing. + + This class is utilized as the protocol class of the ProtocolClientSocketHandle + via the Socket Handle typedefs above. + + \see RawV4SocketProtocol + */ + class RawV6SocketProtocol + : public ConcreteSocketProtocol, + public IPv6Protocol, + public RawInetProtocol, + public BSDSocketProtocol, + public AddressableBSDSocketProtocol//, +// public senf::pool_alloc_mixin + { + public: + /////////////////////////////////////////////////////////////////////////// + // internal interface + + ///\name Constructors + ///@{ + + void init_client() const; ///< Create unconnected client socket for IPPROTO_RAW + /**< \note This member is implicitly called from the + ProtocolClientSocketHandle::ProtocolClientSocketHandle() + constructor */ + + void init_client(int const & protocol) const; ///< Create unconnected client socket for protocol + + void init_client(int const & protocol, INet6SocketAddress const & address) const; + ///< Create client socket and bind + /**< Creates a new client socket for the given protocol and binds to the given + address. + \param[in] protocol Layer 4 protocol to filter for / to send + \param[in] address local address to bind to */ + /**< \note This member is implicitly called from the + ProtocolClientSocketHandle::ProtocolClientSocketHandle() + constructor */ + + ///@} + ///\name Abstract Interface Implementation + + std::auto_ptr clone() const; + + ///@} + }; + + typedef ProtocolClientSocketHandle RawV6ClientSocketHandle; + + /// @} + +} + +#endif /*RAWINETSOCKETHANDLE_HH_*/ diff --git a/Socket/Protocols/INet/RawInetSocketHandle.test.cc b/Socket/Protocols/INet/RawInetSocketHandle.test.cc new file mode 100644 index 0000000..e8ab17a --- /dev/null +++ b/Socket/Protocols/INet/RawInetSocketHandle.test.cc @@ -0,0 +1,192 @@ +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum NETwork research (NET) +// David Wagner +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +/** \file + \brief RawInetSocketHandle.test unit tests */ + +#include +#include +#include +#include +#include +#include +#include "RawInetSocketHandle.hh" +#include + +#include "../../../Utils/auto_unit_test.hh" +#include + +namespace { + + void error(char const * fn, char const * proc="") + { + std::cerr << "\n" << proc << ((*proc)?": ":"") << fn << ": " << strerror(errno) << std::endl; + } + + void fail(char const * proc, char const * fn) + { + error(fn,proc); + _exit(1); + } + + int server_pid = 0; + + void start(void (*fn)()) + { + server_pid = ::fork(); + if (server_pid < 0) BOOST_FAIL("fork()"); + if (server_pid == 0) { + (*fn)(); + _exit(0); + } + } + + void wait() + { + int status; + if (waitpid(server_pid,&status,0)<0) + BOOST_FAIL("waitpid()"); + BOOST_CHECK_EQUAL( status , 0 ); + } + + void stop() + { + if (server_pid) { + kill(server_pid,9); + wait(); + server_pid = 0; + } + } + +} + +/////////////////////////////////////////////////////////////////////////// + +namespace { + + void server_v4() //listen for packets with proto=47 (GRE) and resend them with proto=48 + { + struct sockaddr_in sin; + ::memset(&sin,0,sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(0); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + int sockrec = socket(PF_INET,SOCK_RAW,47); + if (sockrec<0) fail("server_v4","socket(rec)"); + int socksend = socket(PF_INET,SOCK_RAW,48); + if (socksend<0) fail("server_v4","socket(send)"); + + char buffer[1024]; + while (1) { + int n = read(sockrec,buffer,1024); + if (n == 20+4 )//&& strncmp(,"QUIT",4) == 0) + break; + sleep(1); + //jaja, fieses gehacke... + sendto(socksend,buffer+20,n-20,0,(struct sockaddr *)&sin,sizeof(sin)); + } + + if (close(sockrec) < 0) fail("server_v4","close(rec)"); + if (close(socksend) < 0) fail("server_v4","close(send)"); + } + void server_v6() //listen for packets with proto=47 (GRE) and resend them with proto=48 + { + struct sockaddr_in6 sin; + ::memset(&sin,0,sizeof(sin)); + sin.sin6_family = AF_INET6; + sin.sin6_port = htons(0); + inet_pton(AF_INET6, "::1", &sin.sin6_addr); + int sockrec6 = socket(PF_INET6,SOCK_RAW,47); + if (sockrec6<0) fail("server_v6","socket(rec)"); + int socksend6 = socket(PF_INET6,SOCK_RAW,48); + if (socksend6<0) fail("server_v6","socket(send)"); + char buffer[1024]; + while (1) { + int n = read(sockrec6,buffer,1024); + if (n<0) fail("server_v6","read(sockrec6)"); + if (n == 4 && strncmp(buffer,"QUIT",4) == 0) + break; + sleep(1); + //jaja, fieses gehacke... + n = sendto(socksend6,buffer,n,0,(struct sockaddr *)&sin,sizeof(sin)); + if (n<0) fail("server_v6","sendto(socksend6)"); + } + if (close(sockrec6) < 0) fail("server_v6","close(rec)"); + if (close(socksend6) < 0) fail("server_v6","close(send)"); + } + +} + +BOOST_AUTO_UNIT_TEST(RawV4ClientSocketHandle) +{ + if (getuid() != 0) { + BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV4SocketHandle as non-root user"); + return; + } + try { + std::string test = "TEST-WRITE"; + alarm(10); + start(server_v4); + senf::RawV4ClientSocketHandle sock(47); //IPPROTO_GRE + BOOST_CHECK_NO_THROW( sock.rcvbuf(2048) ); + BOOST_CHECK_EQUAL( sock.rcvbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.sndbuf(2048) ); + BOOST_CHECK_EQUAL( sock.sndbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"), test) ); + senf::RawV4ClientSocketHandle sockrec(48); //IPPROTO_GRE+1 + std::string in = sockrec.read(); + BOOST_CHECK_EQUAL(in.substr(20), test); + BOOST_CHECK_NO_THROW( sock.writeto(senf::INet4SocketAddress("127.0.0.1:0"),"QUIT")); + //sock.close(); + //sockrec.close(); + alarm(0); + } catch (...) { + alarm(0); + throw; + } +} + +BOOST_AUTO_UNIT_TEST(RawV6ClientSocketHandle) +{ + if (getuid() != 0) { + BOOST_WARN_MESSAGE(false, "Cannot test senf::RawV6SocketHandle as non-root user"); + return; + } + try { + std::string test = "TEST-WRITE"; + alarm(5); + start(server_v6); + sleep(1); + senf::RawV6ClientSocketHandle sock(47); //IPPROTO_GRE + BOOST_CHECK_NO_THROW( sock.rcvbuf(2048) ); + BOOST_CHECK_EQUAL( sock.rcvbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.sndbuf(2048) ); + BOOST_CHECK_EQUAL( sock.sndbuf(), 2048u ); + BOOST_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"), test) ); + senf::RawV6ClientSocketHandle sockrec(48); //IPPROTO_GRE+1 + std::string in = sockrec.read(); + BOOST_CHECK_EQUAL(in, test); + BOOST_CHECK_NO_THROW( sock.writeto(senf::INet6SocketAddress("[::1]:0"),"QUIT")); + alarm(0); + } catch (...) { + alarm(0); + throw; + } +}