我正在玩STP数据包并编写程序原始套接字来修改它们 . 阅读fropm eth0发送到eth1 . 系统是ubuntu 14.10 / Kernel 3.somewhat . 使用Karat的其他计算机生成数据包,Wireshark也运行此接口 . 注入一个数据包,并在第一次运行recvfrom后没有停止 . 从eth0读取相同的数据包并将其发送到eth1 . 调试会话???????最终版本应该从eth0读取所有帧,转发所有帧并将所有STP放入“单播隧道” - 读取eth1 eth1帧,转发eth0和“解包”特殊“隧道”帧 .

我在这里放了一些代码:

typedef struct {
            unsigned char mac[6];
            unsigned char ifName[IFNAMSIZ];
            int sockfd;
            struct sockaddr_ll socketaddress;
            struct ifreq ifopts;                    /* set promiscuous mode */

    } interfaces;

    extern int errno;

    nt i;
    int sockopt;
    ssize_t numbytes;

    unsigned char InBuf[BUF_SIZ];   // this is the frame buffer

    interfaces in,out;          // interface struct var's

   unsigned char PeerMac[6]; // Peer mac for simple Tunnel
   unsigned char myMac[6];  // my Peer address
   int c;


    unsigned char IEEE802_1q_STP[6] =  {0x01, 0x80, 0xC2, 0x00, 0x00, 0x0d};    


    /* Header structures */
    struct ether_header *InTunnelPtr = (struct ether_header*) InBuf;
    struct ether_header *InPtr = (struct ether_header*) (InBuf+14);  
/ First Do it for IN_IF
    memset(&in.socketaddress, 0, sizeof(struct sockaddr_ll));  // clear Var
    in.socketaddress.sll_family = PF_PACKET;
    in.socketaddress.sll_protocol = htons(ETH_P_ALL); // just dummy, don't needed
    in.socketaddress.sll_halen = ETH_ALEN;


