簡體   English   中英

C程序通過另一個接口接收和發送相同的數據包

[英]C Program to receive and send the same packets out over another interface

我有一個帶有兩個物理接口的linux系統。 我需要在一個接口上截取(讀取)傳入的數據包,讀取(或處理)數據,然后通過另一個接口將其發送出去,就像中間人一樣。 我能夠從數據包中提取所有標頭字段和有效載荷數據,但無法再次將其重新放置在線路上。 如何通過其他接口發送數據包?

// All #includes 

struct sockaddr_in source,dest;
int i,j,k;
int main()
{
    int saddr_size , data_size;
    struct sockaddr_in saddr;
    unsigned char *buffer=malloc(65535);


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

     if(sock_raw < 0)
        perror("setsockopt");

    setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );

    if(sock_raw < 0)
    {
        perror("Socket Error");
        return 1;
    }

    while(1)
    {
        saddr_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("Received %d bytes\n",data_size);

        //Huge code to process the packet

        //Send it out through "eth1" here 

        }
    }
    close(sock_raw);
    return 0;
}

只要假設UDP或ICMP數據包使它更容易解釋(也許使用簡單的“ sendto”功能)即可-我可以處理排序。 不用擔心預定的目的地,我只想將數據包放回網絡上-交付並不重要。

編輯1

如果執行此操作,則會出現運行時錯誤,提示“參數無效”。 我發送緩沖區還是“ Hello World”都沒有關系。

bytes_sent=sendto(sock_raw, buffer, 65536, 0,(struct sockaddr *) &saddr ,saddr_size);
if (bytes_sent < 0) {
    perror("sendto");
    exit(1);
    }

編輯2 :讓我簡化一點-我有兩個管道A和B。球從A滾入,我收到了它們。 我只想將它們放入管道B中,然后按途發送。 以太網橋以類似的方式工作-只是通過所有涉及的接口發送所有數據包。 如果我不必從數據包頭中獲取一些基本信息,我肯定會使用網橋。 而且我也不擅長修改內核橋驅動程序。

編輯3 :我將最后一次嘗試另一個問題。 如果我收到了一個完整的原始數據包,其中的標頭以及所有內容中都包含了源/目標地址,那么我該如何簡單地使用sendto將其發送到任何地方(我不在乎)? 我應該在sendto調用中將任何信息添加到“ struct sockaddr”中,還是可以簡單地使用與recvfrom調用中相同的信息?

我終於得到它的工作! 我能夠將eth0上收到的數據包發送到eth1上,而沒有發生變化。

更正:

  1. 盡管不建議使用“ write”而不是“ sendto”。
  2. 僅用於發送的新套接字。
  3. 似乎使用setsockopt的SO_BINDTODEVICE無法正常工作,因此我不得不使用bind函數將套接字綁定到接口。
  4. struct sockaddr_instruct sockaddr_ll

我急忙將其放在一起,以便其中可能有一些多余的行。 我不知道daddr是否甚至是必需品,但它確實可以使用。 這是完整的代碼:

// All #includes 

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

    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

    memset(&saddr, 0, sizeof(struct sockaddr_ll));
    saddr.sll_family = AF_PACKET;
    saddr.sll_protocol = htons(ETH_P_ALL);
    saddr.sll_ifindex = if_nametoindex("eth0");
    if (bind(sock_raw, (struct sockaddr*) &saddr, sizeof(saddr)) < 0) {
        perror("bind failed\n");
        close(sock_raw);
    }

    memset(&daddr, 0, sizeof(struct sockaddr_ll));
    daddr.sll_family = AF_PACKET;
    daddr.sll_protocol = htons(ETH_P_ALL);
    daddr.sll_ifindex = if_nametoindex("eth1");
    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), "eth1");
    if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
        perror("bind to eth1");
        }

    while(1)
    {
        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("Received %d bytes\n",data_size);

        //Huge code to process the packet (optional)

        //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);
         }

        }
    }
    close(sock_raw);
    return 0;
}

感謝所有回應。

關於編輯2:如果可以選擇設置橋接設備,為什么不可以只在橋接設備上使用嗅探工具(tcpdump,wireshark,基於libpcap的自己的創建工具),而不必擔心自己轉發數據包?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM