Skip to content

Commit f9a47a6

Browse files
committed
Adding --source-port command line option
This eases interoperability with firewalls. Without this option, the port used as a local source of multicast messages is chosen randomly by the OS. Replies are sent to this port as well. Using a fixed port, enables users or firewall configurations to open that port permanently for wsddn.
1 parent 28f7814 commit f9a47a6

File tree

9 files changed

+66
-2
lines changed

9 files changed

+66
-2
lines changed

doc/wsddn.8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ Set the hop limit for multicast packets.
178178
The default is 1 which should prevent packets from leaving the local
179179
network segment.
180180
The equivalent config file option is \f[CR]hoplimit\f[R]
181+
.TP
182+
\f[CR]\-\-source\-port\f[R] \f[I]number\f[R]
183+
Set the source port for outgoing multicast messages, so that replies
184+
will use this as the destination port.
185+
This is useful for firewalls that do not detect incoming unicast replies
186+
to a multicast as part of the flow, so the port needs to be fixed in
187+
order to be allowed manually.
181188
.SS Machine information options
182189
.TP
183190
\f[CR]\-\-uuid\f[R] \f[I]uuid\f[R]
@@ -288,6 +295,9 @@ Same as \f[CR]\-\-chroot\f[R] command line option
288295
\f[CR]hoplimit\f[R] = \f[I]number\f[R]
289296
Same as \f[CR]\-\-hoplimit\f[R] command line option
290297
.TP
298+
\f[CR]source\-port\f[R] = \f[I]number\f[R]
299+
Same as \f[CR]\-\-source\-port\f[R] command line option
300+
.TP
291301
\f[CR]hostname\f[R] = \[lq]\f[I]name\f[R]\[rq]
292302
Same as \f[CR]\-\-hostname\f[R] command line option
293303
.TP

doc/wsddn.8.html

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

doc/wsddn.8.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ exploits into wsddn. If not specified the behavior is as follows
9494
`--hoplimit` _number_
9595
: Set the hop limit for multicast packets. The default is 1 which should prevent packets from leaving the local network segment. The equivalent config file option is `hoplimit`
9696

97+
`--source-port` _number_
98+
: Set the source port for outgoing multicast messages, so that replies will use this as the destination port. This is useful for firewalls that do not detect incoming unicast replies to a multicast as part of the flow, so the port needs to be fixed in order to be allowed manually.
99+
97100
## Machine information options
98101

99102
`--uuid` _uuid_
@@ -154,6 +157,9 @@ Any options specified on command line take precedence over options in the config
154157
`hoplimit` = _number_
155158
: Same as `--hoplimit` command line option
156159

160+
`source-port` = _number_
161+
: Same as `--source-port` command line option
162+
157163
`hostname` = "_name_"
158164
: Same as `--hostname` command line option
159165

installers/wsddn.conf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@
3333

3434
#hoplimit=1
3535

36+
# Set the source port for outgoing multicast messages, so that replies will
37+
# use this as the destination port.
38+
# This is useful for firewalls that do not detect incoming unicast replies
39+
# to a multicast as part of the flow, so the port needs to be fixed in order
40+
# to be allowed manually.
41+
42+
#source-port=12345
43+
3644
###############################################################################
3745
#
3846
# Machine information

src/command_line.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ void CommandLine::parse(int argc, char * argv[]) {
269269
handler([this](std::string_view val){
270270
this->hoplimit = Argum::parseIntegral<unsigned>(val);
271271
}));
272+
parser.add(Option("--source-port").
273+
help("send multicast traffic and receive replies on this port.").
274+
handler([this](std::string_view val){
275+
this->sourcePort = Argum::parseIntegral<unsigned>(val);
276+
}));
272277

273278
//Machine info
274279
parser.add(Option("--uuid").
@@ -419,6 +424,14 @@ void CommandLine::parseConfigKey(std::string_view keyName, const toml::node & va
419424
this->hoplimit = int((unsigned short)*val);
420425
});
421426

