]>
Commit | Line | Data |
---|---|---|
52b7d2ce A |
1 | /* $KAME: setkey.c,v 1.36 2003/09/24 23:52:51 itojun Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. Neither the name of the project nor the names of its contributors | |
16 | * may be used to endorse or promote products derived from this software | |
17 | * without specific prior written permission. | |
18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
29 | * SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | #ifdef HAVE_CONFIG_H | |
33 | #include "config.h" | |
34 | #endif | |
35 | ||
36 | #include <sys/types.h> | |
37 | #include <sys/param.h> | |
38 | #include <sys/socket.h> | |
39 | #include <sys/time.h> | |
40 | #include <sys/stat.h> | |
41 | #include <sys/sysctl.h> | |
42 | #include <err.h> | |
43 | #include <netinet/in.h> | |
44 | #ifdef __APPLE__ | |
45 | #include <System/net/pfkeyv2.h> | |
46 | #else | |
47 | #include <net/pfkeyv2.h> | |
48 | #endif | |
49 | #ifdef HAVE_NETINET6_IPSEC | |
50 | # include <netinet6/ipsec.h> | |
51 | #else | |
52 | # include <netinet/ipsec.h> | |
53 | #endif | |
54 | ||
55 | #include <stdio.h> | |
56 | #include <stdlib.h> | |
57 | #include <limits.h> | |
58 | #include <string.h> | |
59 | #include <ctype.h> | |
60 | #include <unistd.h> | |
61 | #include <errno.h> | |
62 | #include <netdb.h> | |
63 | #include <fcntl.h> | |
64 | #include <dirent.h> | |
65 | #include <time.h> | |
66 | ||
67 | #ifdef HAVE_READLINE | |
68 | #include <readline/readline.h> | |
69 | #include <readline/history.h> | |
70 | #endif | |
71 | ||
72 | #include "config.h" | |
73 | #include "libpfkey.h" | |
74 | //#include "package_version.h" | |
75 | #define extern /* so that variables in extern.h are not extern... */ | |
76 | #include "extern.h" | |
77 | ||
78 | #define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0') | |
79 | ||
80 | void usage __P((/*int*/)); | |
81 | int main __P((int, char **)); | |
82 | int get_supported __P((void)); | |
83 | void sendkeyshort __P((u_int)); | |
84 | void promisc __P((void)); | |
85 | int postproc __P((struct sadb_msg *, int)); | |
86 | int verifypriority __P((struct sadb_msg *m)); | |
87 | int fileproc __P((const char *)); | |
88 | const char *numstr __P((int)); | |
89 | void shortdump_hdr __P((void)); | |
90 | void shortdump __P((struct sadb_msg *)); | |
91 | static void printdate __P((void)); | |
92 | static int32_t gmt2local __P((time_t)); | |
93 | void stdin_loop __P((void)); | |
94 | ||
95 | #define MODE_SCRIPT 1 | |
96 | #define MODE_CMDDUMP 2 | |
97 | #define MODE_CMDFLUSH 3 | |
98 | #define MODE_PROMISC 4 | |
99 | #define MODE_STDIN 5 | |
100 | ||
101 | int so; | |
102 | ||
103 | int f_forever = 0; | |
104 | int f_all = 0; | |
105 | int f_verbose = 0; | |
106 | int f_mode = 0; | |
107 | int f_cmddump = 0; | |
108 | int f_policy = 0; | |
109 | int f_hexdump = 0; | |
110 | int f_tflag = 0; | |
111 | int f_notreally = 0; | |
112 | int f_withports = 0; | |
113 | #ifdef HAVE_POLICY_FWD | |
114 | int f_rfcmode = 1; | |
115 | #define RK_OPTS "rk" | |
116 | #else | |
117 | int f_rkwarn = 0; | |
118 | #define RK_OPTS "" | |
119 | static void rkwarn(void); | |
120 | static void | |
121 | rkwarn(void) | |
122 | { | |
123 | if (!f_rkwarn) { | |
124 | f_rkwarn = 1; | |
125 | printf("warning: -r and -k options are not supported in this environment\n"); | |
126 | } | |
127 | } | |
128 | ||
129 | #endif | |
130 | static time_t thiszone; | |
131 | ||
132 | void | |
133 | usage(/*int only_version*/) | |
134 | { | |
135 | //printf("setkey @(#) %s (%s)\n", TOP_PACKAGE_STRING, TOP_PACKAGE_URL); | |
136 | //if (! only_version) { | |
137 | printf("usage: setkey [-v" RK_OPTS "] file ...\n"); | |
138 | printf(" setkey [-nv" RK_OPTS "] -c\n"); | |
139 | printf(" setkey [-nv" RK_OPTS "] -f filename\n"); | |
140 | printf(" setkey [-Palpv" RK_OPTS "] -D\n"); | |
141 | printf(" setkey [-Pv] -F\n"); | |
142 | printf(" setkey [-H] -x\n"); | |
143 | printf(" setkey [-V] [-h]\n"); | |
144 | //} | |
145 | exit(1); | |
146 | } | |
147 | ||
148 | int | |
149 | main(argc, argv) | |
150 | int argc; | |
151 | char **argv; | |
152 | { | |
153 | FILE *fp = stdin; | |
154 | int c; | |
155 | ||
156 | if (argc == 1) { | |
157 | usage(0); | |
158 | /* NOTREACHED */ | |
159 | } | |
160 | ||
161 | thiszone = gmt2local(0); | |
162 | ||
163 | while ((c = getopt(argc, argv, "acdf:HlnvxDFPphVrk?")) != -1) { | |
164 | switch (c) { | |
165 | case 'c': | |
166 | f_mode = MODE_STDIN; | |
167 | #ifdef HAVE_READLINE | |
168 | /* disable filename completion */ | |
169 | rl_bind_key('\t', rl_insert); | |
170 | #endif | |
171 | break; | |
172 | case 'f': | |
173 | f_mode = MODE_SCRIPT; | |
174 | if ((fp = fopen(optarg, "r")) == NULL) { | |
175 | err(1, "fopen"); | |
176 | /*NOTREACHED*/ | |
177 | } | |
178 | break; | |
179 | case 'D': | |
180 | f_mode = MODE_CMDDUMP; | |
181 | break; | |
182 | case 'F': | |
183 | f_mode = MODE_CMDFLUSH; | |
184 | break; | |
185 | case 'a': | |
186 | f_all = 1; | |
187 | break; | |
188 | case 'l': | |
189 | f_forever = 1; | |
190 | break; | |
191 | case 'n': | |
192 | f_notreally = 1; | |
193 | break; | |
194 | #ifdef __NetBSD__ | |
195 | case 'h': | |
196 | #endif | |
197 | case 'H': | |
198 | f_hexdump = 1; | |
199 | break; | |
200 | case 'x': | |
201 | f_mode = MODE_PROMISC; | |
202 | f_tflag++; | |
203 | break; | |
204 | case 'P': | |
205 | f_policy = 1; | |
206 | break; | |
207 | case 'p': | |
208 | f_withports = 1; | |
209 | break; | |
210 | case 'v': | |
211 | f_verbose = 1; | |
212 | break; | |
213 | case 'r': | |
214 | #ifdef HAVE_POLICY_FWD | |
215 | f_rfcmode = 1; | |
216 | #else | |
217 | rkwarn(); | |
218 | #endif | |
219 | break; | |
220 | case 'k': | |
221 | #ifdef HAVE_POLICY_FWD | |
222 | f_rfcmode = 0; | |
223 | #else | |
224 | rkwarn(); | |
225 | #endif | |
226 | break; | |
227 | case 'V': | |
228 | usage(1); | |
229 | break; | |
230 | /*NOTREACHED*/ | |
231 | #ifndef __NetBSD__ | |
232 | case 'h': | |
233 | #endif | |
234 | case '?': | |
235 | default: | |
236 | usage(0); | |
237 | /*NOTREACHED*/ | |
238 | } | |
239 | } | |
240 | ||
241 | argc -= optind; | |
242 | argv += optind; | |
243 | ||
244 | if (argc > 0) { | |
245 | while (argc--) | |
246 | if (fileproc(*argv++) < 0) { | |
247 | err(1, "%s", argv[-1]); | |
248 | /*NOTREACHED*/ | |
249 | } | |
250 | exit(0); | |
251 | } | |
252 | ||
253 | so = pfkey_open(); | |
254 | if (so < 0) { | |
255 | perror("pfkey_open"); | |
256 | exit(1); | |
257 | } | |
258 | ||
259 | switch (f_mode) { | |
260 | case MODE_CMDDUMP: | |
261 | sendkeyshort(f_policy ? SADB_X_SPDDUMP : SADB_DUMP); | |
262 | break; | |
263 | case MODE_CMDFLUSH: | |
264 | sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); | |
265 | break; | |
266 | case MODE_SCRIPT: | |
267 | if (get_supported() < 0) { | |
268 | errx(1, "%s", ipsec_strerror()); | |
269 | /*NOTREACHED*/ | |
270 | } | |
271 | if (parse(&fp)) | |
272 | exit (1); | |
273 | break; | |
274 | case MODE_STDIN: | |
275 | if (get_supported() < 0) { | |
276 | errx(1, "%s", ipsec_strerror()); | |
277 | /*NOTREACHED*/ | |
278 | } | |
279 | stdin_loop(); | |
280 | break; | |
281 | case MODE_PROMISC: | |
282 | promisc(); | |
283 | /*NOTREACHED*/ | |
284 | default: | |
285 | usage(0); | |
286 | /*NOTREACHED*/ | |
287 | } | |
288 | ||
289 | exit(0); | |
290 | } | |
291 | ||
292 | int | |
293 | get_supported() | |
294 | { | |
295 | ||
296 | if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) | |
297 | return -1; | |
298 | ||
299 | if (pfkey_recv_register(so) < 0) | |
300 | return -1; | |
301 | ||
302 | return (0); | |
303 | } | |
304 | ||
305 | void | |
306 | stdin_loop() | |
307 | { | |
308 | char line[1024], *semicolon, *comment; | |
309 | size_t linelen = 0; | |
310 | ||
311 | memset (line, 0, sizeof(line)); | |
312 | ||
313 | parse_init(); | |
314 | while (1) { | |
315 | #ifdef HAVE_READLINE | |
316 | char *rbuf; | |
317 | rbuf = readline (""); | |
318 | if (! rbuf) | |
319 | break; | |
320 | #else | |
321 | char rbuf[1024]; | |
322 | rbuf[0] = '\0'; | |
323 | fgets (rbuf, sizeof(rbuf), stdin); | |
324 | if (!rbuf[0]) | |
325 | break; | |
326 | if (rbuf[strlen(rbuf)-1] == '\n') | |
327 | rbuf[strlen(rbuf)-1] = '\0'; | |
328 | #endif | |
329 | comment = strchr(rbuf, '#'); | |
330 | if (comment) | |
331 | *comment = '\0'; | |
332 | ||
333 | if (!rbuf[0]) | |
334 | continue; | |
335 | ||
336 | linelen += snprintf (&line[linelen], sizeof(line) - linelen, | |
337 | "%s%s", linelen > 0 ? " " : "", rbuf); | |
338 | ||
339 | semicolon = strchr(line, ';'); | |
340 | while (semicolon) { | |
341 | char saved_char = *++semicolon; | |
342 | *semicolon = '\0'; | |
343 | #ifdef HAVE_READLINE | |
344 | add_history (line); | |
345 | #endif | |
346 | ||
347 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
348 | last_msg_type = -1; /* invalid message type */ | |
349 | #endif | |
350 | ||
351 | parse_string (line); | |
352 | if (exit_now) | |
353 | return; | |
354 | if (saved_char) { | |
355 | *semicolon = saved_char; | |
356 | linelen = strlen (semicolon); | |
357 | memmove (line, semicolon, linelen + 1); | |
358 | semicolon = strchr(line, ';'); | |
359 | } | |
360 | else { | |
361 | semicolon = NULL; | |
362 | linelen = 0; | |
363 | } | |
364 | } | |
365 | } | |
366 | } | |
367 | ||
368 | void | |
369 | sendkeyshort(type) | |
370 | u_int type; | |
371 | { | |
372 | struct sadb_msg msg; | |
373 | ||
374 | msg.sadb_msg_version = PF_KEY_V2; | |
375 | msg.sadb_msg_type = type; | |
376 | msg.sadb_msg_errno = 0; | |
377 | msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; | |
378 | msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); | |
379 | msg.sadb_msg_reserved = 0; | |
380 | msg.sadb_msg_seq = 0; | |
381 | msg.sadb_msg_pid = getpid(); | |
382 | ||
383 | sendkeymsg((char *)&msg, sizeof(msg)); | |
384 | ||
385 | return; | |
386 | } | |
387 | ||
388 | void | |
389 | promisc() | |
390 | { | |
391 | struct sadb_msg msg; | |
392 | u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ | |
393 | ssize_t l; | |
394 | ||
395 | msg.sadb_msg_version = PF_KEY_V2; | |
396 | msg.sadb_msg_type = SADB_X_PROMISC; | |
397 | msg.sadb_msg_errno = 0; | |
398 | msg.sadb_msg_satype = 1; | |
399 | msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); | |
400 | msg.sadb_msg_reserved = 0; | |
401 | msg.sadb_msg_seq = 0; | |
402 | msg.sadb_msg_pid = getpid(); | |
403 | ||
404 | if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { | |
405 | err(1, "send"); | |
406 | /*NOTREACHED*/ | |
407 | } | |
408 | ||
409 | while (1) { | |
410 | struct sadb_msg *base; | |
411 | ||
412 | if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { | |
413 | err(1, "recv"); | |
414 | /*NOTREACHED*/ | |
415 | } | |
416 | ||
417 | if (l != sizeof(*base)) | |
418 | continue; | |
419 | ||
420 | base = (struct sadb_msg *)rbuf; | |
421 | if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), | |
422 | 0)) < 0) { | |
423 | err(1, "recv"); | |
424 | /*NOTREACHED*/ | |
425 | } | |
426 | printdate(); | |
427 | if (f_hexdump) { | |
428 | int i; | |
429 | for (i = 0; i < l; i++) { | |
430 | if (i % 16 == 0) | |
431 | printf("%08x: ", i); | |
432 | printf("%02x ", rbuf[i] & 0xff); | |
433 | if (i % 16 == 15) | |
434 | printf("\n"); | |
435 | } | |
436 | if (l % 16) | |
437 | printf("\n"); | |
438 | } | |
439 | /* adjust base pointer for promisc mode */ | |
440 | if (base->sadb_msg_type == SADB_X_PROMISC) { | |
441 | if ((ssize_t)sizeof(*base) < l) | |
442 | base++; | |
443 | else | |
444 | base = NULL; | |
445 | } | |
446 | if (base) { | |
447 | kdebug_sadb(base); | |
448 | printf("\n"); | |
449 | fflush(stdout); | |
450 | } | |
451 | } | |
452 | } | |
453 | ||
454 | int | |
455 | sendkeymsg(buf, len) | |
456 | char *buf; | |
457 | size_t len; | |
458 | { | |
459 | u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ | |
460 | ssize_t l; | |
461 | struct sadb_msg *msg; | |
462 | ||
463 | if (f_notreally) { | |
464 | goto end; | |
465 | } | |
466 | ||
467 | { | |
468 | struct timeval tv; | |
469 | tv.tv_sec = 1; | |
470 | tv.tv_usec = 0; | |
471 | if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { | |
472 | perror("setsockopt"); | |
473 | goto end; | |
474 | } | |
475 | } | |
476 | ||
477 | if (f_forever) | |
478 | shortdump_hdr(); | |
479 | again: | |
480 | if (f_verbose) { | |
481 | kdebug_sadb((struct sadb_msg *)buf); | |
482 | printf("\n"); | |
483 | } | |
484 | if (f_hexdump) { | |
485 | int i; | |
486 | for (i = 0; i < len; i++) { | |
487 | if (i % 16 == 0) | |
488 | printf("%08x: ", i); | |
489 | printf("%02x ", buf[i] & 0xff); | |
490 | if (i % 16 == 15) | |
491 | printf("\n"); | |
492 | } | |
493 | if (len % 16) | |
494 | printf("\n"); | |
495 | } | |
496 | ||
497 | if ((l = send(so, buf, len, 0)) < 0) { | |
498 | perror("send"); | |
499 | goto end; | |
500 | } | |
501 | ||
502 | msg = (struct sadb_msg *)rbuf; | |
503 | do { | |
504 | if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { | |
505 | perror("recv"); | |
506 | goto end; | |
507 | } | |
508 | ||
509 | if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { | |
510 | warnx("invalid keymsg length"); | |
511 | break; | |
512 | } | |
513 | ||
514 | if (f_verbose) { | |
515 | kdebug_sadb((struct sadb_msg *)rbuf); | |
516 | printf("\n"); | |
517 | } | |
518 | if (postproc(msg, l) < 0) | |
519 | break; | |
520 | } while (msg->sadb_msg_errno || msg->sadb_msg_seq); | |
521 | ||
522 | if (f_forever) { | |
523 | fflush(stdout); | |
524 | sleep(1); | |
525 | goto again; | |
526 | } | |
527 | ||
528 | end: | |
529 | return (0); | |
530 | } | |
531 | ||
532 | int | |
533 | postproc(msg, len) | |
534 | struct sadb_msg *msg; | |
535 | int len; | |
536 | { | |
537 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
538 | static int priority_support_check = 0; | |
539 | #endif | |
540 | ||
541 | if (msg->sadb_msg_errno != 0) { | |
542 | char inf[80]; | |
543 | const char *errmsg = NULL; | |
544 | ||
545 | if (f_mode == MODE_SCRIPT) | |
546 | snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); | |
547 | else | |
548 | inf[0] = '\0'; | |
549 | ||
550 | switch (msg->sadb_msg_errno) { | |
551 | case ENOENT: | |
552 | switch (msg->sadb_msg_type) { | |
553 | case SADB_DELETE: | |
554 | case SADB_GET: | |
555 | case SADB_X_SPDDELETE: | |
556 | errmsg = "No entry"; | |
557 | break; | |
558 | case SADB_DUMP: | |
559 | errmsg = "No SAD entries"; | |
560 | break; | |
561 | case SADB_X_SPDDUMP: | |
562 | errmsg = "No SPD entries"; | |
563 | break; | |
564 | } | |
565 | break; | |
566 | default: | |
567 | errmsg = strerror(msg->sadb_msg_errno); | |
568 | } | |
569 | printf("%s%s.\n", inf, errmsg); | |
570 | return (-1); | |
571 | } | |
572 | ||
573 | switch (msg->sadb_msg_type) { | |
574 | case SADB_GET: | |
575 | if (f_withports) | |
576 | pfkey_sadump_withports(msg); | |
577 | else | |
578 | pfkey_sadump(msg); | |
579 | break; | |
580 | ||
581 | case SADB_DUMP: | |
582 | /* filter out DEAD SAs */ | |
583 | if (!f_all) { | |
584 | caddr_t mhp[SADB_EXT_MAX + 1]; | |
585 | struct sadb_sa *sa; | |
586 | pfkey_align(msg, mhp); | |
587 | pfkey_check(mhp); | |
588 | if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { | |
589 | if (sa->sadb_sa_state == SADB_SASTATE_DEAD) | |
590 | break; | |
591 | } | |
592 | } | |
593 | if (f_forever) { | |
594 | /* TODO: f_withports */ | |
595 | shortdump(msg); | |
596 | } else { | |
597 | if (f_withports) | |
598 | pfkey_sadump_withports(msg); | |
599 | else | |
600 | pfkey_sadump(msg); | |
601 | } | |
602 | msg = (struct sadb_msg *)((caddr_t)msg + | |
603 | PFKEY_UNUNIT64(msg->sadb_msg_len)); | |
604 | if (f_verbose) { | |
605 | kdebug_sadb((struct sadb_msg *)msg); | |
606 | printf("\n"); | |
607 | } | |
608 | break; | |
609 | ||
610 | case SADB_X_SPDGET: | |
611 | if (f_withports) | |
612 | pfkey_spdump_withports(msg); | |
613 | else | |
614 | pfkey_spdump(msg); | |
615 | break; | |
616 | ||
617 | case SADB_X_SPDDUMP: | |
618 | if (f_withports) | |
619 | pfkey_spdump_withports(msg); | |
620 | else | |
621 | pfkey_spdump(msg); | |
622 | if (msg->sadb_msg_seq == 0) break; | |
623 | msg = (struct sadb_msg *)((caddr_t)msg + | |
624 | PFKEY_UNUNIT64(msg->sadb_msg_len)); | |
625 | if (f_verbose) { | |
626 | kdebug_sadb((struct sadb_msg *)msg); | |
627 | printf("\n"); | |
628 | } | |
629 | break; | |
630 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
631 | case SADB_X_SPDADD: | |
632 | if (last_msg_type == SADB_X_SPDADD && last_priority != 0 && | |
633 | msg->sadb_msg_pid == getpid() && !priority_support_check) { | |
634 | priority_support_check = 1; | |
635 | if (!verifypriority(msg)) | |
636 | printf ("WARNING: Kernel does not support policy priorities\n"); | |
637 | } | |
638 | break; | |
639 | #endif | |
640 | } | |
641 | ||
642 | return (0); | |
643 | } | |
644 | ||
645 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
646 | int | |
647 | verifypriority(m) | |
648 | struct sadb_msg *m; | |
649 | { | |
650 | caddr_t mhp[SADB_EXT_MAX + 1]; | |
651 | struct sadb_x_policy *xpl; | |
652 | ||
653 | /* check pfkey message. */ | |
654 | if (pfkey_align(m, mhp)) { | |
655 | printf("(%s\n", ipsec_strerror()); | |
656 | return 0; | |
657 | } | |
658 | if (pfkey_check(mhp)) { | |
659 | printf("%s\n", ipsec_strerror()); | |
660 | return 0; | |
661 | } | |
662 | ||
663 | xpl = (struct sadb_x_policy *) mhp[SADB_X_EXT_POLICY]; | |
664 | ||
665 | if (xpl == NULL) { | |
666 | printf("no X_POLICY extension.\n"); | |
667 | return 0; | |
668 | } | |
669 | ||
670 | /* now make sure they match */ | |
671 | if (last_priority != xpl->sadb_x_policy_priority) | |
672 | return 0; | |
673 | ||
674 | return 1; | |
675 | } | |
676 | #endif | |
677 | ||
678 | int | |
679 | fileproc(filename) | |
680 | const char *filename; | |
681 | { | |
682 | int fd; | |
683 | ssize_t len, l; | |
684 | u_char *p, *ep; | |
685 | struct sadb_msg *msg; | |
686 | u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ | |
687 | ||
688 | fd = open(filename, O_RDONLY); | |
689 | if (fd < 0) | |
690 | return -1; | |
691 | ||
692 | l = 0; | |
693 | while (1) { | |
694 | len = read(fd, rbuf + l, sizeof(rbuf) - l); | |
695 | if (len < 0) { | |
696 | close(fd); | |
697 | return -1; | |
698 | } else if (len == 0) | |
699 | break; | |
700 | l += len; | |
701 | } | |
702 | ||
703 | if (l < sizeof(struct sadb_msg)) { | |
704 | close(fd); | |
705 | errno = EINVAL; | |
706 | return -1; | |
707 | } | |
708 | close(fd); | |
709 | ||
710 | p = rbuf; | |
711 | ep = rbuf + l; | |
712 | ||
713 | while (p < ep) { | |
714 | msg = (struct sadb_msg *)p; | |
715 | len = PFKEY_UNUNIT64(msg->sadb_msg_len); | |
716 | postproc(msg, len); | |
717 | p += len; | |
718 | } | |
719 | ||
720 | return (0); | |
721 | } | |
722 | ||
723 | ||
724 | /*------------------------------------------------------------*/ | |
725 | static const char *satype[] = { | |
726 | NULL, NULL, "ah", "esp" | |
727 | }; | |
728 | static const char *sastate[] = { | |
729 | "L", "M", "D", "d" | |
730 | }; | |
731 | static const char *ipproto[] = { | |
732 | /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", | |
733 | NULL, "tcp", NULL, "egp", NULL, | |
734 | /*10*/ NULL, NULL, NULL, NULL, NULL, | |
735 | NULL, NULL, "udp", NULL, NULL, | |
736 | /*20*/ NULL, NULL, "idp", NULL, NULL, | |
737 | NULL, NULL, NULL, NULL, "tp", | |
738 | /*30*/ NULL, NULL, NULL, NULL, NULL, | |
739 | NULL, NULL, NULL, NULL, NULL, | |
740 | /*40*/ NULL, "ip6", NULL, "rt6", "frag6", | |
741 | NULL, "rsvp", "gre", NULL, NULL, | |
742 | /*50*/ "esp", "ah", NULL, NULL, NULL, | |
743 | NULL, NULL, NULL, "icmp6", "none", | |
744 | /*60*/ "dst6", | |
745 | }; | |
746 | ||
747 | #define STR_OR_ID(x, tab) \ | |
748 | (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) | |
749 | ||
750 | const char * | |
751 | numstr(x) | |
752 | int x; | |
753 | { | |
754 | static char buf[20]; | |
755 | snprintf(buf, sizeof(buf), "#%d", x); | |
756 | return buf; | |
757 | } | |
758 | ||
759 | void | |
760 | shortdump_hdr() | |
761 | { | |
762 | printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", | |
763 | "time", "p", "s", "spi", "ltime", "src", "dst"); | |
764 | } | |
765 | ||
766 | void | |
767 | shortdump(msg) | |
768 | struct sadb_msg *msg; | |
769 | { | |
770 | caddr_t mhp[SADB_EXT_MAX + 1]; | |
771 | char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; | |
772 | struct sadb_sa *sa; | |
773 | struct sadb_address *saddr; | |
774 | struct sadb_lifetime *lts, *lth, *ltc; | |
775 | struct sockaddr *s; | |
776 | u_int t; | |
777 | time_t cur = time(0); | |
778 | ||
779 | pfkey_align(msg, mhp); | |
780 | pfkey_check(mhp); | |
781 | ||
782 | printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); | |
783 | ||
784 | printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); | |
785 | ||
786 | if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { | |
787 | printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); | |
788 | printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); | |
789 | } else | |
790 | printf("%-1s %-8s", "?", "?"); | |
791 | ||
792 | lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; | |
793 | lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; | |
794 | ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; | |
795 | if (lts && lth && ltc) { | |
796 | if (ltc->sadb_lifetime_addtime == 0) | |
797 | t = (u_long)0; | |
798 | else | |
799 | t = (u_long)(cur - ltc->sadb_lifetime_addtime); | |
800 | if (t >= 1000) | |
801 | strlcpy(buf, " big/", sizeof(buf)); | |
802 | else | |
803 | snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); | |
804 | printf("%s", buf); | |
805 | ||
806 | t = (u_long)lth->sadb_lifetime_addtime; | |
807 | if (t >= 1000) | |
808 | strlcpy(buf, "big", sizeof(buf)); | |
809 | else | |
810 | snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); | |
811 | printf("%s", buf); | |
812 | } else | |
813 | printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ | |
814 | ||
815 | printf(" "); | |
816 | ||
817 | if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { | |
818 | if (saddr->sadb_address_proto) | |
819 | printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); | |
820 | s = (struct sockaddr *)(saddr + 1); | |
821 | getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), | |
822 | pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); | |
823 | if (strcmp(pbuf, "0") != 0) | |
824 | printf("%s[%s]", buf, pbuf); | |
825 | else | |
826 | printf("%s", buf); | |
827 | } else | |
828 | printf("?"); | |
829 | ||
830 | printf(" -> "); | |
831 | ||
832 | if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { | |
833 | if (saddr->sadb_address_proto) | |
834 | printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); | |
835 | ||
836 | s = (struct sockaddr *)(saddr + 1); | |
837 | getnameinfo(s, sysdep_sa_len(s), buf, sizeof(buf), | |
838 | pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); | |
839 | if (strcmp(pbuf, "0") != 0) | |
840 | printf("%s[%s]", buf, pbuf); | |
841 | else | |
842 | printf("%s", buf); | |
843 | } else | |
844 | printf("?"); | |
845 | ||
846 | printf("\n"); | |
847 | } | |
848 | ||
849 | /* From: tcpdump(1):gmt2local.c and util.c */ | |
850 | /* | |
851 | * Print the timestamp | |
852 | */ | |
853 | static void | |
854 | printdate() | |
855 | { | |
856 | struct timeval tp; | |
857 | int s; | |
858 | ||
859 | if (gettimeofday(&tp, NULL) == -1) { | |
860 | perror("gettimeofday"); | |
861 | return; | |
862 | } | |
863 | ||
864 | if (f_tflag == 1) { | |
865 | /* Default */ | |
866 | s = (tp.tv_sec + thiszone ) % 86400; | |
867 | (void)printf("%02d:%02d:%02d.%06u ", | |
868 | s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); | |
869 | } else if (f_tflag > 1) { | |
870 | /* Unix timeval style */ | |
871 | (void)printf("%u.%06u ", | |
872 | (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); | |
873 | } | |
874 | ||
875 | printf("\n"); | |
876 | } | |
877 | ||
878 | /* | |
879 | * Returns the difference between gmt and local time in seconds. | |
880 | * Use gmtime() and localtime() to keep things simple. | |
881 | */ | |
882 | int32_t | |
883 | gmt2local(time_t t) | |
884 | { | |
885 | register int dt, dir; | |
886 | register struct tm *gmt, *loc; | |
887 | struct tm sgmt; | |
888 | ||
889 | if (t == 0) | |
890 | t = time(NULL); | |
891 | gmt = &sgmt; | |
892 | *gmt = *gmtime(&t); | |
893 | loc = localtime(&t); | |
894 | dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + | |
895 | (loc->tm_min - gmt->tm_min) * 60; | |
896 | ||
897 | /* | |
898 | * If the year or julian day is different, we span 00:00 GMT | |
899 | * and must add or subtract a day. Check the year first to | |
900 | * avoid problems when the julian day wraps. | |
901 | */ | |
902 | dir = loc->tm_year - gmt->tm_year; | |
903 | if (dir == 0) | |
904 | dir = loc->tm_yday - gmt->tm_yday; | |
905 | dt += dir * 24 * 60 * 60; | |
906 | ||
907 | return (dt); | |
908 | } |