2013-05-23 7 views
13

मैं प्राप्त करते हैं और लिनक्स (Ubuntu) में सी प्रोग्रामिंग का उपयोग कर एआरपी पैकेट भेजने
मेरे कार्यक्रम ठीक काम करता है (यानी किसी भी त्रुटि के बिना चलाता है) करने के लिए कोशिश कर रहा हूँ का उपयोग कर उत्तर देते हैं, लेकिन मुझे लगता है पैकेट का पता लगाने नहीं कर सकते Wireshark का उपयोग कर।एआरपी अनुरोध और ग सॉकेट प्रोग्रामिंग

स्रोत कोड:

#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/time.h> 

#include <asm/types.h> 

#include <math.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 

#include <linux/if_packet.h> 
#include <linux/if_ether.h> 
#include <linux/if_arp.h> 

#define BUF_SIZE 42 
#define DEVICE "eth0" 
#define ETH_P_NULL 0x0 
#define ETH_MAC_LEN ETH_ALEN 
#define ETH_ARP 0x0806 

int s = 0; /*Socketdescriptor*/ 
void* buffer = NULL; 
long total_packets = 0; 
long answered_packets = 0; 

void sigint(int signum); 

struct __attribute__((packed)) arp_header 
{ 
    unsigned short arp_hd; 
    unsigned short arp_pr; 
    unsigned char arp_hdl; 
    unsigned char arp_prl; 
    unsigned short arp_op; 
    unsigned char arp_sha[6]; 
    unsigned char arp_spa[4]; 
    unsigned char arp_dha[6]; 
    unsigned char arp_dpa[4]; 
}; 
int main(void) { 
    buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/ 
    unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/ 
    struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to 
                ethernet header*/ 
    unsigned char* arphead = buffer + 14; 
    struct arp_header *ah; 
    unsigned char src_mac[6]; /*our MAC address*/ 

    struct ifreq ifr; 
    struct sockaddr_ll socket_address; 
    int ifindex = 0;  /*Ethernet Interface index*/ 
    int i; 
    int length; /*length of received packet*/ 
    int sent; 

    printf("Server started, entering initialiation phase...\n"); 

    /*open socket*/ 
    s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
    if (s == -1) { 
     perror("socket():"); 
     exit(1); 
    } 
    printf("Successfully opened socket: %i\n", s); 

    /*retrieve ethernet interface index*/ 
    strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); 
    if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) { 
     perror("SIOCGIFINDEX"); 
     exit(1); 
    } 
    ifindex = ifr.ifr_ifindex; 
    printf("Successfully got interface index: %i\n", ifindex); 

    /*retrieve corresponding MAC*/ 
    if (ioctl(s, 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*/ 
    socket_address.sll_family = PF_PACKET; 
    socket_address.sll_protocol = htons(ETH_P_IP); 
    socket_address.sll_ifindex = ifindex; 
    socket_address.sll_hatype = ARPHRD_ETHER; 
    socket_address.sll_pkttype = PACKET_OTHERHOST; 
    socket_address.sll_halen = 0; 
    socket_address.sll_addr[6] = 0x00; 
    socket_address.sll_addr[7] = 0x00; 
    /*establish signal handler*/ 
    signal(SIGINT, sigint); 
    printf("Successfully established signal handler for SIGINT\n"); 
    printf("We are in production state, waiting for incoming packets....\n"); 

    while (1) { 
     /*Wait for incoming packet...*/ 
     length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL); 
     if (length == -1) 
     { 
      perror("recvfrom():"); 
      exit(1); 
     } 
     if(htons(eh->h_proto) == 0x806) 
     { 

      unsigned char buf_arp_dha[6]; 
      unsigned char buf_arp_dpa[4]; 

      ah = (struct arp_header *)arphead; 
      if(htons(ah->arp_op) != 0x0001) 
       continue; 
      printf("buffer is---------------- %s \n",(char*)ah); 
      printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr); 
      printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl); 
      printf("OPERATION : %x \n", ah->arp_op); 
      printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       ah->arp_sha[0], 
       ah->arp_sha[1], 
       ah->arp_sha[2], 
       ah->arp_sha[3], 
       ah->arp_sha[4], 
       ah->arp_sha[5] 
      ); 
      printf("SENDER IP address: %02d:%02d:%02d:%02d\n", 
       ah->arp_spa[0], 
       ah->arp_spa[1], 
       ah->arp_spa[2], 
       ah->arp_spa[3] 
      ); 
      if(ah->arp_spa[0]==10&&ah->arp_spa[1]==00&&ah->arp_spa[2]==00&&ah->arp_spa[3]==01) 
      { 
       printf("Sender ip is .............bam bam..........................................\n"); 
       system("sudo arp -s 10.0.0.1 00:1e:73:91:04:0d"); 
      } 
      printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       ah->arp_dha[0], 
       ah->arp_dha[1], 
       ah->arp_dha[2], 
       ah->arp_dha[3], 
       ah->arp_dha[4], 
       ah->arp_dha[5] 
      ); 
      printf("TARGET IP address: %02d:%02d:%02d:%02d\n", 
       ah->arp_dpa[0], 
       ah->arp_dpa[1], 
       ah->arp_dpa[2], 
       ah->arp_dpa[3] 
      ); 

      printf("+++++++++++++++++++++++++++++++++++++++\n"); 
      printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       eh->h_dest[0], 
       eh->h_dest[1], 
       eh->h_dest[2], 
       eh->h_dest[3], 
       eh->h_dest[4], 
       eh->h_dest[5] 
      ); 
      printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       eh->h_source[0], 
       eh->h_source[1], 
       eh->h_source[2], 
       eh->h_source[3], 
       eh->h_source[4], 
       eh->h_source[5] 
      ); 
      memcpy((void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN), 
       ETH_MAC_LEN); 
      memcpy((void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac, 
       ETH_MAC_LEN); 
      eh->h_proto = ETH_ARP; 
      printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& \n"); 
      printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       eh->h_dest[0], 
       eh->h_dest[1], 
       eh->h_dest[2], 
       eh->h_dest[3], 
       eh->h_dest[4], 
       eh->h_dest[5] 
      ); 
      printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       eh->h_source[0], 
       eh->h_source[1], 
       eh->h_source[2], 
       eh->h_source[3], 
       eh->h_source[4], 
       eh->h_source[5] 
      ); 
      ah->arp_hd = ntohs(ah->arp_hd); 
      ah->arp_pr = ntohs(ah->arp_pr); 

      ah->arp_op = 0x0002; 

      buf_arp_dpa[0] = ah->arp_dpa[0]; 
      buf_arp_dpa[1] = ah->arp_dpa[1]; 
      buf_arp_dpa[2] = ah->arp_dpa[2]; 
      buf_arp_dpa[3] = ah->arp_dpa[3]; 

      ah->arp_dha[0] = ah->arp_sha[0]; 
      ah->arp_dha[1] = ah->arp_sha[1]; 
      ah->arp_dha[2] = ah->arp_sha[2]; 
      ah->arp_dha[3] = ah->arp_sha[3]; 
      ah->arp_dha[4] = ah->arp_sha[4]; 
      ah->arp_dha[5] = ah->arp_sha[5]; 

      ah->arp_dpa[0] = ah->arp_spa[0]; 
      ah->arp_dpa[1] = ah->arp_spa[1]; 
      ah->arp_dpa[2] = ah->arp_spa[2]; 
      ah->arp_dpa[3] = ah->arp_spa[3]; 

      ah->arp_spa[0] = buf_arp_dpa[0]; 
      ah->arp_spa[1] = buf_arp_dpa[1]; 
      ah->arp_spa[2] = buf_arp_dpa[2]; 
      ah->arp_spa[3] = buf_arp_dpa[3]; 
      //change the sender mac address 
      ah->arp_sha[0] = 0x00; 
      ah->arp_sha[1] = 0x1e; 
      ah->arp_sha[2] = 0x73; 
      ah->arp_sha[3] = 0x78; 
      ah->arp_sha[4] = 0x9a; 
      ah->arp_sha[5] = 0x0d; 

      socket_address.sll_addr[0] = eh->h_dest[0]; 
      socket_address.sll_addr[1] = eh->h_dest[1]; 
      socket_address.sll_addr[2] = eh->h_dest[2]; 
      socket_address.sll_addr[3] = eh->h_dest[3]; 
      socket_address.sll_addr[4] = eh->h_dest[4]; 
      socket_address.sll_addr[5] = eh->h_dest[5]; 
      printf("=======================================\n"); 
      printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       ah->arp_sha[0], 
       ah->arp_sha[1], 
       ah->arp_sha[2], 
       ah->arp_sha[3], 
       ah->arp_sha[4], 
       ah->arp_sha[5] 
      ); 
      printf("SENDER IP address: %02d:%02d:%02d:%02d\n", 
       ah->arp_spa[0], 
       ah->arp_spa[1], 
       ah->arp_spa[2], 
       ah->arp_spa[3] 
      ); 
      if((ah->arp_spa[0]==10 && ah->arp_spa[1]==0 && ah->arp_spa[2]==0 && ah->arp_spa[3]==1)) 
       printf("------------------------------------------10.0.0.1-----------------------------------------\n"); 
      printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
       ah->arp_dha[0], 
       ah->arp_dha[1], 
       ah->arp_dha[2], 
       ah->arp_dha[3], 
       ah->arp_dha[4], 
       ah->arp_dha[5] 
      ); 
      printf("TARGET IP address: %02d:%02d:%02d:%02d\n", 
       ah->arp_dpa[0], 
       ah->arp_dpa[1], 
       ah->arp_dpa[2], 
       ah->arp_dpa[3] 
      ); 
      printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr); 
      printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl); 
      printf("OPERATION : %x \n", ah->arp_op); 

      sent = sendto(s, buffer, BUF_SIZE, 0, (struct 
       sockaddr*)&socket_address, sizeof(socket_address)); 
      if (sent == -1) 
      { 
       perror("sendto():"); 
       exit(1); 
      } 

      answered_packets++; 

     } 

     total_packets++; 

    } 
} 

