सी

2010-06-03 4 views
9

में आईपीवी 6 पार्सिंग मैं जानना चाहता था कि मैं 'सी' में आईपीवी 6 पता कैसे पार्स कर सकता हूं और इसे 128 बिट वैल्यू में बदल सकता हूं? तो एक हेक्स पता जैसे 1: 22: 333: aaaa: b: c: d: e को 128 बिट समकक्ष बाइनरी में परिवर्तित करने की आवश्यकता है। समस्या यह है कि आईपी पता टाइप :: 2 और उसके संस्करण का हो सकता है क्योंकि वे वैध आईपीवी 6 पता हैं।सी

इनपुट कीबोर्ड से है और इसलिए ASCII प्रारूप में है।

कोई सुझाव या पॉइंटर्स की सराहना की जाएगी। धन्यवाद !!!

+2

ऐसा लगता है कि आपके पास 144-बिट आईपी पता है। – Thanatos

+0

ओह ... इसे इंगित करने के लिए धन्यवाद .. असल में मेरा मतलब था 1: 22: 333: aaaa: b: c: d: e –

उत्तर

11

स्ट्रिंग को struct in6_addr में कनवर्ट करने के लिए आप POSIX inet_pton का उपयोग कर सकते हैं।

#include <arpa/inet.h> 

    ... 

const char *ip6str = "::2"; 
struct in6_addr result; 

if (inet_pton(AF_INET6, ip6str, &result) == 1) // success! 
{ 
    //successfully parsed string into "result" 
} 
else 
{ 
    //failed, perhaps not a valid representation of IPv6? 
} 
+0

आप परिणाम को पकड़ने के लिए पर्याप्त कुछ भी पारित कर सकते हैं, उदाहरण के लिए, 8 'शॉर्ट' की एक सरणी भी करेगी; बस जब तक बफर कम से कम 128-बिट लंबाई में होता है। – dreamlax

+1

मुझे व्यक्तिगत रूप से 'getaddrinfo()' से थोड़ा अधिक पसंद है, जिसे मैंने नीचे सुझाया था।अफसोस की बात है, ऐसा लगता है कि विंडोज़ में केवल Vista में 'inet_pton()' शुरू हो रहा है। (और मैं लगभग यकीन है कि यह आरएफसी 2373 के अनुसार पार्स नहीं है, और केवल अपने ठेठ IPv6 पता ... किसी को पता है चाहते?) – Thanatos

+0

