2012-05-30 3 views
1

Я пытаюсь использовать сырые сокеты для отправки пакетов с передатчика на приемник. Код отлично работает, когда я использую как передатчик, так и приемник на моем Mac или моих друзей Dell (Ubuntu 12.04 установлен на обоих). Я запускаю передатчик и приемник в двух разных терминальных окнах, и он работает нормально.Передача сырых сокетов через Wi-Fi - приемник не может принимать пакеты

Но когда я запускаю передатчик на одной машине, а приемник - на другом, приемник не получает никаких пакетов. Может ли кто-нибудь указать на проблему? Я очень новичок в программировании сокетов, поэтому прошу простить любые глупые ошибки.

Передатчик:

/* Функция для отправки пакета, используя 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; } 

} 

/* Функция для создания сокетов для интерфейса монитора, а также связать сокет
интерфейсного */

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]; 

}; 

ответ

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