ThomasHabets / arping

ARP Ping
http://www.habets.pp.se/synscan/programs.php
GNU General Public License v2.0
398 stars 62 forks source link

No replies received using vlan option with older libpcap #50

Closed san3Xian closed 2 years ago

san3Xian commented 2 years ago

arping is displaying Timeout on CentOS-7.6.1810, but I can see the arp reply packages (gratuitous) in tcpdump.

# arping -v
ARPing 2.20, by Thomas Habets <thomas@habets.se>
usage: arping [ -0aAbdDeFpPqrRuUv ] [ -w <sec> ] [ -W <sec> ] [ -S <host/ip> ]
              [ -T <host/ip ] [ -s <MAC> ] [ -t <MAC> ] [ -c <count> ]
              [ -C <count> ] [ -i <interface> ] [ -m <type> ] [ -g <group> ]
              [ -V <vlan> ] [ -Q <priority> ] <host/ip/MAC | -B>
For complete usage info, use --help or check the manpage.

# arping -i eth1 -V 217 -0 10.10.217.1 -c 1 -vvvvvvvv -W3 -p
arping: libnet_init(eth1)
arping: clock_getres() = 0s 1ns
arping: libnet_init(eth1)
arping: libnet_init(eth1)
Timestamp types:
  Name               Description
  host               Host
  adapter            Adapter
  adapter_unsynced   Adapter, not synced with system time
arping: Successfully chrooted to /var/empty/sshd
arping: Successfully dropped uid/gid to 99/99.
arping: pcap_get_selectable_fd(): 4
This box:   Interface: eth1  IP: 255.255.255.255   MAC address: c8:1f:66:ed:74:bd
ARPING 10.10.217.1
arping: sending packet at time 1758649.485481600
arping: receiving packets...
arping: listen for replies for 2.999999530 sec
arping: received response for IP ping
arping: listen for replies for 2.916730013 sec
arping: received response for IP ping
arping: listen for replies for 2.816205510 sec
arping: received response for IP ping
arping: listen for replies for 2.787156679 sec
arping: received response for IP ping
arping: listen for replies for 2.787077017 sec
arping: received response for IP ping
arping: listen for replies for 2.787055684 sec
arping: received response for IP ping
arping: listen for replies for 2.786988205 sec
arping: received response for IP ping
arping: listen for replies for 2.786933507 sec
arping: received response for IP ping
arping: listen for replies for 2.786873469 sec
arping: received response for IP ping
arping: listen for replies for 2.786816478 sec
arping: received response for IP ping
arping: listen for replies for 2.786760759 sec
arping: received response for IP ping
arping: listen for replies for 2.786681887 sec
arping: received response for IP ping
arping: listen for replies for 2.715661653 sec
arping: received response for IP ping
arping: listen for replies for 2.615118869 sec
arping: received response for IP ping
arping: listen for replies for 2.342780055 sec
arping: received response for IP ping
arping: listen for replies for 2.286985953 sec
arping: received response for IP ping
arping: listen for replies for 2.286956056 sec
arping: received response for IP ping
arping: received response for IP ping
arping: listen for replies for 2.286846593 sec
arping: received response for IP ping
arping: listen for replies for 2.286797412 sec
arping: received response for IP ping
arping: listen for replies for 2.286731494 sec
arping: received response for IP ping
arping: listen for replies for 2.286683799 sec
arping: received response for IP ping
arping: listen for replies for 2.286625684 sec
arping: received response for IP ping
arping: received response for IP ping
arping: received response for IP ping
arping: listen for replies for 1.786932023 sec
arping: received response for IP ping
arping: listen for replies for 1.786897342 sec
arping: received response for IP ping
arping: listen for replies for 1.786807094 sec
arping: received response for IP ping
arping: listen for replies for 1.786702378 sec
arping: received response for IP ping
arping: received response for IP ping
arping: listen for replies for 1.286978173 sec
arping: received response for IP ping
arping: listen for replies for 1.286950859 sec
arping: received response for IP ping
arping: listen for replies for 1.286866687 sec
arping: received response for IP ping
arping: listen for replies for 1.286834573 sec
arping: received response for IP ping
arping: received response for IP ping
arping: listen for replies for 0.787018896 sec
Timeout

