Subject: Re: IPv6 PMTUD broken
To: Jun-ichiro itojun Hagino <itojun@itojun.org>
From: Ronald van der Pol <Ronald.vanderPol@rvdp.org>
List: current-users
Date: 06/09/2004 22:14:48
--45Z9DzgjV8m4Oswq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Fri, Jun 04, 2004 at 20:15:51 +0900, Jun-ichiro itojun Hagino wrote:
> > Anything else I could try to pinpoint this?
>
> try monitoring how it works with netstat -rn, netstat -sn and tcpdump,
> and compare them... (yes, it's painful i guess)
The problem only seems to happen with sendto().
I use the attached program. This is what I do:
- delete the host route
- start tcpdump in xterm 1
- start the program in xterm 2
---------------------------------------------------------------------------
connect() and send(), PMTUD works fine
---------------------------------------------------------------------------
xterm 1:
# route delete -inet6 2001:7b8:206:1:240:f4ff:fe37:8232
delete host 2001:7b8:206:1:240:f4ff:fe37:8232
# tcpdump -n -p -i ex0 -s0 -vvv host 2001:7b8:206:1:240:f4ff:fe37:8232 or icmp6
tcpdump: listening on ex0
21:56:13.843027 2001:888:1777:0:260:8ff:fed1:a403.65493 > 2001:7b8:206:1:240:f4ff:fe37:8232.53: [udp sum ok] 0 [0q] (1400) [flowlabel 0x5eb6] (len 1408, hlim 64)
21:56:13.846349 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: too big 1280 (len 1240, hlim 64)
21:56:18.859325 2001:888:1777:0:260:8ff:fed1:a403 > 2001:7b8:206:1:240:f4ff:fe37:8232: frag (0x696ca82c:0|1232) 65493 > 53: 0 [0q] (1224) [flowlabel 0x5eb6] (len 1240, hlim 64)
21:56:18.859464 2001:888:1777:0:260:8ff:fed1:a403 > 2001:7b8:206:1:240:f4ff:fe37:8232: frag (0x696ca82c:1232|176) [flowlabel 0x5eb6] (len 184, hlim 64)
21:56:18.935846 2001:7b8:206:1:240:f4ff:fe37:8232 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: 2001:7b8:206:1:240:f4ff:fe37:8232 udp port 53 unreachable (len 1240, hlim 58)
21:56:23.883967 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: neighbor sol: who has 2001:888:1777:0:260:8ff:fed1:a403(src lladdr: 00:00:24:c0:7b:f4) (len 32, hlim 255)
21:56:23.884109 2001:888:1777:0:260:8ff:fed1:a403 > 2001:888:1777::1: icmp6: neighbor adv: tgt is 2001:888:1777:0:260:8ff:fed1:a403(S) (len 24, hlim 255)
^C
46 packets received by filter
0 packets dropped by kernel
#
xterm 2:
$ ./a.out einstein.nlnetlabs.nl 1
connect()
send()
sleep()
send()
$
---------------------------------------------------------------------------
sendto(), PMTUD fails
---------------------------------------------------------------------------
xterm 1:
# route delete -inet6 2001:7b8:206:1:240:f4ff:fe37:8232
delete host 2001:7b8:206:1:240:f4ff:fe37:8232
# tcpdump -n -p -i ex0 -s0 -vvv host 2001:7b8:206:1:240:f4ff:fe37:8232 or icmp6
tcpdump: listening on ex0
21:59:41.756370 2001:888:1777:0:260:8ff:fed1:a403.65490 > 2001:7b8:206:1:240:f4ff:fe37:8232.53: [udp sum ok] 0 [0q] (1400) (len 1408, hlim 64)
21:59:41.759698 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: too big 1280 (len 1240, hlim 64)
21:59:46.750081 fe80::260:8ff:fed1:a403 > fe80::200:24ff:fec0:7bf4: icmp6: neighbor sol: who has fe80::200:24ff:fec0:7bf4(src lladdr: 00:60:08:d1:a4:03) (len 32, hlim 255)
21:59:46.750824 fe80::200:24ff:fec0:7bf4 > fe80::260:8ff:fed1:a403: icmp6: neighbor adv: tgt is fe80::200:24ff:fec0:7bf4(RS) (len 24, hlim 255)
21:59:46.760530 2001:888:1777:0:260:8ff:fed1:a403.65490 > 2001:7b8:206:1:240:f4ff:fe37:8232.53: [udp sum ok] 0 [0q] (1400) (len 1408, hlim 64)
21:59:46.763826 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: too big 1280 (len 1240, hlim 64)
21:59:46.874537 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: neighbor sol: who has 2001:888:1777:0:260:8ff:fed1:a403(src lladdr: 00:00:24:c0:7b:f4) (len 32, hlim 255)
21:59:46.874652 2001:888:1777:0:260:8ff:fed1:a403 > 2001:888:1777::1: icmp6: neighbor adv: tgt is 2001:888:1777:0:260:8ff:fed1:a403(S) (len 24, hlim 255)
21:59:51.870124 2001:888:1777:0:260:8ff:fed1:a403 > 2001:888:1777::1: icmp6: neighbor sol: who has 2001:888:1777::1(src lladdr: 00:60:08:d1:a4:03) (len 32, hlim 255)
21:59:51.870875 2001:888:1777::1 > 2001:888:1777:0:260:8ff:fed1:a403: icmp6: neighbor adv: tgt is 2001:888:1777::1(RS) (len 24, hlim 255)
21:59:51.874254 fe80::200:24ff:fec0:7bf4 > fe80::260:8ff:fed1:a403: icmp6: neighbor sol: who has fe80::260:8ff:fed1:a403(src lladdr: 00:00:24:c0:7b:f4) (len 32, hlim 255)
21:59:51.874347 fe80::260:8ff:fed1:a403 > fe80::200:24ff:fec0:7bf4: icmp6: neighbor adv: tgt is fe80::260:8ff:fed1:a403(S) (len 24, hlim 255)
^C
63 packets received by filter
0 packets dropped by kernel
#
xterm 2:
$ ./a.out einstein.nlnetlabs.nl 0
sendto()
sleep()
sendto()
$
---------------------------------------------------------------------------
This is what I noticed in udp6_usrreq.c:
revision 1.34
date: 2000/10/19 01:14:13; author: itojun; state: Exp; lines: +52 -8
validate ICMPv6 too big message.
XXX too restrictive given frequent uses of sendto(2)
Commenting out the #if 0 in line 215 did not help. When using sendto()
in6_pcblookup_connect() and in6_pcblookup_bind() both return 0.
Could you have a look at this again please?
rvdp
--45Z9DzgjV8m4Oswq
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="test.c"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#define DELAY 5
int
main(int argc, char **argv)
{
struct sockaddr_in6 src, dst;
socklen_t srclen, dstlen;
int s, err;
char msg[1400];
struct addrinfo hints, *res;
if (argc != 3) {
printf("usage: %s host 0|1\n");
exit(EXIT_FAILURE);
}
memset(&hints, '\0', sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
err = getaddrinfo(argv[1], "domain", &hints, &res);
if (err) {
printf("invalid address %s\n", argv[1]);
exit(EXIT_FAILURE);
}
memcpy(&dst, res->ai_addr, res->ai_addrlen);
dstlen = res->ai_addrlen;
freeaddrinfo(res);
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
memset(&hints, '\0', sizeof(struct addrinfo));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
err = getaddrinfo("bones.rvdp.org", "54321", &hints, &res);
if (err) {
printf("invalid address bones.rvdp.org\n");
exit(EXIT_FAILURE);
}
memcpy(&src, res->ai_addr, res->ai_addrlen);
srclen = res->ai_addrlen;
freeaddrinfo(res);
if (atoi(argv[2])) {
printf("connect()\n");
if (connect(s, (struct sockaddr *) &dst, dstlen) == -1) {
perror("connect");
exit(EXIT_FAILURE);
}
printf("send()\n");
if (send(s, msg, sizeof(msg), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
printf("sleep()\n");
sleep(DELAY);
printf("send()\n");
if (send(s, msg, sizeof(msg), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
} else {
printf("sendto()\n");
if (sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &dst,
dstlen) == -1) {
perror("sendto");
exit(EXIT_FAILURE);
}
printf("sleep()\n");
sleep(DELAY);
printf("sendto()\n");
if (sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &dst,
dstlen) == -1) {
perror("sendto");
exit(EXIT_FAILURE);
}
}
}
--45Z9DzgjV8m4Oswq--