列出C程序中的多个接口

时间:2017-10-23 16:25:56

标签: c sockets

我有一个程序,我想转发来自一个接口(VxBridge)的数据包&在另一个接口上发送它(ens3: - 列出原始套接字),反之亦然。

虽然我的程序监听3个接口

1. VxBridge --> Listing on port 1702
2. ens3 --> listen raw interface
3. tap interface --> tun tap interface

来自ens3< - >的数据包VxBridge

问题: - 如果我在ens3上运行Wireshark列表,那么程序运行正常。 如果wireshark停止,则程序不会监听ens3上的数据包。下面是程序的代码片段。 另外我认为它与select()函数有关,在那里等待I / O事件发生。

我知道我在做一些非常错误的事情。任何重定向帮助将不胜感激。 以下是程序: -

main(int argc, char **argv)
{
    struct sockaddr_in addr;
    struct sockaddr_ll daddr;
    fd_set      rfds;
    fd_set          hfds;
    int     cc,ccd;
    struct sockaddr_in from;
    size_t      fromlen;
    int     fdmax;
    int     i;
    char*  newframe=NULL;
    int fdcounter =0;
    char            *vb = NULL; 
     int vxSocketfdSet,hwSocketfdSet,tapSocketfdSet;
     vxSocketfdSet= hwSocketfdSet=tapSocketfdSet=0;

        // Open sockets for L2 device 
      if (send_to_hw){
         if ( ( destsock_fd = socket( PF_PACKET , SOCK_RAW , IPPROTO_RAW) ) < 0){
           perror("destsocket creation failed exit");
                exit(1);
           }

            global_fd[fdcounter]=destsock_fd;
             fdcounter++;
        } 

          memset(&daddr, 0, sizeof(struct sockaddr_ll));
          daddr.sll_family = AF_PACKET;
          daddr.sll_protocol = htons(ETH_P_ALL);
          daddr.sll_ifindex = if_nametoindex("ens3");
          if (bind(destsock_fd, (struct sockaddr*) &daddr, sizeof(daddr)) < 0) {
                  printf(" ens3 bind failed\n");
                   close(destsock_fd);
           }

          struct ifreq ifr;
          memset(&ifr, 0, sizeof(ifr));
          snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "ens3");
          if (setsockopt(destsock_fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0)       {
                       printf("setsockopt to ens3 failed");
          }

    /* Open a socket for receiving frames from the Bridge, and forwarding to other   l2fwd instances of remote host. */
    if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("socket");
        exit(1);
    }
        global_fd[fdcounter]=sock_fd;

    if (vb != NULL)
    {
        /* create a TAP interface and attach to virtual bridge */
        if ((tap_fd = tap_alloc_via_tun_helper(argv[tap_ip_arg], vb)) < 0)      {
            exit(1);
        }
             global_fd[fdcounter]=tap_fd;
              fdcounter++;

    }


    memset(&addr, '\0', sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(DE);

    if (bind(sock_fd, (void *) &addr, sizeof(addr)) < 0) {
        perror("bind");
        exit(1);
    }

    write(1, "> ", 2);


    if (pcap)
        tv_wait = &pcap_flush_delay;

    for (;;) {
        FD_ZERO(&rfds);
        fdmax = 0;

                for ( i =0;i<=fdcounter;i++){
                    FD_SET(global_fd[i], &rfds);
                    if (global_fd[i] > fdmax)
                         fdmax = global_fd[i];
                }
        if (select(fdmax + 1, &rfds, 0, 0, tv_wait) < 0) {
            perror("select");
            continue;
        }

                  for (i = 0;i <= fdcounter; i++)
                    {
                     if (FD_ISSET(global_fd[i], &rfds)) {
                       printf ("\nfdset value is %d  &&& %d\n",i,global_fd[i]);             
                       if (i==0) 
                       {
                        printf("hw set ");
                        hwSocketfdSet = 1;
                        destsock_fd=global_fd[i];
                       }
                       else if (i==1){
                        printf ("vx Set x");
                        vxSocketfdSet = 1;
                        sock_fd=global_fd[i];
                       } 
                       else if (i ==2){
                         tapSocketfdSet = 1;
                          tap_fd=global_fd[i];
                       }
                     break;
                   }
                }


                if (vxSocketfdSet){ 
            fromlen = sizeof(from);
            cc = recvfrom(sock_fd, buf, sizeof(buf), 0, (void *) &from, &fromlen);

            if (cc < 0) {
                perror("recvfrom");
                continue;
            }

                      printf("\nvx frame buf\n");
                        tempFrom = &from;                       
            forward(buf, cc, &from,0);
        }
        if (tapSocketfdSet){
                      printf("tap frame received");
            /* Ethernet frame received from local XC. */
            if ((cc = read(tap_fd, buf, sizeof(buf))) < 0) {
                perror("read");
                continue;
            }
            forward(buf, cc, NULL,0);
        }

        if (hwSocketfdSet){                
                 printf ("Packet received on ens3 header buffer\n");

            if ((ccd = read(destsock_fd, hbuf, sizeof(hbuf))) < 0) {
                                 printf ("error reading");
                perror("read");
                continue;
            }
                      if (headerbuff != NULL && tempFrom != NULL)
                      {
                         printf("headerbuff =%u\n",headerbuff);
                         printf("headerbuff+ACTUAL_PAYLOAD_OFFSET %u\n",headerbuff+ACTUAL_PAYLOAD_OFFSET);
                         memcpy(headerbuff+ACTUAL_PAYLOAD_OFFSET,hbuf,ccd+ACTUAL_PAYLOAD_OFFSET);
                         newframe=headerbuff;

                         // printing packet with raw buffer  

 //   weird logic is used don't try to understand this one. 
//   forward(headerbuff, ccd+ACTUAL_PAYLOAD_OFFSET,tempFrom,1);

                      }
                    }
         vxSocketfdSet=hwSocketfdSet=tapSocketfdSet=0;
    }
}

1 个答案:

答案 0 :(得分:1)

在接口上启用混杂模式允许它接收任何地址的数据包。否则,接口会忽略外部地址的数据包。为此,请将flags参数中的IFF_PROMISC位设置为SIOCSIFFLAGS ioctl调用。

不要忘记在程序结束时将其关闭。