@Thanatos: [इस कड़ी] (http://msdn.microsoft.com /en-us/library/cc805844\(VS.85\).aspx) को संदर्भित करता है [आरएफसी 2553] (http://www.ietf.org/rfc/rfc2553) जो समारोह 'वाणी inet_pton' एक समारोह के रूप कि आईपीवी 4 और आईपीवी 6 टेक्स्टुअल प्रस्तुतियों को बाइनरी रूप में परिवर्तित करता है, और यह कहता है कि इसे [आरएफसी 2373] (http://www.ietf.org/rfc/rfc2373) की धारा 2.2 में वर्णित प्रतिनिधित्वों में आईपीवी 6 पते स्वीकार करना होगा। – dreamlax

8

getaddrinfo() आईपीवी 6 पते को समझ सकते हैं। संकेतों में AF_INET6 को पास करें, साथ ही AI_NUMERICHOST (DNS लुकअप को रोकने के लिए)। लिनक्स में यह है, विंडोज़ के पास विंडोज एक्सपी है।

+1

फ़ंक्शन सफल होने पर 'freeaddrinfo' का उपयोग करना न भूलें। – dreamlax

2

सी में आईपीवी 6 को पार्स करने के लिए, आप अपने आप को एक उपयोगिता समारोह है, जो स्ट्रिंग tokenized (हेक्स ब्लॉकों के लिए पेट के, और आगे की स्लैश सबनेट बिट के लिए) का निर्माण करने की जरूरत है।

  1. Tokenize कच्चे आईपीवी 6 छोटे-स्ट्रिंग में स्ट्रिंग।
  2. गैर-खाली सबस्ट्रिंग हेक्स ब्लॉक में कनवर्ट करें। (ASCII दशमलव रूपांतरण के लिए)
  3. हेक्स ब्लॉक को सामने में पैडिंग करके 2-बाइट्स में विस्तारित करें। (केवल प्रमुख शून्यों को छंटनी मिलती है)
  4. पूर्ण आईपीवी 6 में 8 हेक्स ब्लॉक होना चाहिए, लापता हेक्स-ब्लॉक की गणना करें। (शून्य समूह केवल एक बार हो सकता है)
  5. पुनर्वितरण हेक्स-ब्लॉक गायब हो गया। (खाली स्ट्रिंग के उपयोग के सूचकांक)
+1

कोई विवरण अगर कोई आईपीवी 6 पार्सिंग सीखना चाहता है। बफ यह वास्तव में पते को पार्स करना चाहता है, अन्य उत्तरों बहुत आसान हैं। विवरण के लिए – bortzmeyer

+0

धन्यवाद YeenFei। मैं फ़ंक्शन लिखना समाप्त कर सकता हूं .. –

0

Windows में, आप WSAStringToAddress उपयोग कर सकते हैं, जो उपलब्ध है विंडोज 2000 के बाद से

0

अगर आप को बढ़ावा देने का उपयोग कर सकते , इस तरह कुछ काम करना चाहिए:

#include<boost/asio.hpp> 

using boost::asio::ip; 

bool parseIpv6String(std::string ipv6_string, char* dest){ 
    try{ 
     address_v6 addr = address_v6::from_string(ipv6_string); 
     memcpy(dest,addr.to_bytes().data(), 16); 
    }catch(...){ 
     return false; 
    } 
    return true; 
} 

उदाहरण के लिए यह कुछ और पोर्टेबल है उदाहरण के लिए POSIX विशिष्ट कार्य।

+0

जब से 'memcpy() 'अपवाद फेंकता है ?! –

+0

आप सही हैं, from_string() करता है। नोटिस के लिए धन्यवाद। – Patryk

1

आप getaddrinfo() POSIX फ़ंक्शन का उपयोग कर सकते हैं। यह inet_pton() से अधिक लचीला है, उदाहरण के लिए यह स्वचालित रूप से आईपीवी 4 और आईपीवी 6 पता प्रारूपों का पता लगाता है, यह होस्टनामों (DNS समाधान का उपयोग करके) और पोर्ट/सेवा नामों का उपयोग कर सकता है (/etc/services का उपयोग कर)।

#include <sys/types.h> 
#include <netdb.h> 
#include <netdb.h> 

.... 

const char *ip6str = "::2"; 

struct sockaddr_storage result; 
socklen_t result_len; 

struct addrinfo *res = NULL; 
struct addrinfo hints; 
memset(&hints, 0, sizeof(struct addrinfo)); 
hints.ai_family = PF_UNSPEC; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_flags = AI_DEFAULT | AI_NUMERICHOST | AI_NUMERICSERV; 

rc = getaddrinfo(ip6str, NULL, &hints, &res); 
if (rc != 0) 
{ 
    fprintf(stderr, "Failure to parse host '%s': %s (%d)", ip6str, gai_strerror(rc), rc); 
    return -1; 
} 

if (res == NULL) 
{ 
    // Failure to resolve 'ip6str' 
    fprintf(stderr, "No host found for '%s'", ip6str); 
    return -1; 
} 

// We use the first returned entry 
result_len = res->ai_addrlen; 
memcpy(&result, res->ai_addr, res->ai_addrlen); 

freeaddrinfo(res); 

IPv6 पता struct sockaddr_storage result चर में संग्रहित है।

if (result.ss_family == AF_INET6) // Ensure that we deal with IPv6 
{ 
    struct sockaddr_in6 * sa6 = (struct sockaddr_in6 *) &result; 
    struct in6_addr * in6 = &sa6->sin6_addr; 
    in6->s6_addr[0]; // This is a first byte of the IPv6 
    in6->s6_addr[15]; // This is a last byte of the IPv6 
}