void sigint(int signum) { 
    /*Clean up.......*/ 

    struct ifreq ifr; 

    if (s == -1) 
     return; 

    strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ); 
    ioctl(s, SIOCGIFFLAGS, &ifr); 
    ifr.ifr_flags &= ~IFF_PROMISC; 
    ioctl(s, SIOCSIFFLAGS, &ifr); 
    close(s); 

    free(buffer); 

    printf("Server terminating....\n"); 

    printf("Totally received: %ld packets\n", total_packets); 
    printf("Answered %ld packets\n", answered_packets); 
    exit(0); 
} 
+0

बेस्ट प्रपत्र [पूछें @ Wireshark] (http://ask.wireshark.org/questions/), यह अपने पीसी पर अन्य आवेदन के लिए पैकेट से पता चलता **? ** –

+0

हाँ, मैं देख सकता हूँ करता है पैकेट अन्य अनुप्रयोगों। – dsharew

+0

समस्या कोड से होनी चाहिए, लेकिन संकलक इसे स्पॉट करने में सक्षम नहीं है। – dsharew

उत्तर

5

योग्य कुछ बातें तार/हवा पर अपने पैकेट प्राप्त करने के लिए।

  • एआरपी उत्तर के लिए उचित .sll_protocol ETH_P_ARP, वहाँ endianness में एक त्रुटि जब आह की स्थापना> arp_op था से <linux/if_ether.h>
  • । यह 2 octets का एक नेटवर्क बाइटऑर्डर क्षेत्र है, इसलिए htons() का उपयोग करें।

  • सामान्य रूप से, कोड नेटवर्क और मेजबान बाइटऑर्डर के बारे में थोड़ा उलझन में है। यह वर्तमान में बहुत उलझन में जवाब भेजता है, लेकिन यह मेरे लिए अस्पष्ट है कि क्या यह कोड का दुर्भावनापूर्ण इरादा है, या दुर्घटना है। अगर आप उत्तर निर्माण करते समय वास्तविक, सही आईपी पते भेजना चाहते हैं, तो htonl और htons का उपयोग करें।

endianness ठीक करने के लिए:

  • ठीक <arpa/inet.h>
  • उपयोग htons(), htonl() ntohs() और ntohl (शामिल), हमेशा। उनके कार्यान्वयन में यह एक एनओपी बनाता है, अगर इसे आपके मंच पर जरूरी नहीं है।
  • होस्ट से भेजे जाने वाले डेटा को सेट करते समय, हमेशा इसे हटन *()
  • नेटवर्क से डेटा की व्याख्या करते समय, हमेशा स्थानीय चर के साथ तुलना करने से पहले ntoh *() इसे संसाधित करते हैं।

संक्षेप में, मेरे द्वारा किए गए परिवर्तन 1) .sll_protocol = htons (ETH_P_ARP) थे। (डेटा भेजते समय) 2) ah-> arp_op = htons (ARPOP_REPLY) (उत्तर arp में) 3) nh-> arp_hd और ah-> arp_pr पर nonsensical ntohs() को हटा दिया गया। जब आप प्रेषण बफर को पॉप्युलेट करते समय डेटा बाइटऑर्डर होस्ट करने के लिए डेटा को कनवर्ट नहीं करना चाहते हैं (जब तक कि आप वास्तव में वास्तव में वास्तव में नहीं करते) 4) एनओटीएस() रूपांतरण और कुछ तुलनाओं में उचित परिभाषित किया गया है 5) कुछ अन्य छोटे फिक्स 6) बिट करने की प्रणाली को अक्षम कर दिया गया है ("sudo ...")!

