[英]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上,而沒有發生變化。
更正:
我急忙將其放在一起,以便其中可能有一些多余的行。 我不知道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.