0

次のコードをコンパイルするとエラーが発生します。要点は、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_ */
4

2 に答える 2

0

最初のエラーから始めて、下に向かって進みます。まず、関数nl_socket_alloc()はヘッダー ファイルのいずれかで宣言されています#includeか? これを見つける方法は、これらのヘッダー ファイル (システムのどこかにある) を grep して、そのシンボルを探し、見つけたファイルが明示的に#include-ed であることを確認することです。

この戦略を他の欠けているシンボルに適用します。

ファイルをインクルードした場合、関数nl_socket_allocはグローバル名前空間で宣言されている可能性があり::nl_socket_allocます。

これらの提案があなたを正しい方向に導くことを願っています。

于 2013-04-11T19:46:27.497 に答える