免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5922 | 回复: 5
打印 上一主题 下一主题

关于双网卡编程的问题~ [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-20 15:51 |只看该作者 |倒序浏览
小弟想通过Raw套接字实现双网卡下,一个接受数据包,一个发送数据包,但是现在情况是可以接受,发送出现错误...大家看看什么情况啊?
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <netdb.h>
#include <stdlib.h>
#include <assert.h>
#include <netpacket/packet.h>

int main(int argc, char *argv[])
{
    int sock_55;
    int i,j,k,len,n;
    char buffer[1500];
    unsigned char src_mac[6];        /*source mac address*/
    unsigned char dest_mac[6] = {0x00, 0x01, 0x02, 0x92, 0xb1, 0x2a}; /*dest mac adress*/
    //struct sockaddr_in in,from;

    unsigned char *iphead,*ethhead,*data;
    struct ip *ipp;
    struct tcphdr *tcp;
    struct udphdr *udp;
   
   
   
    struct ifreq ifr;
    char *dev;
    struct sockaddr_ll sll,tmp;

    /*create sock */
    if ( (sock_55 = socket(AF_PACKET, SOCK_RAW,htons(ETH_P_ALL)))<0)
    {
        printf("socket error!");
    }
    /*retrieve ethernet interface index*/
    dev = "eth0";
    strncpy ((char *)ifr.ifr_name, dev, sizeof(ifr.ifr_name));
    if (ioctl(sock_55, SIOCGIFINDEX, &ifr) == -1)
        {
        perror("SIOCGIFINDEX");
        exit(1);
     }
    printf("Successfully got interface index: %i\n", ifr.ifr_ifindex);

   /*retrieve corresponding MAC*/
   if (ioctl(sock_55, SIOCGIFHWADDR, &ifr) == -1)
    {
        perror("SIOCGIFINDEX");
        exit(1);
       }
    for (i = 0; i < 6; i++)
    {
        src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
    }
    printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
    src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
        /*prepare sockaddr_ll*/
     memset (&sll, 0, sizeof(sll));
    sll.sll_family = PF_PACKET;
    sll.sll_protocol = htons(ETH_P_IP);   
    sll.sll_ifindex = ifr.ifr_ifindex;               
    sll.sll_hatype = 1;
    sll.sll_pkttype = PACKET_OTHERHOST;
    sll.sll_halen = ETH_ALEN;
    sll.sll_addr[0] = dest_mac[0];
    sll.sll_addr[1] = dest_mac[1];
    sll.sll_addr[2] = dest_mac[2];
    sll.sll_addr[3] = dest_mac[3];
    sll.sll_addr[4] = dest_mac[4];
    sll.sll_addr[5] = dest_mac[5];
    sll.sll_addr[6] = 0x00;
    sll.sll_addr[7] = 0x00;     
     while(1)
        {
         memset(buffer,sizeof(buffer),0);
         n = 0;
         n = recvfrom(sock_55,buffer,sizeof(buffer),0,0,0);
         if (n<42){
            close(sock_55);
             exit(0);
          }
        printf("55 receive %d\n",n);
        
        ipp = (struct ip *)(buffer + 14);
        tcp = (struct tcphdr *)(buffer + 4*ipp->ip_hl + 14);
        data = buffer + 14 + ipp->ip_hl * 4 + tcp->doff * 4;

        memset(&tmp,0,sizeof(struct sockaddr_ll));
        tmp.sll_family = sll.sll_family ;
        tmp.sll_protocol= sll.sll_protocol ;        
        tmp.sll_ifindex = sll.sll_ifindex ;               
        tmp.sll_hatype = sll.sll_hatype ;
        tmp.sll_pkttype = sll.sll_pkttype ;
        tmp.sll_halen = sll.sll_halen ;
        tmp.sll_addr[0] = sll.sll_addr[0] ;
        tmp.sll_addr[1] = sll.sll_addr[1] ;
        tmp.sll_addr[2] = sll.sll_addr[2] ;
        tmp.sll_addr[3] = sll.sll_addr[3] ;
        tmp.sll_addr[4] = sll.sll_addr[4] ;
        tmp.sll_addr[5] = sll.sll_addr[5] ;
        tmp.sll_addr[6] = sll.sll_addr[6] ;
        tmp.sll_addr[7] = sll.sll_addr[7] ;                 
        //modify(buffer);        
        n = 0;
        n = sendto(sock_55,buffer,sizeof(buffer),0,(struct sockaddr *)&tmp,sizeof(struct sockaddr_ll));
        printf("55 send %d\n",n);
    }
}




[ 本帖最后由 sillyaboy 于 2009-6-20 16:40 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-06-21 00:00 |只看该作者
发送不出去包吗?抓包看看

论坛徽章:
0
3 [报告]
发表于 2009-06-21 05:34 |只看该作者
没看出哪里是单独操作某个网卡啊?其实要用RAW SOCKET的话,可以考虑用LIBNET。已经封装好的一个库。
连接:http://old.blog.edu.cn/user1/19948/archives/2006/1074177.shtml

论坛徽章:
0
4 [报告]
发表于 2009-06-26 13:18 |只看该作者
sock_raw,多块网卡要bind一下,就是指定哪块网卡用这个socket

论坛徽章:
0
5 [报告]
发表于 2009-06-28 21:36 |只看该作者
需要bind相关NIC的IP地址

论坛徽章:
0
6 [报告]
发表于 2009-06-29 18:45 |只看该作者

回复 #1 sillyaboy 的帖子

楼主,有一种方法叫“打印错误信息”,还有一种方法叫调试,还有另一种方法要二分打印

在你获取网上的编号之后又使用同一个ifreq获取了一次MAC地址,再之后又想使用第一次获取的网卡索引号,很明显已经错了,用一个错误的索引号发数据当然失败了。

另外:
1. 如果想从一个固定的网卡上收数据应该绑定网卡编号。
2. 想从另一个网卡发数据要使用另一个网卡的编号。
3. 创建socket最好用PF_PACKET,AF_PACKET一般用于填写地址中的sll_family,而且对于RAW的发数据这个没意义。

对于PF_PACKET + RAW,发送只要填写一个网卡索引号就够了。

关于PF_PACKET编程,基本上所有的资料如Manual Page等都讲得不太清楚,网上也大多是那么一两份抄来抄去的。要搞清楚最好直接看内核源代码中相关的实现,不复杂。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP