# UDP retransmits



## m4rtin (Feb 20, 2012)

If I configure two nonexistent DNS servers in the /etc/resolv.conf file:


```
[root@ ~]# cat /etc/resolv.conf
nameserver 1.1.1.1
nameserver 2.2.2.2
[root@ ~]#
```

and try to ping for example _http://www.slashdot.org_, then I capture following sent packets from my machine:


```
15:08:19.123979 IP 192.0.43.10.29512 > 1.1.1.1.53: 19983+ A? www.slashdot.org. (34)
15:08:24.144077 IP 192.0.43.10.49257 > 2.2.2.2.53: 19983+ A? www.slashdot.org. (34)
15:08:26.149745 IP 192.0.43.10.29512 > 1.1.1.1.53: 19983+ A? www.slashdot.org. (34)
15:08:36.171772 IP 192.0.43.10.49257 > 2.2.2.2.53: 19983+ A? www.slashdot.org. (34)
```

As I understand with help of strace(1), there are two sockets opened:


```
kqueue(0)                               = 4
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
sendto(5, "\20\2\0005\2\2\2\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\17"..., 34, 0, NULL, 0) = 34
clock_gettime(0, 0xbfbec8dc)            = 0
kevent(0x4, 0xbfbec964, 0x1, 0xbfbec964, 0x1, 0xbfbec978) = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 6
connect(6, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("2.2.2.2")}, 16) = 0
sendto(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\17N\0\0\300\266\34(\0\0\0\0\0\0\0\0\0"..., 34, 0, NULL, 0) = 34
clock_gettime(0, 0xbfbec8dc)            = 0
kevent(0x4, 0xbfbec964, 0x1, 0xbfbec964, 0x1, 0xbfbec978) = 0
sendto(5, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 34, 0, NULL, 0) = 34
clock_gettime(0, 0xbfbec8dc)            = 0
kevent(0x4, 0xbfbec964, 0x1, 0xbfbec964, 0x1, 0xbfbec978) = 0
sendto(6, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 34, 0, NULL, 0) = 34
clock_gettime(0, 0xbfbec8dc)            = 0
kevent(0x4, 0xbfbec964, 0x1, 0xbfbec964, 0x1, 0xbfbec978) = 0
close(5)                                = 0
close(6)                                = 0
```

Am I correct, that in case of UDP it's up to the application to retransmit UDP datagramx if there is no response from the server? Or is this determined by some FreeBSD library which is used by applications? I tried with several different programs and there were always two tries to both DNS servers.


----------



## kpa (Feb 20, 2012)

UDP does not have any error detection or correction, it's entirely up to the application to determine if the packets sent were lost and what to do about it.


----------



## White_Mad_Hatter (Feb 20, 2012)

I hate quoting Wikipedia but http://en.wikipedia.org/wiki/User_Datagram_Protocol. Itâ€™s the best document I have found to describe the protocol and how it functions.


----------



## m4rtin (Feb 21, 2012)

*kpa*, *White_Mad_Hatter*: it's clear that UDP itself has no built-in reliability for lost datagrams. What I meant is that as you can see, there are two tries to resolve DNS A-record for http://www.slashdot.com. I'm trying to find out, are those two tries determined by _ping_ utility or does _ping_ utility use some lower-level library which is responsible for this? :OOO


----------



## SirDice (Feb 22, 2012)

m4rtin said:
			
		

> I'm trying to find out, are those two tries determined by _ping_ utility or does _ping_ utility use some lower-level library which is responsible for this? :OOO


Ping uses ICMP which has nothing to do with UDP.

I suggest reading up on TCP/IP as you seem to be lacking quite some basic background information.


----------



## kpa (Feb 22, 2012)

The responsible lower level library is gethostbyname(3). Ping has to figure out the numeric IP address of a FQDN before it can actually send the ICMP packets.


----------



## anomie (Feb 22, 2012)

m4rtin said:
			
		

> I'm trying to find out, are those two tries determined by _ping_ utility or does _ping_ utility use some lower-level library which is responsible for this?



Based on the info / documentation provided by kpa, my WAG is the _application_ (and not the underlying library) decides to perform a second name lookup. In particular, see the DIAGNOSTICS section in gethostbyname(3). 

It would be arbitrary and annoying if the library insisted on trying multiple times, IMO.


----------



## m4rtin (Feb 24, 2012)

kpa said:
			
		

> The responsible lower level library is gethostbyname(3). Ping has to figure out the numeric IP address of a FQDN before it can actually send the ICMP packets.



How did you know that the responsible lower level library is gethostbyname(3)? I mean this isn't listed in [cmd=]strace -fc ping -c1 http://www.slashdot.org[/cmd] output:


```
[root@martin ~]# strace -fc ping -c1 www.slashdot.org 2>&1 | grep -i gethost
[root@martin ~]#
```




			
				anomie said:
			
		

> Based on the info / documentation provided by kpa, my WAG is the _application_ (and not the underlying library) decides to perform a second name lookup.


Yes, this makes sense


----------



## kpa (Feb 24, 2012)

I'm just guessing because that's the standard function for resolving FQDNs to IP addresses, there may be other methods available in FreeBSD to do the same.


----------



## m4rtin (Feb 24, 2012)

kpa said:
			
		

> I'm just guessing because that's the standard function for resolving FQDNs to IP addresses, there may be other methods available in FreeBSD to do the same.



I see  So you share the same opinion that ping(8) calls gethostbyname(3) twice in case the first try isn't successful and once there has been two tries to all name servers listed under /etc/resolv.conf, then ping exits with error printed to stdout?


----------

