udp packet caught by tcpdump, but not received by

2019-06-15 19:49发布

问题:

I wrote a rawudp program to send udp packet via raw socket, following the webpage http://www.tenouk.com/Module43a.html. Then I wrote a udp server to listen to udp packets on given port. The codes look like follows:

...
sd = socket(AF_INET, SOCK_DGRAM, 0);
bind(sd, (struct sockaddr *)&ipaddr, sizeof(ipaddr));
size = recvfrom(sd, msgbuf.text, 2000, 0, (struct sockaddr *)&sin, &sin_len);
... // print the recevied udp packet

When I used rawudp to send a udp packet to the udp server, it is fine if the source ip address and destination ip address are different. But udp server couldn't receive the udp packet if the source ip address and destination ip address are same.

I tried to use tcpdump to catch the udp packet. And I found tcpdump could show the udp packet when using same source and destination ip address. It seemed when the source and destination ip address were same, somewhere the udp packet was dropped, and therefore it was not received by the socket in udp server.

The following are some logs (ip address was updated in the logs). The only difference between two cases were the source ip address (192.168.0.26 vs. 192.168.0.226).

I was stuck in this issue. Is there anyone could help me. Thanks in advance.

udp client side (rawudp):

case 1> rawudp 192.168.0.26 18321 192.168.0.226 19702 test.bin # using different source and destination ip addresses
size of ip header:  20
size of udp header: 8
read 69 bytes from file test.bin successfully.
socket() - using SOCK_RAW socket and UDP protocol is OK.
setsockopt() is OK.
total length of IP packet: 97
    0000:  4500 6100 0000 4000 4011 CD8F C0A8 001A 
    0010:  C0A8 00E2 4791 4CF6 004D 0000 0104 0401 
    0020:  FF00 0105 084E 0600 5225 1183 0406 0501 
    0030:  5211 3840 0D05 2735 2109 02C0 0023 0101 
    0040:  8080 448D 30C0 0300 9005 093C 5E56 8791 
    0050:  4B2D B7C0 082A 0000 2900 0000 0412 0C95 
    0060:  00
sendto() is OK.

case 2> rawudp 192.168.0.226 18321 192.168.0.226 19702 test.bin # using same source and destination ip addresses
size of ip header:  20
size of udp header: 8
read 69 bytes from file test.bin successfully.
socket() - using SOCK_RAW socket and UDP protocol is OK.
setsockopt() is OK.
total length of IP packet: 97
    0000:  4500 6100 0000 4000 4011 CCC7 C0A8 00E2 
    0010:  C0A8 00E2 4791 4CF6 004D 0000 0104 0401 
    0020:  FF00 0105 084E 0600 5225 1183 0406 0501 
    0030:  5211 3840 0D05 2735 2109 02C0 0023 0101 
    0040:  8080 448D 30C0 0300 9005 093C 5E56 8791 
    0050:  4B2D B7C0 082A 0000 2900 0000 0412 0C95 
    0060:  00
sendto() is OK.

udp server side:

case 1>
udp server receive 69 bytes from ip address 192.168.0.26 port 18321, sin_len 16
02:13:24.252841 IP 192.168.0.26.18321 > 192.168.0.226.19702: UDP, length 69
    0x0000:  4500 0061 0000 4000 4011 0198 c0a8 001a  E..a..@.@.......
    0x0010:  c0a8 00e2 4791 4cf6 004d 0000 0104 0401  ....G.L..M......
    0x0020:  ff00 0105 084e 0600 5225 1183 0406 0501  .....N..R%......
    0x0030:  5211 3840 0d05 2735 2109 02c0 0023 0101  R.8@..'5!....#..
    0x0040:  8080 448d 30c0 0300 9005 093c 5e56 8791  ..D.0......<^V..
    0x0050:  4b2d b7c0 082a 0000 2900 0000 0412 0c95  K-...*..).......
    0x0060:  00
                              .
02:13:39.500469 IP 192.168.0.226.18321 > 192.168.0.226.19702: UDP, length 69
    0x0000:  4500 0061 0000 4000 4011 00d0 c0a8 00e2  E..a..@.@.......
    0x0010:  c0a8 00e2 4791 4cf6 004d 0000 0104 0401  ....G.L..M......
    0x0020:  ff00 0105 084e 0600 5225 1183 0406 0501  .....N..R%......
    0x0030:  5211 3840 0d05 2735 2109 02c0 0023 0101  R.8@..'5!....#..
    0x0040:  8080 448d 30c0 0300 9005 093c 5e56 8791  ..D.0......<^V..
    0x0050:  4b2d b7c0 082a 0000 2900 0000 0412 0c95  K-...*..).......
    0x0060:  00        

When I run rawudp and udp server on same host, upd server could receive the udp packet from rawudp when I set the source and destination ip addresses same. But if I run rawudp on the different host than udp server, udp server couldn't receive the upd packet from rawudp when I set those ip addresses same. In both cases, tcpdump could catch the udp packet on udp server side.

In the latter case, only the udp packet with same source and destination ip address is impacted. If I set them different, the upd server could always receive udp packet. I am not sure the kernel could drop the packet with same local ip address if the packet is not received from lo interface.