使用的setsockopt()系统与设备绑定原始套接字是不是在Fedora Core 6个工作(2.6.18-1.2798.fc6) [英] Raw socket with device bind using setsockopt() system is not working in Fedora core 6(2.6.18-1.2798.fc6)

查看:189
本文介绍了使用的setsockopt()系统与设备绑定原始套接字是不是在Fedora Core 6个工作(2.6.18-1.2798.fc6)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

在下面的示例code,我们与绑定的eth0生袜子。但在运行该程序
原料袜子recvfrom的接收距离为eth0和放包; eth1的同一台机器(xx_86)上。
这是我不清楚为什么,可以帮助人们在这个问题上。
我希望setsockopt的工作不正常
操作系统:Fedora的核心6(2.6.18-1.2798.fc6)

SAMPE code:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&; Linux的/ if_ether.h>
#包括LT&;净/ if.h中>
#包括LT&; Linux的/ filter.h>
#包括LT&; SYS / ioctl.h>
#包括LT&;&string.h中GT;
#包括LT&; ARPA / inet.h>INT主(INT ARGC,字符** argv的){
INT袜子,我;
无符号字符缓冲区[2048];
unsigned char型tbuff [2048];
无符号字符* iphead,* ethhead,* PHEAD;
结构的ifreq ethreq;//注意:使用TCPDUMP来构建滤波器阵列。
//设置过滤器来嗅探端口仅443
// $ sudo的tcpdump的-dd端口443//为原料的eth0 recvfrom的如果((袜子=插座(PF_PACKET,SOCK_RAW,htons(ETH_P_IP)))== -1){
    PERROR(插座);
    出口(1);
}
  //设置网卡promiscuos
函数strncpy(ethreq.ifr_name,eth0的,IFNAMSIZ);
如果(的ioctl(袜子,SIOCGIFFLAGS,&安培; ethreq)== -1){
    PERROR(的ioctl);
    关闭(袜子);
    出口(1);
}
ethreq.ifr_flags | = IFF_PROMISC;
如果(的ioctl(袜子,SIOCSIFFLAGS,&安培; ethreq)== -1){
    PERROR(的ioctl);
    关闭(袜子);
    出口(1);
}//绑定为eth0袜子 结构的ifreq接口;
 memset的(安培;接口,0,sizeof的(接口));
 函数strncpy(Interface.ifr_ifrn.ifrn_name,eth0的,IFNAMSIZ);
 如果(setsockopt的(袜子,SOL_SOCKET,SO_BINDTODEVICE,&安培;接口方面,的sizeof(接口))小于0){接近(袜子); }
    //打开SENDTO RAW套接 INT S =插座(PF_INET,SOCK_RAW,IPPROTO_RAW);     结构SOCKADDR_IN罪。
     memset的(安培;罪,0,sizeof的(罪));
     sin.sin_family = AF_INET;
     sin.sin_port = htons(0);
     sin.sin_addr.s_addr = inet_addr(10.3.161.104);  //通知籽粒不填IP和传输首     诠释1 = 1;
     const int的* VAL =安培;之一;
     如果(setsockopt的(S,IPPROTO_IP,IP_HDRINCL,缬氨酸,的sizeof(一个))小于0)
     的printf(警告:不能设置HDRINCL \\ n!);     //绑定eth0的袜子描述     结构的ifreq接口1;
     memset的(安培;接口1,0,sizeof的(接口1));
     函数strncpy(Interface1.ifr_ifrn.ifrn_name,eth0的,IFNAMSIZ);
     如果(setsockopt的(S,SOL_SOCKET,SO_BINDTODEVICE,&放大器;接口1,sizeof的(接口1))≤; 0){关闭(多个); }
而(1){
    的printf(---------------------- \\ n);
    I = recvfrom的(袜子,缓冲器,的sizeof(缓冲液),0,NULL,NULL);
    的printf(%d字节读\\ N,I);    //检查头大小:以太网= 14,IP = 20,TCP = 8(总和= 42)
    如果(ⅰ&下; 42){
        PERROR(recvfrom的());
        的printf(不完整的数据包(错误为%d)\\ n,错误号);
        关闭(袜子);
        出口(0);
    }    PHEAD =缓冲区+ 14; //(跳过以太网帧头)
    的memcpy(tbuff,PHEAD,I-14);
    iphead = tbuff;
    如果(* iphead ==×45){
        INT ptrindex = iphead [9];
        开关(ptrindex){         情况1:
                的printf(运输通讯协定是:ICMP \\ n);
                打破;
         案例2:
                的printf(运输protol是:IGMP \\ n);
                打破;
         情况6:
               的printf(传输协议是:TCP \\ n);
               打破;
         案例17:
               的printf(传输协议是:UDP \\ n);
               打破;
         案例103:
              的printf(传输协议是:PIM \\ n);
              打破;
         默认:
             的printf(传输协议为:%d个\\ N,iphead [9]);
        }
        //的printf(%d个,* ptrindex);
       //的printf(\\ n传输协议是:%U \\ N,iphead [9]);
        的printf(源地址:%D%D,端口:%d个\\ N,
            iphead [12],iphead [13],iphead [14],iphead [15],(iphead [20]&下;&下; 8)+ iphead [21]);
        的printf(目的地地址:。。%D%D,端口数:%d \\ n,
            iphead [16],iphead [17],iphead [18],iphead [19],(iphead [22]&下;&下; 8)+ iphead [23]);
     如果(SENDTO(S,tbuff,I-14,0,(结构sockaddr *)及罪的sizeof(罪))小于0)
      的printf(错误。\\ n);     其他{printf的(\\ n该接收的数据包被发送\\ n);}     memset的(缓冲液,0,sizeof的(缓冲液));
     memset的(tbuff,0,sizeof的(tbuff));    }
   其他{printf的(非IP收到了);}    }
       关闭(袜子);
}


解决方案

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


  

SO_BINDTODEVICE


  
  

绑定这个套接字像eth0的特定设备,如通过接口名指定。如果该名称是空字符串或选项长度为零,灯座装置结合被除去。传递的选项是一个可变长度的空值终止的接口名字符串IFNAMSIZ的最大尺寸。如果一个套接字绑定到一个接口,只能从特定接口接收的数据包通过套接字进行处理。请注意,这仅适用于一些套接字类型,特别是AF_INET插座。 它不支持分组插座(使用正常绑定(2))


所以,尽量绑定来代替。

Please any one could help on this issue. Please

In the below sample code,we had bind raw sock with eth0. but while running the program the recvfrom of raw sock is receiving packets from eth0 & eth1 on same machine(xx_86). It is not clear to me why,could help one on this issue. I hope the setsockopt is not working properly OS: Fedora core 6(2.6.18-1.2798.fc6)

Sampe code:

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

解决方案

In the linux man page (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).

So, try the bind instead.

这篇关于使用的setsockopt()系统与设备绑定原始套接字是不是在Fedora Core 6个工作(2.6.18-1.2798.fc6)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