427+
} else if (keyName == "source-port"sv) {
428+
429+
setConfigValue<int64_t>(bool(this->sourcePort), keyName, value, [this](const toml::value<int64_t> & val) {
430+
if (*val < 0 || *val >= 65536)
431+
throw ConfigFileError("source-port value must be in [0, 65536) range", spdlog::level::err, val.source());
432+
this->sourcePort = uint16_t(*val);
433+
});
434+
422435
} else
423436

424437
//Machine info

src/command_line.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ struct CommandLine {
1414
std::vector<sys_string> interfaces;
1515
std::optional<AllowedAddressFamily> allowedAddressFamily;
1616
std::optional<int> hoplimit;
17+
std::optional<uint16_t> sourcePort;
1718

1819
std::optional<Uuid> uuid;
1920
std::optional<sys_string> hostname;

src/config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Config::Config(const CommandLine & cmdline):
1111
m_hopLimit = cmdline.hoplimit.value_or(1);
1212
m_allowedAddressFamily = cmdline.allowedAddressFamily.value_or(BothIPv4AndIPv6);
1313
m_interfaceWhitelist.insert(cmdline.interfaces.begin(), cmdline.interfaces.end());
14+
m_sourcePort = cmdline.sourcePort.value_or(0);
1415

1516
m_fullHostName = getHostName();
1617
m_simpleHostName = m_fullHostName.prefix_before_first(U'.').value_or(m_fullHostName);

src/config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class Config : public ref_counted<Config> {
4444
auto isAllowedInterface(const sys_string & name) const -> bool {
4545
return m_interfaceWhitelist.empty() || m_interfaceWhitelist.contains(name);
4646
}
47+
auto sourcePort() const -> uint16_t { return m_sourcePort; }
4748

4849
auto pageSize() const -> size_t { return m_pageSize; }
4950

@@ -73,6 +74,7 @@ class Config : public ref_counted<Config> {
7374
AllowedAddressFamily m_allowedAddressFamily = BothIPv4AndIPv6;
7475
int m_hopLimit = 1;
7576
std::set<sys_string> m_interfaceWhitelist;
77+
uint16_t m_sourcePort;
7678

7779
size_t m_pageSize;
7880
};

src/udp_server.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,17 @@ class UdpServerImpl : public UdpServer {
8383

8484
m_recvSocket.bind(ip::udp::endpoint(multicastGroupAddress, g_WsdUdpPort));
8585
m_unicastSendSocket.bind(ip::udp::endpoint(addr, g_WsdUdpPort));
86-
86+
8787
#if !defined(__NetBSD__) && !defined(__sun)
8888
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv4MulticastIface, multicastGroupRequest);
8989
#else
9090
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv4MulticastIface, multicastGroupRequest.imr_interface);
9191
#endif
9292
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv4MulticastLoop, false);
9393
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv4MulticastTtl, uint8_t(m_config->hopLimit()));
94+
95+
if (m_config->sourcePort() != 0)
96+
m_multicastSendSocket.bind(ip::udp::endpoint(addr, m_config->sourcePort()));
9497
}
9598

9699
void initAddresses(const ip::address_v6 & addr, const NetworkInterface & iface) {
@@ -114,6 +117,10 @@ class UdpServerImpl : public UdpServer {
114117
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv6MulticastLoop, false);
115118
m_multicastSendSocket.set_option(ip::multicast::hops(m_config->hopLimit()));
116119
setSocketOption(m_multicastSendSocket, ptl::SockOptIPv6MulticastIface, iface.index);
120+
121+
if (m_config->sourcePort() != 0)
122+
m_multicastSendSocket.bind(ip::udp::endpoint(ip::udp::endpoint(ip::address_v6(addr.to_bytes(), iface.index), m_config->sourcePort())));
123+
117124
}
118125

119126
void read() {

0 commit comments

Comments
 (0)