chiark / gitweb /
Debianization.
[tripe] / tripe.c
CommitLineData
410c8acf 1/* -*-c-*-
2 *
ef4a1ab7 3 * $Id: tripe.c,v 1.12 2003/11/29 23:49:32 mdw Exp $
410c8acf 4 *
5 * Main program
6 *
7 * (c) 2001 Straylight/Edgeware
8 */
9
10/*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Trivial IP Encryption (TrIPE).
13 *
14 * TrIPE is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * TrIPE is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with TrIPE; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29/*----- Revision history --------------------------------------------------*
30 *
31 * $Log: tripe.c,v $
ef4a1ab7 32 * Revision 1.12 2003/11/29 23:49:32 mdw
33 * Debianization.
34 *
d13e5724 35 * Revision 1.11 2003/05/17 11:02:03 mdw
36 * Document the new `-b' option.
37 *
767b36e2 38 * Revision 1.10 2003/05/16 12:09:03 mdw
39 * Allow binding to a chosen address.
40 *
b303b584 41 * Revision 1.9 2003/04/15 14:11:09 mdw
42 * Rationalize the behaviour of the `-G' and `-U' options.
43 *
d360f042 44 * Revision 1.8 2002/01/13 17:28:29 mdw
45 * Don't turn tracing on if tracing is turned off (!).
46 *
c5a2ea9b 47 * Revision 1.7 2002/01/13 17:14:05 mdw
48 * Don't include the tracing option in the help if not compiled in.
49 *
2666d7dd 50 * Revision 1.6 2001/06/19 22:08:37 mdw
51 * Moved buffers to peer.c.
52 *
680bfcf4 53 * Revision 1.5 2001/02/16 21:43:12 mdw
54 * Provide a more helpful usage message.
55 *
37852359 56 * Revision 1.4 2001/02/16 21:41:31 mdw
57 * Add a new buffer.
58 *
efd6c9e3 59 * Revision 1.3 2001/02/04 17:10:40 mdw
60 * Remove a debugging @abort@ call.
61 *
e31c0b14 62 * Revision 1.2 2001/02/03 22:33:00 mdw
63 * Stuff more randomness into the pool in the interval timer.
64 *
410c8acf 65 * Revision 1.1 2001/02/03 20:26:37 mdw
66 * Initial checkin.
67 *
68 */
69
70/*----- Header files ------------------------------------------------------*/
71
72#include "tripe.h"
73
74/*----- Global variables --------------------------------------------------*/
75
76sel_state sel;
410c8acf 77
78/*----- Static variables --------------------------------------------------*/
79
80static sel_timer it;
81#define T_INTERVAL MIN(1)
82
83/*----- Main code ---------------------------------------------------------*/
84
85/* --- @interval@ --- *
86 *
87 * Arguments: @struct timeval *tv@ = time when called
88 * @void *v@ = boring pointer
89 *
90 * Returns: ---
91 *
92 * Use: Called periodically to do housekeeping tasks.
93 */
94
95void interval(struct timeval *tv, void *v)
96{
97 struct timeval tvv;
98 T( trace(T_PEER, "peer: interval timer"); )
37852359 99 rand_seed(RAND_GLOBAL, HASHSZ);
410c8acf 100 p_interval();
101 tvv = *tv;
102 tvv.tv_sec += T_INTERVAL;
103 sel_addtimer(&sel, &it, &tvv, interval, v);
104}
105
106/* --- @main@ --- *
107 *
108 * Arguments: @int argc@ = number of command line arguments
109 * @char *argv[]@ = vector of arguments
110 *
111 * Returns: Zero if OK, nonzero on error.
112 *
113 * Use: Main program. Provides a simple VPN.
114 */
115
116static void usage(FILE *fp)
117{
d13e5724 118 pquis(fp, "Usage: $ [-D] [-d dir] [-b addr] [-p port]\n\
119 [-U user] [-G group] [-a socket] [-T trace-opts]\n\
120 [-k priv-keyring] [-K pub-keyring] [-t key-tag]\n");
410c8acf 121}
122
123static void version(FILE *fp)
124{
125 pquis(fp, "$, version " VERSION "\n");
126}
127
128static void help(FILE *fp)
129{
130 version(fp);
131 fputc('\n', fp);
132 usage(fp);
133 fputs("\n\
134Options:\n\
135\n\
136-h, --help Display this help text.\n\
137-v, --version Display version number.\n\
138-u, --usage Display pointless usage message.\n\
139\n\
140-D, --daemon Run in the background.\n\
ef4a1ab7 141-d, --directory=DIR Switch to directory DIR [default " CONFIGDIR "].\n\
d13e5724 142-b, --bind-address=ADDR Bind UDP socket to this IP ADDR.\n\
410c8acf 143-p, --port=PORT Select UDP port to listen to.\n\
d13e5724 144-U, --setuid=USER Set uid to USER after initialization.\n\
145-G, --setgid=GROUP Set gid to GROUP after initialization.\n\
410c8acf 146-k, --priv-keyring=FILE Get private key from FILE.\n\
147-K, --pub-keyring=FILE Get public keys from FILE.\n\
148-t, --tag=KEYTAG Use private key labelled TAG.\n\
149-a, --admin-socket=FILE Use FILE as the adminstration socket.\n\
c5a2ea9b 150" T( "\
410c8acf 151-T, --trace=OPTIONS Turn on tracing options.\n\
c5a2ea9b 152" ) "\
410c8acf 153", fp);
154}
155
156int main(int argc, char *argv[])
157{
158 const char *kr_priv = "keyring", *kr_pub = "keyring.pub";
159 const char *tag_priv = "tripe-dh";
ef4a1ab7 160 const char *csock = SOCKETDIR "/tripesock";
161 const char *dir = CONFIGDIR;
410c8acf 162 const char *p;
163 unsigned port = 0;
767b36e2 164 struct in_addr baddr = { INADDR_ANY };
410c8acf 165 unsigned f = 0;
166 uid_t u = -1;
167 gid_t g = -1;
168
169#define f_bogus 1u
170#define f_daemon 2u
171
172 ego(argv[0]);
d360f042 173 T( trace_on(stderr, 0); )
410c8acf 174
175 if ((p = getenv("TRIPEDIR")) != 0)
176 dir = p;
177
178 for (;;) {
179 static const struct option opts[] = {
180 { "help", 0, 0, 'h' },
181 { "version", 0, 0, 'v' },
182 { "usage", 0, 0, 'u' },
183
184 { "daemon", 0, 0, 'D' },
185 { "uid", OPTF_ARGREQ, 0, 'U' },
186 { "setuid", OPTF_ARGREQ, 0, 'U' },
187 { "gid", OPTF_ARGREQ, 0, 'G' },
188 { "setgid", OPTF_ARGREQ, 0, 'G' },
767b36e2 189 { "bind-address", OPTF_ARGREQ, 0, 'b' },
410c8acf 190 { "port", OPTF_ARGREQ, 0, 'p' },
191 { "directory", OPTF_ARGREQ, 0, 'd' },
192 { "priv-keyring", OPTF_ARGREQ, 0, 'k' },
193 { "pub-keyring", OPTF_ARGREQ, 0, 'K' },
194 { "tag", OPTF_ARGREQ, 0, 't' },
195 { "admin-socket", OPTF_ARGREQ, 0, 'a' },
196#ifndef NTRACE
197 { "trace", OPTF_ARGREQ, 0, 'T' },
198#endif
199
ef4a1ab7 200 { "tunnel", 0, 0, '0' },
410c8acf 201 { 0, 0, 0, 0 }
202 };
203
767b36e2 204 int i = mdwopt(argc, argv, "hvu DU:G: b:p:d:k:K:t:a:" T("T:"),
410c8acf 205 opts, 0, 0, 0);
206 if (i < 0)
207 break;
208 switch (i) {
209 case 'h':
210 help(stdout);
211 exit(0);
212 case 'v':
213 version(stdout);
214 exit(0);
215 case 'u':
216 usage(stdout);
217 exit(0);
218
219 case 'D':
220 f |= f_daemon;
221 break;
222 case 'U': {
b303b584 223 struct passwd *pw;
410c8acf 224 char *p;
225 unsigned long i = strtoul(optarg, &p, 0);
226 if (!*p)
b303b584 227 pw = getpwuid(i);
228 else
229 pw = getpwnam(optarg);
230 if (!pw)
231 die(EXIT_FAILURE, "user `%s' not found", optarg);
232 u = pw->pw_uid;
233 if (g == -1)
234 g = pw->pw_gid;
410c8acf 235 } break;
236 case 'G': {
b303b584 237 struct group *gr;
410c8acf 238 char *p;
239 unsigned long i = strtoul(optarg, &p, 0);
240 if (!*p)
b303b584 241 gr = getgrgid(i);
242 else
243 gr = getgrnam(optarg);
244 if (!gr)
245 die(EXIT_FAILURE, "group `%s' not found", optarg);
246 g = gr->gr_gid;
410c8acf 247 } break;
767b36e2 248
249 case 'b': {
250 struct hostent *h = gethostbyname(optarg);
251 if (!h)
252 die(EXIT_FAILURE, "unknown host name `%s'", optarg);
253 memcpy(&baddr, h->h_addr, sizeof(struct in_addr));
254 } break;
410c8acf 255 case 'p': {
256 char *p;
257 unsigned long i = strtoul(optarg, &p, 0);
258 if (*p) {
259 struct servent *s = getservbyname(optarg, "udp");
260 if (!s)
261 die(EXIT_FAILURE, "unknown service name `%s'", optarg);
262 i = ntohs(s->s_port);
263 }
264 if (i == 0 || i >= 65536)
265 die(EXIT_FAILURE, "bad port number %lu", i);
266 port = i;
267 } break;
268 case 'd':
269 dir = optarg;
270 break;
271 case 'k':
272 kr_priv = optarg;
273 break;
274 case 'K':
275 kr_pub = optarg;
276 break;
277 case 'a':
278 csock = optarg;
279 break;
280 case 't':
281 tag_priv = optarg;
282 break;
283#ifndef NTRACE
284 case 'T':
285 tr_flags = traceopt(tr_opts, optarg, tr_flags, 0);
286 trace_level(tr_flags);
287 break;
288#endif
ef4a1ab7 289 case '0': {
290 static const char *tun[] = { "notdef", "unet", "bsd", "linux" };
291 puts(tun[TUN_TYPE]);
292 exit(0);
293 } break;
410c8acf 294 default:
295 f |= f_bogus;
296 break;
297 }
298 }
299
300 if (optind < argc || (f & f_bogus)) {
301 usage(stderr);
302 exit(EXIT_FAILURE);
303 }
304
305 if (chdir(dir)) {
306 die(EXIT_FAILURE, "can't set current directory to `%s': %s",
307 dir, strerror(errno));
308 }
309
310 sel_init(&sel);
311 sig_init(&sel);
312 rand_noisesrc(RAND_GLOBAL, &noise_source);
313 rand_seed(RAND_GLOBAL, RMD160_HASHSZ);
314 signal(SIGPIPE, SIG_IGN);
315 tun_init();
767b36e2 316 p_init(baddr, port);
410c8acf 317 if (!(f & f_daemon))
318 a_create(STDIN_FILENO, STDOUT_FILENO);
b303b584 319 if (g != (gid_t)-1) {
320 if (setgid(g) || (getuid() == 0 && setgroups(1, &g))) {
410c8acf 321 die(EXIT_FAILURE, "couldn't setgid to %u: %s",
322 (unsigned)g, strerror(errno));
323 }
324 }
b303b584 325 if (u != (uid_t)-1) {
410c8acf 326 if (setuid(u)) {
327 die(EXIT_FAILURE, "couldn't setuid to %u: %s",
328 (unsigned)u, strerror(errno));
329 }
330 }
331 km_init(kr_priv, kr_pub, tag_priv);
332 a_init(csock);
333 if (f & f_daemon) {
37852359 334 if (u_daemon())
410c8acf 335 die(EXIT_FAILURE, "couldn't become a daemon: %s", strerror(errno));
336 a_daemon();
337 }
338
339 {
340 struct timeval tv;
341 tv.tv_sec = time(0) + T_INTERVAL;
342 tv.tv_usec = 0;
343 sel_addtimer(&sel, &it, &tv, interval, 0);
344 }
345
346 {
347 int selerr = 0;
348 for (;;) {
349 if (!sel_select(&sel))
350 selerr = 0;
351 else if (errno != EINTR && errno != EAGAIN) {
352 a_warn("select failed: %s", strerror(errno));
410c8acf 353 selerr++;
354 if (selerr > 8) {
355 a_warn("too many select errors: bailing out");
356 a_quit();
357 }
358 }
359 }
360 }
361
362 return (0);
363}
364
365/*----- That's all, folks -------------------------------------------------*/