--- 10.10.217.1 statistics ---
1 packets transmitted, 0 packets received, 100% unanswered (0 extra)

# ldd /usr/local/bin/arping
    linux-vdso.so.1 =>  (0x00007fff2ddc0000)
    libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f6c1c03c000)
    libnet.so.1 => /lib64/libnet.so.1 (0x00007f6c1be22000)
    librt.so.1 => /lib64/librt.so.1 (0x00007f6c1bc1a000)
    libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f6c1ba00000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f6c1b6fe000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f6c1b331000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6c1b115000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6c1c27d000)

# ethtool -i eth1
driver: tg3
version: 3.137
firmware-version: FFV7.8.16 bc 5720-v1.32
expansion-rom-version: 
bus-info: 0000:01:00.1
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: no

# ifconfig eth1
eth1: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST>  mtu 1500
        ether c8:1f:66:ed:74:bd  txqueuelen 1000  (Ethernet)
        RX packets 4300320  bytes 295380129 (281.6 MiB)
        RX errors 0  dropped 34559  overruns 0  frame 0
        TX packets 1206  bytes 77622 (75.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        device interrupt 57 

Running tcpdump gives the following results

# tcpdump -i eth1 -ennvv "( ether src c8:1f:66:ed:74:bd or ether dst c8:1f:66:ed:74:bd )" or host 10.10.217.1 -s0 -nnvv -xx -tt
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
1645976679.181471 c8:1f:66:ed:74:bd > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 62: vlan 217, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.10.217.1 tell 0.0.0.0, length 44
    0x0000:  ffff ffff ffff c81f 66ed 74bd 8100 00d9
    0x0010:  0806 0001 0800 0604 0001 c81f 66ed 74bd
    0x0020:  0000 0000 0000 0000 0000 0a0a d901 0000
    0x0030:  0000 0000 0000 0000 0000 0000 0000
1645976679.285097 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
    0x0000:  ffff ffff ffff e43e c645 4fe8 8100 c0d9
    0x0010:  0806 0001 0800 0604 0002 e43e c645 4fe8
    0x0020:  0a0a d901 ffff ffff ffff 0a0a d901 0000
    0x0030:  0000 0000 0000 0000 0000 0000 0000 0000
1645976679.838619 fa:16:3e:fc:76:01 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 60: vlan 217, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.10.217.1 tell 10.10.217.100, length 42
    0x0000:  ffff ffff ffff fa16 3efc 7601 8100 00d9
    0x0010:  0806 0001 0800 0604 0001 fa16 3efc 7601
    0x0020:  0a0a d964 0000 0000 0000 0a0a d901 0000
    0x0030:  0000 0000 0000 0000 0000 0000
1645976684.333373 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
    0x0000:  ffff ffff ffff e43e c645 4fe8 8100 c0d9
    0x0010:  0806 0001 0800 0604 0002 e43e c645 4fe8
    0x0020:  0a0a d901 ffff ffff ffff 0a0a d901 0000
    0x0030:  0000 0000 0000 0000 0000 0000 0000 0000
1645976689.315901 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
    0x0000:  ffff ffff ffff e43e c645 4fe8 8100 c0d9
    0x0010:  0806 0001 0800 0604 0002 e43e c645 4fe8
    0x0020:  0a0a d901 ffff ffff ffff 0a0a d901 0000
    0x0030:  0000 0000 0000 0000 0000 0000 0000 0000
^C
5 packets captured
5 packets received by filter
0 packets dropped by kernel

Also here are the current kernel parameters, which may help

# sysctl -a 2>&1|grep eth1
net.ipv4.conf.eth1.accept_local = 0
net.ipv4.conf.eth1.accept_redirects = 1
net.ipv4.conf.eth1.accept_source_route = 0
net.ipv4.conf.eth1.arp_accept = 0
net.ipv4.conf.eth1.arp_announce = 1
net.ipv4.conf.eth1.arp_filter = 0
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.eth1.arp_notify = 0
net.ipv4.conf.eth1.bootp_relay = 0
net.ipv4.conf.eth1.disable_policy = 0
net.ipv4.conf.eth1.disable_xfrm = 0
net.ipv4.conf.eth1.force_igmp_version = 0
net.ipv4.conf.eth1.forwarding = 1
net.ipv4.conf.eth1.log_martians = 0
net.ipv4.conf.eth1.mc_forwarding = 0
net.ipv4.conf.eth1.medium_id = 0
net.ipv4.conf.eth1.promote_secondaries = 1
net.ipv4.conf.eth1.proxy_arp = 0
net.ipv4.conf.eth1.proxy_arp_pvlan = 0
net.ipv4.conf.eth1.route_localnet = 0
net.ipv4.conf.eth1.rp_filter = 0
net.ipv4.conf.eth1.secure_redirects = 1
net.ipv4.conf.eth1.send_redirects = 1
net.ipv4.conf.eth1.shared_media = 1
net.ipv4.conf.eth1.src_valid_mark = 0
net.ipv4.conf.eth1.tag = 0
net.ipv4.neigh.eth1.anycast_delay = 100
net.ipv4.neigh.eth1.app_solicit = 0
net.ipv4.neigh.eth1.base_reachable_time_ms = 30000
net.ipv4.neigh.eth1.delay_first_probe_time = 5
net.ipv4.neigh.eth1.gc_stale_time = 60
net.ipv4.neigh.eth1.locktime = 100
net.ipv4.neigh.eth1.mcast_solicit = 3
net.ipv4.neigh.eth1.proxy_delay = 80
net.ipv4.neigh.eth1.proxy_qlen = 64
net.ipv4.neigh.eth1.retrans_time_ms = 1000
net.ipv4.neigh.eth1.ucast_solicit = 3
net.ipv4.neigh.eth1.unres_qlen = 31
net.ipv4.neigh.eth1.unres_qlen_bytes = 65536
net.ipv6.conf.eth1.accept_dad = 0
net.ipv6.conf.eth1.accept_ra = 0
net.ipv6.conf.eth1.accept_ra_defrtr = 0
net.ipv6.conf.eth1.accept_ra_pinfo = 0
net.ipv6.conf.eth1.accept_ra_rt_info_max_plen = 0
net.ipv6.conf.eth1.accept_ra_rtr_pref = 0
net.ipv6.conf.eth1.accept_redirects = 1
net.ipv6.conf.eth1.accept_source_route = 0
net.ipv6.conf.eth1.autoconf = 1
net.ipv6.conf.eth1.dad_transmits = 1
net.ipv6.conf.eth1.disable_ipv6 = 0
net.ipv6.conf.eth1.enhanced_dad = 1
net.ipv6.conf.eth1.force_mld_version = 0
net.ipv6.conf.eth1.force_tllao = 0
net.ipv6.conf.eth1.forwarding = 0
net.ipv6.conf.eth1.hop_limit = 64
net.ipv6.conf.eth1.keep_addr_on_down = 0
net.ipv6.conf.eth1.max_addresses = 16
net.ipv6.conf.eth1.max_desync_factor = 600
net.ipv6.conf.eth1.mc_forwarding = 0
net.ipv6.conf.eth1.mldv1_unsolicited_report_interval = 10000
net.ipv6.conf.eth1.mldv2_unsolicited_report_interval = 1000
net.ipv6.conf.eth1.mtu = 1500
net.ipv6.conf.eth1.ndisc_notify = 0
net.ipv6.conf.eth1.optimistic_dad = 0
net.ipv6.conf.eth1.proxy_ndp = 0
net.ipv6.conf.eth1.regen_max_retry = 3
net.ipv6.conf.eth1.router_probe_interval = 60
net.ipv6.conf.eth1.router_solicitation_delay = 1
net.ipv6.conf.eth1.router_solicitation_interval = 4
net.ipv6.conf.eth1.router_solicitations = 3
sysctl: reading key "net.ipv6.conf.eth1.stable_secret"
net.ipv6.conf.eth1.temp_prefered_lft = 86400
net.ipv6.conf.eth1.temp_valid_lft = 604800
net.ipv6.conf.eth1.use_optimistic = 0
net.ipv6.conf.eth1.use_tempaddr = 0
net.ipv6.neigh.eth1.anycast_delay = 100
net.ipv6.neigh.eth1.app_solicit = 0
net.ipv6.neigh.eth1.base_reachable_time_ms = 30000
net.ipv6.neigh.eth1.delay_first_probe_time = 5
net.ipv6.neigh.eth1.gc_stale_time = 60
net.ipv6.neigh.eth1.locktime = 0
net.ipv6.neigh.eth1.mcast_solicit = 3
net.ipv6.neigh.eth1.proxy_delay = 80
net.ipv6.neigh.eth1.proxy_qlen = 64
net.ipv6.neigh.eth1.retrans_time_ms = 1000
net.ipv6.neigh.eth1.ucast_solicit = 3
net.ipv6.neigh.eth1.unres_qlen = 31
net.ipv6.neigh.eth1.unres_qlen_bytes = 65536
san3Xian commented 2 years ago

I looked at the package data again and I guess the problem is caused by the broadcast address in the target mac address of the arp response packet ? or may be the filter is something wrong, so use "vlan xxx and arp" some time will get not packages https://github.com/ThomasHabets/arping/blob/5efae73f90d79da6723b1f364b4bdee8b121bbe9/src/arping.c#L2279-L2290

[root@test-node:/root/sanXian/arping]
# tcpdump -i eth1 -ennvv arp and vlan 217 and host 10.10.217.1
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel

[root@test-node:/root/sanXian/arping]
# tcpdump -i eth1 -ennvv arp and host 10.10.217.1
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
01:57:29.663125 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
01:57:32.674465 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
01:57:34.736623 e4:3e:c6:45:4f:e8 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 64: vlan 217, p 6, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.10.217.1 is-at e4:3e:c6:45:4f:e8, length 46
^C
3 packets captured
3 packets received by filter
0 packets dropped by kernel
ThomasHabets commented 2 years ago

Thanks for detailed debug info.

It's odd that the reply is to broadcast, but that should not be it. The output with -vvvvv for a successful reception should be:

arping: received response for IP ping
arping: ... packet is ARP reply
arping: ... from IPv4 address
arping: ... to Ethernet address
arping: ... sent by acceptable host
arping: ... destination is the source we used
arping: ... for the right IPv4 address!

Either the packet is not getting through the BPF filter, like you said, or it's not identified as an ARP reply, which is odd.

Could you try recompiling with the pcap_compile lines commented out? (there are two, one for pinging IPs (like you are), and the other for pinging hardware addresses)

san3Xian commented 2 years ago

I have change the filter rules to

                 if (vlan_tag >= 0) {
                         snprintf(bpf_filter, sizeof(bpf_filter),
-                                 "vlan %u and arp", vlan_tag);
+                                 "arp");

https://github.com/ThomasHabets/arping/blob/5efae73f90d79da6723b1f364b4bdee8b121bbe9/src/arping.c#L2283 recompile and I can get the correct result

[root@test-vm:/root/sanXian/arping-origin]
# ./src/arping -i eth1 -V 217 -0 10.10.217.1 -p  -vvvv -c 3
arping: trying libnet_init(LIBNET_LINK, eth1)
arping: clock_getres() = 0s 1ns
arping: trying libnet_init(LIBNET_LINK, eth1)
arping: libnet_getfd(): 3
arping: trying libnet_init(LIBNET_LINK, eth1)
Timestamp types:
  Name               Description
  host               Host
  adapter            Adapter
  adapter_unsynced   Adapter, not synced with system time
arping: Successfully chrooted to /var/empty/sshd
arping: Successfully dropped uid/gid to 99/99.
arping: pcap_get_selectable_fd(): 4
This box:   Interface: eth1  IP: 255.255.255.255   MAC address: c8:1f:66:ed:74:bd
ARPING 10.10.217.1
arping: sending packet at time 1769541.774481800
arping: receiving packets...
arping: listen for replies for 0.999999734 sec
arping: received response for IP ping
arping: ... get a packet, pkt_srcmac is e4:3e:c6:45:4f:e8
arping: ... packet is ARP reply
arping: ... from IPv4 address
arping: ... to Ethernet address
arping: ... sent by acceptable host
arping: ... destination is the source we used
arping: ... for the right IPv4 address!
64 bytes from e4:3e:c6:45:4f:e8 (10.10.217.1): index=0 time=114.667 msec
arping: listen for replies for 0.885256695 sec
arping: sending packet at time 1769542.775495917
arping: receiving packets...
arping: listen for replies for 0.999998973 sec
arping: received response for IP ping
arping: ... get a packet, pkt_srcmac is e4:3e:c6:45:4f:e8
arping: ... packet is ARP reply
arping: ... from IPv4 address
arping: ... to Ethernet address
arping: ... sent by acceptable host
arping: ... destination is the source we used
arping: ... for the right IPv4 address!
64 bytes from e4:3e:c6:45:4f:e8 (10.10.217.1): index=1 time=44.578 msec
arping: listen for replies for 0.955334550 sec
arping: sending packet at time 1769543.776066933
arping: receiving packets...
arping: listen for replies for 0.999999007 sec
arping: received response for IP ping
arping: ... get a packet, pkt_srcmac is e4:3e:c6:45:4f:e8
arping: ... packet is ARP reply
arping: ... from IPv4 address
arping: ... to Ethernet address
arping: ... sent by acceptable host
arping: ... destination is the source we used
arping: ... for the right IPv4 address!
64 bytes from e4:3e:c6:45:4f:e8 (10.10.217.1): index=2 time=79.394 msec
arping: listen for replies for 0.920540912 sec

--- 10.10.217.1 statistics ---
3 packets transmitted, 3 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 44.578/79.546/114.667/28.614 ms

[root@test-vm:/root/sanXian/arping-origin]
# git  diff
diff --git a/src/arping.c b/src/arping.c
index 97baca7..ea4ac57 100644
--- a/src/arping.c
+++ b/src/arping.c
@@ -1349,8 +1349,16 @@ pingip_recv(const char *unused, struct pcap_pkthdr *h, const char * const packet
                 }
        }

