2009-10-22 3 views
0

리눅스에서 ip/tcp 헤더로 메시지를 보내고받는 원시 소켓을 만들려고합니다. 성공적으로 포트에 바인드하여 tcp 메시지를 수신 할 수 있습니다 (예 : syn) 그러나 메시지는 os가 처리하지만 광산은 처리하지 못합니다. 나는 그것의 독자 일뿐입니다 (wireshark와 같은). 원시 소켓이 포트 8888에 바인드 된 다음 해당 포트로 telnet 연결을 시도합니다. wireshark에서 "syn"요청을 수신하면 포트 8888이 "첫 번째 응답"으로 응답 함을 나타냅니다. 내 프로그램에서 그것은 새로운 메시지를 수신했음을 보여 주며 어떤 메시지도 응답하지 않습니다.리눅스 원시 소켓 프로그래밍 질문

어떤 방법이 실제로 해당 포트에 결합하는, 내가 쉽게 읽을 수를 확인하는 오류를 절단하려고

여기

내 코드의 일부입니다 (OS 그것을 처리 방지)

sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); 

int tmp = 1; 
const int *val = &tmp; 
setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp)); 

servaddr.sin_family = AF_INET; 
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
servaddr.sin_port = htons(8888); 
bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)); 

//call recv in loop 
+0

실제 TCP 레이어를 코딩하려는 이유가 무엇입니까? – laura

+0

현재 프로젝트에서 tcp/ip 헤더를 변경해야 할 수도 있습니다. –

+0

Google의 "access tcp header"를 사용하면 처음 몇 가지 결과가 어떤 기능을 사용할 수 있는지 알려줄 것입니다. 나는 "정상적인"소켓 (beej의 가이드에 사용 된 것과 같은)이 매우 유용하다고 생각하지 않는다. – laura

답변

1

편집 : 원시 소켓을 프로그래밍하려는 경우 this을 확인하십시오.

원시 패킷을 송수신하는 방법에 대한 몇 가지 예가 있습니다. 포트 : 당신은 주어진 주소로 바인딩 후 듣고 그것을 말할 필요가

: 경우

당신은 SOCK_STREAMSOCK_SEQPACKET 연결 지향 타입의 소켓을 사용하고 싶습니다.

int connectionQueue = 10; 
if (-1 == listen(sockfd, connectionQueue)) 
{ 
    // Error occurred 
} 

그 후, 당신은 선택을 사용하여 들어오는 연결에 대한 설명을 확인하고 (새 연결을 허용하지으로 이어질 것입니다) 서버 소켓 중 하나에 들어오는 연결, 또는 전용 클라이언트 소켓을 수용해야합니다.

+1

Beej의 가이드는 그를위한 매우 훌륭한 초보자 리소스이다. http://beej.us/guide/bgnet/output/html /multipage/index.html – laura

+0

@laura : 참조 용 +1 :-) –

+0

바인드 함수 다음에이 줄을 추가하려했지만 오류가 있습니다. OS 오류 코드 95 : 작업 지원되지 않음 –

2

man 7 raw는 말한다 :

원시 소켓 리눅스의 모든 IP 프로토콜, 커널 프로토콜 모듈이 ICMP 또는 TCP와 같은 심지어 프로토콜을 누릅니다 수 있습니다. 이 경우 패킷은 커널 모듈과 원시 소켓 모두로 전달됩니다. 물론, 당신이 원하는 것이 아니다, -

나는 당신이 당신의 커널 TCP의 지원이 부족하지 않는 커널에서 간섭없이 원시 소켓 "TCP를 할"수 없음을 의미하는이 걸릴. 어떤 원시 소켓이 좋은지는 커널 이 처리하지 않는 다른 IP 프로토콜을 구현하거나이 처리하지 않는 것입니다. 또는 제작 된 ICMP 패킷을 보내는 것과 같은 특수한 응용 프로그램에 유용합니다.

+0

대신 소켓 (PF_PACKET, SOCK_RAW, htons (ETH_P_IP))을 사용하는 것이 어떻습니까? PF_PACKET이 데이터 링크 계층에서 패킷을 가져오고 거기에서 패킷을 처리 할 수 ​​있다는 정보를 읽었습니까? –

+0

'PF_PACKET'은 pcap의 구현 방법입니다. 그래서 그렇게 생각하지 않습니다. AF_INET/SOCK_RAW와 마찬가지로 원하는 것을들을 수 있으며 원하는 것을 보낼 수는 있지만 커널을 선점 할 수는 없습니다. – hobbs

4

커널이 원격 호스트로부터 SYN/ACK를 수신하면 커널은 그 IPN : PORT 조합 (원시 소켓에서 보낸)에 SYN을 보낸 기록이 없다는 것을 알 수 있습니다. 오류가 발생하여 원격 호스트에 RST를 전송합니다. 이 문제는 해당 포트의 모든 TCP 트래픽을 차단하는 IP 필터를 설정하여 해결할 수 있습니다 (이에 대한 iptables 맨 페이지 확인). 그렇게하면 커널 공간에서 프로그래밍 할 필요가 없으며 기존 커널 TCP 모듈에 영향을 미치지 않습니다.

2

원시 헤더에 액세스하려면 원시 소켓을 포트에 바인딩하지 마십시오. 그게 끝나지 않았어.

들어오는 모든 패킷을 "PICK UP"하고 "YOUR"패킷을 찾으려면 스니퍼를 쓰면됩니다. 그것은 또한 모든 패킷 내용 등에 대한 액세스를 제공합니다.

이 당신이 그것을하는 방법이다 다음 ProcessPacket 기능에서

int sock_raw = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ; 

while(true) 
{ 
    saddr_size = sizeof saddr; 
    //Receive a packet 
    data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size); 
    if(data_size <0) 
    { 
     printf("Recvfrom error , failed to get packets\n"); 
     return 1; 
    } 
    //Now process the packet 
    ProcessPacket(buffer , data_size); 
} 

패킷을 분석하고 응용 프로그램에 속해 있는지 확인합니다.