[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(usagi-users 03061) Bug in function inet6_rth_add of libinet6.a



kernel: 2.4.20-30.7.legacy (Redhat 7.3, non USAGI)
Usagi versions tested:  usagi-tool-stable-20030214.tar.bz2 and
                         usagi-linux24-s20040927.tar.bz2
glibc: glibc-2.2.5-44

Description
===========
The function inet6_rth_add inlibinet6.a which adds an entry in a IPv6
routing header option does not work. It adds the entry at a wrong offset.

Note: By comparison with the libinet rthdr code in KAME FreeBSD code,
the functions inet6_rthdr_getaddr inet6_rth_reverse inet6_rth_getaddr
are also probably incorrect.

How to test
===========
Write a program which send a packet which sendmsg and a routing option
created
with inet6_rth_* with 2 routing segments
(the program works with FreeBSD4/Kame, Solaris 10, FreeBSD5),
and dump the control buffer of the sendmsg:
(gdb) n
105         ret = sendmsg(sock, &msg, flags);
(gdb) p msg
$2 = {msg_name = 0x804dd78, msg_namelen = 28, msg_iov = 0xbfffe220,
   msg_iovlen = 1, msg_control = 0x804dda8, msg_controllen = 52,
msg_flags = 0}
(gdb)  x/3wx 0x804dda8
0x804dda8:      0x00000034      0x00000029      0x00000005
(gdb)  x/40bx
0x804ddb4:  0x00    0x04    0x00    0x02    0x00    0x00    0x00    0x00
0x804ddbc:  0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x804ddc4:  0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x804ddcc:  0x20    0x01    0x02    0x00    0x00    0x00    0x80    0x02
0x804ddd4:  0x02    0x03    0x47    0xff    0xfe    0xa5    0x30    0x85
(gdb) c
Continuing.
send_data: sendmsg: Network is unreachable
send_echo_request6: : Illegal seek

One see that the first routing segment address (at 0x804ddbc) is null
and the second one (at 0x804ddcc) contains an IPv6 address whih is the
first relay address.

Cause
=====
The bug comes from an incorrect use or declaration of struct ip6_rthdr0
in libinet6/rthdr.c and libinet6/include_glibc/netinet/ip6.h:
In libinet6/include_glibc/netinet/ip6.h the struct ip6_rthdr0 is
/* Type 0 Routing header */
struct ip6_rthdr0
   {
     uint8_t  ip6r0_nxt;       /* next header */
     uint8_t  ip6r0_len;       /* length in units of 8 octets */
     uint8_t  ip6r0_type;      /* always zero */
     uint8_t  ip6r0_segleft;   /* segments left */
     uint8_t  ip6r0_reserved;  /* reserved field */
     uint8_t  ip6r0_slmap[3];  /* strict/loose bit map */
     struct in6_addr  ip6r0_addr[1];  /* XXX: removed in RFC2292bis */
   };

but in libinet6/rthdr.c the first address is supposed to be at
nextaddr = (struct in6_addr *)(rth0 + 1)
that is AFTER the ip6r0_addr field.

How to correct
=============
There is 2 possible corrections
- Either correct "struct ip6_rthdr0" in
libinet6/include_glibc/netinet/ip6.h by suppressing the removed field
ip6r0_addr[1], in concordance with the latest RFC 3542
(and adding comment: /* followed by up to 127 struct in6_addr */)

That is the FreeBSD/KAME solution
this can impact on other functions, at least net6_rthdr_space and
inet6_rthdr_init
Suppressing the -DCOMPAT_RFC2292 flag in the Makefile.in should correct
this.
Also the file libinet6/include_glibc/netinet/ip6.h diverges with the
kernel linux /usr/include/netinet/ip6.h (but respects the latest RFC)

- Or correct libinet6/rthdr.c with the following patch:
diff -u rthdr.c*
--- rthdr.c     Wed May 15 07:45:20 2002
+++ rthdr.c.NEW Thu Oct  7 18:13:01 2004
@@ -414,7 +414,7 @@
         switch(rth->ip6r_type) {
         case IPV6_RTHDR_TYPE_0:
                 rth0 = (struct ip6_rthdr0 *)rth;
-               nextaddr = (struct in6_addr *)(rth0 + 1) +
                 rth0->ip6r0_segleft;
+               nextaddr = &rth0->ip6r0_addr[rth0->ip6r0_segleft];
                 *nextaddr = *addr;
                 rth0->ip6r0_segleft++;
                 break;

However the functions inet6_rthdr_getaddr inet6_rth_reverse and
inet6_rth_getaddr should probably be corrected in the same manner.

--
Jean-Luc RICHIER (Jean-Luc.Richier@xxxxxxx  richier@xxxxxxx)
Laboratoire Logiciels, Systemes et Reseaux (LSR-IMAG)
IMAG-CAMPUS, BP 72, F-38402 St Martin d'Heres Cedex
Tel : +33 4 76 82 72 32 Fax : +33 4 76 82 72 87