2010-08-19 1 views
10

POSIXy C++에서 레이어 2 패킷을 수신하려면 어떻게해야합니까? 패킷에는 src 및 dst MAC 주소, 유형/길이 및 사용자 정의 형식의 데이터 만 있습니다. 그들은 TCP 나 UDP 또는 IP 나 IGMP 나 ARP 등이 아닙니다. 그들은 하드웨어 사용자들에 의해 제게 제공되는 양식입니다.C/C++에서 원시 레이어 2 패킷을 어떻게 받습니까?

socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)recvfrom()에서 반환하지 않습니다.

잘 보낼 수 있지만 네트워크 스택에서 어떤 옵션을 선택하든 관계없이 수신 할 수 없습니다.

(플랫폼 Vx 웍스,하지만 난 POSIX 또는 Linux 또는 무엇이든을 ... 번역 할 수 있습니다)

코드 (현재의 화신)가 나타납니다

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

대단한 질문입니다! –

+1

이 POSIX, Windoze에서 이것을 행하려고 행운을 빈다.) –

+0

POSIX는 C++ 바인딩을 정의하지 않고 오직 C 만 정의한다. –

답변

4

이 작업을 수행하는 방법은 VxWorks 네트워크 스택의 MUX 계층에 바인딩하는 자체 네트워크 서비스를 작성하는 것입니다. 이것은 VxWorks Network Programmer 's Guide에 합리적으로 잘 설명되어 있으며 여러 번 해본 적이 있습니다.

맞춤 네트워크 서비스는 윈드 리버 자신의 WDB 프로토콜이 작동하는 방식 인 MUX_PROTO_SNARF 서비스 유형 또는 특정 프로토콜 유형의 패킷을 사용하여 네트워크 인터페이스에서 수신 한 모든 레이어 2 패킷을 확인하도록 구성 할 수 있습니다.

네트워크 서비스와 소켓 API 사이에있는 사용자 지정 소켓 백 엔드를 작성하여 사용자 지정 네트워크 서비스에 소켓 인터페이스를 추가 할 수도 있습니다. 네트워크 서비스에서 응용 프로그램 처리를 기꺼이 수행 할 경우에는 필요하지 않습니다.

당신은 당신이 사용하는 Vx 웍스의 버전을 말했다하지 않은하지만 난 당신의 인터페이스를 모두 얻을 수 있도록 ETH_P_ALL 같은 프로토콜을 지정해야 위의 VxWorks의 5.5.x와 6.x의

+0

감사합니다. 나는 게으른 경로로 가서 네트워크 스택에 들어가기 전에 자일링스 코드에서 패킷을 복사했다. 당신의 길은 ... 게으른 것이 아니라 스케쥴 뒤에서 ... – spydez

3

당신이로 htons(ETH_P_ALL)에 소켓 프로토콜을 설정하려고 되세요 packet(7)에 명시되어 있습니까? 당신이하고있는 일은 IP와는 많이 관련이 없습니다 (IPPROTO_RAW은 와일드 카드 값일 수 있습니다.)

+0

정답 -'socket()'에 전달 된 프로토콜은'IPPROTO_RAW'가 아니어야합니다. 이것은 이더넷이어야합니다 (예 : 802.3) 사용자 정의 프로토콜 용 프로토콜 ID (네트워크 바이트 순서). – caf

+0

감사합니다. 당신 말이 맞지만 여전히 작동하지 않습니다. – spydez

+0

아마도 맨 페이지를 읽고 거기에서 추측 한 모든 인수를 확인하십시오. – mvds

1

나는 이것이 당신이 기대하는 것보다 해결하기 어려운 문제라고 생각합니다. IP가 전혀 없다는 점을 감안할 때, 사용자 수준의 코드로 문제를 완전히 해결할 수있을 것이라고는 생각하지 않습니다. 리눅스에서는 아마도 을 사용하여 자신의 device agnostic interface 드라이버를 작성해야한다고 생각합니다. VxWorks에서 작동하게하는 것은 거의 확실합니다. (대부분의 사람들이 포트라고 생각하는 것보다 완전히 다시 작성하는 것과 비슷합니다).

0

패킷이 실제로 다른 쪽에서 전송되었다는 것을 Wireshark를 통해 확인 했습니까?

또한 디버깅을 위해 하드웨어 사용자에게 패킷을받을 때 어설 션할 수있는 디버그 핀 (논리 분석기에 연결할 수 있음)이 있는지 물어보십시오. 그냥 하드웨어가 패킷을 잘 받고 있는지 확인하십시오.

+0

모든 것이 FPGA 안에 있으므로 상어가 될 수 없습니다. HW가 작동한다고 했으므로 지금은 그걸로 가야합니다. – spydez

0

첫째을 위해 보유하고 생각 패킷. 소켓을 무차별 모드로 설정하십시오. 그런 다음 수신을 수행하기 전에 RAW 소켓을 인터페이스에 바인드하십시오.