Subject: IP packet length patch for 1.2
To: None <netbsd-users@NetBSD.ORG>
From: Jason Thorpe <thorpej@OG.ORG>
List: netbsd-users
Date: 04/23/1997 21:27:52
Attached below is the IP packet length changes I recently committed to
NetBSD-current, merged into NetBSD 1.2.  They should work fine... They
merged into 1.2 trivially.

I want to make sure these get in the first official patch, so please
let me know if there are any problems with them.

--------------------------------------------------------------------------
Jason R. Thorpe                                             thorpej@OG.ORG

          Just me and my collection of obsolete computer gear(s).

 ----- snip -----

Index: ip.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip.h,v
retrieving revision 1.9
diff -c -r1.9 ip.h
*** ip.h	1995/05/15 01:22:44	1.9
--- ip.h	1996/10/26 18:37:07
***************
*** 43,52 ****
  
  /*
   * Structure of an internet header, naked of options.
-  *
-  * We declare ip_len and ip_off to be short, rather than u_short
-  * pragmatically since otherwise unsigned comparisons can result
-  * against negative integers quite easily, and fail in subtle ways.
   */
  struct ip {
  #if BYTE_ORDER == LITTLE_ENDIAN
--- 43,48 ----
***************
*** 58,66 ****
  		  ip_hl:4;		/* header length */
  #endif
  	u_int8_t  ip_tos;		/* type of service */
! 	int16_t	  ip_len;		/* total length */
  	u_int16_t ip_id;		/* identification */
! 	int16_t	  ip_off;		/* fragment offset field */
  #define	IP_DF 0x4000			/* dont fragment flag */
  #define	IP_MF 0x2000			/* more fragments flag */
  #define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */
--- 54,62 ----
  		  ip_hl:4;		/* header length */
  #endif
  	u_int8_t  ip_tos;		/* type of service */
! 	u_int16_t ip_len;		/* total length */
  	u_int16_t ip_id;		/* identification */
! 	u_int16_t ip_off;		/* fragment offset field */
  #define	IP_DF 0x4000			/* dont fragment flag */
  #define	IP_MF 0x2000			/* more fragments flag */
  #define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */
Index: ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.30
diff -c -r1.30 ip_input.c
*** ip_input.c	1996/03/16 23:53:58	1.30
--- ip_input.c	1996/10/26 18:37:21
***************
*** 531,540 ****
  		return (0);
  
  	/*
! 	 * Reassembly is complete; concatenate fragments.
  	 */
  	q = fp->ipq_fragq.lh_first;
  	ip = q->ipqe_ip;
  	m = dtom(q->ipqe_ip);
  	t = m->m_next;
  	m->m_next = 0;
--- 531,546 ----
  		return (0);
  
  	/*
! 	 * Reassembly is complete.  Check for a bogus message size and
! 	 * concatenate fragments.
  	 */
  	q = fp->ipq_fragq.lh_first;
  	ip = q->ipqe_ip;
+ 	if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
+ 		ipstat.ips_toolong++;
+ 		ip_freef(fp);
+ 		return (0);
+ 	}
  	m = dtom(q->ipqe_ip);
  	t = m->m_next;
  	m->m_next = 0;
