Remove __P macros from src/usr.bin and src/usr.sbin.
[dragonfly.git] / usr.sbin / setkey / setkey.c
CommitLineData
984263bc 1/* $FreeBSD: src/usr.sbin/setkey/setkey.c,v 1.1.2.3 2003/04/26 23:53:54 sumikawa Exp $ */
2d8a3be7 2/* $DragonFly: src/usr.sbin/setkey/setkey.c,v 1.3 2003/11/03 19:31:43 eirikn Exp $ */
984263bc
MD
3/* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/time.h>
38#include <err.h>
39#include <net/route.h>
40#include <netinet/in.h>
41#include <net/pfkeyv2.h>
42#include <netkey/keydb.h>
43#include <netkey/key_debug.h>
44#include <netinet6/ipsec.h>
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <limits.h>
49#include <string.h>
50#include <ctype.h>
51#include <unistd.h>
52#include <errno.h>
53#include <netdb.h>
54
55#include "libpfkey.h"
56
2d8a3be7
EN
57void Usage(void);
58int main(int, char **);
59int get_supported(void);
60void sendkeyshort(u_int);
61void promisc(void);
62int sendkeymsg(void);
63int postproc(struct sadb_msg *, int);
64const char *numstr(int);
65void shortdump_hdr(void);
66void shortdump(struct sadb_msg *);
67static void printdate(void);
68static int32_t gmt2local(time_t);
984263bc
MD
69
70#define MODE_SCRIPT 1
71#define MODE_CMDDUMP 2
72#define MODE_CMDFLUSH 3
73#define MODE_PROMISC 4
74
75int so;
76
77int f_forever = 0;
78int f_all = 0;
79int f_debug = 0;
80int f_verbose = 0;
81int f_mode = 0;
82int f_cmddump = 0;
83int f_policy = 0;
84int f_hexdump = 0;
85int f_tflag = 0;
86char *pname;
87
88u_char m_buf[BUFSIZ];
89u_int m_len;
90
91static time_t thiszone;
92
93extern int lineno;
94
2d8a3be7 95extern int parse(FILE **);
984263bc
MD
96
97void
98Usage()
99{
100 printf("Usage:\t%s [-dv] -c\n", pname);
101 printf("\t%s [-dv] -f (file)\n", pname);
102 printf("\t%s [-Padlv] -D\n", pname);
103 printf("\t%s [-Pdv] -F\n", pname);
104 printf("\t%s [-h] -x\n", pname);
105 pfkey_close(so);
106 exit(1);
107}
108
109int
110main(ac, av)
111 int ac;
112 char **av;
113{
114 FILE *fp = stdin;
115 int c;
116
117 pname = *av;
118
119 if (ac == 1) Usage();
120
121 thiszone = gmt2local(0);
122
123 while ((c = getopt(ac, av, "acdf:hlvxDFP")) != -1) {
124 switch (c) {
125 case 'c':
126 f_mode = MODE_SCRIPT;
127 fp = stdin;
128 break;
129 case 'f':
130 f_mode = MODE_SCRIPT;
131 if ((fp = fopen(optarg, "r")) == NULL) {
132 err(-1, "fopen");
133 /*NOTREACHED*/
134 }
135 break;
136 case 'D':
137 f_mode = MODE_CMDDUMP;
138 break;
139 case 'F':
140 f_mode = MODE_CMDFLUSH;
141 break;
142 case 'a':
143 f_all = 1;
144 break;
145 case 'l':
146 f_forever = 1;
147 break;
148 case 'h':
149 f_hexdump = 1;
150 break;
151 case 'x':
152 f_mode = MODE_PROMISC;
153 f_tflag++;
154 break;
155 case 'P':
156 f_policy = 1;
157 break;
158 case 'd':
159 f_debug = 1;
160 break;
161 case 'v':
162 f_verbose = 1;
163 break;
164 default:
165 Usage();
166 /*NOTREACHED*/
167 }
168 }
169
170 switch (f_mode) {
171 case MODE_CMDDUMP:
172 sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP);
173 break;
174 case MODE_CMDFLUSH:
175 sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH);
176 pfkey_close(so);
177 break;
178 case MODE_SCRIPT:
179 if (get_supported() < 0) {
180 errx(-1, "%s", ipsec_strerror());
181 /*NOTREACHED*/
182 }
183 if (parse(&fp))
184 exit (1);
185 break;
186 case MODE_PROMISC:
187 promisc();
188 /*NOTREACHED*/
189 default:
190 Usage();
191 /*NOTREACHED*/
192 }
193
194 exit(0);
195}
196
197int
198get_supported()
199{
200 int so;
201
202 if ((so = pfkey_open()) < 0) {
203 perror("pfkey_open");
204 return -1;
205 }
206
207 /* debug mode ? */
208 if (f_debug)
209 return 0;
210
211 if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0)
212 return -1;
213
214 if (pfkey_recv_register(so) < 0)
215 return -1;
216
217 return 0;
218}
219
220void
221sendkeyshort(type)
222 u_int type;
223{
224 struct sadb_msg *m_msg = (struct sadb_msg *)m_buf;
225
226 m_len = sizeof(struct sadb_msg);
227
228 m_msg->sadb_msg_version = PF_KEY_V2;
229 m_msg->sadb_msg_type = type;
230 m_msg->sadb_msg_errno = 0;
231 m_msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
232 m_msg->sadb_msg_len = PFKEY_UNIT64(m_len);
233 m_msg->sadb_msg_reserved = 0;
234 m_msg->sadb_msg_seq = 0;
235 m_msg->sadb_msg_pid = getpid();
236
237 sendkeymsg();
238
239 return;
240}
241
242void
243promisc()
244{
245 struct sadb_msg *m_msg = (struct sadb_msg *)m_buf;
246 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
247 int so, len;
248
249 m_len = sizeof(struct sadb_msg);
250
251 m_msg->sadb_msg_version = PF_KEY_V2;
252 m_msg->sadb_msg_type = SADB_X_PROMISC;
253 m_msg->sadb_msg_errno = 0;
254 m_msg->sadb_msg_satype = 1;
255 m_msg->sadb_msg_len = PFKEY_UNIT64(m_len);
256 m_msg->sadb_msg_reserved = 0;
257 m_msg->sadb_msg_seq = 0;
258 m_msg->sadb_msg_pid = getpid();
259
260 if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
261 err(1, "socket(PF_KEY)");
262 /*NOTREACHED*/
263 }
264
265 if ((len = send(so, m_buf, m_len, 0)) < 0) {
266 err(1, "send");
267 /*NOTREACHED*/
268 }
269
270 while (1) {
271 struct sadb_msg *base;
272
273 if ((len = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) {
274 err(1, "recv");
275 /*NOTREACHED*/
276 }
277
278 if (len != sizeof(*base))
279 continue;
280
281 base = (struct sadb_msg *)rbuf;
282 if ((len = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len),
283 0)) < 0) {
284 err(1, "recv");
285 /*NOTREACHED*/
286 }
287 printdate();
288 if (f_hexdump) {
289 int i;
290 for (i = 0; i < len; i++) {
291 if (i % 16 == 0)
292 printf("%08x: ", i);
293 printf("%02x ", rbuf[i] & 0xff);
294 if (i % 16 == 15)
295 printf("\n");
296 }
297 if (len % 16)
298 printf("\n");
299 }
300 /* adjust base pointer for promisc mode */
301 if (base->sadb_msg_type == SADB_X_PROMISC) {
302 if (sizeof(*base) < len)
303 base++;
304 else
305 base = NULL;
306 }
307 if (base) {
308 kdebug_sadb(base);
309 printf("\n");
310 fflush(stdout);
311 }
312 }
313}
314
315int
316sendkeymsg()
317{
318 int so;
319
320 u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */
321 int len;
322 struct sadb_msg *msg;
323
324 if ((so = pfkey_open()) < 0) {
325 perror("pfkey_open");
326 return -1;
327 }
328
329 {
330 struct timeval tv;
331 tv.tv_sec = 1;
332 tv.tv_usec = 0;
333 if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
334 perror("setsockopt");
335 goto end;
336 }
337 }
338
339 if (f_forever)
340 shortdump_hdr();
341again:
342 if (f_verbose) {
343 kdebug_sadb((struct sadb_msg *)m_buf);
344 printf("\n");
345 }
346
347 if ((len = send(so, m_buf, m_len, 0)) < 0) {
348 perror("send");
349 goto end;
350 }
351
352 msg = (struct sadb_msg *)rbuf;
353 do {
354 if ((len = recv(so, rbuf, sizeof(rbuf), 0)) < 0) {
355 perror("recv");
356 goto end;
357 }
358
359 if (PFKEY_UNUNIT64(msg->sadb_msg_len) != len) {
360 warnx("invalid keymsg length");
361 break;
362 }
363
364 if (f_verbose) {
365 kdebug_sadb((struct sadb_msg *)rbuf);
366 printf("\n");
367 }
368 if (postproc(msg, len) < 0)
369 break;
370 } while (msg->sadb_msg_errno || msg->sadb_msg_seq);
371
372 if (f_forever) {
373 fflush(stdout);
374 sleep(1);
375 goto again;
376 }
377
378end:
379 pfkey_close(so);
380 return(0);
381}
382
383int
384postproc(msg, len)
385 struct sadb_msg *msg;
386 int len;
387{
388
389 if (msg->sadb_msg_errno != 0) {
390 char inf[80];
391 char *errmsg = NULL;
392
393 if (f_mode == MODE_SCRIPT)
394 snprintf(inf, sizeof(inf), "The result of line %d: ", lineno);
395 else
396 inf[0] = '\0';
397
398 switch (msg->sadb_msg_errno) {
399 case ENOENT:
400 switch (msg->sadb_msg_type) {
401 case SADB_DELETE:
402 case SADB_GET:
403 case SADB_X_SPDDELETE:
404 errmsg = "No entry";
405 break;
406 case SADB_DUMP:
407 errmsg = "No SAD entries";
408 break;
409 case SADB_X_SPDDUMP:
410 errmsg = "No SPD entries";
411 break;
412 }
413 break;
414 default:
415 errmsg = strerror(msg->sadb_msg_errno);
416 }
417 printf("%s%s.\n", inf, errmsg);
418 return(-1);
419 }
420
421 switch (msg->sadb_msg_type) {
422 case SADB_GET:
423 pfkey_sadump(msg);
424 break;
425
426 case SADB_DUMP:
427 /* filter out DEAD SAs */
428 if (!f_all) {
429 caddr_t mhp[SADB_EXT_MAX + 1];
430 struct sadb_sa *sa;
431 pfkey_align(msg, mhp);
432 pfkey_check(mhp);
433 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
434 if (sa->sadb_sa_state == SADB_SASTATE_DEAD)
435 break;
436 }
437 }
438 if (f_forever)
439 shortdump(msg);
440 else
441 pfkey_sadump(msg);
442 msg = (struct sadb_msg *)((caddr_t)msg +
443 PFKEY_UNUNIT64(msg->sadb_msg_len));
444 if (f_verbose) {
445 kdebug_sadb((struct sadb_msg *)msg);
446 printf("\n");
447 }
448 break;
449
450 case SADB_X_SPDDUMP:
451 pfkey_spdump(msg);
452 if (msg->sadb_msg_seq == 0) break;
453 msg = (struct sadb_msg *)((caddr_t)msg +
454 PFKEY_UNUNIT64(msg->sadb_msg_len));
455 if (f_verbose) {
456 kdebug_sadb((struct sadb_msg *)msg);
457 printf("\n");
458 }
459 break;
460 }
461
462 return(0);
463}
464
465/*------------------------------------------------------------*/
466static char *satype[] = {
467 NULL, NULL, "ah", "esp"
468};
469static char *sastate[] = {
470 "L", "M", "D", "d"
471};
472static char *ipproto[] = {
473/*0*/ "ip", "icmp", "igmp", "ggp", "ip4",
474 NULL, "tcp", NULL, "egp", NULL,
475/*10*/ NULL, NULL, NULL, NULL, NULL,
476 NULL, NULL, "udp", NULL, NULL,
477/*20*/ NULL, NULL, "idp", NULL, NULL,
478 NULL, NULL, NULL, NULL, "tp",
479/*30*/ NULL, NULL, NULL, NULL, NULL,
480 NULL, NULL, NULL, NULL, NULL,
481/*40*/ NULL, "ip6", NULL, "rt6", "frag6",
482 NULL, "rsvp", "gre", NULL, NULL,
483/*50*/ "esp", "ah", NULL, NULL, NULL,
484 NULL, NULL, NULL, "icmp6", "none",
485/*60*/ "dst6",
486};
487
488#define STR_OR_ID(x, tab) \
489 (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
490
491const char *
492numstr(x)
493 int x;
494{
495 static char buf[20];
496 snprintf(buf, sizeof(buf), "#%d", x);
497 return buf;
498}
499
500void
501shortdump_hdr()
502{
503 printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n",
504 "time", "p", "s", "spi", "ltime", "src", "dst");
505}
506
507void
508shortdump(msg)
509 struct sadb_msg *msg;
510{
511 caddr_t mhp[SADB_EXT_MAX + 1];
512 char buf[NI_MAXHOST], pbuf[NI_MAXSERV];
513 struct sadb_sa *sa;
514 struct sadb_address *saddr;
515 struct sadb_lifetime *lts, *lth, *ltc;
516 struct sockaddr *s;
517 u_int t;
518 time_t cur = time(0);
519
520 pfkey_align(msg, mhp);
521 pfkey_check(mhp);
522
523 printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60));
524
525 printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype));
526
527 if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) {
528 printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate));
529 printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi));
530 } else
531 printf("%-1s %-8s", "?", "?");
532
533 lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
534 lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
535 ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
536 if (lts && lth && ltc) {
537 if (ltc->sadb_lifetime_addtime == 0)
538 t = (u_long)0;
539 else
540 t = (u_long)(cur - ltc->sadb_lifetime_addtime);
541 if (t >= 1000)
542 strcpy(buf, " big/");
543 else
544 snprintf(buf, sizeof(buf), " %3lu/", (u_long)t);
545 printf("%s", buf);
546
547 t = (u_long)lth->sadb_lifetime_addtime;
548 if (t >= 1000)
549 strcpy(buf, "big");
550 else
551 snprintf(buf, sizeof(buf), "%-3lu", (u_long)t);
552 printf("%s", buf);
553 } else
554 printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */
555
556 printf(" ");
557
558 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) {
559 if (saddr->sadb_address_proto)
560 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
561 s = (struct sockaddr *)(saddr + 1);
562 getnameinfo(s, s->sa_len, buf, sizeof(buf),
563 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
564 if (strcmp(pbuf, "0") != 0)
565 printf("%s[%s]", buf, pbuf);
566 else
567 printf("%s", buf);
568 } else
569 printf("?");
570
571 printf(" -> ");
572
573 if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) {
574 if (saddr->sadb_address_proto)
575 printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto));
576
577 s = (struct sockaddr *)(saddr + 1);
578 getnameinfo(s, s->sa_len, buf, sizeof(buf),
579 pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV);
580 if (strcmp(pbuf, "0") != 0)
581 printf("%s[%s]", buf, pbuf);
582 else
583 printf("%s", buf);
584 } else
585 printf("?");
586
587 printf("\n");
588}
589
590/* From: tcpdump(1):gmt2local.c and util.c */
591/*
592 * Print the timestamp
593 */
594static void
595printdate()
596{
597 struct timeval tp;
598 int s;
599
600 if (gettimeofday(&tp, NULL) == -1) {
601 perror("gettimeofday");
602 return;
603 }
604
605 if (f_tflag == 1) {
606 /* Default */
607 s = (tp.tv_sec + thiszone ) % 86400;
608 (void)printf("%02d:%02d:%02d.%06u ",
609 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec);
610 } else if (f_tflag > 1) {
611 /* Unix timeval style */
612 (void)printf("%u.%06u ",
613 (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec);
614 }
615
616 printf("\n");
617}
618
619/*
620 * Returns the difference between gmt and local time in seconds.
621 * Use gmtime() and localtime() to keep things simple.
622 */
623int32_t
624gmt2local(time_t t)
625{
626 register int dt, dir;
627 register struct tm *gmt, *loc;
628 struct tm sgmt;
629
630 if (t == 0)
631 t = time(NULL);
632 gmt = &sgmt;
633 *gmt = *gmtime(&t);
634 loc = localtime(&t);
635 dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
636 (loc->tm_min - gmt->tm_min) * 60;
637
638 /*
639 * If the year or julian day is different, we span 00:00 GMT
640 * and must add or subtract a day. Check the year first to
641 * avoid problems when the julian day wraps.
642 */
643 dir = loc->tm_year - gmt->tm_year;
644 if (dir == 0)
645 dir = loc->tm_yday - gmt->tm_yday;
646 dt += dir * 24 * 60 * 60;
647
648 return (dt);
649}