2017-11-27 6 views
1

私は、パケットを受信し、その宛先を読み取り、途中で送信するパケットルータを作ろうとしています。それは、問題は、私はのsendto()を行うことをしようとしたとき、私はいつもにそれをロードし、C Linux用パケットルーター。 sendto()を設定する

sendto() failed: No such device or address 

は私が受信したパケットのイーサネットヘッダから宛先MACアドレスをつかんでいますエラーが出るということです、うまくパケットを受信しますa struct sockaddr_llとそれをsendto()に渡しますが、動作しません。

また、あるホストから別のホストにpingを実行すると、私のprintステートメントの出力にソースIPが40.41.42.43、宛先IPに44.45.46.47があり、どちらのデバイスも存在しません。イーサネットとIPヘッダを正しく読んでいますか?あるいは、ソケットがどうにか乱れているかもしれませんか?

とにかくここにコードがあります。

int main(int argc, char *argv[]) 
{ 
int sock1, sock2, sock3; 
int status = 0; 
fd_set readfds; 
int buffer[256]; 
int socknum = 0; 




// Create 3 sockets 
if ((sock1 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){ 
    perror("socket() failed"); 
    exit(1); 
} 
if ((sock2 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){ 
    perror("socket() failed"); 
    exit(1); 
} 
if ((sock3 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) < 0){ 
    perror("socket() failed"); 
    exit(1); 
} 
// Bind sockets to interfaces 
struct ifreq ifr; 
memset(&ifr, 0, sizeof(ifr)); 
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth1"); 
if (setsockopt(sock1, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) { 
perror("setsockopt() inf config failed"); 
exit(1); 
} 
memset(&ifr, 0, sizeof(ifr)); 
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth2"); 
if (setsockopt(sock2, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) { 
perror("setsockopt() inf config failed"); 
exit(1); 
} 
memset(&ifr, 0, sizeof(ifr)); 
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "r0-eth3"); 
if (setsockopt(sock3, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) { 
perror("setsockopt() inf config failed"); 
exit(1); 
} 

printf("All sockets bound to interfaces.\n"); 


while(1) 
{ 
    //Setup select 
    FD_ZERO(&readfds); 
    FD_SET(sock1, &readfds); 
    FD_SET(sock2, &readfds); 
    FD_SET(sock3, &readfds); 
    printf("Sockets set to read.\n"); 

    struct timeval tv = {2, 0}; 

    printf("Starting select.\n"); 
    status = select(sock3 + 1, &readfds , NULL , NULL , &tv); 
    printf("status = %d\n", status); 

    struct sockaddr_in sockAddr; 
    socklen_t sockLen = sizeof(sockAddr); 
    memset(&sockAddr, 0, sockLen); 
    sockAddr.sin_family = AF_INET; 
    sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    int bufLen = 0; 


    // Check select 
    if (status > 0) { 
     printf("status = %d, preparing to read.\n", status); 
     // Read IP datagram (d) 
     if (FD_ISSET(sock1, &readfds)) { 
      printf("Socket 1 ready to receive.\n"); 
      printf("Attempting to receive packet.\n"); 
      bufLen = recvfrom(sock1, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen); 
      printf("Received packet.\n"); 
      socknum = 1; 
     } 
     else if (FD_ISSET(sock2, &readfds)) { 
      printf("Socket 2 ready to receive.\n"); 
      printf("Attempting to receive packet.\n"); 
      bufLen = recvfrom(sock2, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen); 
      printf("Received packet.\n"); 
      socknum = 2; 
     } 
     else if (FD_ISSET(sock3, &readfds)) { 
      printf("Socket 3 ready to receive.\n"); 
      printf("Attempting to receive packet.\n"); 
      bufLen = recvfrom(sock3, buffer, 65535, 0, (struct sockaddr *) &sockAddr, (socklen_t *)&sockLen); 
      printf("Received packet.\n"); 
      socknum = 3; 
     } 
     printf("Testing Packet.\n"); 

     struct ethhdr *eth = (struct ethhdr *)(buffer); 
     printf("\nEthernet Header\n"); 
     printf("\t|-Source Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]); 
     printf("\t|-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]); 
     printf("\t|-Protocol : %d\n",eth->h_proto); 


     // Inspect IP (e) 
     unsigned short iphdrlen; 
     struct sockaddr_in source; 
     struct sockaddr_in dest; 
     struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr)); 
     memset(&source, 0, sizeof(source)); 
     source.sin_addr.s_addr = ip->saddr; 
     memset(&dest, 0, sizeof(dest)); 
     dest.sin_addr.s_addr = ip->daddr; 

     printf("\t|-Version : %d\n",(unsigned int)ip->version); 
     printf("\t|-Internet Header Length : %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4); 
     printf("\t|-Type Of Service : %d\n",(unsigned int)ip->tos); 
     printf("\t|-Total Length : %d Bytes\n",ntohs(ip->tot_len)); 
     printf("\t|-Identification : %d\n",ntohs(ip->id)); 
     printf("\t|-Time To Live : %d\n",(unsigned int)ip->ttl); 
     printf("\t|-Protocol : %d\n",(unsigned int)ip->protocol); 
     printf("\t|-Header Checksum : %d\n",ntohs(ip->check)); 
     printf("\t|-Source IP : %s\n", inet_ntoa(source.sin_addr)); 
     printf("\t|-Destination IP : %s\n",inet_ntoa(dest.sin_addr)); 


     printf("index=%d\n",ifreq_i.ifr_ifindex); 

     // Pull the address from the ethernet header. 
     struct sockaddr_ll addr; 
     memset(&addr, 0, sizeof(struct sockaddr_ll)); 
     addr.sll_family = AF_PACKET; 
     addr.sll_ifindex = ifr.ifr_ifindex; 
     addr.sll_halen = ETHER_ADDR_LEN; 
     addr.sll_protocol = htons(0x0800); 
     addr.sll_addr[0] = eth->h_dest[0]; 
     addr.sll_addr[1] = eth->h_dest[1]; 
     addr.sll_addr[2] = eth->h_dest[2]; 
     addr.sll_addr[3] = eth->h_dest[3]; 
     addr.sll_addr[4] = eth->h_dest[4]; 
     addr.sll_addr[5] = eth->h_dest[5]; 

     if(sendto(sock1, buffer, bufLen, 0, (struct sockaddr *) &addr, sizeof(addr)) < bufLen){ 
      perror("sendto() failed"); 
      exit(1); 
     } 
    } 

助けてください。

答えて

0

私はすぐに答えを見つけましたが、他の人にも同様の問題がある場合に備えて、私はこれを残しておきます。一番下の部分は、struct sockaddr_ll addr;を設定しています。この行は:

addr.sll_ifindex = ifr.ifr_ifindex; 

代わりにこれをする必要があります:()これらのパラメータに合わせてデバイスを見つけることができなかったのsendtoよう

addr.sll_ifindex = ifreq_i.ifr_ifindex; 

ソケットとソケットのインデックスが異なっていました。

関連する問題