svn commit: r264162 - head/lib/libc/net

Marcel Moolenaar marcel at FreeBSD.org
Sat Apr 5 18:32:41 UTC 2014


Author: marcel
Date: Sat Apr  5 18:32:40 2014
New Revision: 264162
URL: http://svnweb.freebsd.org/changeset/base/264162

Log:
  Accept RFC 2292 option values so that RFC 2292 compliant programs that
  are unaware of RFC 3542 can construct control messages.
  
  The kernel disallows mixing RFC 2292 behaviour with RFC 3542 behaviour.
  Only sockets that have specifically been marked as using the RFC 2292
  API can use RFC 2292 specific options. This is all good and well, but
  libc itself seems inconsistent with this.
  
  The root cause of this inconsistency seems to relate to the definitions
  of IPV6_HOPOPTS and IPV6_DSTOPTS. They are defined in RFC 2292 and re-used
  in RFC 3542, yet have distinct values in the kernel. It's for this reason
  that the kernel also has definitions for IPV6_2292HOPOPTS and
  IPV6_2292DSTOPTS. Not so in libc.
  
  For example: some program calls inet6_option_init() (defined by RFC 2292)
  with the RFC 2292 defined IPV6_HOPOPTS and IPV6_DSTOPTS. Before RFC 3542,
  this was translated to values of 22 and 23 (resp.) The libc implementation
  correctly checks that only options IPV6_HOPOPTS and IPV6_DSTOPTS are given
  (as per RFC 2292) but since these defines have taken on the values defined
  by RFC 3542 (values 49 and 50 resp,) rejects the correct option values
  (22 and 23) passed said program and returns -1.
  
  The precisie fix is to have inet6_option_init() and friends only accept the
  RFC 2292 defined IPV6_HOPOPTS & IPV6_DSTOPTS, but that breaks other code
  (like mld6query(8)), which seem to not be aware of RFC 3542 and how it
  hi-jacked the option names. So the best fix is to accept the options from
  both.
  
  Obtained from:	Juniper Networks, Inc.
  MFC after:	1 week

Modified:
  head/lib/libc/net/ip6opt.c

Modified: head/lib/libc/net/ip6opt.c
==============================================================================
--- head/lib/libc/net/ip6opt.c	Sat Apr  5 18:14:58 2014	(r264161)
+++ head/lib/libc/net/ip6opt.c	Sat Apr  5 18:32:40 2014	(r264162)
@@ -45,6 +45,18 @@ __FBSDID("$FreeBSD$");
 static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
 static void inet6_insert_padopt(u_char *p, int len);
 
+#ifndef IPV6_2292HOPOPTS
+#define	IPV6_2292HOPOPTS	22
+#endif
+#ifndef IPV6_2292DSTOPTS
+#define	IPV6_2292DSTOPTS	23
+#endif
+
+#define	is_ipv6_hopopts(x)	\
+	((x) == IPV6_HOPOPTS || (x) == IPV6_2292HOPOPTS)
+#define	is_ipv6_dstopts(x)	\
+	((x) == IPV6_DSTOPTS || (x) == IPV6_2292DSTOPTS)
+
 /*
  * This function returns the number of bytes required to hold an option
  * when it is stored as ancillary data, including the cmsghdr structure
@@ -72,9 +84,9 @@ inet6_option_init(void *bp, struct cmsgh
 	struct cmsghdr *ch = (struct cmsghdr *)bp;
 
 	/* argument validation */
-	if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
+	if (!is_ipv6_hopopts(type) && !is_ipv6_dstopts(type))
 		return(-1);
-	
+
 	ch->cmsg_level = IPPROTO_IPV6;
 	ch->cmsg_type = type;
 	ch->cmsg_len = CMSG_LEN(0);
@@ -234,8 +246,8 @@ inet6_option_next(const struct cmsghdr *
 	u_int8_t *lim;
 
 	if (cmsg->cmsg_level != IPPROTO_IPV6 ||
-	    (cmsg->cmsg_type != IPV6_HOPOPTS &&
-	     cmsg->cmsg_type != IPV6_DSTOPTS))
+	    (!is_ipv6_hopopts(cmsg->cmsg_type) &&
+	     !is_ipv6_dstopts(cmsg->cmsg_type)))
 		return(-1);
 
 	/* message length validation */
@@ -290,8 +302,8 @@ inet6_option_find(const struct cmsghdr *
 	u_int8_t *optp, *lim;
 
 	if (cmsg->cmsg_level != IPPROTO_IPV6 ||
-	    (cmsg->cmsg_type != IPV6_HOPOPTS &&
-	     cmsg->cmsg_type != IPV6_DSTOPTS))
+	    (!is_ipv6_hopopts(cmsg->cmsg_type) &&
+	     !is_ipv6_dstopts(cmsg->cmsg_type)))
 		return(-1);
 
 	/* message length validation */


More information about the svn-src-all mailing list