2011-09-19 31 views
11

Tôi duy trì GPSD, một daemon dịch vụ mã nguồn mở được triển khai rộng rãi theo dõi GPS và các cảm biến trắc địa khác. Nó lắng nghe các kết nối ứng dụng khách trên cổng 2947 trên cả IPv4 và IPv6. Đối với bảo mật và quyền riêng tư, nó thường chỉ nghe trên địa chỉ loopback, nhưng có một tùy chọn -G cho daemon được thiết kế để làm cho nó lắng nghe trên bất kỳ địa chỉ nào.Cách nghe trên tất cả các địa chỉ IPV6 bằng cách sử dụng ổ cắm C API

Vấn đề: tùy chọn -G hoạt động trong IPv4, nhưng tôi không thể tìm ra cách làm cho nó hoạt động với IPv6. Phương pháp nên hoạt động dựa trên các ví dụ hướng dẫn khác nhau, không sản xuất thay vì một lỗi cho biết địa chỉ đã được sử dụng. Tôi đang tìm kiếm sự trợ giúp để khắc phục sự cố này từ những người có kinh nghiệm về lập trình mạng IPv6.

mã có liên quan là tại http://git.berlios.de/cgi-bin/gitweb.cgi?p=gpsd;a=blob;f=gpsd.c;h=ee2156caf03ca23405f57f3e04e9ef306a75686f;hb=HEAD

Mã này hoạt động một cách chính xác trong trường hợp cả hai -G và phi -G dưới IPv4, như có thể dễ dàng xác minh với -l netstat.

Bây giờ hãy xem xung quanh dòng 398 sau "trường hợp AF_INET6:". Tùy chọn listen_global được đặt bởi -G; khi sai, mã thành công. hiện nay có một lời nhận xét sau đây, được thừa hưởng từ một người đóng góp không rõ, mà đọc như thế này:

/* else */ 
     /* BAD: sat.sa_in6.sin6_addr = in6addr_any; 
    * the simple assignment will not work (except as an initializer) 
    * because sin6_addr is an array not a simple type 
    * we could do something like this: 
    * memcpy(sat.sa_in6.sin6_addr, in6addr_any, sizeof(sin6_addr)); 
    * BUT, all zeros is IPv6 wildcard, and we just zeroed the array 
    * so really nothing to do here 
    */ 

Theo ví dụ hướng dẫn khác nhau tôi đã nhìn lên, sự phân công "sat.sa_in6.sin6_addr = in6addr_any;" là (mặc dù bình luận) chính xác, và nó biên dịch. Tuy nhiên, khởi động với -G không xác nhận địa chỉ nghe đã được sử dụng.

Bài tập là "sat.sa_in6.sin6_addr = in6addr_any;" chính xác ở đây? Còn gì nữa, nếu có, tôi có bị mất tích không?

+0

Bạn đã thử truy tìm daemon chưa? – jpalecek

Trả lời

19

Lý do địa chỉ đã được sử dụng là do trên nhiều ngăn xếp mạng IPv6, theo mặc định, ổ cắm IPv6 sẽ nghe cả IPv4 và IPv6 cùng một lúc. Kết nối IPv4 sẽ được xử lý một cách minh bạch và ánh xạ tới một số subset of the IPv6 space. Tuy nhiên, điều này có nghĩa là bạn không thể liên kết với một ổ cắm IPv6 trên cùng một cổng như một ổ cắm IPv4 mà không thay đổi các thiết lập trên ổ cắm IPv6. Có lý?

Chỉ cần làm điều này trước khi cuộc gọi của bạn để bind (điều này được lấy từ một trong những dự án của tôi):

int on = 1; 
if (addr->sa_family == AF_INET6) { 
    r = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); 
    if (r) 
     /* error */ 
} 

Thật không may, không có giá trị mặc định trên nền tảng cho IPV6_V6ONLY - mà về cơ bản có nghĩa là bạn luôn cần phải bật hoặc tắt một cách rõ ràng nếu bạn quan tâm, trừ khi bạn không quan tâm đến các nền tảng khác. Linux lá nó tắt theo mặc định, Windows lá nó theo mặc định ...

+1

Mặc định Linux thực sự là từ sysctl. Vì vậy, bạn không thể dựa vào mặc định ở tất cả ở đó. Nhưng nếu sysadmin không thay đổi, nó sẽ mặc định tắt. (tắt là IMO mặc định hợp lý nhất). –

+1

Câu trả lời của bạn là chính xác và lỗi của tôi đã được sửa. Cảm ơn bạn. – ESR

1

Từ một cái nhìn trong các tập tin ngẫu nhiên một hệ thống bao gồm Linux, in6addr_any được khai báo như sau:

extern const struct in6_addr in6addr_any;  /* :: */ 
extern const struct in6_addr in6addr_loopback; /* ::1 */ 
#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } 

Vì vậy, có lẽ là sự gần gũi để mảng INIT nhầm lẫn với bất kỳ ai để lại nhận xét đó trong các nguồn của GPSD. Loại thực tế rõ ràng là struct in6_addr, có thể gán được.

Tôi đã xem xét xung quanh và tìm thấy một số gợi ý gợi ý rằng nếu IPv4 đã nghe địa chỉ "bất kỳ", IPv6 cũng không thể. Có lẽ đó là những gì cắn bạn.

+0

Phần thứ hai của chẩn đoán của bạn là chính xác (xem câu trả lời của Dietrich Epp) và tôi nghi ngờ bạn cũng đúng về phần đầu tiên. – ESR

Các vấn đề liên quan