+        if (verbose > 3) {
+            char pkt_mac_buf[128];
+            printf("arping: ... get a packet, pkt_srcmac is %s\n", format_mac(pkt_srcmac, pkt_mac_buf, sizeof(pkt_mac_buf)));
+        }
+
         // ARP reply.
         if (htons(harp->ar_op) != ARPOP_REPLY) {
+                if (verbose > 3) {
+                    printf("arping: ... not a arp reply packet\n");
+                }
                 return;
         }
         if (verbose > 3) {
@@ -2280,7 +2288,7 @@ arping_main(int argc, char **argv)
                /* FIXME: better filter with addresses? */
                 if (vlan_tag >= 0) {
                         snprintf(bpf_filter, sizeof(bpf_filter),
-                                 "vlan %u and arp", vlan_tag);
+                                 "arp");
                 } else {
                         snprintf(bpf_filter, sizeof(bpf_filter), "arp");
                 }

[root@test-vm:/root/sanXian/arping-origin]
# 
san3Xian commented 2 years ago

Btw, I looked at the package data found that the the priority value of 802.1q layer is 6 (means Internetwork Control in Wireshark), not clear if there is a relationship

ThomasHabets commented 2 years ago

I would hope that's not a problem. That would mean that bpf doesn't bitwise and out the non-VLAN-ID parts of the 16 bits that contain both priority and vlan id.

If you tcpdump with filter vlan 217 and arp on that interface, do you see the traffic? tcpdump should work the same as arping in this regard.

ThomasHabets commented 2 years ago

Looks like a bug in libpcap, indeed.

Presumably your libpcap is older than the fix they have there?

That said, arping should work around that, so I'm keeping this bug open for that.

ThomasHabets commented 2 years ago

I've added a workaround now, as well as some extra checking. I'll done some more testing, but if you could test it in your environment I would appreciate it.