2010-06-03 103 views
9

Tôi muốn biết cách phân tích địa chỉ IPv6 trong 'C' và chuyển đổi nó thành giá trị 128 bit? Vì vậy, một địa chỉ hex như 1: 22: 333: aaaa: b: c: d: e cần phải được chuyển đổi thành nhị phân tương đương 128 bit. Vấn đề là địa chỉ IP có thể thuộc loại :: 2 và biến thể của nó vì chúng là địa chỉ IPv6 hợp lệ.Phân tích cú pháp IPv6 trong C

Đầu vào là từ bàn phím và do đó có định dạng ASCII.

Mọi đề xuất hoặc con trỏ sẽ được đánh giá cao. Cảm ơn !!!

+2

Đó dường như là địa chỉ IP 144 bit mà bạn đã có. – Thanatos

+0

Rất tiếc ... Cảm ơn bạn đã chỉ ra điều đó .. Thực tế tôi muốn nói 1: 22: 333: aaaa: b: c: d: e –

Trả lời

11

Bạn có thể sử dụng POSIX inet_pton để chuyển đổi chuỗi thành struct in6_addr.

#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

Bạn có thể vượt qua bất cứ điều gì đủ lớn để giữ kết quả, ví dụ, một mảng 8 'short' sẽ làm tốt; miễn là bộ đệm dài ít nhất 128 bit. – dreamlax

+1

Cá nhân tôi thích điều này nhiều hơn một chút so với 'getaddrinfo()', mà tôi đã gợi ý bên dưới.Đáng buồn thay, có vẻ như Windows chỉ có 'inet_pton()' bắt đầu bằng Vista. (Và tôi gần như đặt cược rằng nó không phân tích theo RFC 2373, và chỉ có địa chỉ IPv6 điển hình của bạn ... bất cứ ai biết?) – Thanatos

+0

@Thanatos: [Liên kết này] (http://msdn.microsoft.com /en-us/library/cc805844\ (VS.85\).aspx) dùng để chỉ [RFC 2553] (http://www.ietf.org/rfc/rfc2553) khai báo hàm 'inet_pton' như một hàm chuyển đổi các đại diện văn bản IPv4 và IPv6 thành dạng nhị phân, và nó nói rằng nó phải chấp nhận địa chỉ IPv6 trong các biểu diễn được mô tả trong phần 2.2 của [RFC 2373] (http://www.ietf.org/rfc/rfc2373). – dreamlax

8

getaddrinfo() có thể hiểu địa chỉ IPv6. Chuyển AF_INET6 đến nó trong các gợi ý, cũng như AI_NUMERICHOST (để ngăn chặn tra cứu DNS). Linux có nó, Windows có nó như của Windows XP.

+1

Đừng quên sử dụng 'freeaddrinfo' nếu hàm đã thành công. – dreamlax

2

Để phân tích cú pháp IPv6 trong C, bạn cần tạo cho mình một chức năng tiện ích, chuỗi được mã hóa (dấu hai chấm cho khối hex và dấu gạch chéo cho bit phụ).

  1. Mã hóa chuỗi IPv6 thô thành chuỗi con nhỏ hơn.
  2. Chuyển đổi chuỗi con không trống thành các khối hex. (ASCII để chuyển đổi thập phân)
  3. Mở rộng khối hex thành 2 byte bằng cách đệm 0 ở phía trước. (chỉ có các số 0 hàng đầu được cắt bớt)
  4. Hoàn thành IPv6 nên có 8 khối hex, tính toán các khối hex bị thiếu. (các nhóm zeroes chỉ có thể xảy ra một lần)
  5. Chèn lại khối hex bị thiếu. (Chỉ tiêu sử dụng của chuỗi rỗng)
+1

Mô tả hay nếu ai đó muốn tìm hiểu phân tích cú pháp IPv6. Buf nó chỉ muốn phân tích cú pháp địa chỉ, các câu trả lời khác đơn giản hơn rất nhiều. – bortzmeyer

+0

Cảm ơn YeenFei cho mô tả. Tôi có thể kết thúc viết chức năng .. –

0

Trong Windows, bạn có thể sử dụng WSAStringToAddress, trong đó có sẵn từ Windows 2000.

0

nếu bạn có thể sử dụng tăng , một cái gì đó như thế này sẽ hoạt động:

#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; 
} 

Nó có thể dễ dàng hơn một chút so với các chức năng cụ thể của POSIX.

+0

Vì khi nào thì memcpy() 'ném ngoại lệ ?! –

+0

bạn nói đúng, from_string(). cảm ơn thông báo. – Patryk

1

Bạn có thể sử dụng chức năng getaddrinfo() POSIX. Nó linh hoạt hơn inet_pton(), ví dụ nó tự động phát hiện định dạng địa chỉ IPv4 và IPv6, nó có thể phân giải tên máy chủ (sử dụng giải quyết DNS) và tên cổng/dịch vụ (sử dụng /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); 

Địa chỉ IPv6 được lưu trữ trong biến số 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 
} 
Các vấn đề liên quan