pastebin पर पूरा कोड।

[email protected]:~/src/so/arp$ diff arp2.c arp_orig.c 
13d12 
< #include <arpa/inet.h> 
20c19 
< #define DEVICE "eth1" 
--- 
> #define DEVICE "eth0" 
25c24 
< int s = -1; /*Socketdescriptor*/ 
--- 
> int s = 0; /*Socketdescriptor*/ 
92c91 
<  socket_address.sll_protocol = htons(ETH_P_ARP); 
--- 
>  socket_address.sll_protocol = htons(ETH_P_IP); 
95c94 
<  socket_address.sll_pkttype = 0; //PACKET_OTHERHOST; 
--- 
>  socket_address.sll_pkttype = PACKET_OTHERHOST; 
112c111 
<    if(ntohs(eh->h_proto) == ETH_P_ARP) 
--- 
>    if(htons(eh->h_proto) == 0x806) 
119c118 
<        if(ntohs(ah->arp_op) != ARPOP_REQUEST) 
--- 
>        if(htons(ah->arp_op) != 0x0001) 
139d137 
<        #if 0 
145d142 
<        #endif 
182c179 
<        eh->h_proto = htons(ETH_P_ARP); 
--- 
>        eh->h_proto = ETH_ARP; 
200,201c197,198 
<        //ah->arp_hd = ntohs(ah->arp_hd); 
<        //ah->arp_pr = ntohs(ah->arp_pr); 
--- 
>        ah->arp_hd = ntohs(ah->arp_hd); 
>        ah->arp_pr = ntohs(ah->arp_pr); 
203c200 
<        ah->arp_op = htons(ARPOP_REPLY); 
--- 
>        ah->arp_op = 0x0002; 

