@@ -577,5 +577,123 @@ BOOST_AUTO_TEST_CASE(pcp_ipv4_fail_unsupported_version)
577
577
BOOST_CHECK_EQUAL (*err, MappingError::UNSUPP_VERSION);
578
578
}
579
579
580
+ // NAT-PMP IPv4 protocol error scenarii.
581
+ BOOST_AUTO_TEST_CASE (natpmp_protocol_error)
582
+ {
583
+ // First scenario: non-0 result code when requesting external IP.
584
+ std::vector<TestOp> script{
585
+ {
586
+ 0ms, TestOp::SEND,
587
+ {
588
+ 0x00 , 0x00 , // version, opcode (request external IP)
589
+ }, 0
590
+ },
591
+ {
592
+ 2ms, TestOp::RECV,
593
+ {
594
+ 0x00 , 0x80 , 0x00 , 0x42 , // version, opcode (external IP), result code (*NOT* success)
595
+ 0x66 , 0xfd , 0xa1 , 0xee , // seconds sinds start of epoch
596
+ 0x01 , 0x02 , 0x03 , 0x04 , // external IP address
597
+ }, 0
598
+ },
599
+ };
600
+ CreateSock = [this , &script](int domain, int type, int protocol) {
601
+ if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);
602
+ return std::unique_ptr<PCPTestSock>();
603
+ };
604
+
605
+ auto res = NATPMPRequestPortMap (default_gateway_ipv4, 1234 , 1000 , 1 , 200ms);
606
+
607
+ MappingError* err = std::get_if<MappingError>(&res);
608
+ BOOST_REQUIRE (err);
609
+ BOOST_CHECK_EQUAL (*err, MappingError::PROTOCOL_ERROR);
610
+
611
+ // First scenario: non-0 result code when requesting port mapping.
612
+ script = {
613
+ {
614
+ 0ms, TestOp::SEND,
615
+ {
616
+ 0x00 , 0x00 , // version, opcode (request external IP)
617
+ }, 0
618
+ },
619
+ {
620
+ 2ms, TestOp::RECV,
621
+ {
622
+ 0x00 , 0x80 , 0x00 , 0x00 , // version, opcode (external IP), result code (success)
623
+ 0x66 , 0xfd , 0xa1 , 0xee , // seconds sinds start of epoch
624
+ 0x01 , 0x02 , 0x03 , 0x04 , // external IP address
625
+ }, 0
626
+ },
627
+ {
628
+ 0ms, TestOp::SEND,
629
+ {
630
+ 0x00 , 0x02 , 0x00 , 0x00 , // version, opcode (request map TCP)
631
+ 0x04 , 0xd2 , 0x04 , 0xd2 , // internal port, suggested external port
632
+ 0x00 , 0x00 , 0x03 , 0xe8 , // requested mapping lifetime in seconds
633
+ }, 0
634
+ },
635
+ {
636
+ 2ms, TestOp::RECV,
637
+ {
638
+ 0x00 , 0x82 , 0x00 , 0x43 , // version, opcode (mapped TCP)
639
+ 0x66 , 0xfd , 0xa1 , 0xee , // seconds sinds start of epoch
640
+ 0x04 , 0xd2 , 0x04 , 0xd2 , // internal port, mapped external port
641
+ 0x00 , 0x00 , 0x01 , 0xf4 , // mapping lifetime in seconds
642
+ }, 0
643
+ },
644
+ };
645
+ CreateSock = [this , &script](int domain, int type, int protocol) {
646
+ if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);
647
+ return std::unique_ptr<PCPTestSock>();
648
+ };
649
+
650
+ res = NATPMPRequestPortMap (default_gateway_ipv4, 1234 , 1000 , 1 , 200ms);
651
+
652
+ err = std::get_if<MappingError>(&res);
653
+ BOOST_REQUIRE (err);
654
+ BOOST_CHECK_EQUAL (*err, MappingError::PROTOCOL_ERROR);
655
+ }
656
+
657
+ // PCP IPv4 protocol error scenario.
658
+ BOOST_AUTO_TEST_CASE (pcp_protocol_error)
659
+ {
660
+ const std::vector<TestOp> script{
661
+ {
662
+ 0ms, TestOp::SEND,
663
+ {
664
+ 0x02 , 0x01 , 0x00 , 0x00 , // version, opcode
665
+ 0x00 , 0x00 , 0x03 , 0xe8 , // lifetime
666
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xff , 0xff , 0xc0 , 0xa8 , 0x00 , 0x06 , // internal IP
667
+ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xaa , 0xbb , 0xcc , // nonce
668
+ 0x06 , 0x00 , 0x00 , 0x00 , // protocol (TCP), reserved
669
+ 0x04 , 0xd2 , 0x04 , 0xd2 , // internal port, suggested external port
670
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 , 0x00 , 0x00 , // suggested external IP
671
+ }, 0
672
+ },
673
+ {
674
+ 250ms, TestOp::RECV, // 250ms delay before answer
675
+ {
676
+ 0x02 , 0x81 , 0x00 , 0x42 , // version, opcode, result error
677
+ 0x00 , 0x00 , 0x01 , 0xf4 , // granted lifetime
678
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , // reserved
679
+ 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 , 0xaa , 0xbb , 0xcc , // nonce
680
+ 0x06 , 0x00 , 0x00 , 0x00 , // protocol (TCP), reserved
681
+ 0x04 , 0xd2 , 0x04 , 0xd2 , // internal port, assigned external port
682
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xff , 0xff , 0x01 , 0x02 , 0x03 , 0x04 , // assigned external IP
683
+ }, 0
684
+ },
685
+ };
686
+ CreateSock = [this , &script](int domain, int type, int protocol) {
687
+ if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) return std::make_unique<PCPTestSock>(default_local_ipv4, default_gateway_ipv4, script);
688
+ return std::unique_ptr<PCPTestSock>();
689
+ };
690
+
691
+ auto res = PCPRequestPortMap (TEST_NONCE, default_gateway_ipv4, bind_any_ipv4, 1234 , 1000 , 1 , 1000ms);
692
+
693
+ MappingError* err = std::get_if<MappingError>(&res);
694
+ BOOST_REQUIRE (err);
695
+ BOOST_CHECK_EQUAL (*err, MappingError::PROTOCOL_ERROR);
696
+ }
697
+
580
698
BOOST_AUTO_TEST_SUITE_END ()
581
699
0 commit comments