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

(usagi-users 00642) ANYCAST + other fixes to ipv6_addr_type (addrconf.c)



	Below is a patch to add checking for the reserved ANYCAST addresses
specified in RFC2526 (EUI64 formats only, for now). While adding that, I
noticed that the code returned IPV6_ADDR_RESERVED for pieces of the address
space not listed as reserved in RFC2373. Specifically, addresses beginning
with 000 listed as unassigned (eg, (0000 0001)) are returned as reserved,
rather than IPV6_ADDR_UNICAST.
	The patch below should return the address types for RFC2526 and RFC2373;
it doesn't support non-EUI64 anycast addresses, or the required
(subnet prefix, all 0's) anycast address. I'm going to look into that, but
thought this was a useful first step. Let me know if you see any problems
with it.

							+-DLS

*** addrconf.c	2001/07/16 23:54:33	1.2
--- addrconf.c	2001/07/18 00:48:50
***************
*** 8,14 ****
   *	Pedro Roque		<roque@xxxxxxxxxxx>	
   *	Alexey Kuznetsov	<kuznet@xxxxxxxxxxxxx>
   *
!  *	$Id: addrconf.c,v 1.2 2001/07/16 23:54:33 dls Exp $
   *
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
--- 8,14 ----
   *	Pedro Roque		<roque@xxxxxxxxxxx>	
   *	Alexey Kuznetsov	<kuznet@xxxxxxxxxxxxx>
   *
!  *	$Id: addrconf.c,v 1.3 2001/07/18 00:47:51 dls Exp $
   *
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
***************
*** 214,232 ****
  
  int ipv6_addr_type(struct in6_addr *addr)
  {
! 	u32 st;
  
  	st = addr->s6_addr32[0];
  
- 	/* Consider all addresses with the first three bits different of
- 	   000 and 111 as unicasts.
- 	 */
- 	if ((st & __constant_htonl(0xE0000000)) != __constant_htonl(0x00000000) &&
- 	    (st & __constant_htonl(0xE0000000)) != __constant_htonl(0xE0000000))
- 		return IPV6_ADDR_UNICAST;
- 
  	if ((st & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000)) {
- 		int type;
  
  		switch((st & __constant_htonl(0x00FF0000))) {
  			case __constant_htonl(0x00010000):
--- 214,225 ----
  
  int ipv6_addr_type(struct in6_addr *addr)
  {
! 	int	type;
! 	u32	st;
  
  	st = addr->s6_addr32[0];
  
  	if ((st & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000)) {
  
  		switch((st & __constant_htonl(0x00FF0000))) {
  			case __constant_htonl(0x00010000):
***************
*** 245,256 ****
  		};
  		return type;
  	}
  	
  	if ((st & __constant_htonl(0xFFC00000)) == __constant_htonl(0xFE800000))
! 		return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST);
  
  	if ((st & __constant_htonl(0xFFC00000)) == __constant_htonl(0xFEC00000))
! 		return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST);
  
  	if ((st | addr->s6_addr32[1]) == 0) {
  		if (addr->s6_addr32[2] == 0) {
--- 238,264 ----
  		};
  		return type;
  	}
+ 	/* check for reserved anycast addresses */
+ 	
+ 	if ((st & __constant_htonl(0xE0000000)) &&
+ 	    addr->s6_addr32[2] == __constant_htonl(0xFDFFFFFF) &&
+ 	    (addr->s6_addr32[3] | __constant_htonl(0x7F)) == (u32)~0)
+ 		type = IPV6_ADDR_ANYCAST;
+ 	else
+ 		type = IPV6_ADDR_UNICAST;
+ 
+ 	/* Consider all addresses with the first three bits different of
+ 	   000 and 111 as finished.
+ 	 */
+ 	if ((st & __constant_htonl(0xE0000000)) != __constant_htonl(0x00000000) &&
+ 	    (st & __constant_htonl(0xE0000000)) != __constant_htonl(0xE0000000))
+ 		return type;
  	
  	if ((st & __constant_htonl(0xFFC00000)) == __constant_htonl(0xFE800000))
! 		return (IPV6_ADDR_LINKLOCAL | type);
  
  	if ((st & __constant_htonl(0xFFC00000)) == __constant_htonl(0xFEC00000))
! 		return (IPV6_ADDR_SITELOCAL | type);
  
  	if ((st | addr->s6_addr32[1]) == 0) {
  		if (addr->s6_addr32[2] == 0) {
***************
*** 258,273 ****
  				return IPV6_ADDR_ANY;
  
  			if (addr->s6_addr32[3] == __constant_htonl(0x00000001))
! 				return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST);
  
! 			return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST);
  		}
  
  		if (addr->s6_addr32[2] == __constant_htonl(0x0000ffff))
  			return IPV6_ADDR_MAPPED;
  	}
  
! 	return IPV6_ADDR_RESERVED;
  }
  
  static void addrconf_del_timer(struct inet6_ifaddr *ifp)
--- 266,289 ----
  				return IPV6_ADDR_ANY;
  
  			if (addr->s6_addr32[3] == __constant_htonl(0x00000001))
! 				return (IPV6_ADDR_LOOPBACK | type);
  
! 			return (IPV6_ADDR_COMPATv4 | type);
  		}
  
  		if (addr->s6_addr32[2] == __constant_htonl(0x0000ffff))
  			return IPV6_ADDR_MAPPED;
  	}
  
! 	st &= __constant_htonl(0xFF000000);
! 	if (st == 0)
! 		return IPV6_ADDR_RESERVED;
! 	st &= __constant_htonl(0xFE000000);
! 	if (st == __constant_htonl(0x02000000))
! 		return IPV6_ADDR_RESERVED;	/* for NSAP */
! 	if (st == __constant_htonl(0x04000000))
! 		return IPV6_ADDR_RESERVED;	/* for IPX */
! 	return type;
  }
  
  static void addrconf_del_timer(struct inet6_ifaddr *ifp)