次のコードをコンパイルするとエラーが発生します。要点は、nl_socket_allocの宣言にエラーがあることはわかっていますが、どこでそれを台無しにしたかがわかりません。
.cppのソケットを初期化するとコンパイラが文句を言うので、宣言が間違っているのではないかと推測しています。
前もって感謝します
#include "ibrcommon/net/NetLink3Manager.h"
#include "ibrcommon/net/vsocket.h"
#include "ibrcommon/Logger.h"
#include <netlink/netlink.h>
#include <netlink/route/link.h>
#include <netlink/route/addr.h>
#include <netlink/route/rtnl.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
//#include <net/if.h>
#include <string.h>
namespace ibrcommon
{
static int nl3_callback(struct nl_msg *msg, void *arg)
{
NetLink3Manager *m = static_cast<NetLink3Manager *>(arg);
NetLink3ManagerEvent evt(msg);
m->callback(evt);
return 0;
}
void add_addr_to_list(struct nl_object *obj, void *data)
{
char buf[INET6_ADDRSTRLEN+5];
std::list<vaddress> *list = static_cast<std::list<vaddress>*>(data);
struct nl_addr *naddr = rtnl_addr_get_local((struct rtnl_addr *) obj);
int ifindex = 0;
int scope = rtnl_addr_get_scope((struct rtnl_addr *) obj);
if (scope == rtnl_str2scope("link"))
ifindex = rtnl_addr_get_ifindex((struct rtnl_addr *) obj);
if (naddr)
{
int family = nl_addr_get_family(naddr);
nl_addr2str( naddr, buf, sizeof( buf ) );
vaddress vaddr(vaddress::Family(family), vaddress::strip_netmask(std::string(buf)), ifindex, false);
list->push_back( vaddr );
}
struct nl_addr *baddr = rtnl_addr_get_broadcast((struct rtnl_addr *) obj);
if (baddr)
{
int family = nl_addr_get_family(baddr);
nl_addr2str( baddr, buf, sizeof( buf ) );
vaddress vaddr(vaddress::Family(family), vaddress::strip_netmask(std::string(buf)), ifindex, true);
list->push_back( vaddr );
}
}
NetLink3Manager::NetLink3Manager()
: _refresh_cache(false), _running(true), _sock(NULL)
{
// initialize the sockets
_nl_notify_sock = nl_socket_alloc();//=>First error
_nl_query_sock = nl_socket_alloc();//=>Second error
// disable seq check for notify socket
nl_socket_disable_seq_check(_nl_notify_sock);
// define callback method
nl_socket_modify_cb(_nl_notify_sock, NL_CB_VALID, NL_CB_CUSTOM, nl3_callback, this);
// connect to routing netlink protocol
nl_connect(_nl_notify_sock, NETLINK_ROUTE);
nl_connect(_nl_query_sock, NETLINK_ROUTE);
// init route messages
nl_socket_add_memberships(_nl_notify_sock, RTNLGRP_IPV4_IFADDR);
// IPv6 requires further support in the parsing procedures!
// nl_socket_add_membership(_nl_notify_sock, RTNLGRP_IPV6_IFADDR);
nl_socket_add_memberships(_nl_notify_sock, RTNLGRP_LINK);
// create a cache for the links
if (rtnl_link_alloc_cache(_nl_query_sock, AF_UNSPEC, &_link_cache) < 0)
{
nl_socket_free(_nl_notify_sock);
nl_socket_free(_nl_query_sock);
// error
throw ibrcommon::vsocket_exception("netlink cache allocation failed");
}
// create a cache for addresses
if (rtnl_addr_alloc_cache(_nl_query_sock, &_addr_cache) < 0)
{
nl_socket_free(_nl_notify_sock);
nl_socket_free(_nl_query_sock);
// error
nl_cache_free(_link_cache);
_link_cache = NULL;
throw ibrcommon::vsocket_exception("netlink cache allocation failed");
}
// create a new socket for the netlink interface
_sock = new ibrcommon::vsocket();
}
NetLink3Manager::~NetLink3Manager()
{
stop();
join();
// destroy the socket for the netlink interface
delete _sock;
nl_cache_free(_addr_cache);
nl_cache_free(_link_cache);
nl_socket_free(_nl_notify_sock);
nl_socket_free(_nl_query_sock);
}
const std::string NetLink3Manager::getInterface(int index) const
{
char buf[256];
rtnl_link_i2name(_link_cache, index, (char*)&buf, sizeof buf);
return std::string((char*)&buf);
}
const std::list<vaddress> NetLink3Manager::getAddressList(const vinterface &iface, const vaddress::Family f)
{
ibrcommon::MutexLock l(_call_mutex);
if (_refresh_cache)
{
nl_cache_free(_addr_cache);
nl_cache_free(_link_cache);
// create a cache for the links
if (rtnl_link_alloc_cache(_nl_query_sock, AF_UNSPEC, &_link_cache) < 0)
{
// error
throw ibrcommon::vsocket_exception("netlink cache allocation failed");
}
// create a cache for addresses
if (rtnl_addr_alloc_cache(_nl_query_sock, &_addr_cache) < 0)
{
// error
nl_cache_free(_link_cache);
_link_cache = NULL;
throw ibrcommon::vsocket_exception("netlink cache allocation failed");
}
// mark the cache as refreshed
_refresh_cache = false;
}
std::list<vaddress> addresses;
struct rtnl_addr *filter = rtnl_addr_alloc();
const std::string i = iface.toString();
rtnl_addr_set_ifindex(filter, rtnl_link_name2i(_link_cache, i.c_str()));
if (f == vaddress::VADDRESS_UNSPEC)
{
rtnl_addr_set_family(filter, AF_INET6);
nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
add_addr_to_list, &addresses);
rtnl_addr_set_family(filter, AF_INET);
nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
add_addr_to_list, &addresses);
}
else
{
rtnl_addr_set_family(filter, f);
nl_cache_foreach_filter(_addr_cache, (struct nl_object *) filter,
add_addr_to_list, &addresses);
}
rtnl_addr_put(filter);
return addresses;
}
void NetLink3Manager::callback(const NetLink3ManagerEvent &lme)
{
// ignore if the event is unknown
if (lme.getType() == LinkManagerEvent::EVENT_UNKOWN) return;
// ignore if this is an wireless extension event
if (lme.isWirelessExtension()) return;
// need to refresh the cache
{
ibrcommon::MutexLock l(_call_mutex);
_refresh_cache = true;
}
// print out some debugging
IBRCOMMON_LOGGER_DEBUG(10) << lme.toString() << IBRCOMMON_LOGGER_ENDL;
// notify all subscribers about this event
raiseEvent(lme);
}
void NetLink3Manager::run()
{
// add netlink fd to vsocket
_sock->add(nl_socket_get_fd(_nl_notify_sock));
try {
while (_running)
{
std::list<int> fds;
_sock->select(fds, NULL);
nl_recvmsgs_default(_nl_notify_sock);
}
} catch (const vsocket_exception&) {
// stopped / interrupted
IBRCOMMON_LOGGER(error) << "NetLink connection stopped" << IBRCOMMON_LOGGER_ENDL;
}
}
void NetLink3Manager::__cancellation()
{
_running = false;
_sock->close();
}
/** read a netlink message from the socket and create a new netlink event object **/
NetLink3ManagerEvent::NetLink3ManagerEvent(struct nl_msg *msg)
: _type(EVENT_UNKOWN), _state(0), _wireless(false)
{
int attrlen, nlmsg_len, rta_len, rtl;
struct rtattr *attr;
struct rtattr *rth;
struct ifaddrmsg *ifa;
struct ifinfomsg *ifi;
struct nlmsghdr *nlh;
// cast netlink message
nlh = nlmsg_hdr(msg);
switch (nlh->nlmsg_type)
{
case RTM_BASE:
{
ifi = (struct ifinfomsg *) NLMSG_DATA(nlh);
nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
attrlen = nlh->nlmsg_len - nlmsg_len;
if (attrlen < 0) break;
attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
rta_len = RTA_ALIGN(sizeof(struct rtattr));
while (RTA_OK(attr, attrlen))
{
size_t rta_length = RTA_PAYLOAD(attr);
switch (attr->rta_type)
{
case IFLA_IFNAME:
_interface = ibrcommon::vinterface( std::string((char*)RTA_DATA(attr), rta_length) );
_type = EVENT_LINK_STATE;
break;
case IFLA_OPERSTATE:
{
char s;
::memcpy(&s, (char*)RTA_DATA(attr), 1);
_state = s;
break;
}
case IFLA_WIRELESS:
_wireless = true;
break;
default:
_attributes[attr->rta_type] = std::string((char*)RTA_DATA(attr), rta_length);
break;
}
attr = RTA_NEXT(attr, attrlen);
}
break;
}
case RTM_NEWADDR:
{
ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
rth = IFA_RTA(ifa);
rtl = IFA_PAYLOAD(nlh);
// parse all attributes
while (rtl && RTA_OK(rth, rtl))
{
switch (rth->rta_type)
{
// local address
case IFA_LOCAL:
{
char address[256];
uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth)));
sprintf(address, "%d.%d.%d.%d", (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff);
_address = ibrcommon::vaddress(ibrcommon::vaddress::VADDRESS_INET, std::string(address));
_type = EVENT_ADDRESS_ADDED;
break;
}
// interface name
case IFA_LABEL:
{
//char name[IFNAMSIZ];
char *name = (char *)RTA_DATA(rth);
_interface = ibrcommon::vinterface(name);
break;
}
}
rth = RTA_NEXT(rth, rtl);
}
break;
}
case RTM_DELADDR:
{
ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
rth = IFA_RTA(ifa);
rtl = IFA_PAYLOAD(nlh);
// parse all attributes
while (rtl && RTA_OK(rth, rtl))
{
switch (rth->rta_type)
{
// local address
case IFA_LOCAL:
{
char address[256];
uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth)));
sprintf(address, "%d.%d.%d.%d", (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff);
_address = ibrcommon::vaddress(ibrcommon::vaddress::VADDRESS_INET, std::string(address));
_type = EVENT_ADDRESS_REMOVED;
break;
}
// interface name
case IFA_LABEL:
{
//char name[IFNAMSIZ];
char *name = (char *)RTA_DATA(rth);
_interface = ibrcommon::vinterface(name);
break;
}
}
rth = RTA_NEXT(rth, rtl);
}
break;
}
default:
IBRCOMMON_LOGGER_DEBUG(10) << "unknown netlink type received: " << nlh->nlmsg_type << IBRCOMMON_LOGGER_ENDL;
break;
}
}
NetLink3ManagerEvent::~NetLink3ManagerEvent()
{
}
const ibrcommon::vinterface& NetLink3ManagerEvent::getInterface() const
{
return _interface;
}
const ibrcommon::vaddress& NetLink3ManagerEvent::getAddress() const
{
return _address;
}
unsigned int NetLink3ManagerEvent::getState() const
{
return _state;
}
bool NetLink3ManagerEvent::isWirelessExtension() const
{
return _wireless;
}
LinkManagerEvent::EventType NetLink3ManagerEvent::getType() const
{
return _type;
}
const std::string NetLink3ManagerEvent::toString() const
{
std::stringstream ss;
ss << "NetLinkManagerEvent on " << getInterface().toString() << "; Type: " << getType();
switch (getType())
{
case EVENT_LINK_STATE:
ss << "; State: " << getState();
break;
case EVENT_ADDRESS_ADDED:
ss << "; Address added: " << getAddress().toString();
break;
case EVENT_ADDRESS_REMOVED:
ss << "; Address removed: " << getAddress().toString();
break;
default:
break;
};
return ss.str();
}
void NetLink3ManagerEvent::debug() const
{
// for (std::map<int, std::string>::const_iterator iter = attr.begin(); iter != attr.end(); iter++)
// {
// std::stringstream ss;
// const std::string &value = (*iter).second;
//
// for (std::string::const_iterator si = value.begin(); si != value.end(); si++)
// {
// const char &c = (*si);
// ss << std::hex << "0x" << (int)c << " ";
// }
//
// IBRCOMMON_LOGGER_DEBUG(10) << (*iter).first << ": " << ss.str() << IBRCOMMON_LOGGER_ENDL;
// }
}
} /* namespace ibrcommon */
日食の出力:
./ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:66:37: error: ‘nl_socket_alloc’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:70:46: error: ‘nl_socket_disable_seq_check’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:73:85: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘int nl_socket_modify_cb(nl_handle*, nl_cb_type, nl_cb_kind, nl_recvmsg_msg_cb_t, void*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:76:44: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘int nl_connect(nl_handle*, int)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:77:43: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘int nl_connect(nl_handle*, int)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:80:65: error: ‘nl_socket_add_memberships’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:87:68: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘nl_cache* rtnl_link_alloc_cache(nl_handle*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:89:34: error: ‘nl_socket_free’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:96:57: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘nl_cache* rtnl_addr_alloc_cache(nl_handle*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:98:34: error: ‘nl_socket_free’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp: In destructor ‘virtual ibrcommon::NetLink3Manager::~NetLink3Manager()’:
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:121:33: error: ‘nl_socket_free’ was not declared in this scope
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp: In member function ‘virtual const std::list<ibrcommon::vaddress> ibrcommon::NetLink3Manager::getAddressList(const ibrcommon::vinterface&, ibrcommon::vaddress::Family)’:
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:142:69: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘nl_cache* rtnl_link_alloc_cache(nl_handle*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:149:58: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘nl_cache* rtnl_addr_alloc_cache(nl_handle*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp: In member function ‘virtual void ibrcommon::NetLink3Manager::run()’:
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:213:46: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘int nl_socket_get_fd(nl_handle*)’
../ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.cpp:221:40: error: cannot convert ‘ibrcommon::nl_sock*’ to ‘nl_handle*’ for argument ‘1’ to ‘int nl_recvmsgs_default(nl_handle*)’
make: *** [ibrcommon-0.8.0/ibrcommon/net/NetLink3Manager.o] Error 1
関数NetLink3Manager.hのヘッダーがあります
#ifndef NETLINK3MANAGER_H_
#define NETLINK3MANAGER_H_
#include "ibrcommon/net/LinkManager.h"
#include "ibrcommon/thread/Mutex.h"
#include "ibrcommon/thread/Thread.h"
#include "ibrcommon/net/vsocket.h"
#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/route/link.h>
#include <netlink/msg.h>
namespace ibrcommon
{
class NetLink3ManagerEvent : public LinkManagerEvent
{
public:
NetLink3ManagerEvent(struct nl_msg *msg);
virtual ~NetLink3ManagerEvent();
virtual const ibrcommon::vinterface& getInterface() const;
virtual const ibrcommon::vaddress& getAddress() const;
virtual unsigned int getState() const;
virtual EventType getType() const;
virtual bool isWirelessExtension() const;
void debug() const;
const std::string toString() const;
private:
EventType _type;
unsigned int _state;
bool _wireless;
ibrcommon::vinterface _interface;
ibrcommon::vaddress _address;
std::map<int, std::string> _attributes;
};
class NetLink3Manager : public ibrcommon::LinkManager, public ibrcommon::JoinableThread
{
friend class LinkManager;
public:
virtual ~NetLink3Manager();
const std::string getInterface(int index) const;
const std::list<vaddress> getAddressList(const vinterface &iface, const vaddress::Family f);
class parse_exception : public Exception
{
public:
parse_exception(string error) : Exception(error)
{};
};
void callback(const NetLink3ManagerEvent &evt);
protected:
void run();
void __cancellation();
private:
NetLink3Manager();
struct nl_sock *_nl_notify_sock;
struct nl_sock *_nl_query_sock;
// local link cache
struct nl_cache *_link_cache;
struct nl_cache *_addr_cache;
// mutex for the link cache
ibrcommon::Mutex _call_mutex;
bool _refresh_cache;
bool _running;
ibrcommon::vsocket *_sock;
};
} /* namespace ibrcommon */
#endif /* NETLINK3MANAGER_H_ */