|  | @@ -457,9 +457,7 @@ struct dhcpv6_session {
 | 
		
	
		
			
			| 457 | 457 |  	/** Start time (in ticks) */
 | 
		
	
		
			
			| 458 | 458 |  	unsigned long start;
 | 
		
	
		
			
			| 459 | 459 |  	/** Client DUID */
 | 
		
	
		
			
			| 460 |  | -	void *client_duid;
 | 
		
	
		
			
			| 461 |  | -	/** Client DUID length */
 | 
		
	
		
			
			| 462 |  | -	size_t client_duid_len;
 | 
		
	
		
			
			|  | 460 | +	struct dhcpv6_duid_uuid client_duid;
 | 
		
	
		
			
			| 463 | 461 |  	/** Server DUID, if known */
 | 
		
	
		
			
			| 464 | 462 |  	void *server_duid;
 | 
		
	
		
			
			| 465 | 463 |  	/** Server DUID length */
 | 
		
	
	
		
			
			|  | @@ -578,7 +576,8 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
 | 
		
	
		
			
			| 578 | 576 |  	int rc;
 | 
		
	
		
			
			| 579 | 577 |  
 | 
		
	
		
			
			| 580 | 578 |  	/* Calculate lengths */
 | 
		
	
		
			
			| 581 |  | -	client_id_len = ( sizeof ( *client_id ) + dhcpv6->client_duid_len );
 | 
		
	
		
			
			|  | 579 | +	client_id_len = ( sizeof ( *client_id ) +
 | 
		
	
		
			
			|  | 580 | +			  sizeof ( dhcpv6->client_duid ) );
 | 
		
	
		
			
			| 582 | 581 |  	server_id_len = ( dhcpv6->server_duid ? ( sizeof ( *server_id ) +
 | 
		
	
		
			
			| 583 | 582 |  						  dhcpv6->server_duid_len ) :0);
 | 
		
	
		
			
			| 584 | 583 |  	if ( dhcpv6->state->flags & DHCPV6_TX_IA_NA ) {
 | 
		
	
	
		
			
			|  | @@ -614,8 +613,8 @@ static int dhcpv6_tx ( struct dhcpv6_session *dhcpv6 ) {
 | 
		
	
		
			
			| 614 | 613 |  	client_id->header.code = htons ( DHCPV6_CLIENT_ID );
 | 
		
	
		
			
			| 615 | 614 |  	client_id->header.len = htons ( client_id_len -
 | 
		
	
		
			
			| 616 | 615 |  					sizeof ( client_id->header ) );
 | 
		
	
		
			
			| 617 |  | -	memcpy ( client_id->duid, dhcpv6->client_duid,
 | 
		
	
		
			
			| 618 |  | -		 dhcpv6->client_duid_len );
 | 
		
	
		
			
			|  | 616 | +	memcpy ( client_id->duid, &dhcpv6->client_duid,
 | 
		
	
		
			
			|  | 617 | +		 sizeof ( dhcpv6->client_duid ) );
 | 
		
	
		
			
			| 619 | 618 |  
 | 
		
	
		
			
			| 620 | 619 |  	/* Construct server identifier, if applicable */
 | 
		
	
		
			
			| 621 | 620 |  	if ( server_id_len ) {
 | 
		
	
	
		
			
			|  | @@ -748,8 +747,8 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
 | 
		
	
		
			
			| 748 | 747 |  
 | 
		
	
		
			
			| 749 | 748 |  	/* Verify client identifier */
 | 
		
	
		
			
			| 750 | 749 |  	if ( ( rc = dhcpv6_check_duid ( &options, DHCPV6_CLIENT_ID,
 | 
		
	
		
			
			| 751 |  | -					dhcpv6->client_duid,
 | 
		
	
		
			
			| 752 |  | -					dhcpv6->client_duid_len ) ) != 0 ) {
 | 
		
	
		
			
			|  | 750 | +					&dhcpv6->client_duid,
 | 
		
	
		
			
			|  | 751 | +					sizeof ( dhcpv6->client_duid ) ) ) !=0){
 | 
		
	
		
			
			| 753 | 752 |  		DBGC ( dhcpv6, "DHCPv6 %s received %s without correct client "
 | 
		
	
		
			
			| 754 | 753 |  		       "ID: %s\n", dhcpv6->netdev->name,
 | 
		
	
		
			
			| 755 | 754 |  		       dhcpv6_type_name ( dhcphdr->type ), strerror ( rc ) );
 | 
		
	
	
		
			
			|  | @@ -904,14 +903,12 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 | 
		
	
		
			
			| 904 | 903 |  			struct sockaddr sa;
 | 
		
	
		
			
			| 905 | 904 |  		} server;
 | 
		
	
		
			
			| 906 | 905 |  	} addresses;
 | 
		
	
		
			
			| 907 |  | -	struct dhcpv6_duid_ll *client_duid;
 | 
		
	
		
			
			| 908 |  | -	size_t client_duid_len;
 | 
		
	
		
			
			| 909 | 906 |  	uint32_t xid;
 | 
		
	
		
			
			|  | 907 | +	int len;
 | 
		
	
		
			
			| 910 | 908 |  	int rc;
 | 
		
	
		
			
			| 911 | 909 |  
 | 
		
	
		
			
			| 912 | 910 |  	/* Allocate and initialise structure */
 | 
		
	
		
			
			| 913 |  | -	client_duid_len = ( sizeof ( *client_duid ) + ll_protocol->ll_addr_len);
 | 
		
	
		
			
			| 914 |  | -	dhcpv6 = zalloc ( sizeof ( *dhcpv6 ) + client_duid_len );
 | 
		
	
		
			
			|  | 911 | +	dhcpv6 = zalloc ( sizeof ( *dhcpv6 ) );
 | 
		
	
		
			
			| 915 | 912 |  	if ( ! dhcpv6 )
 | 
		
	
		
			
			| 916 | 913 |  		return -ENOMEM;
 | 
		
	
		
			
			| 917 | 914 |  	ref_init ( &dhcpv6->refcnt, dhcpv6_free );
 | 
		
	
	
		
			
			|  | @@ -921,8 +918,6 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 | 
		
	
		
			
			| 921 | 918 |  	xid = random();
 | 
		
	
		
			
			| 922 | 919 |  	memcpy ( dhcpv6->xid, &xid, sizeof ( dhcpv6->xid ) );
 | 
		
	
		
			
			| 923 | 920 |  	dhcpv6->start = currticks();
 | 
		
	
		
			
			| 924 |  | -	dhcpv6->client_duid = ( ( ( void * ) dhcpv6 ) + sizeof ( *dhcpv6 ) );
 | 
		
	
		
			
			| 925 |  | -	dhcpv6->client_duid_len = client_duid_len;
 | 
		
	
		
			
			| 926 | 921 |  	timer_init ( &dhcpv6->timer, dhcpv6_timer_expired, &dhcpv6->refcnt );
 | 
		
	
		
			
			| 927 | 922 |  
 | 
		
	
		
			
			| 928 | 923 |  	/* Construct client and server addresses */
 | 
		
	
	
		
			
			|  | @@ -935,12 +930,17 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 | 
		
	
		
			
			| 935 | 930 |  	addresses.server.sin6.sin6_scope_id = netdev->index;
 | 
		
	
		
			
			| 936 | 931 |  	addresses.server.sin6.sin6_port = htons ( DHCPV6_SERVER_PORT );
 | 
		
	
		
			
			| 937 | 932 |  
 | 
		
	
		
			
			| 938 |  | -	/* Construct client DUID and IAID from link-layer address */
 | 
		
	
		
			
			| 939 |  | -	client_duid = dhcpv6->client_duid;
 | 
		
	
		
			
			| 940 |  | -	client_duid->type = htons ( DHCPV6_DUID_LL );
 | 
		
	
		
			
			| 941 |  | -	client_duid->htype = ll_protocol->ll_proto;
 | 
		
	
		
			
			| 942 |  | -	memcpy ( client_duid->ll_addr, netdev->ll_addr,
 | 
		
	
		
			
			| 943 |  | -		 ll_protocol->ll_addr_len );
 | 
		
	
		
			
			|  | 933 | +	/* Construct client DUID from system UUID */
 | 
		
	
		
			
			|  | 934 | +	dhcpv6->client_duid.type = htons ( DHCPV6_DUID_UUID );
 | 
		
	
		
			
			|  | 935 | +	if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting,
 | 
		
	
		
			
			|  | 936 | +					  &dhcpv6->client_duid.uuid ) ) < 0 ) {
 | 
		
	
		
			
			|  | 937 | +		rc = len;
 | 
		
	
		
			
			|  | 938 | +		DBGC ( dhcpv6, "DHCPv6 %s could not create DUID-UUID: %s\n",
 | 
		
	
		
			
			|  | 939 | +		       dhcpv6->netdev->name, strerror ( rc ) );
 | 
		
	
		
			
			|  | 940 | +		goto err_client_duid;
 | 
		
	
		
			
			|  | 941 | +	}
 | 
		
	
		
			
			|  | 942 | +
 | 
		
	
		
			
			|  | 943 | +	/* Construct IAID from link-layer address */
 | 
		
	
		
			
			| 944 | 944 |  	dhcpv6->iaid = crc32_le ( 0, netdev->ll_addr, ll_protocol->ll_addr_len);
 | 
		
	
		
			
			| 945 | 945 |  	DBGC ( dhcpv6, "DHCPv6 %s has XID %02x%02x%02x\n", dhcpv6->netdev->name,
 | 
		
	
		
			
			| 946 | 946 |  	       dhcpv6->xid[0], dhcpv6->xid[1], dhcpv6->xid[2] );
 | 
		
	
	
		
			
			|  | @@ -965,6 +965,7 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
 | 
		
	
		
			
			| 965 | 965 |  
 | 
		
	
		
			
			| 966 | 966 |   err_open_socket:
 | 
		
	
		
			
			| 967 | 967 |  	dhcpv6_finished ( dhcpv6, rc );
 | 
		
	
		
			
			|  | 968 | + err_client_duid:
 | 
		
	
		
			
			| 968 | 969 |  	ref_put ( &dhcpv6->refcnt );
 | 
		
	
		
			
			| 969 | 970 |  	return rc;
 | 
		
	
		
			
			| 970 | 971 |  }
 |