summaryrefslogtreecommitdiff
path: root/tests/SOCK_Netlink_Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/SOCK_Netlink_Test.cpp')
-rw-r--r--tests/SOCK_Netlink_Test.cpp973
1 files changed, 0 insertions, 973 deletions
diff --git a/tests/SOCK_Netlink_Test.cpp b/tests/SOCK_Netlink_Test.cpp
deleted file mode 100644
index 5d3ee4164ad..00000000000
--- a/tests/SOCK_Netlink_Test.cpp
+++ /dev/null
@@ -1,973 +0,0 @@
-// $Id$
-
-// ====================================================================//
-//
-// = LIBRARY
-// tests
-//
-// = FILENAME
-// SOCK_Netlink_Test.cpp
-//
-// = DESCRIPTION
-// Tests adding of a secondary IP-address, using linux netlink
-// sockets.
-//
-// = AUTHOR
-//
-// Robert Iakobashvili, coroberti@gmail.com
-//
-// ====================================================================//
-
-#include "test_config.h"
-
-#ifdef ACE_HAS_NETLINK
-
-#include "ace/Event_Handler.h"
-#include "ace/Reactor.h"
-#include "ace/Log_Msg.h"
-#include "ace/Get_Opt.h"
-
-#include "ace/Netlink_Addr.h"
-#include "ace/SOCK_Netlink.h"
-
-#include "ace/OS_NS_sys_socket.h"
-
-#include <linux/rtnetlink.h>
-
-
-/**
- * NETLINK SOCKET INTERFACE is a socket API communication
- * between linux kernel and userland.
- *
- * Main usage of netlink communication is for communication between
- * kernel/custom modules/drivers and userspace;
- *
- * In order not to force ACE-tests runners to install some driver for testing
- * purposes, we are using here a build-in netlink interface used by linux for
- * "routing" purposes (rtnetlink).
- *
- * This test is hopefully a useful example of how via netlink to add a new
- * secondary IPv4 address to an interface and to delete it further. The
- * example is integrated within reactive framework for IO demultiplexing.
- *
- * A one button test adds a new secondary IP-address to a loopback
- * interface and deletes it. Even if the address added remains, this shall no
- * cause any damage. In any case the lifetime of a secondary ip is limited
- * till the next reboot. You may wish to run the test with -d option (not to
- * make an address cleanup after addtion) and see it by 'ip addr' command.
- * Further re-run of the test without -d option will cleanup the address.
- *
- * Please, note, that it is ok that the message "rtnetlink error message:
- * Cannot assign requested address" will appear on your console, because first
- * the test is trying to remove the secondary-ip and errors, if it was not before.
- *
- * The one-button test fails, of there is no a loopback device named "lo" on a
- * host or the device is disabled.
- *
- * The same rtnetlink interface may be used to get/add/delete ip-addresses,
- * get/add/delete routing rules, control ARP entires, control Qdisk disciplines,
- * traffic classes and traffic filters, manage network interface configuration
- *
- * For more information, please, read man pages:
- * netlink (3), netlink (7), rtnetlink (3), rtnetlink (3), rtnetlink (7) and ip (8).
- *
- * Some ideas for the test were borrowed from the code of iprouted2
- * written by Alexey Kuznetsov.
- *
- * Command line options:
- *
- * -d do not cleanup the ip-address after addition (so that you can see it by the
- * 'ip addr' command)
- *
- * -i the name of interface to add the address
- *
- * -a ipv4 slash netmask bits, like "192.168.1.1/24"
- *
-
- From Linux headers:
-
- // Generic structure for encapsulation of optional route information.
- // It is reminiscent of sockaddr, but with sa_family replaced with attribute type.
- struct rtattr
- {
- unsigned short rta_len;
- unsigned short rta_type;
- };
-
- //Interface address.
- struct ifaddrmsg
- {
- unsigned char ifa_family;
- unsigned char ifa_prefixlen; // The prefix length is the length of the address mask
- unsigned char ifa_flags; // Flags: IFA_F_SECONDARY for secondary
- // address (old alias interface), IFA_F_PERMANENT
- // for a permanent address
- unsigned char ifa_scope; // locality
- int ifa_index; // Link index is the interface index in the table of interfaces.
- };
-
- struct nlmsghdr
- {
- __u32 nlmsg_len; // Length of message including header
- __u16 nlmsg_type; // Message content
- __u16 nlmsg_flags; // Additional flags
- __u32 nlmsg_seq; // Sequence number
- __u32 nlmsg_pid; // Sending process PID
- };
-*/
-
-
-// The global config params
-//
-static int one_button_test = 0;
-static char ip_slash_mask[32];
-static char net_dev_name[16];
-static int dont_cleanup_added_ip = 0;
-
-// The function returns index of an interface by its name
-//
-int
-get_if_index (const char*const interface,
- int &if_index)
-{
- if_index = -1;
-
- struct ifreq if_req;
- ACE_OS::memset (&if_req, 0, sizeof (struct ifreq));
-
- ACE_OS::strncpy (if_req.ifr_name,
- static_cast<const char*> (interface),
- sizeof (if_req.ifr_name));
-
- ACE_HANDLE s = ACE_OS::socket (AF_INET,SOCK_DGRAM,0);
-
- if (s == ACE_INVALID_HANDLE)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT ("%p\n"),
- ACE_TEXT ("get_if_index - failed on\n")
- ACE_TEXT ("ACE_OS::socket")),
- -1);
-
- int result = ACE_OS::ioctl (s,
- SIOCGIFINDEX,
- reinterpret_cast<char*> (&if_req));
-
- if (result == -1)
- {
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT ("%p\n"),
- ACE_TEXT ("get_if_index:")
- ACE_TEXT ("ioctl (get interface index)")));
- }
- else
- {
- if_index = if_req.ifr_ifindex;
- }
- return result;
-}
-
-/**
- An assisting structure for passing data via routing netlink socket.
- The idea borrowed from a great iprouted2 utility,
- written by Alexey Kuznetsov.
-*/
-struct Inet_Prefix
-{
- u_char family;
- u_char bytelen;
- ACE_INT16 bitlen;
- ACE_UINT32 data[4];
-};
-
-
-/**
- * Contains header netlink message header of a type nlmsghdr with a
- * following request type dependent controlling structure, which is for
- * adding/deleting IP-addresses is of type ifaddrmsg with a following
- * buffer, containing the data: ip-address, its length, number of netmask
- * bits, etc.
- */
-struct Netlink_Request
-{
- struct nlmsghdr nhdr_; // message header
- struct ifaddrmsg ifa_; // interface
- char buf_[256];
-};
-
-
-
-/**
- * The handler first is trying to delete an ip-address, further
- * to add the ip and, if successful to cleanup the address.
- */
-class Secondary_Ipaddr_Handler : public ACE_Event_Handler
-{
-public:
-
- // Default constructor
- Secondary_Ipaddr_Handler (void);
-
- // Destructor
- virtual ~Secondary_Ipaddr_Handler (void);
-
- // Initialization. Schedules a timer to run start the business.
- //
- int open (ACE_Reactor *const reactor,
- char* const ip_slash_mask,
- const char *const if_name);
-
- // Returns reference to netlink socket. Necessary for reactor.
- virtual ACE_HANDLE get_handle (void) const;
-
- /**
- * Takes care of the input. Reads the incoming messages,
- * makes their processing.
- */
- virtual int handle_input (ACE_HANDLE handle);
-
- // Makes clean-up
- virtual int handle_close (ACE_HANDLE handle,
- ACE_Reactor_Mask close_mask);
-
- // Runs a state machine. Controls adding/deleting of ip-address.
- int handle_timeout (ACE_Time_Value const & tv,
- void const * arg = 0);
-
- // Sends to kernel a request to add secondary ip/mask to an
- // interface.
- int add_ip (char* const ip_slash_mask,
- const char *const if_name);
-
- // Sends to kernel a request to delete secondary ip/mask
- // from an interface.
- int delete_ip (char* const ip_slash_mask,
- const char *const if_name);
-
- /*
- * 1. We are trying to delete the ip-address, if exists.
- * Shall be either successful, or fail, when no-ip yet.
- * 2. Adding the ip-address, shall be successful;
- * 3. Cleaning up the ip-address. Shall be successful as well.
- */
- enum
- {
- START = 0,
- IP_DELETED,
- IP_ADDED,
- IP_CLEANUPED,
- SUCCESS,
- FAILED
- };
-
- // Returns the currect state
- int get_state () const { return this->state_;}
-
-protected:
-
- // De-registers the handler from the reactor,
- // other cleanup jobs
- virtual int close ();
-
- ACE_SOCK_Netlink& socket ();
-
-private:
-
- // Schedule two sec timer.
- int schedule_one_sec_timer ();
-
- // A workhorse for add_ip () and delete_ip ()
- int dispatch_ip_operation (char* const ip_slash_mask,
- const char *const if_name,
- bool action);
-
- /**
- * Initializes netlink request for adding (action = true) or
- * deleting (action = false) of a secondary ip-address/mask.
- */
- int init_netlink_request (char* const ip_slash_mask,
- const char *const if_name,
- Netlink_Request& net_req,
- bool action);
-
- // Fills data part of Netlink_Request
- int fill_inet_prefix (Inet_Prefix &inet_prefix,
- const char*const ip_slash_netmask);
-
- /**
- * Fills routing request (operations with ip-addresses are
- * a part of netlink routing interface).
- */
- void fill_rtnetlink_request (nlmsghdr &hdr,
- int type,
- void *data,
- int data_length);
-
- enum
- {
- COMMAND_TIMEOUT = -3,
- COMMAND_RECV_ERROR = -2,
- COMMAND_ERROR = -1,
- COMMAND_SUCCESS = 0
- };
-
- // Mark command status in handle_input ().
- void on_recv_error () { this->command_status_ = COMMAND_RECV_ERROR; }
- void on_command_success () { this->command_status_ = COMMAND_SUCCESS; }
- void on_command_error () { this->command_status_ = COMMAND_ERROR; }
-
- // The socket.
- ACE_SOCK_Netlink socket_ ;
-
- // The address of the socket.
- ACE_Netlink_Addr address_ ;
-
- // Message sequence number.
- ACE_UINT32 seq_ ;
-
- // The request structure passed to kernel.
- Netlink_Request netlink_request_;
-
- // ip-addr-slash-mask
- char ip_buff_[32];
-
- // interface
- char if_buff_[16];
-
- // Buffer to receive messages. Not too large?
- char recv_buff_[1024];
-
- // The state of the handler.
- int state_;
-
- // The status of the command.
- int command_status_;
-};
-
-Secondary_Ipaddr_Handler::Secondary_Ipaddr_Handler ()
- :
- socket_ (),
- address_ (),
- seq_ (0),
- state_ (START),
- command_status_ (COMMAND_SUCCESS)
-{
-}
-
-Secondary_Ipaddr_Handler::~Secondary_Ipaddr_Handler ()
-{
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("(%P|%t) Secondary_Ipaddr_Handler::~Secondary_Ipaddr_Handler \n")));
- this->close ();
-}
-int
-Secondary_Ipaddr_Handler::open (ACE_Reactor *const reactor,
- char* const ip_slash_mask,
- const char *const if_name)
-{
- if (!reactor ||
- !ip_slash_mask || !ACE_OS::strlen (ip_slash_mask) ||
- !if_name || !ACE_OS::strlen (if_name))
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::open: error ")
- ACE_TEXT("zero pointers or zero length strings used as input. \n")),
- -1);
-
- this->reactor (reactor);
-
- // Another option is to pass a zero pid to the address, to call open () on socket
- // performing binding and after bind () to call getsockbyname to fill the address
-
- this->address_.set (ACE_OS::getpid (), 0);
-
- if (this->socket ().open (this->address_,
- ACE_PROTOCOL_FAMILY_NETLINK,
- NETLINK_ROUTE) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P|%t) Secondary_Ipaddr_Handler::open: - failed \n")
- ACE_TEXT("to initialize netlink socket bu open (). \n")),
- -1);
-
- // register with the reactor for input
- if (this->reactor ()->register_handler (this,
- ACE_Event_Handler::READ_MASK) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P|%t) Secondary_Ipaddr_Handler::open - ")
- ACE_TEXT("can't register with reactor for handling input.\n")),
- -1);
-
- if (this->reactor ()->schedule_timer (this,
- 0,
- ACE_Time_Value::zero) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::open - ")
- ACE_TEXT("can't schedule timer with reactor.\n")),
- -1);
-
- this->seq_ = time (NULL);
-
- ACE_OS::strncpy (this->ip_buff_,
- ip_slash_mask,
- sizeof this->ip_buff_);
-
- ACE_OS::strncpy (this->if_buff_,
- if_name,
- sizeof this->if_buff_);
-
- return 0;
-}
-
-ACE_HANDLE
-Secondary_Ipaddr_Handler::get_handle (void) const
-{
- return this->socket_.get_handle ();
-}
-
-int
-Secondary_Ipaddr_Handler::handle_input (ACE_HANDLE)
-{
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - entered \n")));
-
- nlmsghdr *hdr = 0;
- iovec iov;
-
- iov.iov_base = this->recv_buff_;
- iov.iov_len = sizeof (this->recv_buff_);
-
- int rval_bytes = -1;
- ACE_Netlink_Addr raddr;
- raddr.set (0, 0);
-
- rval_bytes = this->socket ().recv (&iov, 1, raddr);
- switch (rval_bytes)
- {
- case -1: // Complain and leave
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - ")
- ACE_TEXT("%p bad read\n"), ACE_TEXT("client")),
- -1);
-
- case 0: // Complain and leave
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - "),
- ACE_TEXT("eof, closing daemon (fd = %d)\n"),
- this->get_handle ()),
- -1);
-
- default:
- if (raddr.get_size () != sizeof (sockaddr_nl))
- {
- this->on_recv_error ();
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%n %P) Secondary_Ipaddr_Handler::handle_input - ")
- ACE_TEXT("address length not equal sockaddr_nl\n")),
- -1);
- }
-
- hdr = reinterpret_cast <nlmsghdr*> (this->recv_buff_);
-
- if (static_cast <int> (hdr->nlmsg_len) != rval_bytes)
- {
- this->on_recv_error ();
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - ")
- ACE_TEXT("size of nlmsg_len not equal received bytes\n")),
- -1);
- }
-
- if (static_cast <int> (hdr->nlmsg_pid) != this->address_.get_pid () || hdr->nlmsg_seq != this->seq_)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - ")
- ACE_TEXT("process id or message sequence is different \n")),
- -1);
-
- if (hdr->nlmsg_type == NLMSG_ERROR)
- {
- struct nlmsgerr *err = static_cast <struct nlmsgerr*> (NLMSG_DATA(hdr));
-
- errno = -err->error;
- if (errno == 0)
- {
- this->on_command_success ();
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - command success \n")));
- return 0;
- }
-
- this->on_command_error ();
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_input - command informs about error \n")));
-
- // some error message
- perror("rtnetlink error message: ");
-
- return 0;
- }
- }
- return -1;
-}
-
-int
-Secondary_Ipaddr_Handler::handle_timeout (ACE_Time_Value const &,
- void const *)
-{
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_timeout - entered \n")));
-
- if (this->command_status_ != COMMAND_SUCCESS &&
- (this->command_status_ != COMMAND_ERROR &&
- this->state_ == IP_DELETED))
- {
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_timeout - ")
- ACE_TEXT("previous command failed\n")),
- -1);
- }
- else
- this->command_status_ = COMMAND_TIMEOUT; //invalidate command status
-
- switch (this->state_)
- {
- case START: //delete the ip, if it presents
- if (this->delete_ip (this->ip_buff_, this->if_buff_) == -1)
- {
- this->state_ = FAILED;
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_timeout - ")
- ACE_TEXT("delete_ip failed\n")),
- -1);
- }
- break;
-
- case IP_DELETED: // add the ip
- if (this->add_ip (this->ip_buff_, this->if_buff_) == -1)
- {
- this->state_ = FAILED;
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_timeout - ")
- ACE_TEXT("add_ip failed\n")),
- -1);
- }
- break;
-
- case IP_ADDED: //delete added ip to make cleanup
- if (dont_cleanup_added_ip)
- {
- this->state_ = SUCCESS;
- return 0;
- }
- else
- {
- if (this->delete_ip (this->ip_buff_, this->if_buff_) == -1)
- {
- this->state_ = FAILED;
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::handle_timeout - ")
- ACE_TEXT("delete_ip failed\n")),
- -1);
- }
- }
- break;
-
- case IP_CLEANUPED:
- this->state_ = SUCCESS;
- return 0;
-
- default:
- return -1;
- }
-
- this->schedule_one_sec_timer ();
- this->state_++;
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::handle_close (ACE_HANDLE,
- ACE_Reactor_Mask)
-{
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P|%t) Secondary_Ipaddr_Handler::handle_close \n")));
- this->close ();
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::close ()
-{
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::close \n")));
-
- if (this->reactor ())
- {
- this->reactor ()->remove_handler (this,
- ACE_Event_Handler::ALL_EVENTS_MASK |
- ACE_Event_Handler::DONT_CALL);
-
- this->reactor ()->cancel_timer (this);
-
- this->reactor (0);
- }
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::schedule_one_sec_timer ()
-{
- const ACE_Time_Value one_sec (1, 0);
-
- if (this->reactor ()->schedule_timer (this,
- 0,
- one_sec) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::schedule_one_sec_timer - ")
- ACE_TEXT("can't schedule timer with reactor.\n")),
- -1);
- return 0;
-}
-
-ACE_SOCK_Netlink&
-Secondary_Ipaddr_Handler::socket ()
-{
- return this->socket_;
-}
-
-int
-Secondary_Ipaddr_Handler::fill_inet_prefix (
- Inet_Prefix &inet_prefix,
- const char*const ip_slash_netmask)
-{
- ACE_OS::memset (&inet_prefix, 0, sizeof inet_prefix);
- char* slash = const_cast <char *> (ACE_OS::strchr (ip_slash_netmask, '/'));
- if (slash)
- *slash = '\0'; // The idea from Igor Potulnitsky
-
- inet_prefix.family = AF_INET; // another option is AF_UNSPEC
- inet_prefix.bytelen = 4;
- inet_prefix.bitlen = -1;
-
- char ip_buff[32];
- ACE_OS::strncpy (ip_buff, ip_slash_netmask, sizeof (ip_buff));
-
- char* to_search = ip_buff, *dot = 0;
-
- for (int i = 0; i < 4; i++)
- {
- if (i < 3)
- {
- dot = ACE_OS::strchr (to_search, '.');
- if (!dot || !ACE_OS::strlen (to_search))
- return -1;
- else
- *dot = '\0';
- }
- int num = atoi (to_search);
- if (num < 0 || num > 255)
- return -1;
- else
- ((u_char *) &inet_prefix.data)[i] = (u_char)num;
-
- if (i < 3)
- to_search = dot + 1;
- }
-
- inet_prefix.bitlen = 32; // AF_INET: 32
-
- if (slash)
- {
- int mask_len = 0;
- mask_len = ACE_OS::atoi (slash + 1);
- if (mask_len >= 0)
- inet_prefix.bitlen = mask_len;
- *slash = '/';
- }
- return 0;
-}
-
-void
-Secondary_Ipaddr_Handler::fill_rtnetlink_request (
- nlmsghdr &hdr,
- int type,
- void *data,
- int data_length)
-{
- // points to the end of the aligned header
- struct rtattr *rta = reinterpret_cast <struct rtattr*> (((reinterpret_cast <char*>(&hdr)) + NLMSG_ALIGN (hdr.nlmsg_len)));
-
- rta->rta_type = type;
- rta->rta_len = RTA_LENGTH (data_length);
- ACE_OS::memcpy (RTA_DATA(rta), data, data_length);
- hdr.nlmsg_len = NLMSG_ALIGN (hdr.nlmsg_len) + RTA_LENGTH (data_length);
-}
-
-int
-Secondary_Ipaddr_Handler::dispatch_ip_operation (
- char* const ip_slash_mask,
- const char *const if_name,
- bool action)
-{
- if (this->init_netlink_request (ip_slash_mask,
- if_name,
- this->netlink_request_,
- action) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- "Secondary_Ipaddr_Handler::ip_operation - "
- "init_netlink_request () failed.\n"),
- -1);
-
- this->netlink_request_.nhdr_.nlmsg_seq = ++this->seq_;
- this->netlink_request_.nhdr_.nlmsg_flags |= NLM_F_ACK;
-
- iovec iov_send =
- {
- static_cast <void*> (&this->netlink_request_.nhdr_),
- this->netlink_request_.nhdr_.nlmsg_len
- };
-
- ACE_Netlink_Addr addr_send;
- addr_send.set (0, 0);
-
- if (this->socket ().send (&iov_send,
- 1,
- addr_send) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("Secondary_Ipaddr_Handler::ip_operation - ")
- ACE_TEXT("send of request failed with errno %d.\n"),
- errno),
- -1);
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::delete_ip (
- char* const ip_slash_mask,
- const char *const if_name)
-{
- if (this->dispatch_ip_operation (
- ip_slash_mask,
- if_name,
- false) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::delete_ip - ")
- ACE_TEXT("dispatch_ip_operation() failed.\n")),
- -1);
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::add_ip (
- char* const ip_slash_mask,
- const char *const if_name)
-{
- if (this->dispatch_ip_operation (ip_slash_mask,
- if_name,
- true) == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) Secondary_Ipaddr_Handler::add_ip - ")
- ACE_TEXT("dispatch_ip_operation() failed.\n")),
- -1);
- return 0;
-}
-
-int
-Secondary_Ipaddr_Handler::init_netlink_request (
- char* const ip_slash_netmask,
- const char *const if_name,
- Netlink_Request& net_req,
- bool action)
-{
- ACE_OS::memset (&net_req, 0, sizeof(net_req));
-
- // fill the request header
- net_req.nhdr_.nlmsg_len =
- NLMSG_LENGTH (sizeof(struct ifaddrmsg));
- net_req.nhdr_.nlmsg_flags = NLM_F_REQUEST;
- net_req.nhdr_.nlmsg_type = action ? RTM_NEWADDR : RTM_DELADDR;
- net_req.ifa_.ifa_family = AF_INET;
-
- int interface_index = -1;
- if (get_if_index (if_name,
- interface_index) == -1 || interface_index < 0)
- {
- fprintf (stderr, "get_if_index () - failed\n");
- return -1;
- }
- net_req.ifa_.ifa_index = interface_index;
-
- Inet_Prefix local_prefix;
-
- if (fill_inet_prefix (local_prefix,
- ip_slash_netmask) == -1)
- {
- fprintf (stderr, "fill_inet_prefix () - failed\n");
- return -1;
- }
-
- fill_rtnetlink_request (net_req.nhdr_,
- IFA_LOCAL,
- &local_prefix.data,
- local_prefix.bytelen);
-
- net_req.ifa_.ifa_prefixlen = local_prefix.bitlen; // number of bits in netmask
- net_req.ifa_.ifa_scope = 0;
-
- return 0;
-}
-
-static int run_test (char*const ip_slash_netmask,
- const char*const if_name)
-{
- Secondary_Ipaddr_Handler sec_ip_handler;
-
- if (sec_ip_handler.open (ACE_Reactor::instance (),
- ip_slash_netmask,
- if_name)
- == -1)
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("(%P) SOCK_Netlink_Test - run_test () failed ")
- ACE_TEXT("due to sec_ip_handler.open () error.\n")),
- -1);
-
- ACE_Time_Value wait_time (4, 0);
-
- ACE_Reactor::instance()->run_reactor_event_loop (wait_time);
-
- if (sec_ip_handler.get_state () != Secondary_Ipaddr_Handler::SUCCESS)
- return -1;
-
- return 0;
-}
-
-static int
-parse_args (int argc, ACE_TCHAR *argv[])
-{
- if (argc == 1) // one button test
- {
- one_button_test = 1;
- return 0;
- }
-
- ACE_OS::memset (ip_slash_mask, 0, sizeof ip_slash_mask);
- ACE_OS::memset (net_dev_name, 0, sizeof net_dev_name);
-
- ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("a:di:"));
- int c = 0, ip_len = 0, if_len = 0;
- while ((c = get_opt ()) != EOF)
- {
- switch (c)
- {
- case 'a': // ip_slash_netmask_bits
- ACE_OS::strcpy (ip_slash_mask,
- reinterpret_cast <const char*> (get_opt.opt_arg ()));
-
- if (! (ip_len = ACE_OS::strlen (ip_slash_mask)))
- {
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT("%s, -a should be followed by a dotted ipv4 addr slash netmask bits.\n")
- ACE_TEXT("Example: \"-a 192.168.1.1/24\" .\n"),
- ACE_TEXT("SOCK_Netlink_Test")));
- return -1;
- }
- break;
-
- case 'd':
- dont_cleanup_added_ip = 1;
- break;
-
- case 'i': // name of the interface
- ACE_OS::strcpy (net_dev_name,
- reinterpret_cast <const char*> (get_opt.opt_arg ()));
- if (! (if_len = ACE_OS::strlen (net_dev_name)))
- {
- ACE_ERROR ((LM_ERROR,
- ACE_TEXT("%s, -i should be followed by a valid name of network interface.\n"),
- ACE_TEXT("SOCK_Netlink_Test")));
- return -1;
- }
- break;
-
- default:
- break;
- }
- }
-
- if ((ip_len == 0 && if_len) || (ip_len && if_len == 0))
- {
- ACE_ERROR_RETURN ((LM_ERROR,
- ACE_TEXT("%s - error: both options -a and -i should be provided. \n"),
- ACE_TEXT("SOCK_Netlink_Test")),
- -1);
- }
- else if (ip_len == 0 && if_len == 0)
- {
- one_button_test = 1;
- }
-
- return 0;
-}
-
-#define DEFAULT_IP_SLASH_MASK "192.168.1.100/24"
-#define DEFAULT_NET_DEVICE_NAME "lo"
-
-int
-run_main (int argc, ACE_TCHAR *argv[])
-{
- ACE_START_TEST (ACE_TEXT ("SOCK_Netlink_Test"));
-
- if (::geteuid ())
- {
- ACE_DEBUG ((LM_INFO,
- ACE_TEXT ("Process has no superuser priveleges. ")
- ACE_TEXT ("Unable to run this test.\n")));
- }
- else
- {
- if (::parse_args (argc, argv) == -1)
- {
- return -1;
- }
-
- if (one_button_test)
- {
- ACE_OS::strcpy (ip_slash_mask,
- DEFAULT_IP_SLASH_MASK);
- ACE_OS::strcpy (net_dev_name,
- DEFAULT_NET_DEVICE_NAME);
- }
-
- int rval = -1;
- if ((rval = run_test (ip_slash_mask,
- net_dev_name)) < 0)
- {
- ACE_DEBUG ((LM_ERROR,
- ACE_TEXT ("run_test() failed with rval returned %d. "),
- rval));
- return -1;
- }
- }
-
- ACE_END_TEST;
-
- return 0;
-}
-
-#else /* ACE_HAS_NETLINK*/
-
-int
-run_main (int, ACE_TCHAR *[])
-{
- ACE_START_TEST (ACE_TEXT ("SOCK_Netlink_Test"));
-
- ACE_DEBUG ((LM_INFO,
- ACE_TEXT("(%P|%t|%T) \"SOCK_Netlink_Test\" main() - ")
- ACE_TEXT("Linux netlink socket support not configured.\n")
- ACE_TEXT("#define ACE_HAS_NETLINK = 1 in your config.h ")
- ACE_TEXT("file to enable and run the process as a superuser.\n")));
-
- ACE_END_TEST;
-
- return 0;
-}
-
-#endif /* ACE_HAS_NETLINK*/
-