X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/blobdiff_plain/efd6c9e3728bceaf4e355ca1c6584a35f5eb1b1b..042d5c20a1c42002b35aa13c7a44dfb4a94d2e65:/tripe.c diff --git a/tripe.c b/tripe.c index db5a7013..be37617a 100644 --- a/tripe.c +++ b/tripe.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: tripe.c,v 1.3 2001/02/04 17:10:40 mdw Exp $ + * $Id$ * * Main program * @@ -26,20 +26,6 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: tripe.c,v $ - * Revision 1.3 2001/02/04 17:10:40 mdw - * Remove a debugging @abort@ call. - * - * Revision 1.2 2001/02/03 22:33:00 mdw - * Stuff more randomness into the pool in the interval timer. - * - * Revision 1.1 2001/02/03 20:26:37 mdw - * Initial checkin. - * - */ - /*----- Header files ------------------------------------------------------*/ #include "tripe.h" @@ -47,7 +33,6 @@ /*----- Global variables --------------------------------------------------*/ sel_state sel; -octet buf_i[PKBUFSZ], buf_o[PKBUFSZ]; /*----- Static variables --------------------------------------------------*/ @@ -66,17 +51,34 @@ static sel_timer it; * Use: Called periodically to do housekeeping tasks. */ -void interval(struct timeval *tv, void *v) +static void interval(struct timeval *tv, void *v) { struct timeval tvv; T( trace(T_PEER, "peer: interval timer"); ) - rand_seed(RAND_GLOBAL, RMD160_HASHSZ); + rand_seed(RAND_GLOBAL, MAXHASHSZ); p_interval(); tvv = *tv; tvv.tv_sec += T_INTERVAL; sel_addtimer(&sel, &it, &tvv, interval, v); } +/* --- @mystrieq@ --- * + * + * Arguments: @const char *x, *y@ = two strings + * + * Returns: True if @x@ and @y are equal, up to case. + */ + +int mystrieq(const char *x, const char *y) +{ + for (;;) { + if (!*x && !*y) return (1); + if (tolower((unsigned char)*x) != tolower((unsigned char)*y)) + return (0); + x++; y++; + } +} + /* --- @main@ --- * * * Arguments: @int argc@ = number of command line arguments @@ -89,7 +91,9 @@ void interval(struct timeval *tv, void *v) static void usage(FILE *fp) { - pquis(fp, "Usage: $ [-options]\n"); + pquis(fp, "Usage: $ [-D] [-d DIR] [-b ADDR] [-p PORT] [-n TUNNEL]\n\ + [-U USER] [-G GROUP] [-a SOCKET] [-T TRACE-OPTS]\n\ + [-k PRIV-KEYRING] [-K PUB-KEYRING] [-t KEY-TAG]\n"); } static void version(FILE *fp) @@ -108,15 +112,22 @@ Options:\n\ -h, --help Display this help text.\n\ -v, --version Display version number.\n\ -u, --usage Display pointless usage message.\n\ + --tunnels Display IP tunnel drivers and exit.\n\ \n\ -D, --daemon Run in the background.\n\ --d, --directory=DIR Switch to directory DIR (default $TRIPEDIR).\n\ +-d, --directory=DIR Switch to directory DIR [default " CONFIGDIR "].\n\ +-b, --bind-address=ADDR Bind UDP socket to this IP ADDR.\n\ -p, --port=PORT Select UDP port to listen to.\n\ +-n, --tunnel=TUNNEL Seelect default tunnel driver.\n\ +-U, --setuid=USER Set uid to USER after initialization.\n\ +-G, --setgid=GROUP Set gid to GROUP after initialization.\n\ -k, --priv-keyring=FILE Get private key from FILE.\n\ -K, --pub-keyring=FILE Get public keys from FILE.\n\ -t, --tag=KEYTAG Use private key labelled TAG.\n\ -a, --admin-socket=FILE Use FILE as the adminstration socket.\n\ +" T( "\ -T, --trace=OPTIONS Turn on tracing options.\n\ +" ) "\ ", fp); } @@ -124,11 +135,15 @@ int main(int argc, char *argv[]) { const char *kr_priv = "keyring", *kr_pub = "keyring.pub"; const char *tag_priv = "tripe-dh"; - const char *csock = "tripesock"; - const char *dir = "/var/lib/tripe"; + const char *csock = SOCKETDIR "/tripesock"; + const char *dir = CONFIGDIR; const char *p; unsigned port = 0; + struct in_addr baddr = { INADDR_ANY }; unsigned f = 0; + int i; + int selerr = 0; + struct timeval tv; uid_t u = -1; gid_t g = -1; @@ -136,22 +151,26 @@ int main(int argc, char *argv[]) #define f_daemon 2u ego(argv[0]); - trace_on(stderr, 0); + T( trace_on(stderr, 0); ) if ((p = getenv("TRIPEDIR")) != 0) dir = p; + tun_default = tunnels[0]; for (;;) { static const struct option opts[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { "usage", 0, 0, 'u' }, + { "tunnels", 0, 0, '0' }, { "daemon", 0, 0, 'D' }, { "uid", OPTF_ARGREQ, 0, 'U' }, { "setuid", OPTF_ARGREQ, 0, 'U' }, { "gid", OPTF_ARGREQ, 0, 'G' }, { "setgid", OPTF_ARGREQ, 0, 'G' }, + { "bind-address", OPTF_ARGREQ, 0, 'b' }, + { "tunnel", OPTF_ARGREQ, 0, 'n' }, { "port", OPTF_ARGREQ, 0, 'p' }, { "directory", OPTF_ARGREQ, 0, 'd' }, { "priv-keyring", OPTF_ARGREQ, 0, 'k' }, @@ -165,8 +184,8 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0 } }; - int i = mdwopt(argc, argv, "hvu DU:G: p:d:k:K:t:a:" T("T:"), - opts, 0, 0, 0); + i = mdwopt(argc, argv, "hvuDU:G:b:p:d:k:K:t:a:" T("T:"), + opts, 0, 0, 0); if (i < 0) break; switch (i) { @@ -184,30 +203,38 @@ int main(int argc, char *argv[]) f |= f_daemon; break; case 'U': { + struct passwd *pw; char *p; unsigned long i = strtoul(optarg, &p, 0); if (!*p) - u = i; - else { - struct passwd *pw; - if ((pw = getpwnam(optarg)) == 0) - die(EXIT_FAILURE, "user name `%s' not found", optarg); - u = pw->pw_uid; - } + pw = getpwuid(i); + else + pw = getpwnam(optarg); + if (!pw) + die(EXIT_FAILURE, "user `%s' not found", optarg); + u = pw->pw_uid; + if (g == -1) + g = pw->pw_gid; } break; case 'G': { + struct group *gr; char *p; unsigned long i = strtoul(optarg, &p, 0); if (!*p) - g = i; - else { - struct group *gr; - if ((gr = getgrnam(optarg)) == 0) - die(EXIT_FAILURE, "group name `%s' not found", optarg); - g = gr->gr_gid; - } + gr = getgrgid(i); + else + gr = getgrnam(optarg); + if (!gr) + die(EXIT_FAILURE, "group `%s' not found", optarg); + g = gr->gr_gid; + } break; + + case 'b': { + struct hostent *h = gethostbyname(optarg); + if (!h) + die(EXIT_FAILURE, "unknown host name `%s'", optarg); + memcpy(&baddr, h->h_addr, sizeof(struct in_addr)); } break; - case 'p': { char *p; unsigned long i = strtoul(optarg, &p, 0); @@ -221,6 +248,16 @@ int main(int argc, char *argv[]) die(EXIT_FAILURE, "bad port number %lu", i); port = i; } break; + case 'n': { + int i; + for (i = 0;; i++) { + if (!tunnels[i]) + die(EXIT_FAILURE, "unknown tunnel `%s'", optarg); + if (mystrieq(optarg, tunnels[i]->name)) + break; + } + tun_default = tunnels[i]; + } break; case 'd': dir = optarg; break; @@ -242,6 +279,12 @@ int main(int argc, char *argv[]) trace_level(tr_flags); break; #endif + case '0': { + int i; + for (i = 0; tunnels[i]; i++) + puts(tunnels[i]->name); + exit(0); + } break; default: f |= f_bogus; break; @@ -261,19 +304,25 @@ int main(int argc, char *argv[]) sel_init(&sel); sig_init(&sel); rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, RMD160_HASHSZ); + rand_seed(RAND_GLOBAL, MAXHASHSZ); signal(SIGPIPE, SIG_IGN); - tun_init(); - p_init(port); - if (!(f & f_daemon)) - a_create(STDIN_FILENO, STDOUT_FILENO); - if (g != -1) { - if (setgid(g)) { + for (i = 0; tunnels[i]; i++) + tunnels[i]->init(); + p_init(baddr, port); + if (!(f & f_daemon)) { +#ifndef NTRACE + a_create(STDIN_FILENO, STDOUT_FILENO, AF_TRACE | AF_WARN); +#else + a_create(STDIN_FILENO, STDOUT_FILENO, AF_WARN); +#endif + } + if (g != (gid_t)-1) { + if (setgid(g) || (getuid() == 0 && setgroups(1, &g))) { die(EXIT_FAILURE, "couldn't setgid to %u: %s", (unsigned)g, strerror(errno)); } } - if (u != -1) { + if (u != (uid_t)-1) { if (setuid(u)) { die(EXIT_FAILURE, "couldn't setuid to %u: %s", (unsigned)u, strerror(errno)); @@ -282,30 +331,24 @@ int main(int argc, char *argv[]) km_init(kr_priv, kr_pub, tag_priv); a_init(csock); if (f & f_daemon) { - if (u_daemon) + if (u_daemon()) die(EXIT_FAILURE, "couldn't become a daemon: %s", strerror(errno)); a_daemon(); } - { - struct timeval tv; - tv.tv_sec = time(0) + T_INTERVAL; - tv.tv_usec = 0; - sel_addtimer(&sel, &it, &tv, interval, 0); - } + tv.tv_sec = time(0) + T_INTERVAL; + tv.tv_usec = 0; + sel_addtimer(&sel, &it, &tv, interval, 0); - { - int selerr = 0; - for (;;) { - if (!sel_select(&sel)) - selerr = 0; - else if (errno != EINTR && errno != EAGAIN) { - a_warn("select failed: %s", strerror(errno)); - selerr++; - if (selerr > 8) { - a_warn("too many select errors: bailing out"); - a_quit(); - } + for (;;) { + if (!sel_select(&sel)) + selerr = 0; + else if (errno != EINTR && errno != EAGAIN) { + a_warn("SERVER", "select-error", "?ERRNO", A_END); + selerr++; + if (selerr > 8) { + a_warn("ABORT", "repeated-select-errors", A_END); + abort(); } } }