2

送信機から受信機にパケットを送信するためにrawソケットを使用しようとしています。Macまたは友人のDell(両方にUbuntu 12.04がインストールされている)に送信機と受信機の両方を展開すると、コードは正常に機能します。送信機と受信機を2つの異なるターミナルウィンドウで実行しましたが、正常に動作します。

しかし、一方のマシンで送信機を実行し、もう一方のマシンで受信機を実行すると、受信機はパケットを受信しません。誰かが問題を指摘できますか?私はソケットプログラミングに非常に慣れていないので、愚かな間違いは許してください。

送信機:

/*sendtoを使用してパケットを送信する関数*/

int SendPacket(int sockaddress,struct packet *mypacket, int packet_len)
{
   int sent= 0;
   if((sent = write(sockaddress, mypacket, packet_len)) != packet_len)
     { return 0; } 
   else
     { return 1; }

}

/ *モニターインターフェイスのrawソケットを作成し、そのソケットをインターフェイスにバインドする関数
* /

 int create_raw_socket(char *dev) 
 {  
struct sockaddr_ll sll;
struct ifreq ifr;
int fd, ifi, rb;

bzero(&sll, sizeof(sll)); 
    bzero(&ifr, sizeof(ifr));

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

assert(fd != -1);

strncpy((char *)ifr.ifr_name, dev, IFNAMSIZ);
ifi = ioctl(fd, SIOCGIFINDEX, &ifr);
assert(ifi != -1);
sll.sll_protocol = htons(ETH_P_ALL);
sll.sll_family = PF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
    sll.sll_pkttype = PACKET_OTHERHOST;
rb = bind(fd, (struct sockaddr *)&sll,sizeof(sll));
assert(rb != -1);

return fd;  
  }

