kern/87306: IP_PORTRANGE_HIGH causes bad UDP checksum

Maxim Konovalov maxim at macomnet.ru
Wed Oct 12 01:50:18 PDT 2005


The following reply was made to PR kern/87306; it has been noted by GNATS.

From: Maxim Konovalov <maxim at macomnet.ru>
To: bms at freebsd.org
Cc: Rickard Lind <rickard.lind at ntier.se>, bug-followup at freebsd.org
Subject: Re: kern/87306: IP_PORTRANGE_HIGH causes bad UDP checksum
Date: Wed, 12 Oct 2005 12:41:06 +0400 (MSD)

 > >Description:
 > Due to a mixup of two fields, setting the socket option
 > IP_PORTRANGE_HIGH on a UDP socket in order to bind a high (random)
 > port affects the checksum calculation such that the resulting
 > checksum is incorrect.
 > >How-To-Repeat:
 > Create a UDP (SOCK_DGRAM) socket. Set the IP_PORTRANGE_HIGH socket
 > option. Bind with a zero port. Send some data to another host.
 > Ethereal on the receiveing host reports the UDP checksum as
 > incorrect.
 > >Fix:
 > The problem is that the flag INP_ONESBCAST has the same value (0x10)
 > as the flag INP_HIGHPORT in sys/netinet/in_pcb.h, and INP_ONESBCAST
 > is tested against the inp_flags field (in sys/netinet/udp_usrreq.c
 > and sys/netinet/raw_ip.c) when it SHOULD be tested against the
 > inp_vflag field. This causes the checksum calculation on line 867 in
 > udp_usrreq.c to use the broadcast address leading to an incorrect
 > checksum.
 
 Ricard, it seems you analysis is correct.  Thanks for the high quality
 bug report!
 
 Bruce, what is your opinion?
 
 Index: raw_ip.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/raw_ip.c,v
 retrieving revision 1.154
 diff -u -r1.154 raw_ip.c
 --- raw_ip.c	4 Oct 2005 18:19:21 -0000	1.154
 +++ raw_ip.c	12 Oct 2005 08:32:15 -0000
 @@ -316,7 +316,7 @@
  		ipstat.ips_rawout++;
  	}
 
 -	if (inp->inp_flags & INP_ONESBCAST)
 +	if (inp->inp_vflags & INP_ONESBCAST)
  		flags |= IP_SENDONES;
 
  #ifdef MAC
 Index: udp_usrreq.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/udp_usrreq.c,v
 retrieving revision 1.177
 diff -u -r1.177 udp_usrreq.c
 --- udp_usrreq.c	26 Sep 2005 20:25:16 -0000	1.177
 +++ udp_usrreq.c	12 Oct 2005 08:32:31 -0000
 @@ -860,14 +860,14 @@
  		ipflags |= IP_ROUTETOIF;
  	if (inp->inp_socket->so_options & SO_BROADCAST)
  		ipflags |= IP_ALLOWBROADCAST;
 -	if (inp->inp_flags & INP_ONESBCAST)
 +	if (inp->inp_vflags & INP_ONESBCAST)
  		ipflags |= IP_SENDONES;
 
  	/*
  	 * Set up checksum and output datagram.
  	 */
  	if (udpcksum) {
 -		if (inp->inp_flags & INP_ONESBCAST)
 +		if (inp->inp_vflags & INP_ONESBCAST)
  			faddr.s_addr = INADDR_BROADCAST;
  		ui->ui_sum = in_pseudo(ui->ui_src.s_addr, faddr.s_addr,
  		    htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP));
 %%%
 
 -- 
 Maxim Konovalov


More information about the freebsd-bugs mailing list