arp request and reply using c socket programming

前端 未结 3 505
悲哀的现实
悲哀的现实 2020-12-08 03:07

I am trying to receive and send arp packets using c programming in Linux (Ubuntu)
My program works fine (i.e. runs without any error), but I cannot trac

3条回答
  •  执笔经年
    2020-12-08 03:28

    A couple of things to get your packets on the wire/air.

    • The proper .sll_protocol for the arp reply is ETH_P_ARP, from
    • There was an error in endianness when setting ah->arp_op. It is a network byteorder field of 2 octets, so use htons().

    • In general, the code is a little confused about network and host byteorder. It currently sends out the reply very mangled, but it is unclear to me whether that is the malicious intent of the code, or an accident. In the case that you want to send real, correct IP addresses, use htonl and htons, when building the reply.

    To fix endianness:

    • Properly include
    • Use htons(), htonl() ntohs() and ntohl(), always. Their implementation makes it a NOP, if its not needed on your platform.
    • When setting up data to be sent out from host, always process it with hton*()
    • When interpreting data from the network, always ntoh*() it before comparing with local variables.

    In summary, the changes I did were 1) .sll_protocol = htons(ETH_P_ARP). (when sending data) 2) ah->arp_op = htons(ARPOP_REPLY) (in the reply arp) 3) Removed the nonsensical ntohs() on ah->arp_hd and ah->arp_pr. You dont want to convert data to host byteorder when populating the send buffer (unless you really really actually do) 4) Added ntohs() conversions and proper defines in some of the comparisons 5) some other small fixes 6) disabled the bit doing system("sudo...")!

    Full code at pastebin. Here is a diff:

    thuovila@glx:~/src/so/arp$ diff arp2.c arp_orig.c 
    13d12
    < #include 
    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;
    

    EDIT Some wireshark advice. Capture ether proto 0x0806 (or arp for short). Use the pseudo device that captures any packets. Your packets should become visible.

    On linux, if you want to stop the network stack from interfering, use: echo "8" > /proc/sys/net/ipv4/conf/all/arp_ignore

    EDIT #2 I am not completely sure about the ETH_P_ARP. It might have been a snap judgement on my part. Using ETH_P_IP is correct in the ARP header field, but Im not sure which one to use for the packet socket sll_protocol. Also notice that socket_address.sll_pkttype = PACKET_OTHERHOST;has no effect when sending (see man 7 packet). Also the mandatory SO observation, that you should always use at least -Wall (when using gcc or clang) as a compilation flag.

    EDIT #3 I changed the program a little more. and updated the answer and diff accordingly. Surprisingly it does indeed seem, that .sll_protocol needs to be ETH_P_ARP. My copy of the man 7 packet doesnt even say it is used for anything, but the packet doesnt go out on the wire as ARP without it.

提交回复
热议问题