संपादित कुछ wireshark सलाह: यहाँ एक diff है। कैप्चर ईथर प्रोटो 0x0806 (या arp संक्षिप्त के लिए)। किसी भी पैकेट को कैप्चर करने वाले छद्म डिवाइस का उपयोग करें। आपके पैकेट दिखने चाहिए।

linux, यदि आप हस्तक्षेप, उपयोग से नेटवर्क स्टैक बंद करना चाहते हैं: गूंज "8">/proc/sys/नेट/आईपीवी 4/conf// arp_ignore सभी

संपादित करें # 2 मैं कर रहा हूँ ETH_P_ARP के बारे में पूरी तरह से सुनिश्चित नहीं है। यह मेरे हिस्से पर एक स्नैप निर्णय हो सकता है। ETH_P_IP का उपयोग एआरपी हेडर फ़ील्ड में सही है, लेकिन मुझे यकीन नहीं है कि पैकेट सॉकेट sll_protocol के लिए कौन सा उपयोग करना है।यह भी ध्यान दें कि socket_address.sll_pkttype = PACKET_OTHERHOST; भेजने पर कोई प्रभाव नहीं पड़ता है (मैन 7 पैकेट देखें)। इसके अलावा अनिवार्य एसओ अवलोकन, कि आपको हमेशा संकलन ध्वज के रूप में कम से कम -Wall (gcc या clang का उपयोग करते समय) का उपयोग करना चाहिए।

संपादित करें # 3 मैंने प्रोग्राम को थोड़ा और बदल दिया। और जवाब अद्यतन और तदनुसार diff। आश्चर्य की बात यह वास्तव में प्रतीत होती है, कि .sll_protocol को ETH_P_ARP होना आवश्यक है। मैन 7 पैकेट की मेरी प्रति यह भी नहीं कहती कि इसका उपयोग किसी भी चीज़ के लिए किया जाता है, लेकिन पैकेट तार के बिना एआरपी के रूप में बाहर नहीं जाता है।

+0

मैंने आपके कोड का उपयोग किया लेकिन समस्या अभी भी हल नहीं हुई है। – dsharew

+0

क्या यह अभी भी एक ही समस्या है? ऐसा लगता है कि मेरे लिए काम करना प्रतीत होता है। मैंने पैकेट बाहर जाकर देखा और वायरसहार्क ने एआरपी टकराव/डुप्लिकेट मैक का पता लगाया। एआरपी अनुरोध को उत्सर्जित करने वाले मेजबान स्वयं को उत्तर देने के लिए स्वीकार करते थे। – thuovila

4

मुझे पता है कि यह एक बहुत पुरानी पोस्ट है। इस कोड ने मुझे बहुत मदद की। मैंने आईपी को एआरपी अनुरोध भेजने और उत्तर से मैक पते निकालने के लिए कोड संशोधित किया है। मेरी कोड कृपया नीचे

#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/time.h> 

#include <asm/types.h> 

#include <math.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <signal.h> 

#include <linux/if_packet.h> 
#include <linux/if_ether.h> 
#include <linux/if_arp.h> 

#define PROTO_ARP 0x0806 
#define ETH2_HEADER_LEN 14 
#define HW_TYPE 1 
#define PROTOCOL_TYPE 0x800 
#define MAC_LENGTH 6 
#define IPV4_LENGTH 4 
#define ARP_REQUEST 0x01 
#define ARP_REPLY 0x02 
#define BUF_SIZE 60 

