2012-11-06 14 views
5

मैं this और this पर आधारित मल्टीकास्ट क्लाइंट/सर्वर एप्लिकेशन लिख रहा हूं; जो महान काम करता है।AF_NETLINK (नेटलिंक) सॉकेट का उपयोग बूस्ट :: एएसआई

हालांकि, कंप्यूटर में सक्रिय नेटवर्क इंटरफेस की संख्या में कुछ बदलाव करने की भी आवश्यकता होगी, उदाहरण के लिए this page के उदाहरण अनुभाग में प्रोग्राम क्या करता है।

मुझे लगता है मैं बढ़ावा :: asio :: स्थानीय में उपकरणों का उपयोग करना चाहिए, लेकिन मैं अनिश्चित हैं कि मैं boost::asio::local::datagram_protocol या boost::asio::local::stream_protocol या का उपयोग करना चाहिए हूँ ...

कैसे संभव के रूप में कुछ इसी तरह करने के लिए का एक उदाहरण वास्तव में सहायक होगा। धन्यवाद।

+0

यह साफ होगा अगर हम किसी तरह के 'बूस्ट' पूरक पैकेज में ओएस-विशिष्ट विशेषताओं को प्रदान कर सकते हैं। –

उत्तर

11

जैसा कि आपने देखा है कि ऐसा करने के लिए कुछ अतिरिक्त कोड है जो इसे लिखना है।

नेटलिंक अपने स्वयं के पता परिवार (PF_NETLINK) का उपयोग करता है और टीसीपी या यूडीपी नहीं है। इसके बजाय यह रॉ सॉकेट का उपयोग करता है। चूंकि यह एक निजी परिवार है (PF_INET या PF_INET6 नहीं) इसलिए हमें इसे स्वयं परिभाषित करने की आवश्यकता है।

