gpt4 book ai didi

c - 使用 setsockopt() 系统绑定(bind)设备的原始套接字在 Fedora 核心 6 (2.6.18-1.2798.fc6) 中不起作用

转载 作者:太空狗 更新时间:2023-10-29 15:49:13 24 4
gpt4 key购买 nike

请任何人帮助解决这个问题。请

在下面的示例代码中,我们将 raw sock 绑定(bind)到 eth0。但是在运行程序时raw sock 的 recvfrom 正在从同一台机器 (xx_86) 上的 eth0 和 eth1 接收数据包。我不清楚为什么,可以帮助解决这个问题。我希望 setsockopt 不能正常工作操作系统:Fedora core 6(2.6.18-1.2798.fc6)

示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <linux/filter.h>
#include <sys/ioctl.h>
#include <string.h>
#include <arpa/inet.h>

int main(int argc, char **argv) {
int sock, i;
unsigned char buffer[2048];
unsigned char tbuff[2048];
unsigned char *iphead, *ethhead,*phead;
struct ifreq ethreq;

// NOTE: use TCPDUMP to build the filter array.
// set filter to sniff only port 443
// $ sudo tcpdump -dd port 443

// raw for recvfrom eth0

if ((sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP))) == -1) {
perror("socket");
exit(1);
}
// set network card to promiscuos
strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ);
if (ioctl(sock,SIOCGIFFLAGS, &ethreq) == -1) {
perror("ioctl");
close(sock);
exit(1);
}
ethreq.ifr_flags |= IFF_PROMISC;
if (ioctl(sock, SIOCSIFFLAGS, &ethreq) == -1) {
perror("ioctl");
close(sock);
exit(1);
}

//bind to sock with eth0

struct ifreq Interface;
memset(&Interface, 0, sizeof(Interface));
strncpy(Interface.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &Interface, sizeof(Interface)) < 0) { close(sock); }


//open the RAW socket for sendto

int s = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);

struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(0);
sin.sin_addr.s_addr = inet_addr ("10.3.161.104");

// inform kernal don't fill IP and Transport header

int one = 1;
const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
printf ("Warning: Cannot set HDRINCL!\n");

//bind the sock descriptor with eth0

struct ifreq Interface1;
memset(&Interface1, 0, sizeof(Interface1));
strncpy(Interface1.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &Interface1, sizeof(Interface1)) < 0) { close(s); }


while (1) {
printf("----------------------\n");
i = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL);
printf("%d bytes read\n", i);

// check header size: Ethernet = 14, IP = 20, TCP = 8 (sum = 42)
if (i < 42) {
perror("recvfrom():");
printf("Incomplete packet (errno is %d)\n", errno);
close(sock);
exit(0);
}

phead = buffer + 14; // (skip ethernet header)
memcpy(tbuff,phead,i-14);
iphead=tbuff;
if (*iphead == 0x45) {
int ptrindex= iphead[9];
switch(ptrindex){

case 1:
printf("The transport protocl is:ICMP\n");
break;
case 2:
printf("The transport protol is:IGMP\n");
break;
case 6:
printf("The transport protocol is:TCP\n");
break;
case 17:
printf("The transport protocol is:UDP\n");
break;
case 103:
printf("The transport protocol is:PIM\n");
break;
default:
printf("The transport protocol is:%d\n",iphead[9]);
}
//printf("%d",*ptrindex);
// printf("\n The transport protocol is :%u\n",iphead[9]);
printf("Source Address: %d.%d.%d.%d, Port: %d\n",
iphead[12], iphead[13], iphead[14], iphead[15], (iphead[20] << 8) + iphead[21]);
printf("Dest Address: %d.%d.%d.%d, Port: %d\n",
iphead[16], iphead[17], iphead[18], iphead[19], (iphead[22] << 8) + iphead[23]);


if(sendto(s,tbuff,i-14,0,(struct sockaddr *)&sin,sizeof(sin))<0)
printf("error\n");

else{printf("\nThe received packet is send\n");}

memset(buffer,0,sizeof(buffer));
memset(tbuff,0,sizeof(tbuff));

}
else{ printf("The non ip had received");}

}
close(sock);
}

最佳答案

在 linux 手册页 (http://linux.die.net/man/7/socket) 中:

SO_BINDTODEVICE

Bind this socket to a particular device like "eth0", as specified in the passed interface name. If the name is an empty string or the option length is zero, the socket device binding is removed. The passed option is a variable-length null-terminated interface name string with the maximum size of IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this only works for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(2) there).

所以,试试绑定(bind)吧。

关于c - 使用 setsockopt() 系统绑定(bind)设备的原始套接字在 Fedora 核心 6 (2.6.18-1.2798.fc6) 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9919989/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com