struct arp_header 
{ 
     unsigned short hardware_type; 
     unsigned short protocol_type; 
     unsigned char hardware_len; 
     unsigned char protocol_len; 
     unsigned short opcode; 
     unsigned char sender_mac[MAC_LENGTH]; 
     unsigned char sender_ip[IPV4_LENGTH]; 
     unsigned char target_mac[MAC_LENGTH]; 
     unsigned char target_ip[IPV4_LENGTH]; 
}; 

int main() 
{ 
     int sd; 
     unsigned char buffer[BUF_SIZE]; 
     unsigned char source_ip[4] = {10,222,190,160}; 
     unsigned char target_ip[4] = {10,222,190,139}; 
     struct ifreq ifr; 
     struct ethhdr *send_req = (struct ethhdr *)buffer; 
     struct ethhdr *rcv_resp= (struct ethhdr *)buffer; 
     struct arp_header *arp_req = (struct arp_header *)(buffer+ETH2_HEADER_LEN); 
     struct arp_header *arp_resp = (struct arp_header *)(buffer+ETH2_HEADER_LEN); 
     struct sockaddr_ll socket_address; 
     int index,ret,length=0,ifindex; 

memset(buffer,0x00,60); 
     /*open socket*/ 
     sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
     if (sd == -1) { 
       perror("socket():"); 
       exit(1); 
     } 
     strcpy(ifr.ifr_name,"eth1.30"); 
    /*retrieve ethernet interface index*/ 
    if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) { 
     perror("SIOCGIFINDEX"); 
     exit(1); 
    } 
    ifindex = ifr.ifr_ifindex; 
printf("interface index is %d\n",ifindex); 

     /*retrieve corresponding MAC*/ 
     if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) { 
       perror("SIOCGIFINDEX"); 
       exit(1); 
     } 
close (sd); 

     for (index = 0; index < 6; index++) 
     { 

       send_req->h_dest[index] = (unsigned char)0xff; 
       arp_req->target_mac[index] = (unsigned char)0x00; 
       /* Filling the source mac address in the header*/ 
       send_req->h_source[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; 
       arp_req->sender_mac[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; 
       socket_address.sll_addr[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index]; 
     } 
     printf("Successfully got eth1 MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
         send_req->h_source[0],send_req->h_source[1],send_req->h_source[2], 
         send_req->h_source[3],send_req->h_source[4],send_req->h_source[5]); 
     printf(" arp_reqMAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
         arp_req->sender_mac[0],arp_req->sender_mac[1],arp_req->sender_mac[2], 
         arp_req->sender_mac[3],arp_req->sender_mac[4],arp_req->sender_mac[5]); 
     printf("socket_address MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n", 
         socket_address.sll_addr[0],socket_address.sll_addr[1],socket_address.sll_addr[2], 
         socket_address.sll_addr[3],socket_address.sll_addr[4],socket_address.sll_addr[5]); 

     /*prepare sockaddr_ll*/ 
     socket_address.sll_family = AF_PACKET; 
     socket_address.sll_protocol = htons(ETH_P_ARP); 
     socket_address.sll_ifindex = ifindex; 
     socket_address.sll_hatype = htons(ARPHRD_ETHER); 
     socket_address.sll_pkttype = (PACKET_BROADCAST); 
     socket_address.sll_halen = MAC_LENGTH; 
     socket_address.sll_addr[6] = 0x00; 
     socket_address.sll_addr[7] = 0x00; 

     /* Setting protocol of the packet */ 
     send_req->h_proto = htons(ETH_P_ARP); 

     /* Creating ARP request */ 
     arp_req->hardware_type = htons(HW_TYPE); 
     arp_req->protocol_type = htons(ETH_P_IP); 
     arp_req->hardware_len = MAC_LENGTH; 
     arp_req->protocol_len =IPV4_LENGTH; 
     arp_req->opcode = htons(ARP_REQUEST); 
     for(index=0;index<5;index++) 
     { 
       arp_req->sender_ip[index]=(unsigned char)source_ip[index]; 
       arp_req->target_ip[index]=(unsigned char)target_ip[index]; 
     } 
    // Submit request for a raw socket descriptor. 
    if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) { 
    perror ("socket() failed "); 
    exit (EXIT_FAILURE); 
    } 

buffer[32]=0x00; 
     ret = sendto(sd, buffer, 42, 0, (struct sockaddr*)&socket_address, sizeof(socket_address)); 
     if (ret == -1) 
     { 
       perror("sendto():"); 
       exit(1); 
     } 
     else 
     { 
       printf(" Sent the ARP REQ \n\t"); 
       for(index=0;index<42;index++) 
       { 
         printf("%02X ",buffer[index]); 
         if(index % 16 ==0 && index !=0) 
         {printf("\n\t");} 
       } 
     } 
printf("\n\t"); 
     memset(buffer,0x00,60); 
     while(1) 
     { 
       length = recvfrom(sd, buffer, BUF_SIZE, 0, NULL, NULL); 
       if (length == -1) 
       { 
         perror("recvfrom():"); 
         exit(1); 
       } 
       if(htons(rcv_resp->h_proto) == PROTO_ARP) 
       { 
         //if(arp_resp->opcode == ARP_REPLY) 
         printf(" RECEIVED ARP RESP len=%d \n",length); 
         printf(" Sender IP :"); 
         for(index=0;index<4;index++) 
           printf("%u.",(unsigned int)arp_resp->sender_ip[index]); 

         printf("\n Sender MAC :"); 
         for(index=0;index<6;index++) 
           printf(" %02X:",arp_resp->sender_mac[index]); 

         printf("\nReceiver IP :"); 
         for(index=0;index<4;index++) 
           printf(" %u.",arp_resp->target_ip[index]); 

         printf("\n Self MAC :"); 
         for(index=0;index<6;index++) 
           printf(" %02X:",arp_resp->target_mac[index]); 

         printf("\n :"); 

         break; 
       } 
     } 

     return 0; 
} 

