chiark / gitweb /
Write a pidfile on request, and delete it when finished.
[tripe] / tripe.c
CommitLineData
410c8acf 1/* -*-c-*-
2 *
680bfcf4 3 * $Id: tripe.c,v 1.5 2001/02/16 21:43:12 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 $
680bfcf4 32 * Revision 1.5 2001/02/16 21:43:12 mdw
33 * Provide a more helpful usage message.
34 *
37852359 35 * Revision 1.4 2001/02/16 21:41:31 mdw
36 * Add a new buffer.
37 *
efd6c9e3 38 * Revision 1.3 2001/02/04 17:10:40 mdw
39 * Remove a debugging @abort@ call.
40 *
e31c0b14 41 * Revision 1.2 2001/02/03 22:33:00 mdw
42 * Stuff more randomness into the pool in the interval timer.
43 *
410c8acf 44 * Revision 1.1 2001/02/03 20:26:37 mdw
45 * Initial checkin.
46 *
47 */
48
49/*----- Header files ------------------------------------------------------*/
50
51#include "tripe.h"
52
53/*----- Global variables --------------------------------------------------*/
54
55sel_state sel;
37852359 56octet buf_i[PKBUFSZ], buf_o[PKBUFSZ], buf_t[PKBUFSZ];
410c8acf 57
58/*----- Static variables --------------------------------------------------*/
59
60static sel_timer it;
61#define T_INTERVAL MIN(1)
62
63/*----- Main code ---------------------------------------------------------*/
64
65/* --- @interval@ --- *
66 *
67 * Arguments: @struct timeval *tv@ = time when called
68 * @void *v@ = boring pointer
69 *
70 * Returns: ---
71 *
72 * Use: Called periodically to do housekeeping tasks.
73 */
74
75void interval(struct timeval *tv, void *v)
76{
77 struct timeval tvv;
78 T( trace(T_PEER, "peer: interval timer"); )
37852359 79 rand_seed(RAND_GLOBAL, HASHSZ);
410c8acf 80 p_interval();
81 tvv = *tv;
82 tvv.tv_sec += T_INTERVAL;
83 sel_addtimer(&sel, &it, &tvv, interval, v);
84}
85
86/* --- @main@ --- *
87 *
88 * Arguments: @int argc@ = number of command line arguments
89 * @char *argv[]@ = vector of arguments
90 *
91 * Returns: Zero if OK, nonzero on error.
92 *
93 * Use: Main program. Provides a simple VPN.
94 */
95
96static void usage(FILE *fp)
97{
680bfcf4 98 pquis(fp, "Usage: $ [-D] [-p port] [-T trace-opts] [-d dir] [-a socket]\n\
99 [-k priv-keyring] [-K pub-keyring] [-t key-tag]\n");
410c8acf 100}
101
102static void version(FILE *fp)
103{
104 pquis(fp, "$, version " VERSION "\n");
105}
106
107static void help(FILE *fp)
108{
109 version(fp);
110 fputc('\n', fp);
111 usage(fp);
112 fputs("\n\
113Options:\n\
114\n\
115-h, --help Display this help text.\n\
116-v, --version Display version number.\n\
117-u, --usage Display pointless usage message.\n\
118\n\
119-D, --daemon Run in the background.\n\
120-d, --directory=DIR Switch to directory DIR (default $TRIPEDIR).\n\
121-p, --port=PORT Select UDP port to listen to.\n\
122-k, --priv-keyring=FILE Get private key from FILE.\n\
123-K, --pub-keyring=FILE Get public keys from FILE.\n\
124-t, --tag=KEYTAG Use private key labelled TAG.\n\
125-a, --admin-socket=FILE Use FILE as the adminstration socket.\n\
126-T, --trace=OPTIONS Turn on tracing options.\n\
127", fp);
128}
129
130int main(int argc, char *argv[])
131{
132 const char *kr_priv = "keyring", *kr_pub = "keyring.pub";
133 const char *tag_priv = "tripe-dh";
134 const char *csock = "tripesock";
135 const char *dir = "/var/lib/tripe";
136 const char *p;
137 unsigned port = 0;
138 unsigned f = 0;
139 uid_t u = -1;
140 gid_t g = -1;
141
142#define f_bogus 1u
143#define f_daemon 2u
144
145 ego(argv[0]);
146 trace_on(stderr, 0);
147
148 if ((p = getenv("TRIPEDIR")) != 0)
149 dir = p;
150
151 for (;;) {
152 static const struct option opts[] = {
153 { "help", 0, 0, 'h' },
154 { "version", 0, 0, 'v' },
155 { "usage", 0, 0, 'u' },
156
157 { "daemon", 0, 0, 'D' },
158 { "uid", OPTF_ARGREQ, 0, 'U' },
159 { "setuid", OPTF_ARGREQ, 0, 'U' },
160 { "gid", OPTF_ARGREQ, 0, 'G' },
161 { "setgid", OPTF_ARGREQ, 0, 'G' },
162 { "port", OPTF_ARGREQ, 0, 'p' },
163 { "directory", OPTF_ARGREQ, 0, 'd' },
164 { "priv-keyring", OPTF_ARGREQ, 0, 'k' },
165 { "pub-keyring", OPTF_ARGREQ, 0, 'K' },
166 { "tag", OPTF_ARGREQ, 0, 't' },
167 { "admin-socket", OPTF_ARGREQ, 0, 'a' },
168#ifndef NTRACE
169 { "trace", OPTF_ARGREQ, 0, 'T' },
170#endif
171
172 { 0, 0, 0, 0 }
173 };
174
175 int i = mdwopt(argc, argv, "hvu DU:G: p:d:k:K:t:a:" T("T:"),
176 opts, 0, 0, 0);
177 if (i < 0)
178 break;
179 switch (i) {
180 case 'h':
181 help(stdout);
182 exit(0);
183 case 'v':
184 version(stdout);
185 exit(0);
186 case 'u':
187 usage(stdout);
188 exit(0);
189
190 case 'D':
191 f |= f_daemon;
192 break;
193 case 'U': {
194 char *p;
195 unsigned long i = strtoul(optarg, &p, 0);
196 if (!*p)
197 u = i;
198 else {
199 struct passwd *pw;
200 if ((pw = getpwnam(optarg)) == 0)
201 die(EXIT_FAILURE, "user name `%s' not found", optarg);
202 u = pw->pw_uid;
203 }
204 } break;
205 case 'G': {
206 char *p;
207 unsigned long i = strtoul(optarg, &p, 0);
208 if (!*p)
209 g = i;
210 else {
211 struct group *gr;
212 if ((gr = getgrnam(optarg)) == 0)
213 die(EXIT_FAILURE, "group name `%s' not found", optarg);
214 g = gr->gr_gid;
215 }
216 } break;
217
218 case 'p': {
219 char *p;
220 unsigned long i = strtoul(optarg, &p, 0);
221 if (*p) {
222 struct servent *s = getservbyname(optarg, "udp");
223 if (!s)
224 die(EXIT_FAILURE, "unknown service name `%s'", optarg);
225 i = ntohs(s->s_port);
226 }
227 if (i == 0 || i >= 65536)
228 die(EXIT_FAILURE, "bad port number %lu", i);
229 port = i;
230 } break;
231 case 'd':
232 dir = optarg;
233 break;
234 case 'k':
235 kr_priv = optarg;
236 break;
237 case 'K':
238 kr_pub = optarg;
239 break;
240 case 'a':
241 csock = optarg;
242 break;
243 case 't':
244 tag_priv = optarg;
245 break;
246#ifndef NTRACE
247 case 'T':
248 tr_flags = traceopt(tr_opts, optarg, tr_flags, 0);
249 trace_level(tr_flags);
250 break;
251#endif
252 default:
253 f |= f_bogus;
254 break;
255 }
256 }
257
258 if (optind < argc || (f & f_bogus)) {
259 usage(stderr);
260 exit(EXIT_FAILURE);
261 }
262
263 if (chdir(dir)) {
264 die(EXIT_FAILURE, "can't set current directory to `%s': %s",
265 dir, strerror(errno));
266 }
267
268 sel_init(&sel);
269 sig_init(&sel);
270 rand_noisesrc(RAND_GLOBAL, &noise_source);
271 rand_seed(RAND_GLOBAL, RMD160_HASHSZ);
272 signal(SIGPIPE, SIG_IGN);
273 tun_init();
274 p_init(port);
275 if (!(f & f_daemon))
276 a_create(STDIN_FILENO, STDOUT_FILENO);
277 if (g != -1) {
278 if (setgid(g)) {
279 die(EXIT_FAILURE, "couldn't setgid to %u: %s",
280 (unsigned)g, strerror(errno));
281 }
282 }
283 if (u != -1) {
284 if (setuid(u)) {
285 die(EXIT_FAILURE, "couldn't setuid to %u: %s",
286 (unsigned)u, strerror(errno));
287 }
288 }
289 km_init(kr_priv, kr_pub, tag_priv);
290 a_init(csock);
291 if (f & f_daemon) {
37852359 292 if (u_daemon())
410c8acf 293 die(EXIT_FAILURE, "couldn't become a daemon: %s", strerror(errno));
294 a_daemon();
295 }
296
297 {
298 struct timeval tv;
299 tv.tv_sec = time(0) + T_INTERVAL;
300 tv.tv_usec = 0;
301 sel_addtimer(&sel, &it, &tv, interval, 0);
302 }
303
304 {
305 int selerr = 0;
306 for (;;) {
307 if (!sel_select(&sel))
308 selerr = 0;
309 else if (errno != EINTR && errno != EAGAIN) {
310 a_warn("select failed: %s", strerror(errno));
410c8acf 311 selerr++;
312 if (selerr > 8) {
313 a_warn("too many select errors: bailing out");
314 a_quit();
315 }
316 }
317 }
318 }
319
320 return (0);
321}
322
323/*----- That's all, folks -------------------------------------------------*/