/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
    if ((in.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
        perror("listener: socket");
        return -1;
    }

    memset (&in.ifopts, 0, sizeof (struct ifreq));

// Set interface to promiscuous mode - do we need to do this every time?
    strncpy(in.ifopts.ifr_name, in.ifName, IFNAMSIZ-1); // set if name
    ioctl(in.sockfd, SIOCGIFFLAGS, &in.ifopts);   // get current flags
    in.ifopts.ifr_flags |= IFF_PROMISC;         // set promiscuous mode
    ioctl(in.sockfd, SIOCSIFFLAGS, &in.ifopts);  // write flags
    // get my mac addr
    //ioctl(in.sockfd,SIOCGIFHWADDR,&in.ifopts);
    //memcpy(in.mac,in.ifopts.ifr_hwaddr.sa_data,ETH_ALEN);

// find Interface index
    strncpy(in.ifopts.ifr_name, in.ifName, IFNAMSIZ-1);  //
    ioctl(in.sockfd, SIOCGIFINDEX, &in.ifopts);          // get if index

    in.socketaddress.sll_ifindex=in.ifopts.ifr_ifindex;  // set index to sockaddr_ll

// Allow the socket to be reused - incase connection is closed prematurely
    if (setsockopt(in.sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        close(in.sockfd);
        exit(EXIT_FAILURE);
    }
// Bind to device
    if (setsockopt(in.sockfd, SOL_SOCKET, SO_BINDTODEVICE, in.ifName, IFNAMSIZ-1) == -1) {
        perror("SO_BINDTODEVICE");
        close(in.sockfd);
        exit(EXIT_FAILURE);
    }
// -----------------------------------
// Now, do the OUT Interface
// -----------------------------------
    memset(&out.socketaddress, 0, sizeof(struct sockaddr_ll));  // clear Var
    out.socketaddress.sll_family = PF_PACKET;
    out.socketaddress.sll_protocol = htons(ETH_P_ALL); // just dummy, don't needed
    out.socketaddress.sll_halen = ETH_ALEN;


// Open PF_PACKET socket, listening for EtherType ETHER_TYPE */
    if ((out.sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
        perror("listener: socket");
        exit(EXIT_FAILURE);
    }

    memset (&out.ifopts, 0, sizeof (struct ifreq));

// Set interface to promiscuous mode - do we need to do this every time? */
    strncpy(out.ifopts.ifr_name, out.ifName, IFNAMSIZ-1);
    ioctl(out.sockfd, SIOCGIFFLAGS, &out.ifopts);
    out.ifopts.ifr_flags |= IFF_PROMISC;
    ioctl(out.sockfd, SIOCSIFFLAGS, &out.ifopts);
    // get my mac addr
    // ioctl(out.sockfd,SIOCGIFHWADDR,&out.ifopts);
    // memcpy(out.mac, out.ifopts.ifr_hwaddr.sa_data, ETH_ALEN);

// find Interface index */
    strncpy(out.ifopts.ifr_name, out.ifName, IFNAMSIZ-1);
    ioctl(out.sockfd, SIOCGIFINDEX, &out.ifopts);

    out.socketaddress.sll_ifindex=out.ifopts.ifr_ifindex;

// Allow the socket to be reused - incase connection is closed prematurely */
    if (setsockopt(out.sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        close(out.sockfd);
        exit(EXIT_FAILURE);
    }
// Bind to device */
if (setsockopt(out.sockfd, SOL_SOCKET, SO_BINDTODEVICE, out.ifName, IFNAMSIZ-1) == -1) {
        perror("SO_BINDTODEVICE");
        close(out.sockfd);
        exit(EXIT_FAILURE);
    }

// Working LOOP
// interface in
// buffer structur
//   ------------------------------------------------------------
//   | dest  | source | len |   recv packet                     |
//   ------------------------------------------------------------
//   ^InTunnelPtr           ^ InPtr
repeat:
    numbytes=0;

    numbytes = recvfrom(in.sockfd, &InBuf[14], BUF_SIZ, 0, NULL, NULL) ;


/* let the game begin */
// test multicast addresses here
// and do something:-)

    if (numbytes > 0) {
 /*     if (memcmp(InPtr->ether_dhost,CISCOSHARED_STP, ETH_ALEN) == 0) {
            if (debug == 1) printf("Cisco Shard stp found");
        }
        else if (memcmp(InPtr->ether_dhost,IEEE802_1AD_STP, ETH_ALEN)==0) {
            if ( debug == 1) printf("IEEE802.1AD stp found");
        }
        else */

        if (memcmp(InPtr->ether_dhost,IEEE802_1D_STP, ETH_ALEN)==0)   // this tunnel
        {
            if (debug == 1) printf("IEEE802.1D stp for tunnel eth1\n");

            memcpy(InTunnelPtr->ether_dhost,PeerMac , ETH_ALEN);  // Copy PeerMac to destination  address
            memcpy(InTunnelPtr->ether_shost,myMac , ETH_ALEN);    // Copy my peer mac to source address
            InTunnelPtr->ether_type=numbytes+14;                                            // set tunnel header len

//          if (numbytes = sendto(out.sockfd, &InBuf[0] , (numbytes+14), 0,(struct sockaddr_ll *)&out.socketaddress,sizeof(out.socketaddress)) < 0)
            i = numbytes+14;

            if (numbytes = sendall_eth1(out.sockfd, &InBuf[0] , &i, &out.socketaddress, sizeof(out.socketaddress)) < 0)
            {
                printf("send error %s \n",strerror(errno));
            }

        } else {                            // send untunneled packet out

            if (debug == 1) printf ("send untunneled packet eth1\n");
//          if (numbytes = sendto(out.sockfd, &InBuf[14], numbytes, 0,(struct sockaddr_ll *)&out.socketaddress,sizeof(out.socketaddress)) < 0)
            i = numbytes;

            if (numbytes =
                  sendall_eth1(out.sockfd, &InBuf[14], &i, &out.socketaddress, sizeof(out.socketaddress)) < 0)
            {
                printf("send error %s \n",strerror(errno));
            }
        }
    }

goto repeat