धन्यवाद एक बहुत एक बार फिर अरुण कुमार पी

+0

कोड के लिए धन्यवाद, मैंने इसे –

6

मैं user6343961 के कोड ले लिया है, कुछ सफाई किया था और स्प्लिसिंग और स्वचालित रूप से इंटरफेस आईपी पते प्राप्त करने के लिए समर्थन को लागू किया। इसके अलावा पैरामीटर हार्डकोडिंग के बजाय सीएलआई से आते हैं। बाइंड() का उपयोग इंटरफ़ेस से केवल एआरपी प्राप्त करने के लिए भी किया जाता है। मज़े करो। यह कोड मेरे लिए काम करता है।

#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <asm/types.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <linux/if_packet.h> 
#include <linux/if_ether.h> 
#include <linux/if_arp.h> 
#include <arpa/inet.h> //htons etc 

#define PROTO_ARP 0x0806 
#define ETH2_HEADER_LEN 14 
#define HW_TYPE 1 
#define MAC_LENGTH 6 
#define IPV4_LENGTH 4 
#define ARP_REQUEST 0x01 
#define ARP_REPLY 0x02 
#define BUF_SIZE 60 

#define debug(x...) printf(x);printf("\n"); 
#define info(x...) printf(x);printf("\n"); 
#define warn(x...) printf(x);printf("\n"); 
#define err(x...) printf(x);printf("\n"); 

struct arp_header { 
    unsigned short hardware_type; 
    unsigned short protocol_type; 
    unsigned char hardware_len; 
    unsigned char protocol_len; 
    unsigned short opcode; 
    unsigned char sender_mac[MAC_LENGTH]; 
    unsigned char sender_ip[IPV4_LENGTH]; 
    unsigned char target_mac[MAC_LENGTH]; 
    unsigned char target_ip[IPV4_LENGTH]; 
}; 

/* 
* Converts struct sockaddr with an IPv4 address to network byte order uin32_t. 
* Returns 0 on success. 
*/ 
int int_ip4(struct sockaddr *addr, uint32_t *ip) 
{ 
    if (addr->sa_family == AF_INET) { 
     struct sockaddr_in *i = (struct sockaddr_in *) addr; 
     *ip = i->sin_addr.s_addr; 
     return 0; 
    } else { 
     err("Not AF_INET"); 
     return 1; 
    } 
} 

/* 
* Formats sockaddr containing IPv4 address as human readable string. 
* Returns 0 on success. 
*/ 
int format_ip4(struct sockaddr *addr, char *out) 
{ 
    if (addr->sa_family == AF_INET) { 
     struct sockaddr_in *i = (struct sockaddr_in *) addr; 
     const char *ip = inet_ntoa(i->sin_addr); 
     if (!ip) { 
      return -2; 
     } else { 
      strcpy(out, ip); 
      return 0; 
     } 
    } else { 
     return -1; 
    } 
} 

/* 
* Writes interface IPv4 address as network byte order to ip. 
* Returns 0 on success. 
*/ 
int get_if_ip4(int fd, const char *ifname, uint32_t *ip) { 
    int err = -1; 
    struct ifreq ifr; 
    memset(&ifr, 0, sizeof(struct ifreq)); 
    if (strlen(ifname) > (IFNAMSIZ - 1)) { 
     err("Too long interface name"); 
     goto out; 
    } 

    strcpy(ifr.ifr_name, ifname); 
    if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { 
     perror("SIOCGIFADDR"); 
     goto out; 
    } 

    if (int_ip4(&ifr.ifr_addr, ip)) { 
     goto out; 
    } 
    err = 0; 
out: 
    return err; 
} 

