/*
tincctl.c -- Controlling a running tincd
- Copyright (C) 2007-2011 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
" start Start tincd.\n"
" stop Stop tincd.\n"
" restart Restart tincd.\n"
- " reload Reload configuration of running tincd.\n"
+ " reload Partially reload configuration of running tincd.\n"
" pid Show PID of currently running tincd.\n"
" generate-keys [bits] Generate new RSA and ECDSA public/private keypairs.\n"
" generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n"
" purge Purge unreachable nodes\n"
" debug N Set debug level\n"
" retry Retry all outgoing connections\n"
- " reload Partial reload of configuration\n"
" disconnect NODE Close meta connection with NODE\n"
#ifdef HAVE_CURSES
" top Show real-time statistics\n"
#endif
- " pcap Dump traffic in pcap format\n"
+ " pcap [snaplen] Dump traffic in pcap format [up to snaplen bytes per packet]\n"
+ " log [level] Dump log output [up to the specified level]\n"
"\n");
printf("Report bugs to tinc@tinc-vpn.org.\n");
}
}
}
+ if(!netname) {
+ netname = getenv("NETNAME");
+ if(netname)
+ netname = xstrdup(netname);
+ }
+
return true;
}
-FILE *ask_and_open(const char *filename, const char *what, const char *mode) {
+static FILE *ask_and_open(const char *filename, const char *what, const char *mode) {
FILE *r;
char *directory;
char buf[PATH_MAX];
return true;
}
-bool recvdata(int fd, char *data, size_t len) {
+static bool recvdata(int fd, char *data, size_t len) {
while(blen < len) {
int result = recv(fd, buffer + blen, sizeof buffer - blen, 0);
if(result == -1 && errno == EINTR)
return true;
}
-void pcap(int fd, FILE *out) {
- sendline(fd, "%d %d", CONTROL, REQ_PCAP);
+static void pcap(int fd, FILE *out, int snaplen) {
+ sendline(fd, "%d %d %d", CONTROL, REQ_PCAP, snaplen);
char data[9018];
struct {
0xa1b2c3d4,
2, 4,
0, 0,
- sizeof data,
+ snaplen ?: sizeof data,
1,
};
}
}
+static void logcontrol(int fd, FILE *out, int level) {
+ sendline(fd, "%d %d %d", CONTROL, REQ_LOG, level);
+ char data[1024];
+ char line[32];
+
+ while(recvline(fd, line, sizeof line)) {
+ int code, req, len;
+ int n = sscanf(line, "%d %d %d", &code, &req, &len);
+ if(n != 3 || code != CONTROL || req != REQ_LOG || len < 0 || len > sizeof data)
+ break;
+ if(!recvdata(fd, data, len))
+ break;
+ fwrite(data, len, 1, out);
+ fputc('\n', out);
+ fflush(out);
+ }
+}
+
#ifdef HAVE_MINGW
static bool remove_service(void) {
SC_HANDLE manager = NULL;
if(!ControlService(service, SERVICE_CONTROL_STOP, &status))
fprintf(stderr, "Could not stop %s service: %s\n", identname, winerror(GetLastError()));
else
- fprintf(stderr, "%s service stopped", identname);
+ fprintf(stderr, "%s service stopped\n", identname);
if(!DeleteService(service)) {
fprintf(stderr, "Could not remove %s service: %s\n", identname, winerror(GetLastError()));
}
#endif
-int main(int argc, char *argv[], char *envp[]) {
+int main(int argc, char *argv[]) {
int fd;
int result;
char host[128];
if(show_version) {
printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
VERSION, __DATE__, __TIME__, PROT_MAJOR, PROT_MINOR);
- printf("Copyright (C) 1998-2009 Ivo Timmermans, Guus Sliepen and others.\n"
+ printf("Copyright (C) 1998-2012 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"
// First handle commands that don't involve connecting to a running tinc daemon.
if(!strcasecmp(argv[optind], "generate-rsa-keys")) {
- return !rsa_keygen(optind > argc ? atoi(argv[optind + 1]) : 2048);
+ return !rsa_keygen(optind < argc - 1 ? atoi(argv[optind + 1]) : 2048);
}
if(!strcasecmp(argv[optind], "generate-ecdsa-keys")) {
}
if(!strcasecmp(argv[optind], "generate-keys")) {
- return !(rsa_keygen(optind > argc ? atoi(argv[optind + 1]) : 2048) && ecdsa_keygen());
+ return !(rsa_keygen(optind < argc - 1 ? atoi(argv[optind + 1]) : 2048) && ecdsa_keygen());
}
if(!strcasecmp(argv[optind], "start")) {
- argv[optind] = NULL;
- execve(SBINDIR "/tincd", argv, envp);
- fprintf(stderr, "Could not start tincd: %s", strerror(errno));
+ int i, j;
+ char *c;
+ char *slash = strrchr(argv[0], '/');
+#ifdef HAVE_MINGW
+ if ((c = strrchr(argv[0], '\\')) > slash)
+ slash = c;
+#endif
+ if (slash++) {
+ c = xmalloc((slash - argv[0]) + sizeof("tincd"));
+ sprintf(c, "%.*stincd", (int)(slash - argv[0]), argv[0]);
+ }
+ else
+ c = "tincd";
+ argv[0] = c;
+ for(i = j = 1; argv[i]; ++i)
+ if (i != optind && strcmp(argv[i], "--") != 0)
+ argv[j++] = argv[i];
+ argv[j] = NULL;
+ execvp(c, argv);
+ fprintf(stderr, "Could not start %s: %s\n", c, strerror(errno));
return 1;
}
#endif
if(!strcasecmp(argv[optind], "pcap")) {
- pcap(fd, stdout);
+ pcap(fd, stdout, optind < argc - 1 ? atoi(argv[optind + 1]) : 0);
+ return 0;
+ }
+
+ if(!strcasecmp(argv[optind], "log")) {
+ logcontrol(fd, stdout, optind < argc - 1 ? atoi(argv[optind + 1]) : -1);
return 0;
}