使用C套接字在接口上回送数据包

时间:2018-01-18 13:35:27

标签: c sockets networking network-programming

我正在尝试环回在网络接口上收到的数据包。因此,对于我在nf2接口中收到的每个数据包,我想通过nf2接口传输相同的数据包。我不想交换地址或nat。我下面是我在网上获得的代码,旨在实现我的目标。

只要我不启用发送部分,我就可以毫无问题地接收数据包。一旦我添加了传输部分 write(sock,buffer,data_size),设计就会无限期地运行。我已经注释掉了Tx部分(在Tx-part Start和Tx-part Stop之间)。

#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>

int main()
{
int saddr_size , data_size, daddr_size, bytes_sent;
struct sockaddr_ll saddr, daddr;
unsigned char *buffer=malloc(65535);
int n = 0;
int count = 0;  

// Opening the socket

int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ; //For receiving
int sock = socket( PF_PACKET , SOCK_RAW , IPPROTO_RAW) ;            //For sending

// Initializing the memory address and variables for the sockets
memset(&saddr, 0, sizeof(struct sockaddr_ll));
saddr.sll_family = AF_PACKET;
saddr.sll_protocol = htons(ETH_P_ALL);
saddr.sll_ifindex = if_nametoindex("nf2");

// Binding the socket to the address
if (bind(sock_raw, (struct sockaddr*) &saddr, sizeof(saddr)) < 0) {
    perror("bind failed\n");
    close(sock_raw);
}

// Initializing the memory address
memset(&daddr, 0, sizeof(struct sockaddr_ll));
daddr.sll_family = AF_PACKET;
daddr.sll_protocol = htons(ETH_P_ALL);
daddr.sll_ifindex = if_nametoindex("nf2");

// Binding the socket to the address
if (bind(sock, (struct sockaddr*) &daddr, sizeof(daddr)) < 0) {
  perror("bind failed\n");
  close(sock);
}

struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "nf2");
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
    perror("bind to nf2");
    }

while(1)
//while((n = read(sock_raw, &saddr, sizeof(&saddr)-1)) > 0)
{
    saddr_size = sizeof (struct sockaddr);
    daddr_size = sizeof (struct sockaddr);
    //Receive a packet
    data_size = recvfrom(sock_raw , buffer , 65536 , 0 ,(struct sockaddr *) &saddr , (socklen_t*)&saddr_size);

    if(data_size <0 )
    {
        printf("Recvfrom error , failed to get packets\n");
        return 1;
    }
    else{
    printf("%d Received %d bytes\n", count, data_size);
    count++;

    // Tx part -starts
    // The following section runs indefinitely

    //Send the same packet out
    //bytes_sent=write(sock,buffer,data_size);
    //printf("Sent %d bytes\n",bytes_sent);
    // if (bytes_sent < 0) {
    //    perror("sendto");
    //    exit(1);
    // }

    // Tx part - ends  
    }
}
close(sock_raw);
return 0;
} 

任何帮助非常感谢

1 个答案:

答案 0 :(得分:0)

问题是您正在接收正在发送的每个数据包,然后再次重新复制它。 IOW:回应你自己。

使用sll_pkttype中的struct sockaddr_ll来区分传出的数据包,然后忽略它们。你可以在你的循环中做这样的事情:

while (1) {
    saddr_size = sizeof (struct sockaddr_ll);
    //Receive a packet
    data_size = recvfrom(sock_raw, buffer, 65536, 0, (struct sockaddr *)&saddr, &saddr_size);

    if (saddr.sll_pkttype == PACKET_OUTGOING) {
        printf("Ignoring outgoing packet\n");
        continue;
    }

有关数据包类型的说明,请参阅packet(7)