/* 
* Sends an ARP who-has request to dst_ip 
* on interface ifindex, using source mac src_mac and source ip src_ip. 
*/ 
int send_arp(int fd, int ifindex, const unsigned char *src_mac, uint32_t src_ip, uint32_t dst_ip) 
{ 
    int err = -1; 
    unsigned char buffer[BUF_SIZE]; 
    memset(buffer, 0, sizeof(buffer)); 

    struct sockaddr_ll socket_address; 
    socket_address.sll_family = AF_PACKET; 
    socket_address.sll_protocol = htons(ETH_P_ARP); 
    socket_address.sll_ifindex = ifindex; 
    socket_address.sll_hatype = htons(ARPHRD_ETHER); 
    socket_address.sll_pkttype = (PACKET_BROADCAST); 
    socket_address.sll_halen = MAC_LENGTH; 
    socket_address.sll_addr[6] = 0x00; 
    socket_address.sll_addr[7] = 0x00; 

    struct ethhdr *send_req = (struct ethhdr *) buffer; 
    struct arp_header *arp_req = (struct arp_header *) (buffer + ETH2_HEADER_LEN); 
    int index; 
    ssize_t ret, length = 0; 

    //Broadcast 
    memset(send_req->h_dest, 0xff, MAC_LENGTH); 

    //Target MAC zero 
    memset(arp_req->target_mac, 0x00, MAC_LENGTH); 

    //Set source mac to our MAC address 
    memcpy(send_req->h_source, src_mac, MAC_LENGTH); 
    memcpy(arp_req->sender_mac, src_mac, MAC_LENGTH); 
    memcpy(socket_address.sll_addr, src_mac, MAC_LENGTH); 

    /* Setting protocol of the packet */ 
    send_req->h_proto = htons(ETH_P_ARP); 

    /* Creating ARP request */ 
    arp_req->hardware_type = htons(HW_TYPE); 
    arp_req->protocol_type = htons(ETH_P_IP); 
    arp_req->hardware_len = MAC_LENGTH; 
    arp_req->protocol_len = IPV4_LENGTH; 
    arp_req->opcode = htons(ARP_REQUEST); 

    debug("Copy IP address to arp_req"); 
    memcpy(arp_req->sender_ip, &src_ip, sizeof(uint32_t)); 
    memcpy(arp_req->target_ip, &dst_ip, sizeof(uint32_t)); 

    ret = sendto(fd, buffer, 42, 0, (struct sockaddr *) &socket_address, sizeof(socket_address)); 
    if (ret == -1) { 
     perror("sendto():"); 
     goto out; 
    } 
    err = 0; 
out: 
    return err; 
} 

/* 
* Gets interface information by name: 
* IPv4 
* MAC 
* ifindex 
*/ 
int get_if_info(const char *ifname, uint32_t *ip, char *mac, int *ifindex) 
{ 
    debug("get_if_info for %s", ifname); 
    int err = -1; 
    struct ifreq ifr; 
    int sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); 
    if (sd <= 0) { 
     perror("socket()"); 
     goto out; 
    } 
    if (strlen(ifname) > (IFNAMSIZ - 1)) { 
     printf("Too long interface name, MAX=%i\n", IFNAMSIZ - 1); 
     goto out; 
    } 

    strcpy(ifr.ifr_name, ifname); 

    //Get interface index using name 
    if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) { 
     perror("SIOCGIFINDEX"); 
     goto out; 
    } 
    *ifindex = ifr.ifr_ifindex; 
    printf("interface index is %d\n", *ifindex); 

    //Get MAC address of the interface 
    if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) { 
     perror("SIOCGIFINDEX"); 
     goto out; 
    } 

    //Copy mac address to output 
    memcpy(mac, ifr.ifr_hwaddr.sa_data, MAC_LENGTH); 

    if (get_if_ip4(sd, ifname, ip)) { 
     goto out; 
    } 
    debug("get_if_info OK"); 

    err = 0; 
out: 
    if (sd > 0) { 
     debug("Clean up temporary socket"); 
     close(sd); 
    } 
    return err; 
} 

/* 
* Creates a raw socket that listens for ARP traffic on specific ifindex. 
* Writes out the socket's FD. 
* Return 0 on success. 
*/ 
int bind_arp(int ifindex, int *fd) 
{ 
    debug("bind_arp: ifindex=%i", ifindex); 
    int ret = -1; 

    // Submit request for a raw socket descriptor. 
    *fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); 
    if (*fd < 1) { 
     perror("socket()"); 
     goto out; 
    } 

    debug("Binding to ifindex %i", ifindex); 
    struct sockaddr_ll sll; 
    memset(&sll, 0, sizeof(struct sockaddr_ll)); 
    sll.sll_family = AF_PACKET; 
    sll.sll_ifindex = ifindex; 
    if (bind(*fd, (struct sockaddr*) &sll, sizeof(struct sockaddr_ll)) < 0) { 
     perror("bind"); 
     goto out; 
    } 

    ret = 0; 
