错误:' nl_socket_alloc '未在此范围内声明

error: ‘nl_socket_alloc’ was not declared in this scope

本文关键字:范围内 声明 alloc nl 错误 socket      更新时间:2023-10-16

当我编译下面的代码时,我得到了这个错误,关键是我知道nl_socket_alloc的声明有一些错误,但我不知道我到底在哪里搞砸了。

当我在.cpp中初始化套接字时,编译器会报错,所以我猜它们可能声明得不好。

Thanks in advance

#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 */

eclipse输出

./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_ */

不知何故死亡-但我刚刚绊倒了同样的问题-所以也许这可以帮助别人。

首先:您需要安装libnetlink开发头文件。在我古老的Debian 8盒子上

> sudo apt-get install libnl-3-dev

可以。

netlink库的文档包含了关于库结构的部分。在本部分中,您可以找到有关所需头文件以及如何链接到库的所有信息。它基本上归结为包含netlink/netlink.h。但是有时(比如在我的Debian机器上)devel包已经安装,但是包含头文件的目录不在默认搜索路径中。您可以在整个文件系统中运行find来查找netlink.h——这可能会给您一个错误的方向(当然——如果您使用find来查找某些内容,您总是要检查两次以包含正确的文件)。但是有一种更系统的方法……

如果你运行一个使用Debian打包系统的机器,你可以检查安装了哪些netlink库:

> dpkg --list libnl*
...
ii  libnl-3-200:amd64               3.2.24-2             amd64                library for dealing with netlink sockets
ii  libnl-3-dev                     3.2.24-2             amd64                development library and headers for libnl-3
un  libnl-dev                       <none>               <none>               (no description available)
ii  libnl-genl-3-200:amd64          3.2.24-2             amd64                library for dealing with netlink sockets - generic netlink
ii  libnl-route-3-200:amd64         3.2.24-2             amd64                library for dealing with netlink sockets - route interface
un  libnl2-dev                      <none>               <none>               (no description available)
un  libnl3-dev                      <none>               <none>               (no description available)

开头的是相关的。现在使用dpkg来获取包提供的文件列表(并筛选所需的文件):

> dpkg  -L  libnl-3-dev | grep  "netlink.h"
/usr/include/libnl3/netlink/netlink.h

/usr/include/是默认包含路径的一部分(您可以使用这里给出的答案来检查gcc使用的路径),您需要在包含语句中添加前缀libnl3。为了避免在库版本更改时需要更改包含,只需将/usr/include/libl3 添加到包含路径中。对于gcc,这可以使用

标志来完成。
-I /usr/include/libnl3

对于基于cmake的构建系统,只需添加一个 include_directories ()指令:

include_directories("/usr/include/libnl3")

从第一个错误开始,然后依次进行。首先,函数nl_socket_alloc()是在你#include的任何头文件中声明的吗?找到它的方法是在这些头文件(它们将在您的系统中的某个地方)中执行grep,查找该符号,并确保您在其中找到的文件显式地为#include -ed。

将此策略应用于其他缺失的符号。

如果您包含了该文件,则可以在全局名称空间中声明函数nl_socket_alloc,在这种情况下,您可以选择将其称为::nl_socket_alloc(因为您正在定义非全局名称空间)。

希望这些建议能指引你正确的方向。