Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于C-Linux的包路由器。设置sendto()_C_Linux_Sockets_Routing_Network Programming - Fatal编程技术网

用于C-Linux的包路由器。设置sendto()

用于C-Linux的包路由器。设置sendto(),c,linux,sockets,routing,network-programming,C,Linux,Sockets,Routing,Network Programming,我正在尝试制作一个包路由器,它接收一个包,读取它的目的地,并在途中发送它。它可以很好地接收数据包,问题是当我尝试执行sendto()时,总是会出现错误 sendto() failed: No such device or address 我正在从接收到的数据包的以太网报头中获取目标MAC地址,将其加载到struct sockaddr\u ll并将其传递到sendto(),但它不起作用 此外,当我将一台主机ping到另一台主机时,print语句的输出将源ip设置为40.41.42.43,目标ip

我正在尝试制作一个包路由器,它接收一个包,读取它的目的地,并在途中发送它。它可以很好地接收数据包,问题是当我尝试执行sendto()时,总是会出现错误

sendto() failed: No such device or address
我正在从接收到的数据包的以太网报头中获取目标MAC地址,将其加载到
struct sockaddr\u 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);
        }
    }
intmain(intargc,char*argv[])
{
int sock1、sock2、sock3;
int status=0;
fd_设置读取FDS;
int缓冲区[256];
int-socknum=0;
//创建3个套接字
if((sock1=socket(AF_数据包、SOCK_DGRAM、htons(ETH_P_IP)))<0){
perror(“套接字()失败”);
出口(1);
}
if((sock2=socket(AF_数据包、SOCK_DGRAM、htons(ETH_P_IP)))<0){
perror(“套接字()失败”);
出口(1);
}
if((sock3=套接字(AF_数据包、SOCK_DGRAM、htons(ETH_P_IP)))<0){
perror(“套接字()失败”);
出口(1);
}
//将套接字绑定到接口
结构ifreq-ifr;
memset(&ifr,0,sizeof(ifr));
snprintf(ifr.ifr_名称,sizeof(ifr.ifr_名称),“r0-eth1”);
if(setsockopt(sock1,SOL_SOCKET,SO_BINDTODEVICE,(void*)和ifr,sizeof(ifr))<0){
perror(“setsockopt()inf配置失败”);
出口(1);
}
memset(&ifr,0,sizeof(ifr));
snprintf(ifr.ifr_名称,sizeof(ifr.ifr_名称),“r0-eth2”);
if(setsockopt(sock2,SOL_SOCKET,SO_BINDTODEVICE,(void*)和ifr,sizeof(ifr))<0){
perror(“setsockopt()inf配置失败”);
出口(1);
}
memset(&ifr,0,sizeof(ifr));
snprintf(ifr.ifr_名称,sizeof(ifr.ifr_名称),“r0-eth3”);
if(setsockopt(sock3,SOL_SOCKET,SO_BINDTODEVICE,(void*)和ifr,sizeof(ifr))<0){
perror(“setsockopt()inf配置失败”);
出口(1);
}
printf(“绑定到接口的所有套接字。\n”);
而(1)
{
//设置选择
FD_零(&readfds);
FD_集(sock1和readfds);
FD_集(sock2和readfds);
FD_集(sock3和readfds);
printf(“套接字设置为读取。\n”);
结构timeval tv={2,0};
printf(“开始选择。\n”);
状态=选择(sock3+1和readfds、NULL、NULL和tv);
printf(“状态=%d\n”,状态);
sockaddr中的结构sockaddr_;
socklen\u t socklen=sizeof(sockAddr);
memset(&sockAddr,0,sockLen);
sockAddr.sin_family=AF_INET;
sockAddr.sin\u addr.s\u addr=htonl(INADDR\u ANY);
int-bufLen=0;
//勾选
如果(状态>0){
printf(“状态=%d,准备读取。\n”,状态);
//读取IP数据报(d)
if(FD_ISSET(sock1和readfds)){
printf(“套接字1准备接收。\n”);
printf(“正在尝试接收数据包。\n”);
bufLen=recvfrom(sock1,buffer,65535,0,(结构sockaddr*)和sockaddr,(socklen_t*)和socklen);
printf(“收到的数据包。\n”);
socknum=1;
}
否则如果(FD_ISSET(sock2和readfds)){
printf(“套接字2准备接收。\n”);
printf(“正在尝试接收数据包。\n”);
bufLen=recvfrom(sock2,buffer,65535,0,(结构sockaddr*)和sockaddr,(socklen_t*)和socklen);
printf(“收到的数据包。\n”);
socknum=2;
}
否则如果(FD_ISSET(sock3和readfds)){
printf(“套接字3准备接收。\n”);
printf(“正在尝试接收数据包。\n”);
bufLen=recvfrom(sock3,buffer,65535,0,(结构sockaddr*)和sockaddr,(socklen_t*)和socklen);
printf(“收到的数据包。\n”);
socknum=3;
}
printf(“测试包。\n”);
结构ethhdr*eth=(结构ethhdr*)(缓冲区);
printf(“\nEthernet头\n”);
printf(“\t|-源地址:%.2X-%.2X-%.2X-%.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n”,eth->h_源[0],eth->h_源[1],eth->h_源[2],eth->h_源[3],eth->h_源[4],eth->h_源[5]);
printf(“\t |-目的地址:%.2X-%.2X-%.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 |-协议:%d\n”,eth->h|u协议);
//检查仪表板(e)
无符号短iphdrlen;
源中的结构sockaddr_;
dest中的结构sockaddr_;
结构iphdr*ip=(结构iphdr*)(缓冲区+sizeof(结构ethhdr));
memset(&source,0,sizeof(source));
source.sin\u addr.s\u addr=ip->saddr;
memset(&dest,0,sizeof(dest));
dest.sin\u addr.s\u addr=ip->daddr;
printf(“\t |-Version:%d\n”,(unsigned int)ip->Version);
printf(“\t |-Internet头长度:%d个DWORDS或%d个字节\n”,(无符号整数)ip->ihl,((无符号整数)(ip->ihl))*4);
printf(“\t |-服务类型:%d\n”,(未签名int)ip->tos);
printf(“\t |-总长度:%d字节\n”,ntohs(ip->tot|len));
printf(“\t |-标识:%d\n”,ntohs(ip->id));
printf(“\t |-生存时间:%d\n”,(未签名int)ip->ttl);
printf(“\t |-Protocol:%d\n”,(unsigned int)ip->Protocol);
printf(“\t |-头校验和:%d\n”,ntohs(ip->check));
printf(“\t |-源IP:%s\n”,inet_ntoa(Source.sin_addr));
printf(“\t |-目标IP:%s\n”,inet_ntoa(dest.sin_addr));
printf(“索引=%d\n”,ifreq\u i.ifr\u ifindex);
//从以太网报头中提取地址。
结构sockaddr\u ll addr;
memset(&addr,0,sizeof(struct sockaddr_ll));
addr.sll_family=AF_数据包;
addr.sll\u ifindex=ifr.ifr\u ifindex;
addr.sll_halen=以太地址;
addr.sll_协议=htons(0x0800);
地址sll_addr[0]=eth->h_dest[0];
地址sll_addr[1]=eth->h_dest[1];
地址sll_addr[2]=eth->h_dest[2];
地址sll_addr[3]=eth->h_dest[3];
地址sll_addr[4]=eth->h_dest[4];
地址sll_addr[5]=eth->h_dest[5];
addr.sll_ifindex = ifr.ifr_ifindex;
addr.sll_ifindex = ifreq_i.ifr_ifindex;