diff --git a/doc/dhtnode.1 b/doc/dhtnode.1
new file mode 100644
index 0000000000000000000000000000000000000000..55a6d192eceaaf866620fe9200c5f4c34598837a
--- /dev/null
+++ b/doc/dhtnode.1
@@ -0,0 +1,83 @@
+.TH DHTNODE 1 2016-06-27
+
+.SH NAME
+.B dhtnode
+- a simple OpenDHT command line node runner.
+
+.SH SYNOPSYS
+.B dhtnode [-h]
+
+.B dhtnode [-v [\fIlogfile\fP]] [-i] [-d] [-n \fInetwork_id\fP] [-p \fIlocal_port\fP] [-b [\fIbootstrap_host\fP[:\fIport\fP]]]
+
+.SH DESCRIPTION
+
+This program runs a simple OpenDHT node in an interactive way. If you rather
+want to run the node in daemon mode, option \fB'-d'\fP is provided. When running
+in the interractive shell, you benefit from the readline capabilites for writing
+your commands such as command history. Here are the available commands in the
+interractive shell:
+
+.EE
+    h, help    Print this help message.
+    q, quit    Quit the program.
+    log        Start/stop printing DHT logs.
+
+    Node information:
+    ll         Print basic information and stats about the current node.
+    ls         Print basic information about current searches.
+    ld         Print basic information about currenty stored values on this node.
+    lr         Print the full current routing table of this node
+
+    Operations on the DHT:
+    b ip:port             Ping potential node at given IP address/port.
+    g [key]               Get values at [key].
+    l [key]               Listen for value changes at [key].
+    p [key] [str]         Put string value at [key].
+    s [key] [str]         Put string value at [key], signed with our generated
+                          private key.
+    e [key] [dest] [str]  Put string value at [key], encrypted for [dest] with
+                          its public key (if found).
+
+.SH OPTIONS
+
+.TP
+\fB-h\fP
+Prints some help.
+
+.TP
+\fB-v\fP \fIlogfile\fP
+Enable the verbose mode. Optionaly provide a log file.
+
+.TP
+\fB-i\fP
+Generate cryptographic identity for the node.
+
+.TP
+\fB-d\fP
+Run the program in daemon mode (will fork in the background).
+
+.TP
+\fB-n\fP \fInetwork_id\fP
+Specify the network id. This let you connect to distinct networks and prevents
+the merge of two diffrent networks (available since OpenDHT v0.6.1).
+
+.TP
+\fB-p\fP \fIlocal_port\fP
+Use port \fIlocal_port\fP for the program to bind to.
+
+.TP
+\fB-b\fP \fIbootstrap_host\fP[:\fIport\fP]
+The program needs to be given a node to connect to the network. You use this
+option to provide the ip address of that node.
+
+.SH AUTHORS
+.TP
+Program written by
+.IP \(bu
+.\}
+Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+.TP
+Man page written by
+.IP \(bu
+.\}
+Simon Désaulniers <sim.desaulniers@gmail.com>
diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp
index 49ddef7ef03e19c18b1df6558c5045a40b06296c..322087ab095d9214db7dbb3e169bff6e7193f827 100644
--- a/tools/dhtnode.cpp
+++ b/tools/dhtnode.cpp
@@ -29,7 +29,7 @@ extern "C" {
 using namespace dht;
 
 void print_usage() {
-    std::cout << "Usage: dhtnode [-p local_port] [-b bootstrap_host:port]" << std::endl << std::endl;
+    std::cout << "Usage: dhtnode [-v [logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b [bootstrap_host[:port]]]" << std::endl << std::endl;
     std::cout << "dhtnode, a simple OpenDHT command line node runner." << std::endl;
     std::cout << "Report bugs to: http://opendht.net" << std::endl;
 }
diff --git a/tools/tools_common.h b/tools/tools_common.h
index 84347082d9242956c38bac1fe31e86a48dbe0de0..d1f68dc759914020b8043b7858d59643110d2986 100644
--- a/tools/tools_common.h
+++ b/tools/tools_common.h
@@ -164,14 +164,14 @@ dht_params
 parseArgs(int argc, char **argv) {
     dht_params params;
     int opt;
-    while ((opt = getopt_long(argc, argv, ":hidv:p:n:b:", long_options, nullptr)) != -1) {
+    while ((opt = getopt_long(argc, argv, "hidv::p:n:b::", long_options, nullptr)) != -1) {
         switch (opt) {
         case 'p': {
                 int port_arg = atoi(optarg);
                 if (port_arg >= 0 && port_arg < 0x10000)
                     params.port = port_arg;
                 else
-                    std::cout << "Invalid port: " << port_arg << std::endl;
+                    std::cerr << "Invalid port: " << port_arg << std::endl;
             }
             break;
         case 'n':
@@ -185,8 +185,7 @@ parseArgs(int argc, char **argv) {
                     ss << DHT_DEFAULT_PORT;
                     params.bootstrap.second = ss.str();
                 }
-            }
-            else
+            } else
                 params.is_bootstrap_node = true;
             break;
         case 'h':
@@ -203,19 +202,9 @@ parseArgs(int argc, char **argv) {
         case 'd':
             params.daemonize = true;
             break;
-        case ':':
-            switch (optopt) {
-            case 'b':
-                params.is_bootstrap_node = true;
-                break;
-            case 'v':
-                params.log = true;
-                break;
-            default:
-                std::cout << "option requires an argument -- '" << optopt << '\'' << std::endl;
-                break;
-            }
-            break;
+        case '?':
+            std::cerr << "unrecognized option -- '" << static_cast<char>(optopt) << '\'' << std::endl;
+            exit(EXIT_FAILURE);
         default:
             break;
         }