Index: ip_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_var.h,v
retrieving revision 1.16
diff -c -r1.16 ip_var.h
*** ip_var.h	1996/02/13 23:43:20	1.16
--- ip_var.h	1996/10/26 18:37:26
***************
*** 41,51 ****
   * Overlay for ip header used by other protocols (tcp, udp).
   */
  struct ipovly {
! 	u_int8_t ih_x1[9];		/* (unused) */
! 	u_int8_t ih_pr;			/* protocol */
! 	int16_t	 ih_len;		/* protocol length */
! 	struct	 in_addr ih_src;	/* source internet address */
! 	struct	 in_addr ih_dst;	/* destination internet address */
  };
  
  /*
--- 41,51 ----
   * Overlay for ip header used by other protocols (tcp, udp).
   */
  struct ipovly {
! 	u_int8_t  ih_x1[9];		/* (unused) */
! 	u_int8_t  ih_pr;		/* protocol */
! 	u_int16_t ih_len;		/* protocol length */
! 	struct	  in_addr ih_src;	/* source internet address */
! 	struct	  in_addr ih_dst;	/* destination internet address */
  };
  
  /*
***************
*** 143,148 ****
--- 143,149 ----
  	u_long	ips_rawout;		/* total raw ip packets generated */
  	u_long	ips_badfrags;		/* malformed fragments (bad length) */
  	u_long	ips_rcvmemdrop;		/* frags dropped for lack of memory */
+ 	u_long	ips_toolong;		/* ip length > max ip packet size */
  };
  
  #ifdef _KERNEL
Index: raw_ip.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/raw_ip.c,v
retrieving revision 1.25
diff -c -r1.25 raw_ip.c
*** raw_ip.c	1996/02/18 18:58:33	1.25
--- raw_ip.c	1996/10/26 18:37:28
***************
*** 171,176 ****
--- 171,180 ----
  	 * Otherwise, allocate an mbuf for a header and fill it in.
  	 */
  	if ((inp->inp_flags & INP_HDRINCL) == 0) {
+ 		if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
+ 			m_freem(m);
+ 			return (EMSGSIZE);
+ 		}
  		M_PREPEND(m, sizeof(struct ip), M_WAIT);
  		ip = mtod(m, struct ip *);
  		ip->ip_tos = 0;
***************
*** 182,187 ****
--- 186,195 ----
  		ip->ip_ttl = MAXTTL;
  		opts = inp->inp_options;
  	} else {
+ 		if (m->m_pkthdr.len > IP_MAXPACKET) {
+ 			m_freem(m);
+ 			return (EMSGSIZE);
+ 		}
  		ip = mtod(m, struct ip *);
  		if (ip->ip_id == 0)
  			ip->ip_id = htons(ip_id++);
Index: udp.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp.h,v
retrieving revision 1.6
diff -c -r1.6 udp.h
*** udp.h	1995/04/13 06:37:10	1.6
--- udp.h	1996/10/26 18:37:29
***************
*** 1,4 ****
! /*	$NetBSD: udp.h,v 1.6 1995/04/13 06:37:10 cgd Exp $	*/
  
  /*
   * Copyright (c) 1982, 1986, 1993
--- 1,4 ----
! /*	$NetBSD: udp.h,v 1.7 1996/10/25 06:22:25 thorpej Exp $	*/
  
  /*
   * Copyright (c) 1982, 1986, 1993
***************
*** 42,47 ****
  struct udphdr {
  	u_int16_t uh_sport;		/* source port */
  	u_int16_t uh_dport;		/* destination port */
! 	int16_t	  uh_ulen;		/* udp length */
  	u_int16_t uh_sum;		/* udp checksum */
  };
--- 42,47 ----
  struct udphdr {
  	u_int16_t uh_sport;		/* source port */
  	u_int16_t uh_dport;		/* destination port */
! 	u_int16_t uh_ulen;		/* udp length */
  	u_int16_t uh_sum;		/* udp checksum */
  };
Index: udp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.29
diff -c -r1.29 udp_usrreq.c
*** udp_usrreq.c	1996/05/20 16:56:20	1.29
--- udp_usrreq.c	1996/10/26 18:37:35
***************
*** 462,467 ****
--- 462,476 ----
  	}
  
  	/*
+ 	 * Compute the packet length of the IP header, and
+ 	 * punt if the length looks bogus.
+ 	 */
+ 	if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
+ 		error = EMSGSIZE;
+ 		goto release;
+ 	}
+ 
+ 	/*
  	 * Fill in mbuf with extended UDP header
  	 * and addresses and length put into network format.
  	 */