net: Add NAT-PMP port forwarding support #18077

pull hebasto wants to merge 13 commits into bitcoin:master from hebasto:20200130-natpmp changing 33 files +547 −173
  1. hebasto commented at 9:02 pm on February 5, 2020: member

    Close #11902 This PR is an alternative to:

    To compile with NAT-PMP support on Ubuntu libnatpmp-dev should be available.

    Log excerpt:

    02020-02-05T20:12:28Z [mapport] NAT-PMP: public address = 95.164.65.194
    12020-02-05T20:12:28Z [mapport] AddLocal(95.164.65.194:18333,3)
    22020-02-05T20:12:28Z [mapport] NAT-PMP: port mapping successful.
    

    See: libnatpmp


    Some follow-ups are out of this PR’s scope:

    • mention NAT-PMP library in the version message
    • ~integrate NAT-PMP into the GUI~ (already added)
  2. DrahtBot added the label Build system on Feb 5, 2020
  3. DrahtBot added the label GUI on Feb 5, 2020
  4. DrahtBot added the label P2P on Feb 5, 2020
  5. DrahtBot commented at 11:18 pm on February 5, 2020: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #20864 (net: Move SocketSendData lock annotation to header by MarcoFalke)
    • #20744 ([POC] Use std::filesystem. Remove Boost Filesystem & System by fanquake)
    • #20487 (draft: Add syscall sandboxing using seccomp-bpf (Linux secure computing mode) by practicalswift)
    • #20201 (build: pkg-config related cleanup by hebasto)
    • #20196 (net: fix GetListenPort() to derive the proper port by vasild)
    • #19683 (depends: Pin clang search paths for darwin host by dongcarl)
    • #19064 (refactor: Cleanup thread ctor calls by hebasto)
    • #17920 (guix: Build support for macOS by dongcarl)
    • #16546 (External signer support - Wallet Box edition by Sjors)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  6. laanwj commented at 11:22 am on February 6, 2020: member
    Thanks for picking this up again. I hope we manage to do this this time.
  7. hebasto force-pushed on Feb 6, 2020
  8. in src/mapport.cpp:119 in 60e2524c8a outdated
    114+    }
    115+
    116+    closenatpmp(&natpmp);
    117+}
    118+
    119+#else // USE_UPNP
    


    luke-jr commented at 6:06 pm on February 6, 2020:
    This will break building with both NAT-PMP and UPnP support…

    hebasto commented at 6:14 pm on February 6, 2020:

    This will break building with both NAT-PMP and UPnP support…

    Yes, I’m aware of that. This PR in its current state is intended for NAT-PMP functionality tests and concept (N)ACKs.

  9. luke-jr commented at 6:16 pm on February 6, 2020: member
    Concept ACK
  10. hebasto force-pushed on Feb 7, 2020
  11. hebasto marked this as ready for review on Feb 7, 2020
  12. hebasto renamed this:
    [WIP] net: Add NAT-PMP port forwarding support
    net: Add NAT-PMP port forwarding support
    on Feb 7, 2020
  13. hebasto commented at 8:53 pm on February 7, 2020: member
    It is ready for reviewing now.
  14. hebasto force-pushed on Feb 7, 2020
  15. hebasto commented at 9:49 pm on February 7, 2020: member

    Updated 4ff5349a3172d02fceb976bf4989996c88f86680 -> cf94431e8f4bfd6636998a17e2355feb2c5c3d58 (pr18077.03 -> pr18077.04, compare):

    added libnatpmp package to macOS 10.14 native Travis build.

  16. hebasto commented at 8:17 am on February 8, 2020: member

    Updated cf94431e8f4bfd6636998a17e2355feb2c5c3d58 -> 88248a44241c8e3922a80729ce4a9a178ef2dbea (pr18077.04 -> pr18077.05, compare):

    added:

    • changes to docs
    • release notes
  17. DrahtBot added the label Needs rebase on Feb 10, 2020
  18. hebasto force-pushed on Feb 10, 2020
  19. hebasto commented at 5:20 pm on February 10, 2020: member
    Rebased after #17398 and #18081 have been merged.
  20. DrahtBot removed the label Needs rebase on Feb 10, 2020
  21. dongcarl assigned dongcarl on Feb 10, 2020
  22. dongcarl commented at 7:26 pm on February 10, 2020: member
    Concept ACK, will test on my home router.
  23. MarcoFalke removed the label Build system on Feb 10, 2020
  24. MarcoFalke removed the label GUI on Feb 10, 2020
  25. Sjors commented at 5:57 pm on February 11, 2020: member

    Concept ACK. Lightly tested configure / build on macOS.

    Unfortunately I’m behind a IPv6 DS-Lite router, I can’t test the IPv4 port forward. Perhaps -7 could be replaced by something more readable.

    02020-02-11T17:48:27Z natpmp thread start
    12020-02-11T17:48:27Z Bound to [::]:8333
    22020-02-11T17:48:27Z Bound to 0.0.0.0:8333
    32020-02-11T17:48:27Z init message: Loading P2P addresses...
    42020-02-11T17:48:27Z NAT-PMP: readnatpmpresponseorretry() for public address failed with -7 error.
    52020-02-11T17:48:27Z NAT-PMP: readnatpmpresponseorretry() for port mapping failed with -7 error. 
    

    I looked up the error code, and it’s what I would expect given my setup:

    0/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
    1#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
    

    Two suggesitons for followups, or this PR:

    • add checkbox in QT Settings (above UPNP)
    • add support for IPv6 pinhole if the library supports it, see #17012 (looks like it doesn’t)
  26. hebasto commented at 7:11 pm on February 11, 2020: member

    @Sjors

    Thank you for your review and testing.

    I looked up the error code, and it’s what I would expect given my setup:

    0/* NATPMP_ERR_NOGATEWAYSUPPORT : the gateway does not support NAT-PMP */
    1#define NATPMP_ERR_NOGATEWAYSUPPORT (-7)
    

    Agree. But in this initial PR I intentionally do not provide user-friendly error messages in order to keep ThreadNatpmp() dense and tight for easier reviewing ;)

    In followups every library call (initnatpmp(), sendpublicaddressrequest() and sendnewportmappingrequest()) with the following readnatpmpresponseorretry() loops could be refactored out to separate functions with user-friendly error messages.

    Two suggesitons for followups, or this PR:

    * add checkbox in QT Settings (above UPNP)
    

    Agree. From the OP:

    Some follow-ups are out of this PR’s scope:

    * mention NAT-PMP library in the version message
    
    * integrate NAT-PMP into the GUI
    
  27. in src/mapport.cpp:242 in c7e90ca40a outdated
    194+#endif // #ifdef USE_NATPMP
    195+            return;
    196+        }
    197+        case MapPort::UPNP: {
    198+#ifdef USE_UPNP
    199+            g_mapport_thread = std::thread((std::bind(&TraceThread<void (*)()>, "upnp", &ThreadUpnp)));
    


    luke-jr commented at 2:12 am on February 12, 2020:
    Won’t this overwrite the g_mapport_thread set above if both are enabled?

    hebasto commented at 7:10 am on February 12, 2020:
    I believe that the both port mapping protocols shouldn’t be enabled simultaneously: https://github.com/bitcoin/bitcoin/blob/c7e90ca40ad9b7c66f3429b792435e9279ceca6b/src/init.cpp#L1781-L1786

    luke-jr commented at 12:05 pm on February 12, 2020:
    It should be possible to enable both.

    Sjors commented at 12:26 pm on February 12, 2020:
    If both are enabled, would you try to open de port with NAT_PMP first and if that fails UPNP?

    hebasto commented at 12:31 pm on February 12, 2020:

    It should be possible to enable both.

    Do you mean that a router could do port mapping using both NAT-PMP and UPnP simultaneously? What is the reason for that?


    Sjors commented at 12:43 pm on February 12, 2020:
    I wouldn’t use them simultaneously, but one fails it makes sense to try the other. Though I believe our long plan is to remove UPnP, if NAT-PMP does the job.

    hebasto commented at 1:01 pm on February 12, 2020:

    I wouldn’t use them simultaneously, but one fails it makes sense to try the other.

    Good suggestion for a followup.

    Though I believe our long plan is to remove UPnP, if NAT-PMP does the job.

    Not all routers with stock software have NAT-PMP port mapping feature.


    luke-jr commented at 1:04 pm on February 12, 2020:

    Users who don’t know what their router supports should be able to just flip both on. And laptops might very well migrate between different routers using each protocol.

    Agree with @hebasto that NAT-PMP can’t be a complete substitute for UPnP since routers might not support both.


    hebasto commented at 4:00 pm on February 16, 2020:
    Addressed in the latest push.
  28. hebasto force-pushed on Feb 16, 2020
  29. hebasto commented at 3:59 pm on February 16, 2020: member

    Updated c7e90ca40ad9b7c66f3429b792435e9279ceca6b -> dc228d6db8d2e9406d6d6e0eb04e37940b1ffb82 (pr18077.06 -> pr18077.07, compare):

    Changes:

    • added a user-friendly error message for the NATPMP_ERR_NOGATEWAYSUPPORT error
    • enable both NAT-PMP and UPnP if -natpmp and -upnp options are supplied

    @Sjors

    Perhaps -7 could be replaced by something more readable.

    Done.

    If both are enabled, would you try to open de port with NAT_PMP first and if that fails UPNP? I wouldn’t use them simultaneously, but one fails it makes sense to try the other.

    Done.

  30. in src/init.cpp:455 in dc228d6db8 outdated
    451 #ifdef USE_UPNP
    452 #if USE_UPNP
    453     gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    454 #else
    455-    gArgs.AddArg("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    456+    gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    


    luke-jr commented at 2:09 am on February 17, 2020:
    Prefer to leave this alone (and use %s in the new options)

    hebasto commented at 6:25 am on February 17, 2020:
    Agree. It will be fixed.

    hebasto commented at 4:56 pm on February 17, 2020:
    Done.
  31. luke-jr commented at 2:13 am on February 17, 2020: member
    The logic here still seems broken. Again, consider that users may migrate between different routers each with NAT-PMP or UPnP support. So there should be a common thread main that at each refresh (which ideally should trigger when network availability changes, but that can be another PR) checks for which protocol to use and does the right thing.
  32. hebasto commented at 6:28 am on February 17, 2020: member

    @luke-jr

    The logic here still seems broken. Again, consider that users may migrate between different routers each with NAT-PMP or UPnP support. So there should be a common thread main that at each refresh (which ideally should trigger when network availability changes, but that can be another PR) checks for which protocol to use and does the right thing.

    ThreadAnyAvailable() does almost the same: if a used protocol becomes unavailable, ThreadAnyAvailable() switches to another one, no?

  33. luke-jr commented at 2:23 pm on February 17, 2020: member
    Yes, re-reading it, you’re right, it does. I saw the loops in the per-protocol functions and missed the outer one.
  34. hebasto force-pushed on Feb 17, 2020
  35. hebasto commented at 4:55 pm on February 17, 2020: member

    Updated dc228d6db8d2e9406d6d6e0eb04e37940b1ffb82 -> 2d5d98ce0aa07401c6771731f4e27634629f197c (pr18077.07 -> pr18077.08, compare):

    Changes:

  36. in src/init.cpp:1786 in 2d5d98ce0a outdated
    1784+    // Map ports with NAT-PMP (preferable) or UPnP.
    1785+    {
    1786+        const bool natpmp = gArgs.GetBoolArg("-natpmp", DEFAULT_NATPMP);
    1787+        const bool upnp = gArgs.GetBoolArg("-upnp", DEFAULT_UPNP);
    1788+        if (natpmp && upnp) {
    1789+            StartMapPort(MapPort::ANY_AVAILABLE);
    


    luke-jr commented at 8:16 pm on February 17, 2020:
    Suggest just making this StartMapPort(bool use_upnp, bool use_natpmp)

    luke-jr commented at 9:26 pm on February 17, 2020:
    Or better yet: Just check gArgs inside StartMapPort…

    hebasto commented at 10:01 pm on February 18, 2020:
    Reworked in the latest push.
  37. in src/qt/optionsmodel.cpp:367 in 2d5d98ce0a outdated
    361@@ -350,9 +362,13 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
    362             fMinimizeToTray = value.toBool();
    363             settings.setValue("fMinimizeToTray", fMinimizeToTray);
    364             break;
    365+        case MapPortNatpmp: // core option - can be changed on-the-fly
    366+            settings.setValue("fUseNatpmp", value.toBool());
    367+            m_node.mapPort(value.toBool(), MapPort::NAT_PMP);
    


    luke-jr commented at 8:17 pm on February 17, 2020:
    This logic won’t work if the thread is already running…

    hebasto commented at 8:42 am on February 18, 2020:
    Going to fix it.

    hebasto commented at 10:01 pm on February 18, 2020:
    Fixed in the latest push.
  38. luke-jr changes_requested
  39. in src/init.cpp:446 in 2d5d98ce0a outdated
    438@@ -438,6 +439,15 @@ void SetupServerArgs()
    439     gArgs.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    440     gArgs.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
    441     gArgs.AddArg("-asmap=<file>", "Specify asn mapping used for bucketing of the peers. Path should be relative to the -datadir path.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    442+#ifdef USE_NATPMP
    443+#if USE_NATPMP
    444+    gArgs.AddArg("-natpmp", "Use NAT-PMP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    445+#else
    446+    gArgs.AddArg("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %u)", 0), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    


    luke-jr commented at 8:54 pm on February 17, 2020:
    %s > %u

    hebasto commented at 8:46 am on February 18, 2020:

    %s > %u

    What is the rationale? We already use the %u specifier for unsigned integers in tfm::format().


    luke-jr commented at 0:08 am on February 19, 2020:

    %s doesn’t care what type the value is.

    You can use the same format string above, with a value of "1 when listening and no -proxy"


    hebasto commented at 8:05 pm on February 19, 2020:
    Done in the latest push.
  40. hebasto force-pushed on Feb 18, 2020
  41. hebasto commented at 10:01 pm on February 18, 2020: member

    Updated 2d5d98ce0aa07401c6771731f4e27634629f197c -> ccb4a7ea18c38914f084b7c070303d020adad326 (pr18077.08 -> pr18077.09, compare):

  42. dongcarl commented at 11:11 pm on February 18, 2020: member

    Hi all, did some testing on ccb4a7ea18c38914f084b7c070303d020adad326. What I did:

    1. Installed natpmpd on my OpenBSD gateway router
    2. Started natpmpd, added relevant pf.conf line, reloaded pf
    3. Configure and compile bitcoind with --without-miniupnpc --disable-bench --disable-wallet --without-gui --with-natpmp
    4. Start bitcoind with -natpmp
    5. Saw the following lines:
    02020-02-18T22:26:26Z NAT-PMP: Public address = 108.21.84.253
    12020-02-18T22:26:26Z AddLocal(108.21.84.253:8333,3)
    22020-02-18T22:26:26Z NAT-PMP: Port mapping failed.
    32020-02-18T22:26:26Z NAT-PMP: Port mapping removed successfully.
    
    1. Checked my natpmpd anchored pfctl rules:
    0$ doas pfctl -a natpmpd -s rules
    1pass in quick on rdomain 0 inet proto tcp from any to <my-egress-ip> port = 62774 flags any rdr-to 192.168.0.5 port 8333
    

    I believe this means that natpmpd successfully allocated a port 62774 to bitcoind, but since that port does not equal our private port, this check failed: https://github.com/bitcoin/bitcoin/pull/18077/files#diff-161ad6a962291e0bbafeb83ddc8a977cR109. I believe this is because natpmpd ignores our “Suggested External Port”, which is perfectly valid, and we should probably account for that possibility.

  43. luke-jr commented at 0:19 am on February 19, 2020: member
    If NAT-PMP allows ignoring the suggested port, then we probably should handle that by advertising the correct port for the external IP in addrman.
  44. hebasto commented at 9:29 am on February 19, 2020: member

    @dongcarl Thank you for testing this PR with natpmpd on OpenBSD (I’ve tested with miniupnpd on OpenWrt).

    I believe this is because natpmpd ignores our “Suggested External Port”, which is perfectly valid, and we should probably account for that possibility.

    Correct. From natpmpd docs:

    The external TCP or UDP port assigned to the client is always randomised rather than giving the first client the port it actually requested and then trying to work out what to do for additional clients that want the same external port.

    (highlighted in italics by me).

    OTOH, RFC 6886 states:

    If the client would prefer to have a high-numbered “anonymous” external port assigned, then it should set the Suggested External Port to zero, which indicates to the gateway that it should allocate a high-numbered port of its choosing. If the client would prefer instead to have the mapped external port be the same as its local internal port if possible (e.g., a web server listening on port 80 that would ideally like to have external port 80), then it should set the Suggested External Port to the desired value. However, the gateway is not obliged to assign the port suggested, and may choose not to, either for policy reasons (e.g., port 80 is reserved and clients may not request it) or because that port has already been assigned to some other client.

    (highlighted in italics by me). @luke-jr

    If NAT-PMP allows ignoring the suggested port, then we probably should handle that by advertising the correct port for the external IP in addrman.

    Sure, we should.

  45. hebasto force-pushed on Feb 19, 2020
  46. hebasto commented at 8:05 pm on February 19, 2020: member

    Updated ccb4a7ea18c38914f084b7c070303d020adad326 -> 03e2733be1772ef69caf34e84c7b400f64a8ea9f (pr18077.09 -> pr18077.10, compare):

    • aligned with RFC 6886 @dongcarl @luke-jr Thank you for your reviews. All your comments have been addressed.
  47. in src/qt/optionsmodel.cpp:367 in 03e2733be1 outdated
    363             fMinimizeToTray = value.toBool();
    364             settings.setValue("fMinimizeToTray", fMinimizeToTray);
    365             break;
    366+        case MapPortNatpmp: // core option - can be changed on-the-fly
    367+            settings.setValue("fUseNatpmp", value.toBool());
    368+            m_node.mapPort(value.toBool(), settings.value("fUseUPnP").toBool());
    


    luke-jr commented at 9:26 pm on February 19, 2020:

    This logic breaks the “command line overrides GUI options” stuff above (see addOverriddenOption)…

    Not really sure what the best solution here is.


    hebasto commented at 10:21 am on February 20, 2020:
    The separate issue #18184 has been submitted.
  48. in src/mapport.cpp:275 in 03e2733be1 outdated
    268+
    269+    if (g_mapport_current_proto == MapPortProto::NONE) {
    270+        if (g_mapport_target_proto == MapPortProto::NONE) {
    271+            return;
    272+        }
    273+    } else if (g_mapport_target_proto & g_mapport_current_proto) {
    


    luke-jr commented at 9:33 pm on February 19, 2020:
    This won’t work if we used to have both protocols enabled, are currently using UPnP, but want to disable UPnP.

    hebasto commented at 11:29 pm on February 20, 2020:

    Sure it works. The log excerpt for the mentioned case:

    02020-02-20T23:26:30Z [mapport] UPNP_DeletePortMapping() returned: 0
    12020-02-20T23:26:30Z [mapport] AddLocal(95.164.65.194:18333,3)
    22020-02-20T23:26:30Z [mapport] NAT-PMP: Port mapping successful. External address = 95.164.65.194:18333
    

    luke-jr commented at 11:55 pm on February 20, 2020:
    Why would it? You’d return early here without making the change…

    hebasto commented at 11:59 pm on February 20, 2020:
    If both protocols were enabled, g_mapport_target_proto != MapPortProto::NONE

    luke-jr commented at 3:13 am on February 21, 2020:
    The conditional here is (g_mapport_target_proto & g_mapport_current_proto)

    hebasto commented at 12:06 pm on February 21, 2020:
     0void StartMapPort(bool use_natpmp, bool use_upnp)
     1{
     2    // Both protocols are enabled, so
     3    // g_mapport_target_proto == MapPortProto::NAT_PMP | MapPortProto::UPNP
     4    //
     5    // UPnP is currently using, so
     6    // g_mapport_current_proto == MapPortProto::UPNP
     7    //
     8    // A user disables UPnP then passed arguments are:
     9    // use_natpmp == true, use_upnp = false
    10
    11    if (use_natpmp) {
    12        // Effectively noop here as MapPortProto::NAT_PMP is set already.
    13        g_mapport_target_proto |= MapPortProto::NAT_PMP;
    14    } else {
    15        g_mapport_target_proto &= ~MapPortProto::NAT_PMP;
    16    }
    17
    18    if (use_upnp) {
    19        g_mapport_target_proto |= MapPortProto::UPNP;
    20    } else {
    21        // Unset MapPortProto::UPNP bit.
    22        g_mapport_target_proto &= ~MapPortProto::UPNP;
    23    }
    24
    25    // At this point variables are set to the following values:
    26    // g_mapport_target_proto == MapPortProto::NAT_PMP
    27    // g_mapport_current_proto == MapPortProto::UPNP
    28    // ...
    29    if (g_mapport_current_proto == MapPortProto::NONE) {
    30        if (g_mapport_target_proto == MapPortProto::NONE) {
    31            return;
    32        }
    33    // ... and the next condition evaluates to false.
    34    } else if (g_mapport_target_proto & g_mapport_current_proto) {
    35        return;
    36    }
    37
    38    // Making the changes...
    39    ...
    40}
    

    And logs confirm this logic.


    luke-jr commented at 1:07 pm on February 21, 2020:
    Got it. I was confusing it with (target & new_target)
  49. in src/mapport.cpp:286 in 03e2733be1 outdated
    279+        StopMapPort();
    280+        return;
    281+    }
    282+
    283+    if (g_mapport_thread.joinable()) {
    284+        g_mapport_interrupt();
    


    luke-jr commented at 9:35 pm on February 19, 2020:
    Won’t this cause the thread to shut down?

    hebasto commented at 11:24 pm on February 20, 2020:
    Fixed in the latest push.
  50. in src/mapport.cpp:131 in 03e2733be1 outdated
    132+    struct in_addr external_ipv4_addr;
    133+    if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) {
    134+        bool external_ip_discovered = false;
    135+        const uint16_t private_port = GetListenPort();
    136+        do {
    137+            ret = NatpmpMapping(&natpmp, external_ipv4_addr, private_port, external_ip_discovered);
    


    luke-jr commented at 9:36 pm on February 19, 2020:
    I don’t see the logic here to handle being assigned a different port number.

    hebasto commented at 7:49 am on February 20, 2020:
    The logic to handle being assigned a different external port number by the gateway uses the g_mapport_external_port variable.
  51. luke-jr commented at 9:37 pm on February 19, 2020: member

    I suggest putting the variable renames in a separate commit for easier review.

    Also, since NAT-PMP apparently maps random ports often, I think we should prefer UPnP…

  52. hebasto closed this on Feb 20, 2020

  53. hebasto reopened this on Feb 20, 2020

  54. hebasto commented at 7:56 am on February 20, 2020: member

    @luke-jr

    I suggest putting the variable renames in a separate commit for easier review.

    There is a dedicated commit “refactor: Rename UPnP stuff” (a2de373a96dc1b9f5374eb70d605dcaf49f9b244). What variable rename did I miss to put it to?

  55. hebasto force-pushed on Feb 20, 2020
  56. hebasto commented at 11:21 pm on February 20, 2020: member

    Updated 03e2733be1772ef69caf34e84c7b400f64a8ea9f -> dd3229e7af8563c69d26955c4207f73ae1d3bc94 (pr18077.10 -> pr18077.11, compare):

    • fixed CI issues
    • the NAT-PMP checkbox added to the GUI (this simplifies testing a lot)
    • fixed a bug pointed by @luke-jr
  57. hebasto commented at 11:42 pm on February 20, 2020: member

    @luke-jr

    Also, since NAT-PMP apparently maps random ports often, I think we should prefer UPnP…

    Does this behavior of NAT-PMP gateways hurt the entire p2p network?

    OTOH, NAT-PMP seems more secure than UPnP (for example, one could compare numbers of CVEs for each protocol).

  58. luke-jr commented at 11:52 pm on February 20, 2020: member

    Does this behavior of NAT-PMP gateways hurt the entire p2p network?

    DNS seeds can’t provide port numbers, so using anything other than 8333 reduces the list of nodes we can advertise. Currently, mine (which is IIRC more restrictive than others) has 3090 eligible nodes, so it’s not a big deal, but it’d be nicer to have a wider selection available than a narrower selection.

    OTOH, NAT-PMP seems more secure than UPnP (for example, one could compare numbers of CVEs for each protocol).

    The CVEs AFAIK are for the implementations, not the protocol.

    In any case, when we are using either, I think we’re reduced to the weakest no matter which we prefer (a hostile router could block NAT-PMP to force fallback to UPnP).

  59. in src/mapport.cpp:136 in dd3229e7af outdated
    131+    natpmp_t natpmp;
    132+    struct in_addr external_ipv4_addr;
    133+    if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) {
    134+        bool external_ip_discovered = false;
    135+        const uint16_t private_port = GetListenPort();
    136+        g_mapport_interrupt.reset();
    


    luke-jr commented at 6:58 pm on February 21, 2020:
    This should be reset outside of the protocol-specific functions, or else we could end up with a race.
  60. in src/mapport.cpp:251 in dd3229e7af outdated
    249+        if (g_mapport_target_proto == MapPortProto::NONE) {
    250+            g_mapport_current_proto = MapPortProto::NONE;
    251+            return;
    252+        }
    253+
    254+    } while (ok || g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD));
    


    luke-jr commented at 6:59 pm on February 21, 2020:
    This will exit if it get the interrupt, causing target changes to shut off port mapping entirely.

    hebasto commented at 10:51 am on February 22, 2020:

    If the protocol switch is initiated by a user, the g_mapport_interrupt() call will end the internal protocol-specific loop in the ThreadNatpmp() or in the ThreadUpnp(), ok == true and g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD) will not call at all.

    If the protocol switch is initiated by a protocol failure, ok == false and g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD) will behave as intended.

    Setting g_mapport_target_proto variable to MapPortProto::NONE also causes shutting off port mapping entirely.

  61. luke-jr changes_requested
  62. luke-jr commented at 7:01 pm on February 21, 2020: member

    Re NAT-PMP preference: Also, with the port number changing every startup, it will be hard for peers to reconnect or meaningfully pass on addr messages for you…

    I think cd7a0f689c5 should get split up. It’s too hard to follow what it’s doing.

  63. hebasto commented at 8:43 am on February 22, 2020: member

    Re NAT-PMP preference: Also, with the port number changing every startup, it will be hard for peers to reconnect or meaningfully pass on addr messages for you…

    Only natpmpd on OpenBSD will change external port number on every startup. miniupnpd assigns suggested one, i.e. 8333.

  64. luke-jr commented at 4:00 pm on February 22, 2020: member
    Yes, but UPnP is reliably using the same/requested port if it works.
  65. hebasto force-pushed on Feb 23, 2020
  66. hebasto commented at 1:00 am on February 23, 2020: member

    Updated dd3229e7af8563c69d26955c4207f73ae1d3bc94 -> d9ecda8fa0ebce5b6da972691b19f4425164ae43 (pr18077.11 -> pr18077.12, compare):

    • UPnP is prioritized (as @luke-jr suggested)
    • a note about possible random external port number is added to the NAT-PMP tooltip
    • commits are split and reordered to make review easier, I hope
  67. in src/mapport.cpp:133 in d9ecda8fa0 outdated
    134+        bool external_ip_discovered = false;
    135+        const uint16_t private_port = GetListenPort();
    136+        do {
    137+            ret = NatpmpMapping(&natpmp, external_ipv4_addr, private_port, external_ip_discovered);
    138+        } while (ret && g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD));
    139+        g_mapport_interrupt.reset();
    


    hebasto commented at 1:08 am on February 23, 2020:

    @luke-jr

    This should be reset outside of the protocol-specific functions, or else we could end up with a race.

    Looking into the CThreadInterrupt class implementation I couldn’t see possibilities for a race.

    What did I miss?

  68. in src/mapport.cpp:120 in acb567e3ee outdated
    116@@ -115,14 +117,39 @@ static void ThreadMapPort()
    117     } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD));
    118 }
    119 
    120-void StartMapPort()
    121+void StartThread()
    


    luke-jr commented at 2:11 am on February 23, 2020:
    This name is way too vague…

    hebasto commented at 8:23 pm on February 24, 2020:

    This name is way too vague…

    Yeah… I’m not good at choosing English names, and will appreciate your suggestion.


    luke-jr commented at 8:32 pm on February 24, 2020:
    StartThreadMapPort maybe

    hebasto commented at 5:30 pm on February 25, 2020:
    Done.
  69. in src/mapport.h:15 in acb567e3ee outdated
    11@@ -12,7 +12,12 @@ static const bool DEFAULT_UPNP = USE_UPNP;
    12 static const bool DEFAULT_UPNP = false;
    13 #endif
    14 
    15-void StartMapPort();
    16+enum MapPortProto : unsigned int {
    


    luke-jr commented at 2:14 am on February 23, 2020:
    enum class

    hebasto commented at 8:29 pm on February 24, 2020:

    It will require to define bitwise operators which are used here: https://github.com/bitcoin/bitcoin/blob/d9ecda8fa0ebce5b6da972691b19f4425164ae43/src/mapport.cpp#L297-L304

    Maybe in follow-up?


    luke-jr commented at 11:15 pm on February 24, 2020:
    I wish there was a C++ standard QFlags…
  70. in src/qt/optionsdialog.cpp:56 in 2b0ba0cfe4 outdated
    50@@ -50,6 +51,10 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
    51 #ifndef USE_UPNP
    52     ui->mapPortUpnp->setEnabled(false);
    53 #endif
    54+    connect(this, &QDialog::accepted, [this](){
    55+        QSettings settings;
    56+        model->node().mapPort(settings.value("fUseUPnP").toBool());
    


    luke-jr commented at 3:09 am on February 23, 2020:
    Are we sure the settings are changed before the signal? Or could it be in parallel and therefore a race?

    hebasto commented at 1:51 pm on February 25, 2020:

    Are we sure the settings are changed before the signal? Or could it be in parallel and therefore a race?

    Yes, we are. Please consider the following slot: https://github.com/bitcoin/bitcoin/blob/d9ecda8fa0ebce5b6da972691b19f4425164ae43/src/qt/optionsdialog.cpp#L284-L289

    All changes are submitted to the model in the mapper->submit() call before the QDialog::accepted() signal is emitted when the dialog has been accepted by calling accept().

    Then the following connection: https://github.com/bitcoin/bitcoin/blob/d9ecda8fa0ebce5b6da972691b19f4425164ae43/src/qt/optionsdialog.cpp#L57-L60 does its work.


    ryanofsky commented at 6:09 pm on January 19, 2021:

    In commit “gui: Apply port mapping changes on dialog exit” (58e8364dcdc4e57b0caac09f8402e6535301de9b) @hebasto It seems like this commit has a bug and will incorrectly overwrite command line and config file -upnp and -natpmp options. I think this might have happened before, but previously only if these settings were changed, now if the dialog is just opened and closed.

    Would you have an opinion on reverting this change? Aside from the bug, it seems simpler to go back to fully applying settings in OptionsModel, instead of using half-using OptionsModel to apply the setting, and then reading the setting later in a different code path and QSettings instance in dialog code outside of OptionsModel.

    (Encountered this while rebasing #15936)


    hebasto commented at 7:20 am on January 30, 2021:

    @ryanofsky

    You are right.

    It seems like this commit has a bug and will incorrectly overwrite command line and config file -upnp and -natpmp options.

    The concerns about user-friendly and correct behavior were raised in #18184. Now users are able to switch -upnp and -natpmp on/off on-the-fly via the GUI. Should we drop this feature?

    I think this might have happened before, but previously only if these settings were changed, now if the dialog is just opened and closed.

    Exiting the dialog via the “Cancel” push button or pressing the “Esc” key should not trigger that code path.

    Anyway, I’ll happy to revert (or enhance) that change in a proper way.

  71. in src/init.cpp:452 in de19f109c7 outdated
    446@@ -447,7 +447,12 @@ void SetupServerArgs()
    447 #endif
    448 #else
    449     hidden_args.emplace_back("-upnp");
    450-#endif
    451+#endif // #ifdef USE_UPNP
    452+#ifdef USE_NATPMP
    453+    gArgs.AddArg("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %s)", DEFAULT_NATPMP ? "1 when listening and no -proxy" : 0), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    


    luke-jr commented at 8:14 pm on February 23, 2020:
    Pretty sure a?b:c requires b and c to have the same type.

    luke-jr commented at 8:18 pm on February 23, 2020:
    Pretty sure a?b:c requires b and c to have the same type.

    hebasto commented at 5:30 pm on February 25, 2020:
    Fixed.

    hebasto commented at 5:30 pm on February 25, 2020:
    Fixed.
  72. luke-jr changes_requested
  73. hebasto force-pushed on Feb 25, 2020
  74. hebasto commented at 5:27 pm on February 25, 2020: member

    Updated d9ecda8fa0ebce5b6da972691b19f4425164ae43 -> 405e85c61a6690ff2f7159c51715fdbafcbf2b1e (pr18077.12 -> pr18077.13, compare):

  75. in src/mapport.cpp:1 in f93e76ad1b outdated
    0@@ -0,0 +1,137 @@
    1+// Copyright (c) 2020 The Bitcoin Core developers
    


    sipa commented at 0:17 am on February 26, 2020:

    In commit “refactor: Move port mapping code to own files”

    Nit: when you’re copying/moving code, retain the copyright years of the original code.


    hebasto commented at 7:22 am on February 26, 2020:

    The UPnP support code has been added in 2011 (see #133). Is it correct to retain pre-2011 copyright years?

    Could it be “2011-2020” in new files?


    hebasto commented at 7:46 am on February 26, 2020:
    See the latest push.
  76. in src/mapport.cpp:40 in 9945c2e193 outdated
    34@@ -35,9 +35,11 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
    35 static CThreadInterrupt g_upnp_interrupt;
    36 static std::thread g_upnp_thread;
    37 static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20);
    38+static constexpr auto PORT_MAPPING_RETRY_PERIOD = std::chrono::minutes(5);
    39 
    40-static void ThreadMapPort()
    41+static bool ThreadUpnp()
    


    sipa commented at 0:17 am on February 26, 2020:

    In commit “net: Keep trying to use UPnP when -upnp=1”

    This is confusingly named when it isn’t actually a thread on its own anymore.


    hebasto commented at 7:47 am on February 26, 2020:
  77. sipa commented at 0:34 am on February 26, 2020: member
    Concept ACK, left a few code review nits. I haven’t reviewed the actual natpmp interaction code.
  78. hebasto force-pushed on Feb 26, 2020
  79. hebasto commented at 7:45 am on February 26, 2020: member

    Updated 405e85c61a6690ff2f7159c51715fdbafcbf2b1e -> 4e7b9f03b8a3dd02bc9831e77905a8022770c846 (pr18077.13 -> pr18077.14, compare):

  80. DrahtBot added the label Needs rebase on Mar 1, 2020
  81. hebasto force-pushed on Mar 3, 2020
  82. hebasto commented at 3:29 pm on March 3, 2020: member
    Rebased after #17399 has been merged.
  83. DrahtBot removed the label Needs rebase on Mar 3, 2020
  84. DrahtBot added the label Needs rebase on Mar 10, 2020
  85. hebasto force-pushed on Mar 11, 2020
  86. hebasto commented at 4:12 pm on March 11, 2020: member
    Rebased due to the conflict with merged #18264.
  87. DrahtBot removed the label Needs rebase on Mar 11, 2020
  88. DrahtBot added the label Needs rebase on Mar 25, 2020
  89. hebasto force-pushed on Mar 28, 2020
  90. hebasto commented at 6:50 pm on March 28, 2020: member
    Rebased 4be5c3c72d98b616367d1aa3de22702e6f9f81ee -> 1bf61f0557637b5bedd670a4fba7bb11bf42ac6a due to the conflicts with #18134 and #18438.
  91. DrahtBot removed the label Needs rebase on Mar 28, 2020
  92. DrahtBot added the label Needs rebase on Apr 6, 2020
  93. hebasto force-pushed on Apr 11, 2020
  94. hebasto commented at 1:13 pm on April 11, 2020: member
    Rebased 1bf61f0557637b5bedd670a4fba7bb11bf42ac6a -> 607144bab1aecb8b970e17aeb145d62175d58c4c (pr18077.17 -> pr18077.18) due to the conflicts with #18514 and #16367.
  95. DrahtBot removed the label Needs rebase on Apr 11, 2020
  96. hebasto force-pushed on Apr 11, 2020
  97. hebasto commented at 2:43 pm on April 11, 2020: member
    Rebased 607144bab1aecb8b970e17aeb145d62175d58c4c -> a388fae1dca9b4983bc95d50d07503aae527f29e (pr18077.18 -> pr18077.19) due to the conflict with #18588.
  98. laanwj added this to the milestone 0.21.0 on Apr 11, 2020
  99. DrahtBot added the label Needs rebase on Apr 15, 2020
  100. hebasto force-pushed on Apr 16, 2020
  101. hebasto commented at 4:51 pm on April 16, 2020: member
    Rebased a388fae1dca9b4983bc95d50d07503aae527f29e -> 95e943cb1855dca3ed5fb4fd98b357515d1a3646 (pr18077.19 -> pr18077.20) due to the conflict with #18571.
  102. DrahtBot removed the label Needs rebase on Apr 16, 2020
  103. DrahtBot added the label Needs rebase on Apr 20, 2020
  104. hebasto force-pushed on Apr 20, 2020
  105. hebasto commented at 7:10 pm on April 20, 2020: member
    Rebased 95e943cb1855dca3ed5fb4fd98b357515d1a3646 -> f4a4643712eca819a5b7ed0a143216e06125d1a9 (pr18077.20 -> pr18077.21) due to the conflicts with #18676 and #18705.
  106. DrahtBot removed the label Needs rebase on Apr 20, 2020
  107. tryphe commented at 4:28 am on May 17, 2020: contributor

    tACK f4a4643712eca819a5b7ed0a143216e06125d1a9 on Debian 9

    02020-05-17T04:14:52Z NAT-PMP: Port mapping successful. External address = [redacted]:8333
    12020-05-17T04:22:05Z NAT-PMP: Port mapping removed successfully.
    

    The port is accessible externally without any other forwarding rules.

  108. DrahtBot added the label Needs rebase on May 19, 2020
  109. hebasto force-pushed on May 19, 2020
  110. hebasto commented at 4:24 pm on May 19, 2020: member
    Rebased f4a4643712eca819a5b7ed0a143216e06125d1a9 -> 2f7a01708482ad9f8fede1d7b7a9d59901370aa1 (pr18077.21 -> pr18077.22) due to the conflict with #19008.
  111. DrahtBot removed the label Needs rebase on May 19, 2020
  112. DrahtBot added the label Needs rebase on May 21, 2020
  113. hebasto force-pushed on May 22, 2020
  114. hebasto commented at 5:33 am on May 22, 2020: member
    Rebased 2f7a01708482ad9f8fede1d7b7a9d59901370aa1 -> f0cf6523c9fb4c3bb0bc64af72cdcadfa7747748 (pr18077.22 -> pr18077.23) due to the conflict with #18677.
  115. DrahtBot removed the label Needs rebase on May 22, 2020
  116. DrahtBot added the label Needs rebase on May 22, 2020
  117. hebasto force-pushed on May 22, 2020
  118. hebasto commented at 11:38 am on May 22, 2020: member
    Rebased f0cf6523c9fb4c3bb0bc64af72cdcadfa7747748 -> 1b006d618d02eac38bd434937d6d5c42084992bf (pr18077.23 -> pr18077.24) due to the conflict with #19014.
  119. DrahtBot removed the label Needs rebase on May 22, 2020
  120. DrahtBot added the label Needs rebase on Jun 3, 2020
  121. hebasto force-pushed on Jun 4, 2020
  122. hebasto commented at 7:09 am on June 4, 2020: member
    Rebased 1b006d618d02eac38bd434937d6d5c42084992bf -> 0692bed243adb8d4f3aa8192e9d1952d1de4a2ad (pr18077.24 -> pr18077.25) due to the conflict with #19041.
  123. DrahtBot removed the label Needs rebase on Jun 4, 2020
  124. DrahtBot added the label Needs rebase on Jun 8, 2020
  125. hebasto force-pushed on Jun 8, 2020
  126. hebasto commented at 3:06 pm on June 8, 2020: member
    Rebased 0692bed243adb8d4f3aa8192e9d1952d1de4a2ad -> 5a29078b373f5ffecb452317a1bd6fb165b08b42 (pr18077.25 -> pr18077.26) due to the conflict with #19180.
  127. DrahtBot removed the label Needs rebase on Jun 8, 2020
  128. hebasto closed this on Jun 15, 2020

  129. hebasto reopened this on Jun 15, 2020

  130. DrahtBot added the label Needs rebase on Jun 19, 2020
  131. hebasto force-pushed on Jun 20, 2020
  132. hebasto commented at 8:01 am on June 20, 2020: member
    Rebased 5a29078b373f5ffecb452317a1bd6fb165b08b42 -> 570c1060058d7f52286107df217b66d28d0b1f91 (pr18077.26 -> pr18077.27) due to the conflict with #19267.
  133. DrahtBot removed the label Needs rebase on Jun 20, 2020
  134. DrahtBot added the label Needs rebase on Jul 1, 2020
  135. hebasto force-pushed on Jul 3, 2020
  136. hebasto commented at 7:16 am on July 3, 2020: member
    Rebased 570c1060058d7f52286107df217b66d28d0b1f91 -> a660ecc26e691ed9b931d6fe27c26899ef66be64 (pr18077.27 -> pr18077.28) due to the conflict with #19331.
  137. DrahtBot removed the label Needs rebase on Jul 3, 2020
  138. hebasto force-pushed on Jul 5, 2020
  139. hebasto commented at 9:06 am on July 5, 2020: member

    Rebased a660ecc26e691ed9b931d6fe27c26899ef66be64 -> d4a143ae233fc5fd0cb3c08ce7c388434d256574 (pr18077.28 -> pr18077.29, diff):

    • fixed dependency libnatpmp build with the custom CC variable.
  140. DrahtBot added the label Needs rebase on Jul 9, 2020
  141. hebasto force-pushed on Jul 10, 2020
  142. hebasto commented at 7:55 am on July 10, 2020: member
    Rebased d4a143ae233fc5fd0cb3c08ce7c388434d256574 -> b61233d7ab4afe6cd7875b178e923fab59f0534a (pr18077.29 -> pr18077.30) due to the conflicts with #19191 and #19314.
  143. DrahtBot removed the label Needs rebase on Jul 10, 2020
  144. DrahtBot added the label Needs rebase on Jul 14, 2020
  145. hebasto force-pushed on Jul 14, 2020
  146. hebasto commented at 8:17 am on July 14, 2020: member
    Rebased b61233d7ab4afe6cd7875b178e923fab59f0534a -> 1c4bfdb46d48fed6c3f43bbdd7973069cdd21baf (pr18077.30 -> pr18077.31) due to the conflict with #19495.
  147. DrahtBot removed the label Needs rebase on Jul 14, 2020
  148. DrahtBot added the label Needs rebase on Jul 16, 2020
  149. hebasto force-pushed on Jul 16, 2020
  150. hebasto commented at 6:42 pm on July 16, 2020: member
    Rebased 1c4bfdb46d48fed6c3f43bbdd7973069cdd21baf -> 155d87877c11a32abe1ed91799776691b5977a31 (pr18077.31 -> pr18077.32) due to the conflict with #17919.
  151. DrahtBot removed the label Needs rebase on Jul 16, 2020
  152. DrahtBot added the label Needs rebase on Jul 30, 2020
  153. hebasto force-pushed on Jul 31, 2020
  154. hebasto commented at 12:14 pm on July 31, 2020: member
    Rebased 155d87877c11a32abe1ed91799776691b5977a31 -> 88b1f0357c332bc67fa20450dda9f77fa449576e (pr18077.32 -> pr18077.33) due to the conflict with #19561.
  155. DrahtBot removed the label Needs rebase on Jul 31, 2020
  156. DrahtBot added the label Needs rebase on Aug 7, 2020
  157. hebasto force-pushed on Aug 8, 2020
  158. hebasto commented at 7:19 am on August 8, 2020: member
    Rebased 88b1f0357c332bc67fa20450dda9f77fa449576e -> 225f512438f4391f6af255f851131358e3c466a2 (pr18077.33 -> pr18077.34) due to the conflict with #19098.
  159. DrahtBot removed the label Needs rebase on Aug 8, 2020
  160. adamjonas commented at 2:02 pm on August 10, 2020: member

    For those looking to review or revisit:

    (All pre-rebase) There are concept ACKs from: luke-jr, dongcarl, Sjors, Sipa a tACK from tryphe with no NACKs or blocking issues

  161. dongcarl commented at 7:11 pm on August 20, 2020: member

    Tested 225f512438f4391f6af255f851131358e3c466a2, works:

    02020-08-20T19:07:08Z NAT-PMP: Port mapping successful. External address = <redacted>
    

    Did not read code yet

  162. in doc/release-notes-18077.md:9 in 225f512438 outdated
    0@@ -0,0 +1,9 @@
    1+P2P and network changes
    2+-----------------------
    3+
    4+- Added NAT-PMP port mapping support via [`libnatpmp`](https://miniupnp.tuxfamily.org/libnatpmp.html)
    5+
    6+Command-line options
    7+--------------------
    8+
    9+-  The `-natpmp` option has been added to use NAT-PMP to map the listening port. If both `-upnp` and `-natpmp` options are provided, the former prevails.
    


    luke-jr commented at 9:26 pm on August 20, 2020:
    Neither should prevail - one should be attempted before the other, but both should work.

    dongcarl commented at 5:20 pm on October 30, 2020:

    Perhaps I’m reading the code wrong, but it seems like “If both UPnP and NAT-PMP are enabled, a successful allocation from UPnP prevails over one from NAT-PMP” is a more accurate description here?

    I’m thinking about the case where both UPnP and NAT-PMP are enabled, but the gateway box is not responding to UPnP, in that case, a NAT-PMP allocation would still be accepted, right?


    hebasto commented at 5:39 pm on October 30, 2020:

    Perhaps I’m reading the code wrong, but it seems like “If both UPnP and NAT-PMP are enabled, a successful allocation from UPnP prevails over one from NAT-PMP” is a more accurate description here?

    Thanks! It remained from the initial version of the PR :) Updated.


    hebasto commented at 5:41 pm on October 30, 2020:

    I’m thinking about the case where both UPnP and NAT-PMP are enabled, but the gateway box is not responding to UPnP, in that case, a NAT-PMP allocation would still be accepted, right

    The do loop introduced in the c01073db04e94a8d67f29de3daead0e2574b1c26 commit is responsible for that.


    hebasto commented at 11:59 pm on October 30, 2020:
    Simultaneously?
  163. DrahtBot added the label Needs rebase on Aug 26, 2020
  164. hebasto force-pushed on Aug 26, 2020
  165. hebasto commented at 9:13 am on August 26, 2020: member
    Rebased 225f512438f4391f6af255f851131358e3c466a2 -> 22cbf4eefaa7333a3e2bf94fbf4d3e7b4bf379cb (pr18077.34 -> pr18077.35) due to the conflict with #19779.
  166. DrahtBot removed the label Needs rebase on Aug 26, 2020
  167. DrahtBot added the label Needs rebase on Aug 26, 2020
  168. hebasto force-pushed on Aug 26, 2020
  169. hebasto commented at 5:01 pm on August 26, 2020: member
    Rebased 22cbf4eefaa7333a3e2bf94fbf4d3e7b4bf379cb -> 2b6bd32e915d13928577b038c18194ac4024fc10 (pr18077.35 -> pr18077.36) due to the conflict with https://github.com/bitcoin-core/gui/pull/35.
  170. DrahtBot removed the label Needs rebase on Aug 26, 2020
  171. DrahtBot added the label Needs rebase on Sep 15, 2020
  172. hebasto force-pushed on Sep 15, 2020
  173. hebasto commented at 2:34 pm on September 15, 2020: member
    Rebased 2b6bd32e915d13928577b038c18194ac4024fc10 -> 62601a5a158b8c3710fde7cac8aadaa71a72f110 (pr18077.36 -> pr18077.37) due to the conflict with #19558.
  174. DrahtBot removed the label Needs rebase on Sep 15, 2020
  175. jonatack commented at 10:09 am on September 17, 2020: member
    Concept ACK
  176. laanwj removed this from the milestone 0.21.0 on Oct 8, 2020
  177. laanwj added this to the milestone 0.22.0 on Oct 8, 2020
  178. DrahtBot added the label Needs rebase on Oct 12, 2020
  179. gmaxwell commented at 7:03 pm on October 12, 2020: contributor

    I performed basic functional testing against this branch (but not master with this applied due to rebase hell) against http://www.nongnu.org/natpmp/.

    I don’t really like the natpmp default being set by configure. I see the UPNP is currently handled that way, but I think that is an artefact of the fact that UPNP is disabled for implementation specific security reasons. Otherwise, no other bitcoin setting has its default set by configure. That said, this could easily be something changed after getting the functionality merged or even in a subsequent release.

    I found that it successfully mapped 8333 and released the mapping on shutdown.

    I restricted the port range at the pmp-daemon and found that it successfully mapped a different port and correctly learned the other port number.

    I killed the pmp-daemon while bitcoind was running then shutdown and verified that it didn’t hang up waiting for some unmap confirmation or anything like that.

    I did not change my external IP to confirm that it learned about the IP change (as I couldn’t do that without disrupting other people). I think this would be a useful thing to test, but even if it didn’t work right I don’t think it would block merging this.

    Looks to me like it works!

  180. hebasto force-pushed on Oct 13, 2020
  181. hebasto commented at 5:47 am on October 13, 2020: member
    Rebased 62601a5a158b8c3710fde7cac8aadaa71a72f110 -> 44a697619d3fc3d9311c3d099cae04b21de071f3 (pr18077.37 -> pr18077.38) due to the conflict with #19998.
  182. DrahtBot removed the label Needs rebase on Oct 13, 2020
  183. gmaxwell commented at 9:41 am on October 15, 2020: contributor
    ultra minor nit, ignore if you like: I didn’t like that the logs calls it “NAT-PMP” but the configuration option is natpmp, so I had to go read the code to figure out what I should be looking for. I’d prefer to see logs say “natpmp” for optimum greppability.
  184. hebasto force-pushed on Oct 15, 2020
  185. hebasto commented at 10:26 am on October 15, 2020: member

    Rebased 44a697619d3fc3d9311c3d099cae04b21de071f3 -> 81a791d88d68e64968e52d8ff6ec20879bd5fad1 (pr18077.38 -> pr18077.39) due to the conflict with #19077, and addressed @gmaxwell’s comment:

    ultra minor nit, ignore if you like: I didn’t like that the logs calls it “NAT-PMP” but the configuration option is natpmp, so I had to go read the code to figure out what I should be looking for. I’d prefer to see logs say “natpmp” for optimum greppability.

  186. gmaxwell commented at 9:54 pm on October 15, 2020: contributor
    Still works. Looks good to me.
  187. jamesob commented at 4:52 pm on October 19, 2020: member
    Concept ACK - reviewing this shortly
  188. in depends/packages/libnatpmp.mk:5 in 81a791d88d outdated
    0@@ -0,0 +1,19 @@
    1+package=libnatpmp
    2+$(package)_version=20150609
    3+$(package)_download_path=https://miniupnp.tuxfamily.org/files/
    4+$(package)_file_name=$(package)-$($(package)_version).tar.gz
    5+$(package)_sha256_hash=e1aa9c4c4219bc06943d6b2130f664daee213fb262fcb94dd355815b8f4536b0
    


    jamesob commented at 3:01 pm on October 20, 2020:

    Verified this locally.

    0% curl -O https://miniupnp.tuxfamily.org/files/libnatpmp-20150609.tar.gz
    1% sha256sum libnatpmp-20150609.tar.gz
    2e1aa9c4c4219bc06943d6b2130f664daee213fb262fcb94dd355815b8f4536b0  libnatpmp-20150609.tar.gz
    
  189. in src/mapport.cpp:149 in 035a41ca37 outdated
    29+#include <chrono>
    30+#include <functional>
    31+#include <string>
    32+#include <thread>
    33+
    34+#ifdef USE_UPNP
    


    jamesob commented at 8:33 pm on October 20, 2020:
  190. in src/net.h:37 in 035a41ca37 outdated
    32@@ -33,11 +33,6 @@
    33 #include <memory>
    34 #include <condition_variable>
    35 
    36-#ifndef WIN32
    37-#include <arpa/inet.h>
    


    jamesob commented at 8:36 pm on October 20, 2020:

    hebasto commented at 5:05 pm on October 22, 2020:
    Yes. I’ve submitted a dedicated #20221.
  191. in src/mapport.cpp:35 in 5b6af78096 outdated
    34@@ -35,9 +35,11 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
    35 static CThreadInterrupt g_upnp_interrupt;
    


    jamesob commented at 8:43 pm on October 20, 2020:

    (Note on https://github.com/bitcoin/bitcoin/pull/18077/commits/5b6af780967c428ec38fa18ae68a193d2d036f57 as a whole)

    I certainly don’t have qualms with this change but it seems orthogonal to NAT-PMP per se. Is it necessary for NAT-PMP somehow? Just curious.


    hebasto commented at 5:17 pm on October 22, 2020:
    The “net: Keep trying to use UPnP when -upnp=1” commit (5b6af780967c428ec38fa18ae68a193d2d036f57) is a prerequisite for the “net: Add NAT-PMP to port mapping loop” commit (c329ae5b6834e8dae6d178bc84321c7dc6e3c6fc). Both commits make possible to switch port forwarding method at runtime.
  192. in src/mapport.cpp:291 in ea445ad4bc outdated
    134+        InterruptMapPort();
    135+        StopMapPort();
    136+    }
    137+}
    138+
    139+static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled)
    


    jamesob commented at 8:48 pm on October 20, 2020:

    https://github.com/bitcoin/bitcoin/pull/18077/commits/ea445ad4bc5b4d2904cbe234a627700a6d22d32e

    Note: simultaneous use of either NAT-PMP or upnp enabled in a later commit.

  193. in src/mapport.cpp:41 in 1bf23f291d outdated
    32@@ -33,8 +33,8 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"
    33 #include <thread>
    34 
    35 #ifdef USE_UPNP
    36-static CThreadInterrupt g_upnp_interrupt;
    37-static std::thread g_upnp_thread;
    38+static CThreadInterrupt g_mapport_interrupt;
    


    jamesob commented at 8:49 pm on October 20, 2020:
    (Note on https://github.com/bitcoin/bitcoin/pull/18077/commits/1bf23f291d7c053538245f1a7f6f7699daf4a3b9 as a whole:) could be a scripteddiff AFAICT, but not a huge deal.

    hebasto commented at 6:38 pm on October 22, 2020:
    Thanks! Updated.
  194. in src/mapport.cpp:128 in f6bd717f3f outdated
    129+{
    130+    bool ret = false;
    131+    natpmp_t natpmp;
    132+    struct in_addr external_ipv4_addr;
    133+    if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) {
    134+        bool external_ip_discovered = false;
    


    jamesob commented at 9:00 pm on October 20, 2020:

    https://github.com/bitcoin/bitcoin/pull/18077/commits/f6bd717f3f44f2a167ce2e548df1132789d0ea98

    Hm, I see we’re explicitly setting this in NetpmpMapping but then it goes unused. No big deal, just curious.


    hebasto commented at 5:31 pm on October 22, 2020:
    As an in-out parameter, external_ip_discovered is used here https://github.com/bitcoin/bitcoin/blob/81a791d88d68e64968e52d8ff6ec20879bd5fad1/src/mapport.cpp#L104-L107 to prevent consecutive AddLocal calls.

    jamesob commented at 3:58 pm on October 26, 2020:
    Oh I see, thanks.
  195. in src/init.cpp:484 in ea022f30db outdated
    478@@ -479,7 +479,12 @@ void SetupServerArgs(NodeContext& node)
    479 #endif
    480 #else
    481     hidden_args.emplace_back("-upnp");
    482-#endif
    483+#endif // #ifdef USE_UPNP
    484+#ifdef USE_NATPMP
    485+    argsman.AddArg("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %s)", DEFAULT_NATPMP ? "1 when listening and no -proxy" : "0"), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
    


    jamesob commented at 9:06 pm on October 20, 2020:
    Nit: linebreak would be nice.

    hebasto commented at 6:38 pm on October 22, 2020:

    hebasto commented at 8:17 am on October 23, 2020:
    Reverted back as a linebreak breaks test/lint/check-doc.py linter: https://travis-ci.org/github/bitcoin/bitcoin/jobs/738110074
  196. in src/qt/optionsdialog.cpp:55 in 1f93ddff18 outdated
    49@@ -50,6 +50,9 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
    50     /* Network elements init */
    51 #ifndef USE_UPNP
    52     ui->mapPortUpnp->setEnabled(false);
    53+#endif
    54+#ifndef USE_NATPMP
    55+    ui->mapPortNatpmp->setEnabled(false);
    


    jamesob commented at 9:10 pm on October 20, 2020:
    Nit: not s/false/USE_NATPMP ?

    hebasto commented at 5:43 pm on October 22, 2020:
    It won’t compile if USE_NATPMP is undefined. Did I understand you correctly?

    jamesob commented at 5:47 pm on October 22, 2020:
    Oh my mistake; I read that as ifdef.
  197. jamesob approved
  198. jamesob commented at 9:14 pm on October 20, 2020: member

    Code review ACK 81a791d88d68e64968e52d8ff6ec20879bd5fad1

    Really worthwhile change; all else equal the easier we can make offering inbound conn capacity the better.

    I’ve reviewed and built locally, though my router doesn’t support NAT-PMP out of the box. I’ll see what I can do in the meantime in terms of more comprehensive testing.

  199. hebasto force-pushed on Oct 22, 2020
  200. hebasto commented at 6:37 pm on October 22, 2020: member

    Updated 81a791d88d68e64968e52d8ff6ec20879bd5fad1 -> cb4060686155c011cbece84fd551dfa000277d51 (pr18077.39 -> pr18077.40, diff).

    Addressed @jamesob’s comments:

    (Note on 1bf23f2 as a whole:) could be a scripteddiff AFAICT, but not a huge deal.

    Nit: linebreak would be nice.

  201. hebasto force-pushed on Oct 22, 2020
  202. hebasto commented at 8:19 am on October 23, 2020: member
    Updated cb4060686155c011cbece84fd551dfa000277d51 -> bddfeade1e7740f04002f6d88e6e9840ed985bea (pr18077.40 -> pr18077.41, diff): #18077 (review)
  203. DrahtBot added the label Needs rebase on Oct 27, 2020
  204. hebasto force-pushed on Oct 27, 2020
  205. hebasto commented at 10:27 am on October 27, 2020: member
    Rebased bddfeade1e7740f04002f6d88e6e9840ed985bea -> 5fd127243f452827dab3b4f4f47b6e96816fdfb8 (pr18077.41 -> pr18077.42) due to the conflict with #19124.
  206. DrahtBot removed the label Needs rebase on Oct 27, 2020
  207. jamesob approved
  208. jamesob commented at 6:45 pm on October 27, 2020: member

    ACK https://github.com/bitcoin/bitcoin/commit/5fd127243f452827dab3b4f4f47b6e96816fdfb8

    Re-reviewed diffs after rebase. Built locally with NAT-PMP enabled. My gateway doesn’t support NAT-PMP, but regular IBD works okay.

  209. DrahtBot added the label Needs rebase on Oct 29, 2020
  210. hebasto force-pushed on Oct 29, 2020
  211. hebasto commented at 2:58 pm on October 29, 2020: member
    Rebased 5fd127243f452827dab3b4f4f47b6e96816fdfb8 -> 90d9547f135ef0ffc00dd790072c3ae307f053ad (pr18077.42 -> pr18077.43) due to the conflict with #20156.
  212. DrahtBot removed the label Needs rebase on Oct 29, 2020
  213. hebasto closed this on Oct 30, 2020

  214. hebasto reopened this on Oct 30, 2020

  215. hebasto force-pushed on Oct 30, 2020
  216. hebasto commented at 5:38 pm on October 30, 2020: member

    Updated 90d9547f135ef0ffc00dd790072c3ae307f053ad -> 29fb5708ca04da9ca0c25c1b801887354eb714bc (pr18077.43 -> pr18077.44, diff):

    Perhaps I’m reading the code wrong, but it seems like “If both UPnP and NAT-PMP are enabled, a successful allocation from UPnP prevails over one from NAT-PMP” is a more accurate description her

  217. in src/mapport.cpp:285 in 29fb5708ca outdated
    286+        // Enabling another protocol does not cause switching from the currently used one.
    287+        return;
    288+    }
    289+
    290+    assert(g_mapport_thread.joinable());
    291+    assert(!g_mapport_interrupt);
    


    luke-jr commented at 10:51 pm on October 30, 2020:
    Couldn’t this be true if the user is impossibly fast?

    hebasto commented at 3:44 pm on December 7, 2020:
    I don’t think so due to the CThreadInterrupt class implementation.
  218. DrahtBot added the label Needs rebase on Nov 9, 2020
  219. hebasto force-pushed on Dec 7, 2020
  220. hebasto commented at 11:02 am on December 7, 2020: member
    Rebased 29fb5708ca04da9ca0c25c1b801887354eb714bc -> 3c26d53f538442363834178a45bc8b459b5b334d (pr18077.44 -> pr18077.45) due to the conflicts with #20202, #20494 and the recent CI changes.
  221. DrahtBot removed the label Needs rebase on Dec 7, 2020
  222. DrahtBot added the label Needs rebase on Dec 10, 2020
  223. hebasto force-pushed on Dec 10, 2020
  224. hebasto commented at 6:30 pm on December 10, 2020: member
    Rebased 3c26d53f538442363834178a45bc8b459b5b334d -> cc68169e72c5b28fe53466a86eeac9fd214cd0d1 (pr18077.45 -> pr18077.46) due to the conflict with #20527.
  225. DrahtBot removed the label Needs rebase on Dec 10, 2020
  226. DrahtBot added the label Needs rebase on Dec 15, 2020
  227. hebasto force-pushed on Dec 15, 2020
  228. hebasto commented at 6:29 pm on December 15, 2020: member
    Rebased cc68169e72c5b28fe53466a86eeac9fd214cd0d1 -> 93ff21a929ba3036d6cd5d822f300cf036ff939f (pr18077.46 -> pr18077.47) due to the conflict with https://github.com/bitcoin-core/gui/pull/115.
  229. DrahtBot removed the label Needs rebase on Dec 15, 2020
  230. LarryRuane commented at 8:44 pm on December 16, 2020: contributor

    In case any of this is helpful… I wanted to try running this, I’m running Ubuntu 18.04 as a Virtualbox guest on a Windows 10 host running at home (Xfinity-Comcast, nothing unusual), I checked out branch pr18077.47, ran

    0$ sudo apt install libminiupnpc-dev libnatpmp-dev
    1(... successful)
    2$ ./autogen.sh && ./configure --disable-wallet --without-miniupnpc --enable-natpmp-default && make
    3(...)
    4checking whether to build with support for UPnP... no
    5checking whether to build with support for NAT-PMP... yes
    6checking whether to build with NAT-PMP enabled by default... yes
    7(...)
    8$ src/bitcoind
    

    Starts up normally, but this prints to debug.log every 5 minutes:

    02020-12-16T19:14:17Z natpmp: The gateway does not support NAT-PMP.
    

    and bitcoin-cli -netstat shows that I have no incoming peers. I think this is all as expected, but I’m not testing much. I don’t know how to change my gateway to support NAT-PMP (I’d appreciate any help). I did change my cable modem router’s firewall to allow P2P applications on both IPv4 and IPv6, but that didn’t make any difference.

  231. hebasto commented at 9:32 am on December 17, 2020: member

    @LarryRuane

    Thanks for testing!

    I don’t know how to change my gateway to support NAT-PMP (I’d appreciate any help).

    Your gateway s/w manual (if available) could help. My TP-Link Archer C6 does not have NAT-PMP support with stock s/w, so I’ve flashed the OpenWrt on it.

  232. laanwj commented at 1:10 pm on December 17, 2020: member
    Looked over the overall changes, they look reasonable to me. Will test.
  233. in src/mapport.cpp:238 in 93ff21a929 outdated
    239+            if (ok) continue;
    240+        }
    241+#endif // #ifdef USE_UPNP
    242+
    243+#ifdef USE_NATPMP
    244+        // Low priority protocol.
    


    laanwj commented at 1:11 pm on December 17, 2020:
    Why is NATPMP “low priority”? I think NATPMP is the preferred protocol? (for one, it’s simpler so less prone to exploitation)

    hebasto commented at 1:15 pm on December 17, 2020:

    laanwj commented at 1:16 pm on December 17, 2020:
    FWIW, I disagree. I think we should prefer NATPMP and phase out UPnP in the longer run when it has proven to be stable. (of course, if a lot of issues actually come up it’s different, but I wouldn’t do this based on one comment)

    vasild commented at 9:11 am on December 18, 2020:

    @luke-jr, what do you mean by “maps random ports often”? Some implementation of natpmp has bugs? Can you give an example?

    Maybe just remove this comment “// Low priority protocol.” – it is unclear what is meant by it and is missing in other places where #ifdef USE_NATPMP is used.


    hebasto commented at 10:04 pm on December 18, 2020:

    @vasild

    @luke-jr, what do you mean by “maps random ports often”? Some implementation of natpmp has bugs? Can you give an example?

    Some NAT-PMP daemon implementations do randomize an external port. For example, see #18077 (comment) and http://bodgitandscarper.co.uk/natpmpd/:

    The external TCP or UDP port assigned to the client is always randomised rather than giving the first client the port it actually requested and then trying to work out what to do for additional clients that want the same external port.


    vasild commented at 8:52 am on December 21, 2020:

    @hebasto, Thanks for the clarification! IMO the nat-pmp implementation overriding the desired external port is fine as long as we advertise the overriden one instead of the desired one (I guess we do). That should also be expected as it is allowed by the RFC.

    I guess something like that happens with UPnP too if the desired port is already used?


    hebasto commented at 9:37 am on December 25, 2020:

    IMO the nat-pmp implementation overriding the desired external port is fine as long as we advertise the overriden one instead of the desired one (I guess we do).

    Yes, we do: https://github.com/bitcoin/bitcoin/blob/890e59c64d62fd39778ede620a70fe6bc60d9993/src/mapport.cpp#L97-L102

    I guess something like that happens with UPnP too if the desired port is already used?

    https://github.com/bitcoin/bitcoin/blob/890e59c64d62fd39778ede620a70fe6bc60d9993/src/mapport.cpp#L173-L186

  234. laanwj commented at 3:14 pm on December 17, 2020: member

    It works !

    • On Ubuntu 20.04 I installed the libnatpmp-dev package, re-ran configure, it was detected correctly and enabled
    • I run bitcoind with -natpmp -regtest

    I see the following in my log

    02020-12-17T15:06:10Z natpmp: Port mapping successful. External address = x.x.x.x:18444
    

    My router’s admin interface show the redirect:

    0Protocol | External Port | Client Address | Client Port |  
    1-- | -- | -- | -- | --
    2TCP | 18444 | 192.168.x.x | 18444
    

    I have verified that I can connect to the host/port from a remote server.

  235. in src/mapport.cpp:22 in 93ff21a929 outdated
    17+#include <util/system.h>
    18+
    19+#ifdef USE_NATPMP
    20+#include <natpmp.h>
    21+#ifdef WIN32
    22+#include <winsock2.h>
    


    laanwj commented at 3:32 pm on December 17, 2020:
    I think we can avoid this platform dependent include dance by including <compat.h>.

    hebasto commented at 11:04 pm on December 18, 2020:
    Thanks! Updated.
  236. in src/mapport.cpp:80 in 93ff21a929 outdated
    75+        } else if (r_read == NATPMP_ERR_NOGATEWAYSUPPORT) {
    76+            LogPrintf("natpmp: The gateway does not support NAT-PMP.\n");
    77+        } else {
    78+            LogPrintf("natpmp: readnatpmpresponseorretry() for public address failed with %d error.\n", r_read);
    79+        }
    80+
    


    laanwj commented at 3:49 pm on December 17, 2020:
    Spurious newline?

    hebasto commented at 11:04 pm on December 18, 2020:
  237. in src/mapport.cpp:215 in 93ff21a929 outdated
    216+        FreeUPNPUrls(&urls);
    217+    } else {
    218+        LogPrintf("No valid UPnP IGDs found\n");
    219+        freeUPNPDevlist(devlist); devlist = nullptr;
    220+        if (r != 0)
    221+            FreeUPNPUrls(&urls);
    


    laanwj commented at 3:53 pm on December 17, 2020:
    0        if (r != 0) FreeUPNPUrls(&urls);
    

    laanwj commented at 3:55 pm on December 17, 2020:
    Oh, this is a move-only part, ok.
  238. in src/mapport.cpp:222 in 93ff21a929 outdated
    223+
    224+    return ret;
    225+}
    226+#endif // #ifdef USE_UPNP
    227+
    228+static void ThreadMapPort()
    


    laanwj commented at 5:31 pm on December 17, 2020:
    I guess at some point in the future we could replace this thread (which does nothing but waiting and periodically run stuff) with scheduler runnables instead? (not in this PR)
  239. DrahtBot added the label Needs rebase on Dec 17, 2020
  240. hebasto force-pushed on Dec 18, 2020
  241. hebasto commented at 11:03 pm on December 18, 2020: member

    Updated 93ff21a929ba3036d6cd5d822f300cf036ff939f -> 890e59c64d62fd39778ede620a70fe6bc60d9993 (pr18077.47 -> pr18077.48):

    • rebased due to the conflict with #20681
    • addressed the recent @laanwj’s comments
    • used C++14 chrono literal
  242. DrahtBot removed the label Needs rebase on Dec 19, 2020
  243. DrahtBot added the label Needs rebase on Jan 7, 2021
  244. refactor: Move port mapping code to its own module
    This commit does not change behavior.
    02ccf69dd6
  245. refactor: Replace magic number with named constant 28e2961fd6
  246. net: Keep trying to use UPnP when -upnp=1 8b50d1b5bb
  247. net: Add flags for port mapping protocols 4e91b1e24d
  248. scripted-diff: Rename UPnP stuff
    -BEGIN VERIFY SCRIPT-
    sed -i 's/g_upnp_interrupt/g_mapport_interrupt/' src/mapport.cpp
    sed -i 's/if(g_upnp_thread/if (g_mapport_thread/' src/mapport.cpp
    sed -i 's/g_upnp_thread/g_mapport_thread/' src/mapport.cpp
    sed -i 's/LOCAL_UPNP/LOCAL_MAPPED/' src/mapport.cpp
    sed -i 's/\bupnp\b/mapport/' src/mapport.cpp
    sed -i 's/LOCAL_UPNP,  /LOCAL_MAPPED,/' src/net.h
    -END VERIFY SCRIPT-
    cf151cc68c
  249. gui: Apply port mapping changes on dialog exit
    This commit does not change behavior. It is a prerequisite for NAT-PMP
    support adding.
    58e8364dcd
  250. net: Add libnatpmp support a8d9f275d0
  251. net: Add NAT-PMP to port mapping loop 28acffd9d5
  252. net: Add -natpmp command line option a39f7336a3
  253. gui: Add NAT-PMP network option 5a0185b6c9
  254. ci: Add libnatpmp-dev package to some builds e28f9be87a
  255. doc: Add libnatpmp stuff ae749d12dd
  256. doc: Add release notes a191e23b8e
  257. hebasto force-pushed on Jan 7, 2021
  258. hebasto commented at 4:25 pm on January 7, 2021: member
    Rebased 890e59c64d62fd39778ede620a70fe6bc60d9993 -> a191e23b8e7f0e19fc0359825eb7ca0d47966fa9 (pr18077.48 -> pr18077.49) due to the conflict with #20864.
  259. DrahtBot removed the label Needs rebase on Jan 7, 2021
  260. laanwj commented at 6:39 pm on January 7, 2021: member
    Tested and code review ACK a191e23b8e7f0e19fc0359825eb7ca0d47966fa9
  261. laanwj merged this on Jan 7, 2021
  262. laanwj closed this on Jan 7, 2021

  263. hebasto deleted the branch on Jan 7, 2021
  264. sidhujag referenced this in commit 8d8f45119e on Jan 7, 2021
  265. random-zebra referenced this in commit fce12cf6c3 on Jun 24, 2021
  266. apoelstra referenced this in commit fdfc181255 on Jul 11, 2021
  267. apoelstra referenced this in commit 8964d4c5e1 on Jul 11, 2021
  268. apoelstra referenced this in commit 4f33ba757d on Jul 11, 2021
  269. kittywhiskers referenced this in commit 687c7d4a5d on Feb 26, 2022
  270. PastaPastaPasta referenced this in commit 47ad9ab146 on Mar 5, 2022
  271. ryanofsky referenced this in commit 101ea8668c on Apr 19, 2022
  272. ryanofsky referenced this in commit 236bede111 on Apr 23, 2022
  273. ryanofsky referenced this in commit d50e50ef67 on May 2, 2022
  274. ryanofsky referenced this in commit 4954e35808 on May 16, 2022
  275. ryanofsky referenced this in commit 7962bbd470 on May 17, 2022
  276. ryanofsky referenced this in commit dc43c4fc01 on May 19, 2022
  277. ryanofsky referenced this in commit 4848368071 on May 19, 2022
  278. ryanofsky referenced this in commit 29e371de75 on May 19, 2022
  279. ryanofsky referenced this in commit 69ebadd5f3 on May 20, 2022
  280. ryanofsky referenced this in commit da33f2d8fe on May 20, 2022
  281. ryanofsky referenced this in commit fc30d78f10 on May 20, 2022
  282. ryanofsky referenced this in commit 56590dc8f0 on May 20, 2022
  283. ryanofsky referenced this in commit 1821316f8f on May 23, 2022
  284. ryanofsky referenced this in commit f299e12104 on May 23, 2022
  285. ryanofsky referenced this in commit f854ab8ee0 on May 26, 2022
  286. ryanofsky referenced this in commit b2c8fc344f on May 26, 2022
  287. ryanofsky referenced this in commit 383aee6ba2 on May 31, 2022
  288. ryanofsky referenced this in commit 13ce751718 on Jun 6, 2022
  289. ryanofsky referenced this in commit d2ada6e635 on Jun 9, 2022
  290. janus referenced this in commit 4e8d501701 on Aug 4, 2022
  291. DrahtBot locked this on Aug 16, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-01 10:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me