Skip to content

Commit acb19d9

Browse files
committed
UDP search traverse NAT
Change the CMD_SEARCH message, adding a reply-to-sender-port flag to allow for replies to traverse a NAT. The meaning of that flag is that the recipient should ignore the replyPort field, and instead send a reply to the apparent port which sent the request. A forwarder should overwrite the replyPort field, and clear this new MustReply flag.
1 parent cd5570b commit acb19d9

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

src/client.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,12 @@ void ContextImpl::tickSearch(SearchKind kind, bool poked)
10441044
// flags and reserved.
10451045
// initially flags[7] is cleared (bcast)
10461046
auto pflags = M.save();
1047-
to_wire(M, uint8_t(kind == SearchKind::discover ?
1048-
pva_search_flags::MustReply : 0u)); // must-reply to discovery, ignore regular negative search
1047+
to_wire(M, uint8_t(
1048+
// must-reply to discovery, ignore regular negative search
1049+
(kind == SearchKind::discover ? pva_search_flags::MustReply : 0u)
1050+
| pva_search_flags::ReplyPort
1051+
)
1052+
);
10491053
to_wire(M, uint8_t(0u));
10501054
to_wire(M, uint16_t(0u));
10511055

src/pvaproto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ void from_wire(Buffer& buf, shared_array<const void>& varr)
579579

580580
struct pva_version {
581581
enum {
582-
client = 2,
582+
client = 3,
583583
server = 2,
584584
};
585585
};
@@ -640,6 +640,7 @@ enum pva_app_msg_t : uint8_t {
640640
struct pva_search_flags {
641641
enum type_t : uint8_t {
642642
MustReply = 0x01,
643+
ReplyPort = 0x02,
643644
Unicast = 0x80,
644645
};
645646
};

src/udp_collector.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,13 @@ void UDPCollector::process_one(const SockAddr &dest, const uint8_t *buf, size_t
317317
return;
318318
}
319319
}
320+
if((origin==Broadcast || origin==Forwarding)
321+
&& peerVersion >= 3
322+
&& (flags&pva_search_flags::ReplyPort))
323+
{
324+
// peer requests reply to (apparent) sender port
325+
port = src.port();
326+
}
320327
server.setPort(port);
321328

322329
if(!M.good() || !(flags&pva_search_flags::Unicast) || dest.family()!=AF_INET) {
@@ -325,11 +332,12 @@ void UDPCollector::process_one(const SockAddr &dest, const uint8_t *buf, size_t
325332
} else if(dest.compare(lo_mcast_addr.addr,false)!=0) {
326333
assert(buf==&this->buf[cmd_origin_tag_size]);
327334
// clear unicast flag in forwarded message
328-
*save_flags &= ~pva_search_flags::Unicast;
335+
*save_flags &= ~(pva_search_flags::Unicast | pva_search_flags::ReplyPort);
329336
// recipient of forwarded message must use, and trust, replyAddr in body :(
330337
{
331-
FixedBuf R(M.be, save_replyAddr, 16u);
338+
FixedBuf R(M.be, save_replyAddr, 16u + 2u);
332339
to_wire(R, server);
340+
to_wire(R, port);
333341
assert(R.good());
334342
}
335343
forwardM(dest, buf, nrx);

0 commit comments

Comments
 (0)