@@ -36,6 +36,9 @@ use crate::proto::evenport::EvenPort;
36
36
use crate :: proto:: lifetime:: * ;
37
37
use crate :: proto:: peeraddr:: PeerAddress ;
38
38
use crate :: proto:: relayaddr:: RelayedAddress ;
39
+ use crate :: proto:: reqfamily:: {
40
+ RequestedAddressFamily , REQUESTED_FAMILY_IPV4 , REQUESTED_FAMILY_IPV6 ,
41
+ } ;
39
42
use crate :: proto:: reqtrans:: RequestedTransport ;
40
43
use crate :: proto:: rsrvtoken:: ReservationToken ;
41
44
use crate :: proto:: * ;
@@ -299,6 +302,7 @@ impl Request {
299
302
} ;
300
303
let mut requested_port = 0 ;
301
304
let mut reservation_token = "" . to_owned ( ) ;
305
+ let mut use_ipv4 = true ;
302
306
303
307
// 2. The server checks if the 5-tuple is currently in use by an
304
308
// existing allocation. If yes, the server rejects the request with
@@ -397,7 +401,8 @@ impl Request {
397
401
// the token is not valid for some reason, the server rejects the
398
402
// request with a 508 (Insufficient Capacity) error.
399
403
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 ( ) {
401
406
let mut even_port = EvenPort :: default ( ) ;
402
407
if even_port. get_from ( m) . is_ok ( ) {
403
408
let bad_request_msg = build_msg (
@@ -418,6 +423,65 @@ impl Request {
418
423
}
419
424
}
420
425
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
+
421
485
// 6. The server checks if the request contains an EVEN-PORT attribute.
422
486
// If yes, then the server checks that it can satisfy the request
423
487
// (i.e., can allocate a relayed transport address as described
@@ -475,6 +539,7 @@ impl Request {
475
539
requested_port,
476
540
lifetime_duration,
477
541
username,
542
+ use_ipv4,
478
543
)
479
544
. await
480
545
{
@@ -570,6 +635,31 @@ impl Request {
570
635
if lifetime_duration != Duration :: from_secs ( 0 ) {
571
636
let a = self . allocation_manager . get_allocation ( & five_tuple) . await ;
572
637
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
+ }
573
663
a. refresh ( lifetime_duration) . await ;
574
664
} else {
575
665
return Err ( Error :: ErrNoAllocationFound ) ;
@@ -626,6 +716,30 @@ impl Request {
626
716
break ;
627
717
}
628
718
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
+
629
743
log:: debug!(
630
744
"adding permission for {}" ,
631
745
format!( "{}:{}" , peer_address. ip, peer_address. port)
@@ -734,9 +848,41 @@ impl Request {
734
848
}
735
849
736
850
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
+ )
739
859
. 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
+ }
740
886
}
741
887
742
888
log:: debug!(
0 commit comments