Skip to content

Commit 611d1f2

Browse files
committed
feat: improved cli, less panics
1 parent 488cb98 commit 611d1f2

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

src/bins/daemon.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ static TERMINATE: AtomicBool = AtomicBool::new(false);
1212
// TODO: better error handling, keep going even if everything goes boom
1313
pub(crate) fn daemon() {
1414
signal_hook();
15+
println!(
16+
"Daemon capabilities: {:?}",
17+
caps::read(None, caps::CapSet::Effective)
18+
);
1519
println!("starting daemon...");
1620
let mut store = Store::load_or_create().expect("boom");
1721
println!("store loaded, entering main loop");

src/bins/netpulse.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ fn main() {
77
let program = &args[0];
88
let mut opts = Options::new();
99
opts.optflag("h", "help", "print this help menu");
10+
opts.optflag("V", "version", "print the version");
1011
opts.optflag("t", "test", "test run all checks");
1112
let matches = match opts.parse(&args[1..]) {
1213
Ok(m) => m,
@@ -17,6 +18,8 @@ fn main() {
1718

1819
if matches.opt_present("help") {
1920
print_usage(program, opts);
21+
} else if matches.opt_present("version") {
22+
println!("{} {}", env!("CARGO_BIN_NAME"), env!("CARGO_PKG_VERSION"))
2023
} else if matches.opt_present("test") {
2124
test_checks();
2225
} else {

src/bins/netpulsed.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use getopts::Options;
77
use netpulse::store::Store;
88
use netpulse::{DAEMON_LOG_ERR, DAEMON_LOG_INF, DAEMON_PID_FILE, DAEMON_USER};
99
use nix::errno::Errno;
10-
use nix::libc::ESRCH;
1110
use nix::sys::signal::{self, Signal};
1211
use nix::unistd::Pid;
1312

@@ -19,7 +18,13 @@ fn main() {
1918
let program = &args[0];
2019
let mut opts = Options::new();
2120
opts.optflag("h", "help", "print this help menu");
21+
opts.optflag("V", "version", "print the version");
2222
opts.optflag("s", "start", "start the netpulse daemon");
23+
opts.optflag(
24+
"d",
25+
"daemon",
26+
"run directly as the daemon, do not setup a pidfile or drop privileges",
27+
);
2328
opts.optflag("i", "info", "info about the running netpulse daemon");
2429
opts.optflag("e", "end", "stop the running netpulse daemon");
2530
let matches = match opts.parse(&args[1..]) {
@@ -31,12 +36,16 @@ fn main() {
3136

3237
if matches.opt_present("help") {
3338
print_usage(program, opts);
39+
} else if matches.opt_present("version") {
40+
println!("{} {}", env!("CARGO_BIN_NAME"), env!("CARGO_PKG_VERSION"))
3441
} else if matches.opt_present("start") {
3542
startd();
3643
} else if matches.opt_present("info") {
3744
infod();
3845
} else if matches.opt_present("end") {
3946
endd();
47+
} else if matches.opt_present("test") {
48+
daemon();
4049
} else {
4150
print_usage(program, opts);
4251
}
@@ -81,6 +90,7 @@ fn pid_runs(pid: i32) -> bool {
8190
}
8291

8392
fn endd() {
93+
root_guard();
8494
let mut terminated = false;
8595
let pid: Pid = match getpid() {
8696
None => {
@@ -102,7 +112,10 @@ fn endd() {
102112
Errno::ESRCH => {
103113
terminated = true;
104114
}
105-
_ => panic!("Failed to terminate netpulsed: {e}"),
115+
_ => {
116+
eprintln!("Failed to terminate netpulsed: {e}");
117+
std::process::exit(1)
118+
}
106119
}
107120
}
108121
}
@@ -139,7 +152,15 @@ fn print_usage(program: &str, opts: Options) {
139152
print!("{}", opts.usage(&brief));
140153
}
141154

155+
fn root_guard() {
156+
if !nix::unistd::getuid().is_root() {
157+
eprintln!("This needs to be run as root");
158+
std::process::exit(1)
159+
}
160+
}
161+
142162
fn startd() {
163+
root_guard();
143164
let path = Store::path();
144165
let parent_path = path.parent().expect("store file has no parent directory");
145166
println!("Parent: {parent_path:?}");
@@ -166,6 +187,13 @@ fn startd() {
166187
)
167188
.expect("could not set permissions for the netpulse run directory");
168189

190+
// NOTE: Daemonize is the defacto standard way of becoming a daemon in rust (besides extra
191+
// tools like systemd or writing it all yourself with nix or just the libc).
192+
// Sadly, Daemonize just drops all capabilities when we become a daemon, including an important
193+
// one: CAP_NET_RAW. This capability allows us to use raw sockets, which are required for
194+
// things like ICMP (ping) messages.
195+
// I have implemented ICMP checks, but the daemon drops the CAP_NET_RAW capability and then is
196+
// no longer allowed to make the custom pings.
169197
let daemonize = Daemonize::new()
170198
.pid_file(pid_path)
171199
.chown_pid_file(true)

0 commit comments

Comments
 (0)