Repository: fujiapple852/trippy (rust)

Issue:
Add flag to bypass platform privilege checks
Add a `unsafe-assume-privileged` configuration option which will bypass the existing platform specific privilege checks.  

This option can be helpful for execution environments which use non-standard techniques to allow unprivileged processes to create raw sockets which cannot be detected automatically.

One such environment is `snap` packages, where `trip` runs with the `network-observe` interface which allows for raw sockets without elevated privileges, but does not set `CAP_NET_RAW` and as such `trip` must be run with elevated privileges.

Pull request description:
feat: added `unsafe-assume-privileged` option (#1062)
## **User description**
Closes #1062


___

## **Type**
enhancement


___

## **Description**
- Introduced a new configuration option `unsafe_assume_privileged` to allow assuming elevated privileges, which can be useful in environments that allow unprivileged processes to create raw sockets.
- Added support for this new option across the application, including command-line arguments, configuration files, and shell completions.
- Updated documentation and usage texts to reflect the addition of the `unsafe_assume_privileged` option.


___



## **Changes walkthrough**
<table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>9 files</summary><table>
<tr>
  <td>
    <details>
      <summary><strong>config.rs</strong><dd><code>Add Support for Assuming Elevated Privileges</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

src/config.rs
<li>Introduced a new configuration option <code>unsafe_assume_privileged</code> to <br>assume elevated privileges.<br> <li> Added logic to determine effective privileges by combining <br><code>has_privileges</code> with the new <code>unsafe_assume_privileged</code> flag.<br> <li> Updated privilege validation to use <code>effective_has_privileges</code>.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-cba64c21ab992eaad29fce147a08f4560a4769bc14682b8a96081a5fd02dbecd">+7/-1</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>cmd.rs</strong><dd><code>Command-line Support for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

src/config/cmd.rs
<li>Added a new command-line argument <code>--unsafe-assume-privileged</code> to enable <br>the assumption of elevated privileges.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-53654673fb59793d0004c1feec94a06d60b3e4079a6a696225f6191ec70eb000">+4/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>constants.rs</strong><dd><code>Default Constant for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

src/config/constants.rs
<li>Defined a new constant <code>DEFAULT_UNSAFE_ASSUME_PRIVILEGED</code> to represent <br>the default state of the new privilege assumption feature.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-c1cfbff157312bdee7e6ff89e8a4272ed49b754db04e66415455cc6d02b665dc">+3/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>file.rs</strong><dd><code>Config File Support for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

src/config/file.rs
<li>Added <code>unsafe_assume_privileged</code> field to <code>ConfigTrippy</code> struct to support <br>the new configuration option in config files.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-868ba6c88b7d3b38111961d8233990ccbaa0b07cb40a66eb249017485910cd06">+2/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>completions_bash.txt</strong><dd><code>Bash Completions for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/completions_bash.txt
<li>Updated bash completions to include the <code>--unsafe-assume-privileged</code> <br>option.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-79fe741eb692646e9aa127752aa2c10b253c4a87aeb719873774a0556272b169">+1/-1</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>completions_elvish.txt</strong><dd><code>Elvish Completions for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/completions_elvish.txt
<li>Added support for the <code>--unsafe-assume-privileged</code> option in Elvish <br>completions.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-e90afc34b6b7e7401debe298efe8fa46a15db9ed81cc84cd788f09a0b6d68ff4">+1/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>completions_fish.txt</strong><dd><code>Fish Shell Completions for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/completions_fish.txt
<li>Included the <code>--unsafe-assume-privileged</code> option in fish shell <br>completions.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-899f176a0fb5d45f91db08ac9ef87fb63a7eed172046366eec370a2931dff85c">+1/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>completions_powershell.txt</strong><dd><code>PowerShell Completions for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/completions_powershell.txt
<li>Added the <code>--unsafe-assume-privileged</code> option to PowerShell completions.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-0058b4cb3590403f163146fc3f94c191a38fa38b502c6e2f431a47d584800c93">+1/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>completions_zsh.txt</strong><dd><code>Zsh Completions for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/completions_zsh.txt
<li>Updated Zsh completions to support the <code>--unsafe-assume-privileged</code> <br>option.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-a2b40d43d1c10954638abb2bf55e343df2085a7dff7803c5c5ae93a2392ae2ed">+1/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    
</table></details></td></tr><tr><td><strong>Documentation</strong></td><td><details><summary>3 files</summary><table>
<tr>
  <td>
    <details>
      <summary><strong>usage_long.txt</strong><dd><code>Documentation of Unsafe Privilege Assumption in Usage Text</code></dd></summary>
<hr>

test_resources/config/usage_long.txt
<li>Documented the <code>--unsafe-assume-privileged</code> option in the long usage <br>text.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-65b50ba6a7cb8cb318fdcde51e772cf4e59e49fe21b6a51624e68f363b72d405">+3/-0</a>&nbsp; &nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>usage_short.txt</strong><dd><code>Short Usage Text Update for Unsafe Privilege Assumption</code>&nbsp; &nbsp; </dd></summary>
<hr>

test_resources/config/usage_short.txt
<li>Included the <code>--unsafe-assume-privileged</code> option in the short usage <br>text.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-af867d19c614537334ac2f7b339c6f14bc7cbe7c3ca296efca888a01ed5deea4">+7/-12</a>&nbsp; &nbsp; </td>
</tr>                    

<tr>
  <td>
    <details>
      <summary><strong>trippy-config-sample.toml</strong><dd><code>Sample Configuration for Unsafe Privilege Assumption</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary>
<hr>

trippy-config-sample.toml
<li>Added a sample configuration for the <code>unsafe-assume-privileged</code> option <br>in the sample TOML file.


</details>
    

  </td>
  <td><a href="https://github.com/fujiapple852/trippy/pull/1063/files#diff-b367acc0474f1419a4a9d53a3379b400ed1655005a8fab955dace822a8ae8cfc">+10/-0</a>&nbsp; &nbsp; </td>
</tr>                    
</table></details></td></tr></tr></tbody></table>

___

> ✨ **PR-Agent usage**:
>Comment `/help` on the PR to get a list of all available PR-Agent tools and their descriptions



Patch:
diff --git a/src/config.rs b/src/config.rs
index 7bb8594..85e2925 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -364,6 +364,12 @@ impl TrippyConfig {
             cfg_file_trace.unprivileged,
             defaults::DEFAULT_PRIVILEGE_MODE.is_unprivileged(),
         );
+        let unsafe_assume_privileged = cfg_layer_bool_flag(
+            args.unsafe_assume_privileged,
+            cfg_file_trace.unsafe_assume_privileged,
+            constants::DEFAULT_UNSAFE_ASSUME_PRIVILEGED,
+        );
+        let effective_has_privileges = has_privileges || unsafe_assume_privileged;
         let privilege_mode = if unprivileged {
             PrivilegeMode::Unprivileged
         } else {
@@ -646,7 +652,7 @@ impl TrippyConfig {
             Some(n) if n > 0 => Some(n),
             _ => None,
         };
-        validate_privilege(privilege_mode, has_privileges, needs_privileges)?;
+        validate_privilege(privilege_mode, effective_has_privileges, needs_privileges)?;
         validate_logging(mode, verbose)?;
         validate_strategy(multipath_strategy, unprivileged)?;
         validate_protocol_strategy(protocol, multipath_strategy)?;
@@ -1597,6 +1603,7 @@ mod tests {
     #[test_case("trip example.com --unprivileged", false, false, Ok(cfg().privilege_mode(PrivilegeMode::Unprivileged).build()); "no privilege and not needs in unprivileged mode")]
     #[test_case("trip example.com --unprivileged", false, true, Err(anyhow!("unprivileged mode not supported on this platform\n\nsee https://github.com/fujiapple852/trippy#privileges for details")); "no privilege and needs in unprivileged mode")]
     #[test_case("trip example.com --unprivileged", true, true, Err(anyhow!("unprivileged mode not supported on this platform (hint: process is privileged so disable unprivileged mode)\n\nsee https://github.com/fujiapple852/trippy#privileges for details")); "has privilege and needs in unprivileged mode")]
+    #[test_case("trip example.com --unsafe-assume-privileged", false, false, Ok(cfg().privilege_mode(PrivilegeMode::Privileged).build()); "unsafe assume privileged")]
     fn test_privilege(
         cmd: &str,
         has_privileges: bool,
diff --git a/src/config/cmd.rs b/src/config/cmd.rs
index c11decd..4a79471 100644
--- a/src/config/cmd.rs
+++ b/src/config/cmd.rs
@@ -30,6 +30,10 @@ pub struct Args {
     #[arg(short = 'u', long)]
     pub unprivileged: bool,
 
+    /// Assume elevated privileges [default: false]
+    #[arg(long)]
+    pub unsafe_assume_privileged: bool,
+
     /// Tracing protocol [default: icmp]
     #[arg(value_enum, short = 'p', long)]
     pub protocol: Option<ProtocolConfig>,
diff --git a/src/config/constants.rs b/src/config/constants.rs
index bbb1f5d..15a38d7 100644
--- a/src/config/constants.rs
+++ b/src/config/constants.rs
@@ -13,7 +13,10 @@ pub const MAX_HOPS: usize = u8::MAX as usize;
 /// The default value for `mode`.
 pub const DEFAULT_MODE: Mode = Mode::Tui;
 
-/// The default value for `all_resolved_ips`.
+/// The default value for `unsafe-assume-privileged`.
+pub const DEFAULT_UNSAFE_ASSUME_PRIVILEGED: bool = false;
+
+/// The default value for `all-resolved-ips`.
 pub const DEFAULT_DNS_RESOLVE_ALL: bool = false;
 
 /// The default value for `log-format`.
@@ -55,7 +58,7 @@ pub const DEFAULT_TUI_ADDRESS_MODE: AddressMode = AddressMode::Host;
 /// The default value for `tui-refresh-rate`.
 pub const DEFAULT_TUI_REFRESH_RATE: &str = "100ms";
 
-/// The default value for `tui_privacy_max_ttl`.
+/// The default value for `tui-privacy-max-ttl`.
 pub const DEFAULT_TUI_PRIVACY_MAX_TTL: u8 = 0;
 
 /// The default value for `dns-resolve-method`.
diff --git a/src/config/file.rs b/src/config/file.rs
index a9fe30c..7cbe751 100644
--- a/src/config/file.rs
+++ b/src/config/file.rs
@@ -106,6 +106,7 @@ impl Default for ConfigFile {
 pub struct ConfigTrippy {
     pub mode: Option<Mode>,
     pub unprivileged: Option<bool>,
+    pub unsafe_assume_privileged: Option<bool>,
     pub log_format: Option<LogFormat>,
     pub log_filter: Option<String>,
     pub log_span_events: Option<LogSpanEvents>,
@@ -116,6 +117,7 @@ impl Default for ConfigTrippy {
         Self {
             mode: Some(super::constants::DEFAULT_MODE),
             unprivileged: Some(defaults::DEFAULT_PRIVILEGE_MODE.is_unprivileged()),
+            unsafe_assume_privileged: Some(super::constants::DEFAULT_UNSAFE_ASSUME_PRIVILEGED),
             log_format: Some(super::constants::DEFAULT_LOG_FORMAT),
             log_filter: Some(String::from(super::constants::DEFAULT_LOG_FILTER)),
             log_span_events: Some(super::constants::DEFAULT_LOG_SPAN_EVENTS),
diff --git a/trippy-config-sample.toml b/trippy-config-sample.toml
index f970ed4..423cab0 100644
--- a/trippy-config-sample.toml
+++ b/trippy-config-sample.toml
@@ -44,6 +44,16 @@ mode = "tui"
 # Note: not supported on all platforms.
 unprivileged = false
 
+# Assume elevated privileges [default: false]
+#
+# This option can be helpful for execution environments which use non-standard
+# techniques to allow unprivileged processes to create raw sockets which cannot
+# be detected automatically.
+#
+# Warning: setting this option to true will bypass platform specifc checks for
+# elevated privileges and as a result ungraceful runtime failures may occur.
+unsafe-assume-privileged = false
+
 # How to format log data.
 #
 # Allowed values are:


Test patch:
diff --git a/test_resources/config/completions_bash.txt b/test_resources/config/completions_bash.txt
index acc0112..f409c90 100644
--- a/test_resources/config/completions_bash.txt
+++ b/test_resources/config/completions_bash.txt
@@ -19,7 +19,7 @@ _trip() {
 
     case "${cmd}" in
         trip)
-            opts="-c -m -u -p -F -4 -6 -P -S -A -I -i -T -g -R -U -f -t -Q -e -r -y -z -a -M -s -C -G -v -h -V --config-file --mode --unprivileged --protocol --udp --tcp --icmp --addr-family --ipv4 --ipv6 --target-port --source-port --source-address --interface --min-round-duration --max-round-duration --grace-duration --initial-sequence --multipath-strategy --max-inflight --first-ttl --max-ttl --packet-size --payload-pattern --tos --icmp-extensions --read-timeout --dns-resolve-method --dns-resolve-all --dns-timeout --dns-lookup-as-info --tui-address-mode --tui-as-mode --tui-custom-columns --tui-icmp-extension-mode --tui-geoip-mode --tui-max-addrs --tui-max-samples --tui-max-flows --tui-preserve-screen --tui-refresh-rate --tui-privacy-max-ttl --tui-theme-colors --print-tui-theme-items --tui-key-bindings --print-tui-binding-commands --report-cycles --geoip-mmdb-file --generate --print-config-template --log-format --log-filter --log-span-events --verbose --help --version [TARGETS]..."
+            opts="-c -m -u -p -F -4 -6 -P -S -A -I -i -T -g -R -U -f -t -Q -e -r -y -z -a -M -s -C -G -v -h -V --config-file --mode --unprivileged --unsafe-assume-privileged --protocol --udp --tcp --icmp --addr-family --ipv4 --ipv6 --target-port --source-port --source-address --interface --min-round-duration --max-round-duration --grace-duration --initial-sequence --multipath-strategy --max-inflight --first-ttl --max-ttl --packet-size --payload-pattern --tos --icmp-extensions --read-timeout --dns-resolve-method --dns-resolve-all --dns-timeout --dns-lookup-as-info --tui-address-mode --tui-as-mode --tui-custom-columns --tui-icmp-extension-mode --tui-geoip-mode --tui-max-addrs --tui-max-samples --tui-max-flows --tui-preserve-screen --tui-refresh-rate --tui-privacy-max-ttl --tui-theme-colors --print-tui-theme-items --tui-key-bindings --print-tui-binding-commands --report-cycles --geoip-mmdb-file --generate --print-config-template --log-format --log-filter --log-span-events --verbose --help --version [TARGETS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
diff --git a/test_resources/config/completions_elvish.txt b/test_resources/config/completions_elvish.txt
index 7fa7443..0b725de 100644
--- a/test_resources/config/completions_elvish.txt
+++ b/test_resources/config/completions_elvish.txt
@@ -82,6 +82,7 @@ set edit:completion:arg-completer[trip] = {|@words|
             cand --log-span-events 'The debug log format [default: off]'
             cand -u 'Trace without requiring elevated privileges on supported platforms [default: false]'
             cand --unprivileged 'Trace without requiring elevated privileges on supported platforms [default: false]'
+            cand --unsafe-assume-privileged 'Assume elevated privileges [default: false]'
             cand --udp 'Trace using the UDP protocol'
             cand --tcp 'Trace using the TCP protocol'
             cand --icmp 'Trace using the ICMP protocol'
diff --git a/test_resources/config/completions_fish.txt b/test_resources/config/completions_fish.txt
index b291578..84f5bc5 100644
--- a/test_resources/config/completions_fish.txt
+++ b/test_resources/config/completions_fish.txt
@@ -39,6 +39,7 @@ complete -c trip -l log-format -d 'The debug log format [default: pretty]' -r -f
 complete -c trip -l log-filter -d 'The debug log filter [default: trippy=debug]' -r
 complete -c trip -l log-span-events -d 'The debug log format [default: off]' -r -f -a "{off	'Do not display event spans',active	'Display enter and exit event spans',full	'Display all event spans'}"
 complete -c trip -s u -l unprivileged -d 'Trace without requiring elevated privileges on supported platforms [default: false]'
+complete -c trip -l unsafe-assume-privileged -d 'Assume elevated privileges [default: false]'
 complete -c trip -l udp -d 'Trace using the UDP protocol'
 complete -c trip -l tcp -d 'Trace using the TCP protocol'
 complete -c trip -l icmp -d 'Trace using the ICMP protocol'
diff --git a/test_resources/config/completions_powershell.txt b/test_resources/config/completions_powershell.txt
index 9916b06..4a25c46 100644
--- a/test_resources/config/completions_powershell.txt
+++ b/test_resources/config/completions_powershell.txt
@@ -85,6 +85,7 @@ Register-ArgumentCompleter -Native -CommandName 'trip' -ScriptBlock {
             [CompletionResult]::new('--log-span-events', 'log-span-events', [CompletionResultType]::ParameterName, 'The debug log format [default: off]')
             [CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'Trace without requiring elevated privileges on supported platforms [default: false]')
             [CompletionResult]::new('--unprivileged', 'unprivileged', [CompletionResultType]::ParameterName, 'Trace without requiring elevated privileges on supported platforms [default: false]')
+            [CompletionResult]::new('--unsafe-assume-privileged', 'unsafe-assume-privileged', [CompletionResultType]::ParameterName, 'Assume elevated privileges [default: false]')
             [CompletionResult]::new('--udp', 'udp', [CompletionResultType]::ParameterName, 'Trace using the UDP protocol')
             [CompletionResult]::new('--tcp', 'tcp', [CompletionResultType]::ParameterName, 'Trace using the TCP protocol')
             [CompletionResult]::new('--icmp', 'icmp', [CompletionResultType]::ParameterName, 'Trace using the ICMP protocol')
diff --git a/test_resources/config/completions_zsh.txt b/test_resources/config/completions_zsh.txt
index b0bb264..3041b64 100644
--- a/test_resources/config/completions_zsh.txt
+++ b/test_resources/config/completions_zsh.txt
@@ -135,6 +135,7 @@ active\:"Display enter and exit event spans"
 full\:"Display all event spans"))' \
 '-u[Trace without requiring elevated privileges on supported platforms \[default\: false\]]' \
 '--unprivileged[Trace without requiring elevated privileges on supported platforms \[default\: false\]]' \
+'--unsafe-assume-privileged[Assume elevated privileges \[default\: false\]]' \
 '(-p --protocol --tcp --icmp)--udp[Trace using the UDP protocol]' \
 '(-p --protocol --udp --icmp)--tcp[Trace using the TCP protocol]' \
 '(-p --protocol --udp --tcp)--icmp[Trace using the ICMP protocol]' \
diff --git a/test_resources/config/usage_long.txt b/test_resources/config/usage_long.txt
index ebfa241..0db7593 100644
--- a/test_resources/config/usage_long.txt
+++ b/test_resources/config/usage_long.txt
@@ -27,6 +27,9 @@ Options:
   -u, --unprivileged
           Trace without requiring elevated privileges on supported platforms [default: false]
 
+      --unsafe-assume-privileged
+          Assume elevated privileges [default: false]
+
   -p, --protocol <PROTOCOL>
           Tracing protocol [default: icmp]
 
diff --git a/test_resources/config/usage_short.txt b/test_resources/config/usage_short.txt
index 5c4d678..88325ae 100644
--- a/test_resources/config/usage_short.txt
+++ b/test_resources/config/usage_short.txt
@@ -6,65 +6,119 @@ Arguments:
   [TARGETS]...  A space delimited list of hostnames and IPs to trace
 
 Options:
-  -c, --config-file <CONFIG_FILE>                          Config file
-  -m, --mode <MODE>                                        Output mode [default: tui] [possible values: tui, stream, pretty, markdown, csv, json, dot,
-                                                           flows, silent]
-  -u, --unprivileged                                       Trace without requiring elevated privileges on supported platforms [default: false]
-  -p, --protocol <PROTOCOL>                                Tracing protocol [default: icmp] [possible values: icmp, udp, tcp]
-      --udp                                                Trace using the UDP protocol
-      --tcp                                                Trace using the TCP protocol
-      --icmp                                               Trace using the ICMP protocol
-  -F, --addr-family <ADDR_FAMILY>                          The address family [default: Ipv4thenIpv6] [possible values: ipv4, ipv6, ipv6-then-ipv4,
-                                                           ipv4-then-ipv6]
-  -4, --ipv4                                               Use IPv4 only
-  -6, --ipv6                                               Use IPv6 only
-  -P, --target-port <TARGET_PORT>                          The target port (TCP & UDP only) [default: 80]
-  -S, --source-port <SOURCE_PORT>                          The source port (TCP & UDP only) [default: auto]
-  -A, --source-address <SOURCE_ADDRESS>                    The source IP address [default: auto]
-  -I, --interface <INTERFACE>                              The network interface [default: auto]
-  -i, --min-round-duration <MIN_ROUND_DURATION>            The minimum duration of every round [default: 1s]
-  -T, --max-round-duration <MAX_ROUND_DURATION>            The maximum duration of every round [default: 1s]
-  -g, --grace-duration <GRACE_DURATION>                    The period of time to wait for additional ICMP responses after the target has responded [default:
-                                                           100ms]
-      --initial-sequence <INITIAL_SEQUENCE>                The initial sequence number [default: 33000]
-  -R, --multipath-strategy <MULTIPATH_STRATEGY>            The Equal-cost Multi-Path routing strategy (UDP only) [default: classic] [possible values:
-                                                           classic, paris, dublin]
-  -U, --max-inflight <MAX_INFLIGHT>                        The maximum number of in-flight ICMP echo requests [default: 24]
-  -f, --first-ttl <FIRST_TTL>                              The TTL to start from [default: 1]
-  -t, --max-ttl <MAX_TTL>                                  The maximum number of TTL hops [default: 64]
-      --packet-size <PACKET_SIZE>                          The size of IP packet to send (IP header + ICMP header + payload) [default: 84]
-      --payload-pattern <PAYLOAD_PATTERN>                  The repeating pattern in the payload of the ICMP packet [default: 0]
-  -Q, --tos <TOS>                                          The TOS (i.e. DSCP+ECN) IP header value (TCP and UDP only) [default: 0]
-  -e, --icmp-extensions                                    Parse ICMP extensions
-      --read-timeout <READ_TIMEOUT>                        The socket read timeout [default: 10ms]
-  -r, --dns-resolve-method <DNS_RESOLVE_METHOD>            How to perform DNS queries [default: system] [possible values: system, resolv, google,
-                                                           cloudflare]
-  -y, --dns-resolve-all                                    Trace to all IPs resolved from DNS lookup [default: false]
-      --dns-timeout <DNS_TIMEOUT>                          The maximum time to wait to perform DNS queries [default: 5s]
-  -z, --dns-lookup-as-info                                 Lookup autonomous system (AS) information during DNS queries [default: false]
-  -a, --tui-address-mode <TUI_ADDRESS_MODE>                How to render addresses [default: host] [possible values: ip, host, both]
-      --tui-as-mode <TUI_AS_MODE>                          How to render AS information [default: asn] [possible values: asn, prefix, country-code,
-                                                           registry, allocated, name]
-      --tui-custom-columns <TUI_CUSTOM_COLUMNS>            Custom columns to be displayed in the TUI hops table [default: holsravbwdt]
-      --tui-icmp-extension-mode <TUI_ICMP_EXTENSION_MODE>  How to render ICMP extensions [default: off] [possible values: off, mpls, full, all]
-      --tui-geoip-mode <TUI_GEOIP_MODE>                    How to render GeoIp information [default: short] [possible values: off, short, long, location]
-  -M, --tui-max-addrs <TUI_MAX_ADDRS>                      The maximum number of addresses to show per hop [default: auto]
-  -s, --tui-max-samples <TUI_MAX_SAMPLES>                  The maximum number of samples to record per hop [default: 256]
-      --tui-max-flows <TUI_MAX_FLOWS>                      The maximum number of flows to show [default: 64]
-      --tui-preserve-screen                                Preserve the screen on exit [default: false]
-      --tui-refresh-rate <TUI_REFRESH_RATE>                The Tui refresh rate [default: 100ms]
-      --tui-privacy-max-ttl <TUI_PRIVACY_MAX_TTL>          The maximum ttl of hops which will be masked for privacy [default: 0]
-      --tui-theme-colors <TUI_THEME_COLORS>                The TUI theme colors [item=color,item=color,..]
-      --print-tui-theme-items                              Print all TUI theme items and exit
-      --tui-key-bindings <TUI_KEY_BINDINGS>                The TUI key bindings [command=key,command=key,..]
-      --print-tui-binding-commands                         Print all TUI commands that can be bound and exit
-  -C, --report-cycles <REPORT_CYCLES>                      The number of report cycles to run [default: 10]
-  -G, --geoip-mmdb-file <GEOIP_MMDB_FILE>                  The supported MaxMind or IPinfo GeoIp mmdb file
-      --generate <GENERATE>                                Generate shell completion [possible values: bash, elvish, fish, powershell, zsh]
-      --print-config-template                              Print a template toml config file and exit
-      --log-format <LOG_FORMAT>                            The debug log format [default: pretty] [possible values: compact, pretty, json, chrome]
-      --log-filter <LOG_FILTER>                            The debug log filter [default: trippy=debug]
-      --log-span-events <LOG_SPAN_EVENTS>                  The debug log format [default: off] [possible values: off, active, full]
-  -v, --verbose                                            Enable verbose debug logging
-  -h, --help                                               Print help (see more with '--help')
-  -V, --version                                            Print version
+  -c, --config-file <CONFIG_FILE>
+          Config file
+  -m, --mode <MODE>
+          Output mode [default: tui] [possible values: tui, stream, pretty, markdown, csv, json, dot, flows, silent]
+  -u, --unprivileged
+          Trace without requiring elevated privileges on supported platforms [default: false]
+      --unsafe-assume-privileged
+          Assume elevated privileges [default: false]
+  -p, --protocol <PROTOCOL>
+          Tracing protocol [default: icmp] [possible values: icmp, udp, tcp]
+      --udp
+          Trace using the UDP protocol
+      --tcp
+          Trace using the TCP protocol
+      --icmp
+          Trace using the ICMP protocol
+  -F, --addr-family <ADDR_FAMILY>
+          The address family [default: Ipv4thenIpv6] [possible values: ipv4, ipv6, ipv6-then-ipv4, ipv4-then-ipv6]
+  -4, --ipv4
+          Use IPv4 only
+  -6, --ipv6
+          Use IPv6 only
+  -P, --target-port <TARGET_PORT>
+          The target port (TCP & UDP only) [default: 80]
+  -S, --source-port <SOURCE_PORT>
+          The source port (TCP & UDP only) [default: auto]
+  -A, --source-address <SOURCE_ADDRESS>
+          The source IP address [default: auto]
+  -I, --interface <INTERFACE>
+          The network interface [default: auto]
+  -i, --min-round-duration <MIN_ROUND_DURATION>
+          The minimum duration of every round [default: 1s]
+  -T, --max-round-duration <MAX_ROUND_DURATION>
+          The maximum duration of every round [default: 1s]
+  -g, --grace-duration <GRACE_DURATION>
+          The period of time to wait for additional ICMP responses after the target has responded [default: 100ms]
+      --initial-sequence <INITIAL_SEQUENCE>
+          The initial sequence number [default: 33000]
+  -R, --multipath-strategy <MULTIPATH_STRATEGY>
+          The Equal-cost Multi-Path routing strategy (UDP only) [default: classic] [possible values: classic, paris,
+          dublin]
+  -U, --max-inflight <MAX_INFLIGHT>
+          The maximum number of in-flight ICMP echo requests [default: 24]
+  -f, --first-ttl <FIRST_TTL>
+          The TTL to start from [default: 1]
+  -t, --max-ttl <MAX_TTL>
+          The maximum number of TTL hops [default: 64]
+      --packet-size <PACKET_SIZE>
+          The size of IP packet to send (IP header + ICMP header + payload) [default: 84]
+      --payload-pattern <PAYLOAD_PATTERN>
+          The repeating pattern in the payload of the ICMP packet [default: 0]
+  -Q, --tos <TOS>
+          The TOS (i.e. DSCP+ECN) IP header value (TCP and UDP only) [default: 0]
+  -e, --icmp-extensions
+          Parse ICMP extensions
+      --read-timeout <READ_TIMEOUT>
+          The socket read timeout [default: 10ms]
+  -r, --dns-resolve-method <DNS_RESOLVE_METHOD>
+          How to perform DNS queries [default: system] [possible values: system, resolv, google, cloudflare]
+  -y, --dns-resolve-all
+          Trace to all IPs resolved from DNS lookup [default: false]
+      --dns-timeout <DNS_TIMEOUT>
+          The maximum time to wait to perform DNS queries [default: 5s]
+  -z, --dns-lookup-as-info
+          Lookup autonomous system (AS) information during DNS queries [default: false]
+  -a, --tui-address-mode <TUI_ADDRESS_MODE>
+          How to render addresses [default: host] [possible values: ip, host, both]
+      --tui-as-mode <TUI_AS_MODE>
+          How to render AS information [default: asn] [possible values: asn, prefix, country-code, registry, allocated,
+          name]
+      --tui-custom-columns <TUI_CUSTOM_COLUMNS>
+          Custom columns to be displayed in the TUI hops table [default: holsravbwdt]
+      --tui-icmp-extension-mode <TUI_ICMP_EXTENSION_MODE>
+          How to render ICMP extensions [default: off] [possible values: off, mpls, full, all]
+      --tui-geoip-mode <TUI_GEOIP_MODE>
+          How to render GeoIp information [default: short] [possible values: off, short, long, location]
+  -M, --tui-max-addrs <TUI_MAX_ADDRS>
+          The maximum number of addresses to show per hop [default: auto]
+  -s, --tui-max-samples <TUI_MAX_SAMPLES>
+          The maximum number of samples to record per hop [default: 256]
+      --tui-max-flows <TUI_MAX_FLOWS>
+          The maximum number of flows to show [default: 64]
+      --tui-preserve-screen
+          Preserve the screen on exit [default: false]
+      --tui-refresh-rate <TUI_REFRESH_RATE>
+          The Tui refresh rate [default: 100ms]
+      --tui-privacy-max-ttl <TUI_PRIVACY_MAX_TTL>
+          The maximum ttl of hops which will be masked for privacy [default: 0]
+      --tui-theme-colors <TUI_THEME_COLORS>
+          The TUI theme colors [item=color,item=color,..]
+      --print-tui-theme-items
+          Print all TUI theme items and exit
+      --tui-key-bindings <TUI_KEY_BINDINGS>
+          The TUI key bindings [command=key,command=key,..]
+      --print-tui-binding-commands
+          Print all TUI commands that can be bound and exit
+  -C, --report-cycles <REPORT_CYCLES>
+          The number of report cycles to run [default: 10]
+  -G, --geoip-mmdb-file <GEOIP_MMDB_FILE>
+          The supported MaxMind or IPinfo GeoIp mmdb file
+      --generate <GENERATE>
+          Generate shell completion [possible values: bash, elvish, fish, powershell, zsh]
+      --print-config-template
+          Print a template toml config file and exit
+      --log-format <LOG_FORMAT>
+          The debug log format [default: pretty] [possible values: compact, pretty, json, chrome]
+      --log-filter <LOG_FILTER>
+          The debug log filter [default: trippy=debug]
+      --log-span-events <LOG_SPAN_EVENTS>
+          The debug log format [default: off] [possible values: off, active, full]
+  -v, --verbose
+          Enable verbose debug logging
+  -h, --help
+          Print help (see more with '--help')
+  -V, --version
+          Print version