@@ -36,6 +36,9 @@ use crate::proto::evenport::EvenPort;
3636use crate :: proto:: lifetime:: * ;
3737use crate :: proto:: peeraddr:: PeerAddress ;
3838use crate :: proto:: relayaddr:: RelayedAddress ;
39+ use crate :: proto:: reqfamily:: {
40+ RequestedAddressFamily , REQUESTED_FAMILY_IPV4 , REQUESTED_FAMILY_IPV6 ,
41+ } ;
3942use crate :: proto:: reqtrans:: RequestedTransport ;
4043use crate :: proto:: rsrvtoken:: ReservationToken ;
4144use crate :: proto:: * ;
@@ -299,6 +302,7 @@ impl Request {
299302 } ;
300303 let mut requested_port = 0 ;
301304 let mut reservation_token = "" . to_owned ( ) ;
305+ let mut use_ipv4 = true ;
302306
303307 // 2. The server checks if the 5-tuple is currently in use by an
304308 // existing allocation. If yes, the server rejects the request with
@@ -397,7 +401,8 @@ impl Request {
397401 // the token is not valid for some reason, the server rejects the
398402 // request with a 508 (Insufficient Capacity) error.
399403 let mut reservation_token_attr = ReservationToken :: default ( ) ;
400- if reservation_token_attr. get_from ( m) . is_ok ( ) {
404+ let reservation_token_attr_result = reservation_token_attr. get_from ( m) ;
405+ if reservation_token_attr_result. is_ok ( ) {
401406 let mut even_port = EvenPort :: default ( ) ;
402407 if even_port. get_from ( m) . is_ok ( ) {
403408 let bad_request_msg = build_msg (
@@ -418,6 +423,65 @@ impl Request {
418423 }
419424 }
420425
426+ // RFC 6156, Section 4.2:
427+ //
428+ // If it contains both a RESERVATION-TOKEN and a
429+ // REQUESTED-ADDRESS-FAMILY, the server replies with a 400
430+ // (Bad Request) Allocate error response.
431+ //
432+ // 4.2.1. Unsupported Address Family
433+ // This document defines the following new error response code:
434+ // 440 (Address Family not Supported): The server does not support the
435+ // address family requested by the client.
436+ let mut req_family = RequestedAddressFamily :: default ( ) ;
437+ match req_family. get_from ( m) {
438+ Err ( err) => {
439+ // Currently, the RequestedAddressFamily::get_from() function returns
440+ // Err::Other only when it is an unsupported address family.
441+ if let stun:: Error :: Other ( _) = err {
442+ let addr_family_not_supported_msg = build_msg (
443+ m. transaction_id ,
444+ MessageType :: new ( METHOD_ALLOCATE , CLASS_ERROR_RESPONSE ) ,
445+ vec ! [ Box :: new( ErrorCodeAttribute {
446+ code: CODE_ADDR_FAMILY_NOT_SUPPORTED ,
447+ reason: vec![ ] ,
448+ } ) ] ,
449+ ) ?;
450+ return build_and_send_err (
451+ & self . conn ,
452+ self . src_addr ,
453+ addr_family_not_supported_msg,
454+ Error :: ErrInvalidRequestedFamilyValue ,
455+ )
456+ . await ;
457+ }
458+ }
459+ Ok ( ( ) ) => {
460+ if reservation_token_attr_result. is_ok ( ) {
461+ let bad_request_msg = build_msg (
462+ m. transaction_id ,
463+ MessageType :: new ( METHOD_ALLOCATE , CLASS_ERROR_RESPONSE ) ,
464+ vec ! [ Box :: new( ErrorCodeAttribute {
465+ code: CODE_BAD_REQUEST ,
466+ reason: vec![ ] ,
467+ } ) ] ,
468+ ) ?;
469+
470+ return build_and_send_err (
471+ & self . conn ,
472+ self . src_addr ,
473+ bad_request_msg,
474+ Error :: ErrRequestWithReservationTokenAndReqAddressFamily ,
475+ )
476+ . await ;
477+ }
478+
479+ if req_family == REQUESTED_FAMILY_IPV6 {
480+ use_ipv4 = false ;
481+ }
482+ }
483+ }
484+
421485 // 6. The server checks if the request contains an EVEN-PORT attribute.
422486 // If yes, then the server checks that it can satisfy the request
423487 // (i.e., can allocate a relayed transport address as described
@@ -475,6 +539,7 @@ impl Request {
475539 requested_port,
476540 lifetime_duration,
477541 username,
542+ use_ipv4,
478543 )
479544 . await
480545 {
@@ -570,6 +635,31 @@ impl Request {
570635 if lifetime_duration != Duration :: from_secs ( 0 ) {
571636 let a = self . allocation_manager . get_allocation ( & five_tuple) . await ;
572637 if let Some ( a) = a {
638+ // If a server receives a Refresh Request with a REQUESTED-ADDRESS-FAMILY
639+ // attribute, and the attribute's value doesn't match the address
640+ // family of the allocation, the server MUST reply with a 443 (Peer
641+ // Address Family Mismatch) Refresh error response. [RFC 6156, Section 5.2]
642+ let mut req_family = RequestedAddressFamily :: default ( ) ;
643+ if req_family. get_from ( m) . is_ok ( )
644+ && ( ( req_family == REQUESTED_FAMILY_IPV6 && !a. relay_addr . is_ipv6 ( ) )
645+ || ( req_family == REQUESTED_FAMILY_IPV4 && !a. relay_addr . is_ipv4 ( ) ) )
646+ {
647+ let peer_address_family_mismatch_msg = build_msg (
648+ m. transaction_id ,
649+ MessageType :: new ( METHOD_REFRESH , CLASS_ERROR_RESPONSE ) ,
650+ vec ! [ Box :: new( ErrorCodeAttribute {
651+ code: CODE_PEER_ADDR_FAMILY_MISMATCH ,
652+ reason: vec![ ] ,
653+ } ) ] ,
654+ ) ?;
655+ return build_and_send_err (
656+ & self . conn ,
657+ self . src_addr ,
658+ peer_address_family_mismatch_msg,
659+ Error :: ErrPeerAddressFamilyMismatch ,
660+ )
661+ . await ;
662+ }
573663 a. refresh ( lifetime_duration) . await ;
574664 } else {
575665 return Err ( Error :: ErrNoAllocationFound ) ;
@@ -626,6 +716,30 @@ impl Request {
626716 break ;
627717 }
628718
719+ // If an XOR-PEER-ADDRESS attribute contains an address of an address
720+ // family different than that of the relayed transport address for the
721+ // allocation, the server MUST generate an error response with the 443
722+ // (Peer Address Family Mismatch) response code. [RFC 6156, Section 6.2]
723+ if ( peer_address. ip . is_ipv4 ( ) && !a. relay_addr . is_ipv4 ( ) )
724+ || ( peer_address. ip . is_ipv6 ( ) && !a. relay_addr . is_ipv6 ( ) )
725+ {
726+ let peer_address_family_mismatch_msg = build_msg (
727+ m. transaction_id ,
728+ MessageType :: new ( METHOD_CREATE_PERMISSION , CLASS_ERROR_RESPONSE ) ,
729+ vec ! [ Box :: new( ErrorCodeAttribute {
730+ code: CODE_PEER_ADDR_FAMILY_MISMATCH ,
731+ reason: vec![ ] ,
732+ } ) ] ,
733+ ) ?;
734+ return build_and_send_err (
735+ & self . conn ,
736+ self . src_addr ,
737+ peer_address_family_mismatch_msg,
738+ Error :: ErrPeerAddressFamilyMismatch ,
739+ )
740+ . await ;
741+ }
742+
629743 log:: debug!(
630744 "adding permission for {}" ,
631745 format!( "{}:{}" , peer_address. ip, peer_address. port)
@@ -734,9 +848,41 @@ impl Request {
734848 }
735849
736850 let mut peer_addr = PeerAddress :: default ( ) ;
737- if let Err ( err) = peer_addr. get_from ( m) {
738- return build_and_send_err ( & self . conn , self . src_addr , bad_request_msg, err. into ( ) )
851+ match peer_addr. get_from ( m) {
852+ Err ( err) => {
853+ return build_and_send_err (
854+ & self . conn ,
855+ self . src_addr ,
856+ bad_request_msg,
857+ err. into ( ) ,
858+ )
739859 . await ;
860+ }
861+ _ => {
862+ // If the XOR-PEER-ADDRESS attribute contains an address of an address
863+ // family different than that of the relayed transport address for the
864+ // allocation, the server MUST generate an error response with the 443
865+ // (Peer Address Family Mismatch) response code. [RFC 6156, Section 7.2]
866+ if ( peer_addr. ip . is_ipv4 ( ) && !a. relay_addr . is_ipv4 ( ) )
867+ || ( peer_addr. ip . is_ipv6 ( ) && !a. relay_addr . is_ipv6 ( ) )
868+ {
869+ let peer_address_family_mismatch_msg = build_msg (
870+ m. transaction_id ,
871+ MessageType :: new ( METHOD_CHANNEL_BIND , CLASS_ERROR_RESPONSE ) ,
872+ vec ! [ Box :: new( ErrorCodeAttribute {
873+ code: CODE_PEER_ADDR_FAMILY_MISMATCH ,
874+ reason: vec![ ] ,
875+ } ) ] ,
876+ ) ?;
877+ return build_and_send_err (
878+ & self . conn ,
879+ self . src_addr ,
880+ peer_address_family_mismatch_msg,
881+ Error :: ErrPeerAddressFamilyMismatch ,
882+ )
883+ . await ;
884+ }
885+ }
740886 }
741887
742888 log:: debug!(
0 commit comments