/* 主な機能 */

 int main(int argc, char**argv)
  {
   int x,fd,s; 

    int sockaddress,len;
    char dest_packet[PACKET_LENGTH];
    int count= atoi(argv[2]);
    char ch;
   struct packet mypacket;
   struct ieee80211_radiotap_header ratap_header;
   struct ieee80211_hdr_3addr iee802_header;
   unsigned char addr1[ETH_ALEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; 
   unsigned char addr2[ETH_ALEN] = {0x13,0x22,0x33,0x44,0x55,0x66};
   unsigned char addr3[ETH_ALEN] = {0x13,0x22,0x33,0x44,0x55,0x66};


   /* Radio tap header data */
   ratap_header.it_version = 0x00;
   ratap_header.it_pad = 0x00;
   ratap_header.it_len = 0x06;  
   ratap_header.it_pad2 = 0x00; 
   ratap_header.it_present = 0x8000;

   mypacket.rtap_header = ratap_header;

   /* ieee80211 header data */

    iee802_header.frame_ctl = 0x0801;
    iee802_header.duration_id = 0x0000;
    strcpy(iee802_header.addr1,addr1);
    strcpy(iee802_header.addr2,addr2);
    strcpy(iee802_header.addr3,addr3);
    iee802_header.seq_ctl = 0x1086;

    mypacket.iee802_header=iee802_header;

   /* Payload */

   unsigned char payload[PACKET_LENGTH]="test";
   unsigned char stop_injection[5]="stop";
   strcpy(mypacket.payload , payload);

   len = sizeof(mypacket) ;

   /* Sending the packet over the interface */
   printf("\n Press Y to start packet injection \n");
   while((ch = getchar()) != 'Y');


  while((count--) > 0)
   {

     sockaddress = create_raw_socket(argv[1]);
   if(!SendPacket(sockaddress, &mypacket, len))
     perror("Error sending packet");
   else
     {
     printf("Packet sent successfully with payload : %s\n" , mypacket.payload);

     printf("\n size of the packet being send is %d \n " , len);
     }


   }

  /* Packet to indicate the end of reception */

  strcpy(mypacket.payload , stop_injection);
  len = sizeof(mypacket) ;
  int temp=SendPacket(sockaddress , &mypacket , len);

  close(sockaddress);
  printf("\n End of packet transmission ........................ \n");
  return 0; 
 }

受信機:

int main(int argc, char **argv)
{
 struct sockaddr addr;
 int sock_fd, fromlen,s;
 char buf[PACKET_LENGTH];
 char *dev = argv[1];
 struct packet mypacket;
 struct packet *ptr;
 int recv_count=0;

 sock_fd = create_raw_socket(dev);   /* Creating the raw socket */

 printf("\n Waiting to receive packets ........ \n"); 

 while(1)
  {

  fromlen=sizeof(addr);

  int x= recvfrom(sock_fd,&mypacket,sizeof(struct packet),0,&addr,&fromlen);

  struct sockaddr_ll* temp;
  temp = (struct sockaddr_ll*)(&addr);

  if(temp->sll_pkttype == 4)     
   {
   recv_count++;

   if(strcmp(mypacket.payload , "stop") == 0)
    break; 

   /* Payload received */

   printf("\nPayload  Received from client    :    %s   \n ",  mypacket.payload);

   } 

}
  close(sock_fd);
return 0;

データ構造:

 struct ieee80211_radiotap_header {
unsigned char it_version;
unsigned char it_pad;
uint16_t it_len;    
    uint16_t it_pad2;   
uint32_t it_present;
 };

/* Structure for 80211 header */


struct ieee80211_hdr_3addr {
    uint16_t frame_ctl;
    uint16_t duration_id;
    unsigned char addr1[ETH_ALEN];
    unsigned char addr2[ETH_ALEN];
    unsigned char addr3[ETH_ALEN];
    uint16_t seq_ctl;
} __attribute__ ((packed));


/* Structure of the packet containing the radiotap header, ieee802.11 header and payload 
 */

 struct packet {
   struct ieee80211_radiotap_header rtap_header;
   struct ieee80211_hdr_3addr iee802_header;
   unsigned char payload[30];

 };
4

1 に答える 1

0
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <net/ethernet.h> /* the L2 protocols */
#include <linux/if.h>
#include <linux/if_arp.h>
#include <arpa/inet.h>


#define NIC_NAME "wlan0"


/*our MAC address*/
static uint8_t gu8a_src_mac[6]  = {0x11, 0x22, 0x33, 0x44 0x55, 0x66};

/*other host MAC address*/
static uint8_t gu8a_dest_mac[6] = {0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC};


int32_t get_nic_index (uint8_t *pu8_nic_card_name);

void* sock_recv_thread (void *p_arg);

int
main (void)
{
    struct sockaddr_ll  s_dest_addr;
    int32_t             s32_sock        = -1;
    int32_t             s32_res         = -1;
    pthread_t           ul_recv_thd_id  = -1;
    uint16_t            u16_data_off    = 0;
    uint16_t            u16_i           = 0;
    uint8_t             *pu8a_frame     = NULL;
    uint8_t             *pu8a_data      = NULL;

    printf ("Socket raw test\n");

    (void) memset (&s_dest_addr, 0, sizeof (s_dest_addr));

    pu8a_frame = (uint8_t *) calloc (ETH_FRAME_LEN, 1);

    if( NULL == pu8a_frame )
    {
        printf ("Could not get memory for the transmit frame\n");
        goto LABEL_CLEAN_EXIT;
    }

    u16_data_off = (uint16_t) (ETH_FRAME_LEN - ETH_DATA_LEN);

    pu8a_data = pu8a_frame + u16_data_off;

    s32_sock = socket (AF_PACKET, SOCK_RAW, htons (ETH_P_ALL));

    if( -1 == s32_sock )
    {
        perror ("Could not create the socket");
        goto LABEL_CLEAN_EXIT;
    }

    printf ("Socket created\n");

    fflush (stdout);

    (void) pthread_create (&ul_recv_thd_id, NULL, sock_recv_thread, &s32_sock);

    sleep (1);

    s_dest_addr.sll_family      = AF_PACKET;
    /*we don't use a protocol above ethernet layer, just use anything here*/
    s_dest_addr.sll_protocol    = htons(ETH_P_ALL);
    s_dest_addr.sll_ifindex     = get_nic_index ((uint8_t *) NIC_NAME);
    s_dest_addr.sll_hatype      = ARPHRD_ETHER;
    s_dest_addr.sll_pkttype     = PACKET_OTHERHOST; //PACKET_OUTGOING
    s_dest_addr.sll_halen       = ETH_ALEN;
    /*MAC - begin*/
    s_dest_addr.sll_addr[0]     = gu8a_dest_mac[0];
    s_dest_addr.sll_addr[1]     = gu8a_dest_mac[1];
    s_dest_addr.sll_addr[2]     = gu8a_dest_mac[2];
    s_dest_addr.sll_addr[3]     = gu8a_dest_mac[3];
    s_dest_addr.sll_addr[4]     = gu8a_dest_mac[4];
    s_dest_addr.sll_addr[5]     = gu8a_dest_mac[5];
    /*MAC - end*/
    s_dest_addr.sll_addr[6]     = 0x00;/*not used*/
    s_dest_addr.sll_addr[7]     = 0x00;/*not used*/

    /*set the frame header*/
    (void) memcpy (pu8a_frame, gu8a_dest_mac, ETH_ALEN);
    (void) memcpy (pu8a_frame+ETH_ALEN , gu8a_src_mac, ETH_ALEN);

    printf ("******Sending data using raw socket over '" NIC_NAME "'\n");

    while( 1 )
    {
        (void) memset (&pu8a_data[u16_data_off], '\0', ETH_DATA_LEN);

        (void) snprintf ((char *) &pu8a_data[u16_data_off],
                         ETH_DATA_LEN,
                         "Raw packet test, %d",
                         u16_i++);

        s32_res = sendto (s32_sock,
                          pu8a_frame,
                          ETH_FRAME_LEN,
                          0,
                          (struct sockaddr*)&s_dest_addr,
                          sizeof(s_dest_addr));

        if( -1 == s32_res )
        {
            perror ("Socket send failed");
            goto LABEL_CLEAN_EXIT;
        }

        sleep (1);
    }

    /*printf ("Waiting for receive thread to exit\n");
    pthread_join (ul_recv_thd_id, NULL);*/

LABEL_CLEAN_EXIT:
    if( s32_sock > 0 )
    {
        close (s32_sock);
    }

    printf ("***** Raw Socket test- end\n");

    return EXIT_SUCCESS;
}

void*
sock_recv_thread (void *p_arg)
{
    struct sockaddr_ll  s_src_addr;
    int32_t             s32_sock        = * ((int32_t *)p_arg);
    int32_t             s32_res         = -1;
    uint16_t            u16_data_off    = 0;
    uint8_t             *pu8a_frame     = NULL;

    printf ("Socket receive thread\n");

    u16_data_off = (uint16_t) (ETH_FRAME_LEN - ETH_DATA_LEN);

    pu8a_frame = (uint8_t*) calloc (ETH_FRAME_LEN, 1);

    if( NULL == pu8a_frame )
    {
        printf ("Could not get memory for the receive frame\n");
        goto LABEL_CLEAN_EXIT;
    }

    (void) memset (&s_src_addr, 0, sizeof (s_src_addr));

    s_src_addr.sll_family       = AF_PACKET;
    /*we don't use a protocol above ethernet layer, just use anything here*/
    s_src_addr.sll_protocol     = htons(ETH_P_ALL);
    s_src_addr.sll_ifindex      = get_nic_index ((uint8_t *) NIC_NAME);
    s_src_addr.sll_hatype       = ARPHRD_ETHER;
    s_src_addr.sll_pkttype      = PACKET_HOST;//PACKET_OTHERHOST;
    s_src_addr.sll_halen        = ETH_ALEN;

    s32_res = bind (s32_sock,
                    (struct sockaddr *) &s_src_addr,
                    sizeof(s_src_addr));

    if( -1 == s32_res )
    {
        perror ("Could not bind to the socket");
        goto LABEL_CLEAN_EXIT;
    }

    printf ("Socket bind successful\n");

    while( 1 )
    {
        struct sockaddr_ll  s_sender_addr;
        socklen_t           u32_sender_addr_len = sizeof (s_sender_addr);

        (void) memset (&s_sender_addr, 0, sizeof (s_sender_addr));

        s32_res = recvfrom (s32_sock,
                            pu8a_frame,
                            ETH_FRAME_LEN,
                            0,
                            (struct sockaddr *) &s_sender_addr,
                            &u32_sender_addr_len);

        if( -1 == s32_res )
        {
            perror ("Socket receive failed");
            break;
        }
        else if( s32_res < 0 )
        {
            perror ("Socket receive, error ");
        }
        else
        {
            uint16_t u16_i = 0;

            printf ("Received data from ");

            for( u16_i=0; u16_i<sizeof(s_sender_addr.sll_addr)-2; u16_i++ )
            {
                printf ("%02x:", s_sender_addr.sll_addr[u16_i]);
            }

            printf ("\t");

            printf ("Received data %s\n\n", &pu8a_frame[u16_data_off]);
        }

    }

LABEL_CLEAN_EXIT:
    return (NULL);
}


int32_t
get_nic_index (uint8_t *pu8_nic_card_name)
{
    int32_t         s32_sock_fd     = -1;
    int32_t         s32_res         = -1;
    struct  ifreq   s_ifr;

    (void) memset (&s_ifr, 0, sizeof (s_ifr));

    s32_sock_fd = socket (AF_INET, SOCK_DGRAM, 0);

    if( -1 == s32_sock_fd )
    {
        perror ("get_nic_index(): socket failed");
        goto LABEL_CLEAN_EXIT;
    }

    s_ifr.ifr_addr.sa_family = AF_INET;

    strncpy(s_ifr.ifr_name, (char *) pu8_nic_card_name, IFNAMSIZ);

    s32_res = ioctl(s32_sock_fd, SIOCGIFINDEX, &s_ifr);

    if( -1 == s32_res )
    {
        perror ("get_nic_index(): ioctl failed");
    }

    close (s32_sock_fd);

LABEL_CLEAN_EXIT:
    return (s_ifr.ifr_ifru.ifru_ivalue);
}
于 2014-07-21T07:07:02.563 に答える