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