8.4 | Running ping like this is an easy way to see ICMP messages that are received by the host on which ping is being run. We reduce the number of packets sent from the normal one per second just to reduce the output. If we run our UDP client on our host aix, specifying the server's IP address as 192.168.42.1, and also run the ping program, we get the following output:
aix % ping -v -i 60 127.0.0.1
PING 127.0.0.1: (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=0 ms
36 bytes from 192.168.42.1: Destination Port Unreachable
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data
4 5 00 0022 0007 0 0000 1e 11 c770 192.168.42.2 192.168.42.1
UDP: from port 40645, to port 9877 (decimal)
Note that not all ping clients print received ICMP errors, even with the -v flag.
|
8.6 | We run the sock program on the multihomed host freebsd, specifying the -u option (use UDP) and the -l option (specifying the local IP address and port).
freebsd % sock -u -l 12.106.32.254.4444 192.168.42.2 8888
hello
The local IP address is the Internet-side interface in Figure 1.16, but the datagram must go out the other interface to get to the destination. Watching the network with tcpdump shows that the source IP address is the one that was bound by the client, not the outgoing interface address.
14:28:29.614846 12.106.32.254.4444 > 192.168.42.2.8888: udp 6
14:28:29.615225 192.168.42.2 > 12.106.32.254: icmp: 192.168.42.2
udp port 8888 unreachable
|
8.8 | The largest IPv4 datagram is 65,535 bytes, limited by the 16-bit total length field in Figure A.1. The IP header requires 20 bytes and the UDP header requires 8 bytes, leaving a maximum of 65,507 bytes for user data. With IPv6 without jumbogram support, the size of the IPv6 header is 40 bytes, leaving a maximum of 65,487 bytes for user data. Figure E.9 shows the new version of dg_cli. If you forget to set the send buffer size, Berkeley-derived kernels return an error of EMSGSIZE from sendto, since the size of the socket send buffer is normally less than required for a maximum-sized UDP datagram (be sure to do Exercise 7.1). But if we set the client's socket buffer sizes as shown in Figure E.9 and run the client program, nothing is returned by the server. We can verify that the client's datagram is sent to the server by running tcpdump, but if we put a printf in the server, its call to recvfrom does not return the datagram. The problem is that the server's UDP socket receive buffer is smaller than the datagram we are sending, so the datagram is discarded and not delivered to the socket. On a FreeBSD system, we can verify this by running netstat -s and looking at the "dropped due to full socket buffers" counter before and after our big datagram is received. The final solution is to modify the server, setting its socket send and receive buffer sizes.
Figure E.9 Writing the maximum-sized UDP/IPv4 datagram.
udpcliserv/dgclibig.c
1 #include "unp.h"
2 #undef MAXLINE
3 #define MAXLINE 65507
4 void
5 dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
6 {
7 int size;
8 char sendline[MAXLINE], recvline[MAXLINE + 1];
9 ssize_t n;
10 size = 70000;
11 Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
12 Setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
13 Sendto(sockfd, sendline, MAXLINE, 0, pservaddr, servlen);
14 n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
15 printf("received %d bytes\n", n);
16 }
On most networks, a 65,535-byte IP datagram is fragmented. Recall from Section 2.11 that an IP layer must support a reassembly buffer size of only 576 bytes. Therefore, you may encounter hosts that will not receive the maximum-sized datagrams sent in this exercise. Also, many Berkeley-derived implementations, including 4.4BSD-Lite2, have a sign bug that prevents UDP from accepting a datagram larger than 32,767 bytes (line 95 of p.770 of TCPv2). |