completed partial IPv6 compatibility in DNS; does retrieve and Cache IPv6 IPs
[pingcheck] / src / host / pingerfactory.cpp
1 /*
2  The software in this package is distributed under the GNU General
3  Public License version 2 (with a special exception described below).
4
5  A copy of GNU General Public License (GPL) is included in this distribution,
6  in the file COPYING.GPL.
7
8  As a special exception, if other files instantiate templates or use macros
9  or inline functions from this file, or you compile this file and link it
10  with other works to produce a work based on this file, this file
11  does not by itself cause the resulting work to be covered
12  by the GNU General Public License.
13
14  However the source code for this file must still be made available
15  in accordance with section (3) of the GNU General Public License.
16
17  This exception does not invalidate any other reasons why a work based
18  on this file might be covered by the GNU General Public License.
19  */
20
21 #include "host/pingerfactory.h"
22
23 #include <cstdlib>
24
25 #include <iostream>
26
27 #include <boost/asio/ip/tcp_raw_protocol.hpp>
28 #include <boost/system/system_error.hpp>
29
30 #include <logfunc.hpp>
31
32 #include "boost_assert_handler.h"
33 #include "icmp/icmppinger.h"
34 #include "tcp/tcppinger.h"
35
36 using namespace std;
37 using boost::shared_ptr;
38 using boost::asio::ip::icmp;
39 using boost::asio::ip::tcp_raw_protocol;
40 using boost::system::system_error;
41 using I2n::Logger::GlobalLogger;
42
43 //-----------------------------------------------------------------------------
44 // PingerFactory
45 //-----------------------------------------------------------------------------
46
47 /**
48  * @brief Default constructor.
49  */
50 PingerFactory::PingerFactory()
51 {
52 }
53
54 /**
55  * @brief Destructor.
56  */
57 PingerFactory::~PingerFactory()
58 {
59 }
60
61 /**
62  * @brief Create a Pinger object suitable to the given protocol.
63  *
64  * @param protocol One of the available ping protocols.
65  * @param io_serv The one @c io_service object that controls async processing
66  * @param network_interface The network interface name from where the ping
67  * packet will be sent.
68  * @return a Pinger object to able to ping using the given protocol.
69  */
70 PingerItem PingerFactory::createPinger(
71         const PingProtocol protocol,
72         const IoServiceItem io_serv,
73         const string &network_interface,
74         const int ping_reply_timeout
75 )
76 {
77     BOOST_ASSERT( /*( PingProtocol_First <= protocol ) && */( protocol <= PingProtocol_Last ) );
78     BOOST_ASSERT( !network_interface.empty() );
79
80     try
81     {
82         if (protocol == PingProtocol_ICMP)
83         {
84             PingerItem new_pinger = IcmpPinger::create( io_serv, icmp::v4(),
85                                                          network_interface,
86                                                          ping_reply_timeout );
87             return new_pinger;
88         }
89         else if (protocol == PingProtocol_ICMPv6)
90         {
91             PingerItem new_pinger = IcmpPinger::create( io_serv, icmp::v6(),
92                                                          network_interface,
93                                                          ping_reply_timeout );
94             return new_pinger;
95         }
96         else if (protocol == PingProtocol_TCP)
97         {
98             PingerItem new_pinger = TcpPinger::create( io_serv, tcp_raw_protocol::v4(),
99                                                         network_interface,
100                                                         ping_reply_timeout );
101             return new_pinger;
102         }
103         else if (protocol == PingProtocol_TCP_IPv6)
104         {
105             PingerItem new_pinger = TcpPinger::create( io_serv, tcp_raw_protocol::v6(),
106                                                         network_interface,
107                                                         ping_reply_timeout );
108             return new_pinger;
109         }
110         else
111         {
112             BOOST_ASSERT( !"Try to create a pinger from an invalid protocol" );                                                 //lint !e506
113             return PingerItem();                                                                                                             //lint !e527
114         }
115     }
116     catch ( const system_error &ex )
117     {
118         // Raw sockets are locked down by Unix operating systems to prevent
119         // malware and security holes, thus it requires root access to use it.
120         GlobalLogger.error() << "Error creating Pinger: " << ex.what()
121             << " (you may have to run pingcheck as root)" << endl;
122         exit( EXIT_FAILURE );
123     }
124
125     return PingerItem();                                                                                                                        //lint !e527
126 }
127