out: 
    if (ret && *fd > 0) { 
     debug("Cleanup socket"); 
     close(*fd); 
    } 
    return ret; 
} 

/* 
* Reads a single ARP reply from fd. 
* Return 0 on success. 
*/ 
int read_arp(int fd) 
{ 
    debug("read_arp"); 
    int ret = -1; 
    unsigned char buffer[BUF_SIZE]; 
    ssize_t length = recvfrom(fd, buffer, BUF_SIZE, 0, NULL, NULL); 
    int index; 
    if (length == -1) { 
     perror("recvfrom()"); 
     goto out; 
    } 
    struct ethhdr *rcv_resp = (struct ethhdr *) buffer; 
    struct arp_header *arp_resp = (struct arp_header *) (buffer + ETH2_HEADER_LEN); 
    if (ntohs(rcv_resp->h_proto) != PROTO_ARP) { 
     debug("Not an ARP packet"); 
     goto out; 
    } 
    if (ntohs(arp_resp->opcode) != ARP_REPLY) { 
     debug("Not an ARP reply"); 
     goto out; 
    } 
    debug("received ARP len=%ld", length); 
    struct in_addr sender_a; 
    memset(&sender_a, 0, sizeof(struct in_addr)); 
    memcpy(&sender_a.s_addr, arp_resp->sender_ip, sizeof(uint32_t)); 
    debug("Sender IP: %s", inet_ntoa(sender_a)); 

    debug("Sender MAC: %02X:%02X:%02X:%02X:%02X:%02X", 
      arp_resp->sender_mac[0], 
      arp_resp->sender_mac[1], 
      arp_resp->sender_mac[2], 
      arp_resp->sender_mac[3], 
      arp_resp->sender_mac[4], 
      arp_resp->sender_mac[5]); 

    ret = 0; 

out: 
    return ret; 
} 

/* 
* 
* Sample code that sends an ARP who-has request on 
* interface <ifname> to IPv4 address <ip>. 
* Returns 0 on success. 
*/ 
int test_arping(const char *ifname, const char *ip) { 
    int ret = -1; 
    uint32_t dst = inet_addr(ip); 
    if (dst == 0 || dst == 0xffffffff) { 
     printf("Invalid source IP\n"); 
     return 1; 
    } 

    int src; 
    int ifindex; 
    char mac[MAC_LENGTH]; 
    if (get_if_info(ifname, &src, mac, &ifindex)) { 
     err("get_if_info failed, interface %s not found or no IP set?", ifname); 
     goto out; 
    } 
    int arp_fd; 
    if (bind_arp(ifindex, &arp_fd)) { 
     err("Failed to bind_arp()"); 
     goto out; 
    } 

    if (send_arp(arp_fd, ifindex, mac, src, dst)) { 
     err("Failed to send_arp"); 
     goto out; 
    } 

    while(1) { 
     int r = read_arp(arp_fd); 
     if (r == 0) { 
      info("Got reply, break out"); 
      break; 
     } 
    } 

    ret = 0; 
out: 
    if (arp_fd) { 
     close(arp_fd); 
     arp_fd = 0; 
    } 
    return ret; 
} 

int main(int argc, const char **argv) { 
    int ret = -1; 
    if (argc != 3) { 
     printf("Usage: %s <INTERFACE> <DEST_IP>\n", argv[0]); 
     return 1; 
    } 
    const char *ifname = argv[1]; 
    const char *ip = argv[2]; 
    return test_arping(ifname, ip); 
} 
+0

+1 के लिए आधार के रूप में उपयोग किया है। अच्छा कोड। लेकिन अगर + गेटो के बजाए if-else स्टेटमेंट्स का उपयोग करें। यह सिर्फ गंदा है, जैसे पहले अपने हाथ धोने के बिना खाना। सभी अप्रयुक्त चर भी हटा दें। – zoran404

+0

मुझे गोटो, आईएचएमओ के बारे में असहमत होना है जो त्रुटि प्रबंधन और स्मृति रिलीज करने का सबसे साफ तरीका है। मैंने वैकल्पिक समाधान देखा है और कुछ भी करीब नहीं आता है। यही कारण है कि गेटो का कभी भी उपयोग नहीं किया जाना चाहिए, यानी अंत में जाने के लिए जहां आप मूल्य वापस करने से पहले कुछ रिलीज करते हैं। यहां इसके बारे में एक उदाहरण चर्चा है: http://stackoverflow.com/questions/570317/what-is-the-best-way-to-free-memory-after-returning-from-an-error –

+0

क्या आप इसे नहीं देखते हैं आपने सचमुच 'if-else' ब्लॉक लिखा है? केवल अंतर यह है कि आपने 'else' कीवर्ड के स्थान पर' goto' कीवर्ड का उपयोग किया था। – zoran404

संबंधित मुद्दे