2013-07-03 2 views
2
나는 리눅스/데비안에 RAW 소켓 함께 일하고

내가 쓰기 (사용할 때이 문제가)() : 리눅스 RAW 소켓

struct sockaddr_ll socket_address; 
/* Index of the network device */ 
socket_address.sll_ifindex = if_idx.ifr_ifindex; 
/* Address length*/ 
socket_address.sll_halen = ETH_ALEN; 
/* Destination MAC */ 
socket_address.sll_addr[0] = 0x00; 
socket_address.sll_addr[1] = 0x11; 
socket_address.sll_addr[2] = 0x22; 
socket_address.sll_addr[3] = 0x33; 
socket_address.sll_addr[4] = 0x44; 
socket_address.sll_addr[5] = 0x55; 

/* Send packet */ 
int b_written = 0; 

if ((b_written = write(sockfd, sendbuf, tx_len, 
            (struct sockaddr*)&socket_address, 
            sizeof(struct sockaddr_ll))) < 0) 
/* 
if ((b_written = sendto(sockfd, sendbuf, tx_len, 0, 
            (struct sockaddr*)&socket_address, 
        sizeof(struct sockaddr_ll))) < 0) 
*/ 
{ 
    perror("Could not write socket..."); 
    fprintf(stderr, "ERRNO = %d\n", errno); 
    exit(-1); 
} 
printf("Packet sent!, Bytes written = %d\n", b_written); 

내가 사용하는 경우

대신 sendto를의 "쓰기", 다음과 같은 오류가 발생합니다 : "해당 장치 또는 주소가 없습니다"(errno = 6, EXNIO로 정의 됨).

"sendto"를 사용하면 "tcpdump -nettti eth0 '(ether dst 호스트 00 : 11 : 22 : 33 : 44 : 55)' '에 패킷이 표시됩니다.

man (sendto)에 따르면 sendto는 플래그를 지정하지 않고 쓰기와 동일합니다. "sendto"에 사용하는 플래그 필드가 '0'이기 때문에 두 시스템 호출이 동일하다고 생각합니다.

내가 뭘 잘못하고 있니? 두 통화가 동등한가요?

+0

'write()'는 5 개의 매개 변수를 가질 수 없습니다. – nouney

+0

해당 맨 페이지의 내용은 sendto()와 sendmsg() 사이의 유일한 차이점은 인수를 해당 함수에 전달하는 방법 인 것 같습니다. 링크 레이어 레벨 RAW 소켓에 대해 "sendmsg()"를 "sendto()"보다 사용하는 것이 더 적절한 이유는 무엇입니까? – Ricardo

+0

원본 코드입니까? 당신은'쓰기'또는'보내기'를 의미 했습니까? 명사가 한 말은 맞습니다. 만약 그것이'send'라면, 당신은 비 연결 서비스를 위해 그것을 사용할 수 없습니다. 예 : SOCK_RAW – Aravind

답변

3

sendto() 호출은 소켓이 연결된 상태 (의도 된받는 사람을 알 수 있도록) 일 때만 사용할 수 있습니다. 다음은 쓰기 기능의 프로토 타입이며, 3 가지 매개 변수는 send()과 같지 않습니다.

write(int fd, const void *buf, size_t count);

+0

3 개의 인수를 사용해도 같은 errno # 6 (EXNIO : "No such device or address")를 얻습니다. write (sockfd, sendbuf, tx_len) 호출은 다음과 같습니다. – Ricardo

+0

내 마음에 새로운 질문이 있습니다 : "write"의 맨 페이지에 따르면이 함수에는 3 가지 인수가 있습니다. 왜 "write"에 5 가지 인수를 전달하는 코드를 컴파일하고 실행할 수 있습니까? 여러 인수를 지원하고 필요없는 인수를 무시합니까? GCC가이 문제에 대해 (최소한) 경고해야하지 않습니까? – Ricardo

+1

@Ricardo 아니요 여러 인수를 지원하지 않습니다. 귀하의 컴파일러 옵션은 무엇입니까? ** - Wall **으로 컴파일 했습니까? – nouney

0

이 메시지는 존재하지 않거나 장치 한도를 초과하는 특수 파일의 하위 장치에 대한 입출력에서 발생합니다. 그래서 당신이 쓰기 작업을 수행 할 곳을 쓸 권한이나 액세스 권한이 있는지 확인하십시오. 또한 3 개의 매개 변수 만 가질 수 있으므로 쓰기 매개 변수를 변경하십시오. man 페이지

int write(fd, buf, nbyte) 

에서

나는이 문제를 해결할 수 있기를 바랍니다.

+1

권한 오류 인 경우 왜 sendto가 아닌 쓰기에 대해 오류가 발생합니까? – xaxxon

+0

지금 당장은 그 응용 프로그램을 으로 실행하고 있습니다. 소켓을 여는 권한이 필요하기 때문입니다. 그래서 나는 권한 문제가 아니라고 생각합니다. – Ricardo

+0

@ 리카르도 ... 나는 당신이 errno = 6을 얻고 있기 때문에 그것을 말했습니다. 이것은 장치가 없다는 것을 의미합니다. 물리적으로 (내가 가정했듯이) 그 장치를 가지고 있다면 문제는 하나뿐입니다. 따라서 장치 파일을 확인하십시오. 사용 권한은 666 (crw-rw-rw-)을 읽어야합니다. – someone

3

당신은 bind() (see manual) 당신의 소켓에 주소, 다음 (만 3 매개 변수, 즉 의미)가 제대로 write()를 사용합니다.

/* Send packet */ 
int b_written = 0; 

if (bind(sockfd, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) == -1) 
{ 
    perror("bind"); 
    exit(-1); 
} 
if ((b_written = write(sockfd, sendbuf, tx_len)) < 0) 
{ 
    perror("Could not write socket..."); 
    fprintf(stderr, "ERRNO = %d\n", errno); 
    exit(-1); 
} 
printf("Packet sent!, Bytes written = %d\n", b_written); 
+0

네, 그러면이 문제가 해결됩니다. @ 감사합니다! 내 대답은 sockaddr_ll 구조의 특정 필드를 채우는 것이 중요하기 때문에 전체 솔루션을 찾으십시오. – Ricardo

관련 문제