2010-08-19 18 views
10

Làm cách nào để nhận các gói lớp 2 trong POSIXy C++? Các gói chỉ có địa chỉ MAC và dst, loại/độ dài và dữ liệu được định dạng tùy chỉnh. Chúng không phải là TCP hoặc UDP hoặc IP hoặc IGMP hay ARP hay bất cứ thứ gì - chúng là một định dạng được pha chế tại nhà cho các phần cứng của tôi.Làm cách nào để nhận các gói dữ liệu thô, lớp 2 trong C/C++?

My socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) không bao giờ trả về từ số recvfrom().

Tôi có thể gửi tiền phạt, tôi chỉ không thể nhận được bất kể tôi chọn tùy chọn nào trong mạng.

(Platform là VxWorks, nhưng tôi có thể dịch POSIX hoặc Linux hoặc bất cứ điều gì ...)

nhận được mã (hóa thân hiện tại):

int s; 

if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
    printf("socket create error."); 
     return -1; 
} 

    struct ifreq   _ifr; 
    strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0")); 
    ioctl(s, IP_SIOCGIFINDEX, &_ifr); 

    struct sockaddr_ll _sockAttrib; 
    memset(&_sockAttrib, 0, sizeof(_sockAttrib)); 
    _sockAttrib.sll_len  = sizeof(_sockAttrib); 
    _sockAttrib.sll_family = AF_PACKET; 
    _sockAttrib.sll_protocol = IFT_ETHER; 
    _sockAttrib.sll_ifindex = _ifr.ifr_ifindex; 
    _sockAttrib.sll_hatype = 0xFFFF; 
    _sockAttrib.sll_pkttype = PACKET_HOST; 
    _sockAttrib.sll_halen = 6; 
    _sockAttrib.sll_addr[0] = 0x00; 
    _sockAttrib.sll_addr[1] = 0x02; 
    _sockAttrib.sll_addr[2] = 0x03; 
    _sockAttrib.sll_addr[3] = 0x12; 
    _sockAttrib.sll_addr[4] = 0x34; 
    _sockAttrib.sll_addr[5] = 0x56; 
    int _sockAttribLen = sizeof(_sockAttrib); 


char packet[64]; 
memset(packet, 0, sizeof(packet)); 

    if (recvfrom(s, (char *)packet, sizeof(packet), 0, 
       (struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0) 
    { 
     printf("packet receive error."); 
    } 

    // code never reaches here 
+0

Câu hỏi tuyệt vời! –

+1

Tôi rất vui vì bạn đã gắn thẻ POSIX này, chúc may mắn cố gắng thực hiện điều này trên Windoze;) –

+0

Chỉ cần một nitpick: POSIX không xác định ràng buộc C++, chỉ C. –

Trả lời

4

Tôi nghĩ cách để làm điều này là viết Dịch vụ mạng của riêng bạn liên kết với lớp MUX trong ngăn xếp mạng VxWorks. Đây là tài liệu hợp lý trong Hướng dẫn lập trình mạng của VxWorks và một số thứ tôi đã thực hiện một số lần.

Dịch vụ mạng tùy chỉnh có thể được cấu hình để xem tất cả gói 2 nhận được trên giao diện mạng sử dụng loại dịch vụ MUX_PROTO_SNARF, đó là cách giao thức WDB của Wind River hoạt động, hoặc gói với loại giao thức cụ thể.

Cũng có thể thêm giao diện ổ cắm vào Dịch vụ mạng tùy chỉnh của bạn bằng cách viết một back-end socket tùy chỉnh nằm giữa Dịch vụ mạng và API socket. Điều này không bắt buộc nếu bạn vui lòng thực hiện việc xử lý ứng dụng trong Dịch vụ mạng.

Bạn chưa cho biết phiên bản nào của VxWorks bạn đang sử dụng nhưng tôi nghĩ rằng nắm giữ trên cho VxWorks 5.5.x và 6.x

+0

Cảm ơn. Tôi đã đi con đường lười biếng và chỉ cần sao chép các gói tin từ mã Xilinx trước khi nó đã vào ngăn xếp mạng. Cách của bạn sẽ là ... không lười biếng, không phải theo cách lịch biểu ... :) – spydez

3

Bạn đã cố gắng thiết lập giao thức socket để htons(ETH_P_ALL) như được quy định trong packet(7)? Những gì bạn đang làm không liên quan nhiều đến IP (mặc dù IPPROTO_RAW có thể là một số giá trị ký tự đại diện, dunno)

+0

Câu trả lời đúng - giao thức được chuyển tới 'socket()' không nên là 'IPPROTO_RAW', nó phải là ethernet (802.3) ID giao thức cho giao thức tùy chỉnh của bạn, theo thứ tự byte mạng. – caf

+0

Cảm ơn. Bạn nói đúng nhưng nó vẫn không hoạt động. – spydez

+0

có thể bắt đầu đọc trang người đàn ông và kiểm tra bất kỳ đối số nào bạn đã đoán trong đó. – mvds

1

Tôi nghĩ rằng vấn đề này sẽ khó giải quyết hơn bạn mong đợi. Cho rằng nó không phải là IP ở tất cả (hoặc dường như bất kỳ giao thức khác bất cứ điều gì sẽ nhận ra), tôi không nghĩ rằng bạn sẽ có thể giải quyết vấn đề của bạn (s) hoàn toàn với mã cấp người dùng. Trên Linux, tôi nghĩ bạn cần viết trình điều khiển device agnostic interface của riêng mình (có thể sử dụng NAPI). Bắt nó làm việc theo VxWorks sẽ gần như chắc chắn là không tầm thường (giống như một viết lại hoàn chỉnh từ mặt đất lên hơn những gì hầu hết mọi người sẽ nghĩ đến như một cổng).

0

Bạn đã thử xác nhận qua Wireshark rằng một gói thực sự đã được gửi từ đầu kia chưa?

Ngoài ra, để gỡ lỗi, hãy hỏi những người phần cứng của bạn nếu họ có một pin gỡ lỗi (bạn có thể đính kèm vào một máy phân tích logic) mà họ có thể khẳng định khi nó nhận được một gói. Chỉ cần để đảm bảo rằng phần cứng là nhận được các gói tin tốt.

+0

Đó là tất cả bên trong một FPGA, do đó, nó không thể bị mập. HW nói nó hoạt động, vì vậy tôi phải đi với điều đó bây giờ. – spydez

0

Trước tiên, bạn cần phải xác định giao thức như ETH_P_ALL để giao diện của bạn được tất cả cái túi. Đặt ổ cắm của bạn ở chế độ promiscuous. Sau đó kết nối ổ cắm RAW của bạn với một giao diện trước khi bạn thực hiện một nhận.

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