मैंने इसे लागू करने के लिए एक टेम्पलेट के रूप में एक मूल यूनिक्स स्थानीय सॉकेट का उपयोग किया (परीक्षण कार्यक्रम के लिए नीचे देखें)। आप सभी कोड पेस्ट कॉपी नहीं करना चाहते हैं, तो मैं भी यह GitHub पर डाल (http://github.com/gille/boost_netlink):

template <typename Protocol> 
class nl_endpoint 
{ 
private: 
    sockaddr_nl sockaddr; 
public: 
    /// The protocol type associated with the endpoint. 
    typedef Protocol protocol_type; 
    typedef boost::asio::detail::socket_addr_type data_type;   

    /// Default constructor. 
    nl_endpoint() 
    { 
     sockaddr.nl_family = PF_NETLINK; 
     sockaddr.nl_groups = 0; 
     sockaddr.nl_pid = getpid(); 
    } 

    /// Construct an endpoint using the specified path name. 
    nl_endpoint(int group, int pid=getpid()) 
    { 
     sockaddr.nl_family = PF_NETLINK; 
     sockaddr.nl_groups = group; 
     sockaddr.nl_pid = pid; 
    } 

    /// Copy constructor. 
    nl_endpoint(const nl_endpoint& other) 
    { 
     sockaddr = other.sockaddr; 
    } 

    /// Assign from another endpoint. 
    nl_endpoint& operator=(const nl_endpoint& other) 
    { 
     sockaddr = other.sockaddr; 
     return *this; 
    } 

    /// The protocol associated with the endpoint. 
    protocol_type protocol() const 
    { 
     return protocol_type(); 
    } 

    /// Get the underlying endpoint in the native type. 
    data_type* data() 
    { 
     return &sockaddr; 
    } 

    /// Get the underlying endpoint in the native type. 
    const data_type* data() const 
    { 
     return (struct sockaddr*)&sockaddr; 
    } 

    /// Get the underlying size of the endpoint in the native type. 
    std::size_t size() const 
    { 
     return sizeof(sockaddr); 
    } 

    /// Set the underlying size of the endpoint in the native type. 
    void resize(std::size_t size) 
    { 
    /* nothing we can do here */ 
    } 

    /// Get the capacity of the endpoint in the native type. 
    std::size_t capacity() const 
    { 
     return sizeof(sockaddr); 
    } 

    /// Compare two endpoints for equality. 
    friend bool operator==(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return e1.sockaddr == e2.sockaddr; 
    } 

    /// Compare two endpoints for inequality. 
    friend bool operator!=(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return !(e1.sockaddr == e2.sockaddr); 
    } 

    /// Compare endpoints for ordering. 
    friend bool operator<(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return e1.sockaddr < e2.sockaddr; 
    } 

    /// Compare endpoints for ordering. 
    friend bool operator>(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return e2.sockaddr < e1.sockaddr; 
    } 

    /// Compare endpoints for ordering. 
    friend bool operator<=(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return !(e2 < e1); 
    } 

    /// Compare endpoints for ordering. 
    friend bool operator>=(const nl_endpoint<Protocol>& e1, 
       const nl_endpoint<Protocol>& e2) 
    { 
     return !(e1 < e2); 
    } 
}; 

प्रोटोकॉल:

class nl_protocol 
{ 
private: 
    int proto; 
public: 
    nl_protocol() { 
     proto = 0; 
    } 
    nl_protocol(int proto) { 
     this->proto = proto; 
    } 
    /// Obtain an identifier for the type of the protocol. 
    int type() const 
    { 
     return SOCK_RAW; 
    } 
    /// Obtain an identifier for the protocol. 
    int protocol() const 
    { 
     return proto; 
    } 
    /// Obtain an identifier for the protocol family. 
    int family() const 
    { 
     return PF_NETLINK; 
    } 

    typedef nl_endpoint<nl_protocol> endpoint; 
    typedef boost::asio::basic_raw_socket<nl_protocol> socket; 
}; 

फिर यहां से पैदा करते हैं सब हम क्या करने की जरूरत एक कच्ची सॉकेट और इसे पढ़ें:

void handle_netlink(struct nlmsghdr *nlm); 

int main(int argc, char* argv[]) 
{ 
    try 
    { 
     boost::asio::io_service io_service; 
     boost::asio::basic_raw_socket<nl_protocol> s(io_service); 

     s.open(nl_protocol(NETLINK_ROUTE)); 
     s.bind(nl_endpoint<nl_protocol>(RTMGRP_LINK)); 

     char buffer[max_length]; 
     int bytes; 

     while((bytes=s.receive(boost::asio::buffer(buffer, max_length)))) { 
      struct nlmsghdr *nlm; 

      for (nlm = (struct nlmsghdr *)buffer; 
       NLMSG_OK(nlm, (size_t)bytes); 
       nlm = NLMSG_NEXT(nlm, bytes)) 
      { 
      handle_netlink(nlm); 
      } 
     } 
    } 
    catch (std::exception& e) 
    { 
     std::cerr << "Exception: " << e.what() << "\n"; 
    }   
    return 0; 
} 

/* This code just prints out what interface went up or down */  
void handle_netlink(struct nlmsghdr *nlm) { 
    int len; 
    char ifname[IF_NAMESIZE + 1]; 
    ifinfomsg *ifi; 
    rtattr *rta; 

    if (nlm->nlmsg_type == RTM_NEWLINK) { 
     len = nlm->nlmsg_len - sizeof(*nlm); 
     if ((size_t)len < sizeof(*ifi)) { 
      errno = EBADMSG; 
      return; 
     } 
     ifi = (ifinfomsg*)NLMSG_DATA(nlm); 
     if (ifi->ifi_flags & IFF_LOOPBACK) 
      return; 

     rta = (rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); 
     len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); 
     ifname[0] = '\0'; 
     while (RTA_OK(rta, len)) { 
      switch (rta->rta_type) { 
       case IFLA_IFNAME: 
       strncpy(ifname, (char*)RTA_DATA(rta), sizeof(ifname)); 
       break; 
       default: 
        break; 
      } 
      rta = RTA_NEXT(rta, len);  
     } 
    } 
    if (nlm->nlmsg_type == RTM_NEWLINK) 
     len = ifi->ifi_change == ~0U ? 1 : 0; 

    std::cout << "Interface " << ifname << " changed status, now: "; 
    if((ifi->ifi_flags&IFF_LOWER_UP)==IFF_LOWER_UP) 
     std::cout << " Up" << std::endl; 
    else 
     std::cout << " Down" << std::endl;  
} 
+0

आपकी मदद की ज़रूरत है; http://stackoverflow.com/questions/23852866/netlink-giving-kernel-panic – SGG

संबंधित मुद्दे