1cf43a054SHajimu UMEMOTO /* $KAME: setkey.c,v 1.28 2003/06/27 07:15:45 itojun Exp $ */ 23c62e87aSJun-ichiro itojun Hagino 38a16b7a1SPedro F. Giffuni /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro F. Giffuni * 69a4365d0SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 79a4365d0SYoshinobu Inoue * All rights reserved. 89a4365d0SYoshinobu Inoue * 99a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 109a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 119a4365d0SYoshinobu Inoue * are met: 129a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 139a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 149a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 159a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 169a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 179a4365d0SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 189a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 199a4365d0SYoshinobu Inoue * without specific prior written permission. 209a4365d0SYoshinobu Inoue * 219a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 229a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 259a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319a4365d0SYoshinobu Inoue * SUCH DAMAGE. 329a4365d0SYoshinobu Inoue */ 339a4365d0SYoshinobu Inoue 349a4365d0SYoshinobu Inoue #include <sys/types.h> 359a4365d0SYoshinobu Inoue #include <sys/param.h> 360aef8628SEugene Grosbein #include <sys/linker.h> 370aef8628SEugene Grosbein #include <sys/module.h> 389a4365d0SYoshinobu Inoue #include <sys/socket.h> 399a4365d0SYoshinobu Inoue #include <sys/time.h> 409a4365d0SYoshinobu Inoue #include <err.h> 419a4365d0SYoshinobu Inoue #include <net/route.h> 429a4365d0SYoshinobu Inoue #include <netinet/in.h> 439a4365d0SYoshinobu Inoue #include <net/pfkeyv2.h> 448409aedfSGeorge V. Neville-Neil #include <netipsec/keydb.h> 458409aedfSGeorge V. Neville-Neil #include <netipsec/key_debug.h> 468409aedfSGeorge V. Neville-Neil #include <netipsec/ipsec.h> 479a4365d0SYoshinobu Inoue 489a4365d0SYoshinobu Inoue #include <stdio.h> 499a4365d0SYoshinobu Inoue #include <stdlib.h> 509a4365d0SYoshinobu Inoue #include <limits.h> 519a4365d0SYoshinobu Inoue #include <string.h> 529a4365d0SYoshinobu Inoue #include <ctype.h> 539a4365d0SYoshinobu Inoue #include <unistd.h> 549a4365d0SYoshinobu Inoue #include <errno.h> 559a4365d0SYoshinobu Inoue #include <netdb.h> 569a4365d0SYoshinobu Inoue 573c62e87aSJun-ichiro itojun Hagino #include "libpfkey.h" 583c62e87aSJun-ichiro itojun Hagino 59784bddbcSKevin Lo void usage(void); 60784bddbcSKevin Lo int main(int, char **); 61784bddbcSKevin Lo int get_supported(void); 6222986c67SAndrey V. Elsukov void sendkeyshort(u_int, uint8_t); 63784bddbcSKevin Lo void promisc(void); 64784bddbcSKevin Lo int sendkeymsg(char *, size_t); 651e67e310SMateusz Guzik int postproc(struct sadb_msg *); 66784bddbcSKevin Lo const char *numstr(int); 67784bddbcSKevin Lo void shortdump_hdr(void); 68784bddbcSKevin Lo void shortdump(struct sadb_msg *); 69784bddbcSKevin Lo static void printdate(void); 70784bddbcSKevin Lo static int32_t gmt2local(time_t); 710aef8628SEugene Grosbein static int modload(const char *name); 729a4365d0SYoshinobu Inoue 739a4365d0SYoshinobu Inoue #define MODE_SCRIPT 1 749a4365d0SYoshinobu Inoue #define MODE_CMDDUMP 2 759a4365d0SYoshinobu Inoue #define MODE_CMDFLUSH 3 763c62e87aSJun-ichiro itojun Hagino #define MODE_PROMISC 4 779a4365d0SYoshinobu Inoue 78b2981787SMateusz Guzik static int so; 799a4365d0SYoshinobu Inoue 80b2981787SMateusz Guzik static int f_forever = 0; 81b2981787SMateusz Guzik static int f_all = 0; 82b2981787SMateusz Guzik static int f_verbose = 0; 83b2981787SMateusz Guzik static int f_mode = 0; 84b2981787SMateusz Guzik static int f_cmddump = 0; 85b2981787SMateusz Guzik static int f_policy = 0; 86b2981787SMateusz Guzik static int f_hexdump = 0; 87b2981787SMateusz Guzik static int f_tflag = 0; 88b2981787SMateusz Guzik static int f_scope = 0; 8933841545SHajimu UMEMOTO static time_t thiszone; 9033841545SHajimu UMEMOTO 919a4365d0SYoshinobu Inoue extern int lineno; 929a4365d0SYoshinobu Inoue 93784bddbcSKevin Lo extern int parse(FILE **); 949a4365d0SYoshinobu Inoue 959a4365d0SYoshinobu Inoue void 96e0c0612dSMateusz Guzik usage(void) 979a4365d0SYoshinobu Inoue { 98cf43a054SHajimu UMEMOTO 99cf43a054SHajimu UMEMOTO printf("usage: setkey [-v] -c\n"); 100cf43a054SHajimu UMEMOTO printf(" setkey [-v] -f filename\n"); 1013cb80822SKonstantin Belousov printf(" setkey [-v] -e \"<script>\"\n"); 10222986c67SAndrey V. Elsukov printf(" setkey [-Pagltv] -D\n"); 103cf43a054SHajimu UMEMOTO printf(" setkey [-Pv] -F\n"); 104cf43a054SHajimu UMEMOTO printf(" setkey [-h] -x\n"); 1053c62e87aSJun-ichiro itojun Hagino exit(1); 1069a4365d0SYoshinobu Inoue } 1079a4365d0SYoshinobu Inoue 1080aef8628SEugene Grosbein static int 1090aef8628SEugene Grosbein modload(const char *name) 1100aef8628SEugene Grosbein { 1110aef8628SEugene Grosbein if (modfind(name) < 0) 1120aef8628SEugene Grosbein if (kldload(name) < 0 || modfind(name) < 0) { 1130aef8628SEugene Grosbein warn("%s: module not found", name); 1140aef8628SEugene Grosbein return 0; 1150aef8628SEugene Grosbein } 1160aef8628SEugene Grosbein return 1; 1170aef8628SEugene Grosbein } 1180aef8628SEugene Grosbein 1199a4365d0SYoshinobu Inoue int 120e0c0612dSMateusz Guzik main(int ac, char **av) 1219a4365d0SYoshinobu Inoue { 1229a4365d0SYoshinobu Inoue FILE *fp = stdin; 1239a4365d0SYoshinobu Inoue int c; 1249a4365d0SYoshinobu Inoue 1252f4c5de9SHajimu UMEMOTO if (ac == 1) { 1262f4c5de9SHajimu UMEMOTO usage(); 1272f4c5de9SHajimu UMEMOTO /* NOTREACHED */ 1282f4c5de9SHajimu UMEMOTO } 1299a4365d0SYoshinobu Inoue 13033841545SHajimu UMEMOTO thiszone = gmt2local(0); 13133841545SHajimu UMEMOTO 1323cb80822SKonstantin Belousov while ((c = getopt(ac, av, "acde:f:ghltvxDFP")) != -1) { 1339a4365d0SYoshinobu Inoue switch (c) { 1349a4365d0SYoshinobu Inoue case 'c': 1359a4365d0SYoshinobu Inoue f_mode = MODE_SCRIPT; 1369a4365d0SYoshinobu Inoue fp = stdin; 1379a4365d0SYoshinobu Inoue break; 1383cb80822SKonstantin Belousov case 'e': 1393cb80822SKonstantin Belousov if (fp != stdin) { 1403cb80822SKonstantin Belousov err(-1, "only one -f/-e option is accepted"); 1413cb80822SKonstantin Belousov } 1423cb80822SKonstantin Belousov f_mode = MODE_SCRIPT; 1433cb80822SKonstantin Belousov fp = fmemopen(optarg, strlen(optarg), "r"); 1443cb80822SKonstantin Belousov if (fp == NULL) { 1453cb80822SKonstantin Belousov err(-1, "fmemopen"); 1463cb80822SKonstantin Belousov /*NOTREACHED*/ 1473cb80822SKonstantin Belousov } 1483cb80822SKonstantin Belousov break; 1499a4365d0SYoshinobu Inoue case 'f': 1503cb80822SKonstantin Belousov if (fp != stdin) { 1513cb80822SKonstantin Belousov err(-1, "only one -f/-e option is accepted"); 1523cb80822SKonstantin Belousov } 1539a4365d0SYoshinobu Inoue f_mode = MODE_SCRIPT; 1549a4365d0SYoshinobu Inoue if ((fp = fopen(optarg, "r")) == NULL) { 1559a4365d0SYoshinobu Inoue err(-1, "fopen"); 1569a4365d0SYoshinobu Inoue /*NOTREACHED*/ 1579a4365d0SYoshinobu Inoue } 1589a4365d0SYoshinobu Inoue break; 1599a4365d0SYoshinobu Inoue case 'D': 1609a4365d0SYoshinobu Inoue f_mode = MODE_CMDDUMP; 1619a4365d0SYoshinobu Inoue break; 1629a4365d0SYoshinobu Inoue case 'F': 1639a4365d0SYoshinobu Inoue f_mode = MODE_CMDFLUSH; 1649a4365d0SYoshinobu Inoue break; 1659a4365d0SYoshinobu Inoue case 'a': 1669a4365d0SYoshinobu Inoue f_all = 1; 1679a4365d0SYoshinobu Inoue break; 1689a4365d0SYoshinobu Inoue case 'l': 1699a4365d0SYoshinobu Inoue f_forever = 1; 1709a4365d0SYoshinobu Inoue break; 1719a4365d0SYoshinobu Inoue case 'h': 1729a4365d0SYoshinobu Inoue f_hexdump = 1; 1739a4365d0SYoshinobu Inoue break; 1749a4365d0SYoshinobu Inoue case 'x': 1753c62e87aSJun-ichiro itojun Hagino f_mode = MODE_PROMISC; 17633841545SHajimu UMEMOTO f_tflag++; 1773c62e87aSJun-ichiro itojun Hagino break; 1789a4365d0SYoshinobu Inoue case 'P': 1799a4365d0SYoshinobu Inoue f_policy = 1; 1809a4365d0SYoshinobu Inoue break; 18122986c67SAndrey V. Elsukov case 'g': /* global */ 18222986c67SAndrey V. Elsukov f_scope |= IPSEC_POLICYSCOPE_GLOBAL; 18322986c67SAndrey V. Elsukov break; 18422986c67SAndrey V. Elsukov case 't': /* tunnel */ 18522986c67SAndrey V. Elsukov f_scope |= IPSEC_POLICYSCOPE_IFNET; 18622986c67SAndrey V. Elsukov break; 1879a4365d0SYoshinobu Inoue case 'v': 1889a4365d0SYoshinobu Inoue f_verbose = 1; 1899a4365d0SYoshinobu Inoue break; 1909a4365d0SYoshinobu Inoue default: 1912f4c5de9SHajimu UMEMOTO usage(); 1929a4365d0SYoshinobu Inoue /*NOTREACHED*/ 1939a4365d0SYoshinobu Inoue } 1949a4365d0SYoshinobu Inoue } 1959a4365d0SYoshinobu Inoue 1960aef8628SEugene Grosbein modload("ipsec"); 197cf43a054SHajimu UMEMOTO so = pfkey_open(); 198cf43a054SHajimu UMEMOTO if (so < 0) { 199cf43a054SHajimu UMEMOTO perror("pfkey_open"); 200cf43a054SHajimu UMEMOTO exit(1); 201cf43a054SHajimu UMEMOTO } 202cf43a054SHajimu UMEMOTO 2039a4365d0SYoshinobu Inoue switch (f_mode) { 2049a4365d0SYoshinobu Inoue case MODE_CMDDUMP: 20522986c67SAndrey V. Elsukov sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP, 20622986c67SAndrey V. Elsukov f_policy ? f_scope: SADB_SATYPE_UNSPEC); 2079a4365d0SYoshinobu Inoue break; 2089a4365d0SYoshinobu Inoue case MODE_CMDFLUSH: 20922986c67SAndrey V. Elsukov sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH, 21022986c67SAndrey V. Elsukov SADB_SATYPE_UNSPEC); 2119a4365d0SYoshinobu Inoue break; 2129a4365d0SYoshinobu Inoue case MODE_SCRIPT: 2139a4365d0SYoshinobu Inoue if (get_supported() < 0) { 2149a4365d0SYoshinobu Inoue errx(-1, "%s", ipsec_strerror()); 2159a4365d0SYoshinobu Inoue /*NOTREACHED*/ 2169a4365d0SYoshinobu Inoue } 2173c62e87aSJun-ichiro itojun Hagino if (parse(&fp)) 2183c62e87aSJun-ichiro itojun Hagino exit (1); 2199a4365d0SYoshinobu Inoue break; 2203c62e87aSJun-ichiro itojun Hagino case MODE_PROMISC: 2213c62e87aSJun-ichiro itojun Hagino promisc(); 2223c62e87aSJun-ichiro itojun Hagino /*NOTREACHED*/ 2239a4365d0SYoshinobu Inoue default: 2242f4c5de9SHajimu UMEMOTO usage(); 2253c62e87aSJun-ichiro itojun Hagino /*NOTREACHED*/ 2269a4365d0SYoshinobu Inoue } 2279a4365d0SYoshinobu Inoue 2289a4365d0SYoshinobu Inoue exit(0); 2299a4365d0SYoshinobu Inoue } 2309a4365d0SYoshinobu Inoue 2319a4365d0SYoshinobu Inoue int 232e0c0612dSMateusz Guzik get_supported(void) 2339a4365d0SYoshinobu Inoue { 2349a4365d0SYoshinobu Inoue 23533841545SHajimu UMEMOTO if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) 2369a4365d0SYoshinobu Inoue return -1; 2379a4365d0SYoshinobu Inoue 2389a4365d0SYoshinobu Inoue if (pfkey_recv_register(so) < 0) 2399a4365d0SYoshinobu Inoue return -1; 2409a4365d0SYoshinobu Inoue 2419a4365d0SYoshinobu Inoue return 0; 2429a4365d0SYoshinobu Inoue } 2439a4365d0SYoshinobu Inoue 2449a4365d0SYoshinobu Inoue void 24522986c67SAndrey V. Elsukov sendkeyshort(u_int type, uint8_t satype) 2469a4365d0SYoshinobu Inoue { 247cf43a054SHajimu UMEMOTO struct sadb_msg msg; 2489a4365d0SYoshinobu Inoue 249cf43a054SHajimu UMEMOTO msg.sadb_msg_version = PF_KEY_V2; 250cf43a054SHajimu UMEMOTO msg.sadb_msg_type = type; 251cf43a054SHajimu UMEMOTO msg.sadb_msg_errno = 0; 25222986c67SAndrey V. Elsukov msg.sadb_msg_satype = satype; 253cf43a054SHajimu UMEMOTO msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 254cf43a054SHajimu UMEMOTO msg.sadb_msg_reserved = 0; 255cf43a054SHajimu UMEMOTO msg.sadb_msg_seq = 0; 256cf43a054SHajimu UMEMOTO msg.sadb_msg_pid = getpid(); 2579a4365d0SYoshinobu Inoue 258cf43a054SHajimu UMEMOTO sendkeymsg((char *)&msg, sizeof(msg)); 2599a4365d0SYoshinobu Inoue 2609a4365d0SYoshinobu Inoue return; 2619a4365d0SYoshinobu Inoue } 2629a4365d0SYoshinobu Inoue 2639a4365d0SYoshinobu Inoue void 264e0c0612dSMateusz Guzik promisc(void) 2659a4365d0SYoshinobu Inoue { 266cf43a054SHajimu UMEMOTO struct sadb_msg msg; 2679a4365d0SYoshinobu Inoue u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 268cf43a054SHajimu UMEMOTO ssize_t l; 2699a4365d0SYoshinobu Inoue 270cf43a054SHajimu UMEMOTO msg.sadb_msg_version = PF_KEY_V2; 271cf43a054SHajimu UMEMOTO msg.sadb_msg_type = SADB_X_PROMISC; 272cf43a054SHajimu UMEMOTO msg.sadb_msg_errno = 0; 273cf43a054SHajimu UMEMOTO msg.sadb_msg_satype = 1; 274cf43a054SHajimu UMEMOTO msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); 275cf43a054SHajimu UMEMOTO msg.sadb_msg_reserved = 0; 276cf43a054SHajimu UMEMOTO msg.sadb_msg_seq = 0; 277cf43a054SHajimu UMEMOTO msg.sadb_msg_pid = getpid(); 2789a4365d0SYoshinobu Inoue 279cf43a054SHajimu UMEMOTO if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { 2809a4365d0SYoshinobu Inoue err(1, "send"); 2819a4365d0SYoshinobu Inoue /*NOTREACHED*/ 2829a4365d0SYoshinobu Inoue } 2839a4365d0SYoshinobu Inoue 2849a4365d0SYoshinobu Inoue while (1) { 2859a4365d0SYoshinobu Inoue struct sadb_msg *base; 2869a4365d0SYoshinobu Inoue 2872f4c5de9SHajimu UMEMOTO if ((l = recv(so, rbuf, sizeof(*base), MSG_PEEK)) < 0) { 2889a4365d0SYoshinobu Inoue err(1, "recv"); 2899a4365d0SYoshinobu Inoue /*NOTREACHED*/ 2909a4365d0SYoshinobu Inoue } 2919a4365d0SYoshinobu Inoue 2922f4c5de9SHajimu UMEMOTO if (l != sizeof(*base)) 2939a4365d0SYoshinobu Inoue continue; 2949a4365d0SYoshinobu Inoue 2959a4365d0SYoshinobu Inoue base = (struct sadb_msg *)rbuf; 2962f4c5de9SHajimu UMEMOTO if ((l = recv(so, rbuf, PFKEY_UNUNIT64(base->sadb_msg_len), 2979a4365d0SYoshinobu Inoue 0)) < 0) { 2989a4365d0SYoshinobu Inoue err(1, "recv"); 2999a4365d0SYoshinobu Inoue /*NOTREACHED*/ 3009a4365d0SYoshinobu Inoue } 30133841545SHajimu UMEMOTO printdate(); 3029a4365d0SYoshinobu Inoue if (f_hexdump) { 3039a4365d0SYoshinobu Inoue int i; 3042f4c5de9SHajimu UMEMOTO for (i = 0; i < l; i++) { 3059a4365d0SYoshinobu Inoue if (i % 16 == 0) 3069a4365d0SYoshinobu Inoue printf("%08x: ", i); 3079a4365d0SYoshinobu Inoue printf("%02x ", rbuf[i] & 0xff); 3089a4365d0SYoshinobu Inoue if (i % 16 == 15) 3099a4365d0SYoshinobu Inoue printf("\n"); 3109a4365d0SYoshinobu Inoue } 3112f4c5de9SHajimu UMEMOTO if (l % 16) 3129a4365d0SYoshinobu Inoue printf("\n"); 3139a4365d0SYoshinobu Inoue } 3149a4365d0SYoshinobu Inoue /* adjust base pointer for promisc mode */ 3159a4365d0SYoshinobu Inoue if (base->sadb_msg_type == SADB_X_PROMISC) { 316cf43a054SHajimu UMEMOTO if ((ssize_t)sizeof(*base) < l) 3179a4365d0SYoshinobu Inoue base++; 3189a4365d0SYoshinobu Inoue else 3199a4365d0SYoshinobu Inoue base = NULL; 3209a4365d0SYoshinobu Inoue } 3219a4365d0SYoshinobu Inoue if (base) { 3229a4365d0SYoshinobu Inoue kdebug_sadb(base); 3239a4365d0SYoshinobu Inoue printf("\n"); 3249a4365d0SYoshinobu Inoue fflush(stdout); 3259a4365d0SYoshinobu Inoue } 3269a4365d0SYoshinobu Inoue } 3279a4365d0SYoshinobu Inoue } 3289a4365d0SYoshinobu Inoue 3299a4365d0SYoshinobu Inoue int 330e0c0612dSMateusz Guzik sendkeymsg(char *buf, size_t len) 3319a4365d0SYoshinobu Inoue { 3329a4365d0SYoshinobu Inoue u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ 333cf43a054SHajimu UMEMOTO ssize_t l; 3349a4365d0SYoshinobu Inoue struct sadb_msg *msg; 3359a4365d0SYoshinobu Inoue 3369a4365d0SYoshinobu Inoue { 3379a4365d0SYoshinobu Inoue struct timeval tv; 3389a4365d0SYoshinobu Inoue tv.tv_sec = 1; 3399a4365d0SYoshinobu Inoue tv.tv_usec = 0; 3409a4365d0SYoshinobu Inoue if (setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { 3419a4365d0SYoshinobu Inoue perror("setsockopt"); 3429a4365d0SYoshinobu Inoue goto end; 3439a4365d0SYoshinobu Inoue } 3449a4365d0SYoshinobu Inoue } 3459a4365d0SYoshinobu Inoue 3469a4365d0SYoshinobu Inoue if (f_forever) 3479a4365d0SYoshinobu Inoue shortdump_hdr(); 3489a4365d0SYoshinobu Inoue again: 3493c62e87aSJun-ichiro itojun Hagino if (f_verbose) { 350cf43a054SHajimu UMEMOTO kdebug_sadb((struct sadb_msg *)buf); 351cf43a054SHajimu UMEMOTO printf("\n"); 352cf43a054SHajimu UMEMOTO } 353cf43a054SHajimu UMEMOTO if (f_hexdump) { 354b2981787SMateusz Guzik size_t i; 355cf43a054SHajimu UMEMOTO for (i = 0; i < len; i++) { 356cf43a054SHajimu UMEMOTO if (i % 16 == 0) 357b2981787SMateusz Guzik printf("%08x: ", (u_int)i); 358cf43a054SHajimu UMEMOTO printf("%02x ", buf[i] & 0xff); 359cf43a054SHajimu UMEMOTO if (i % 16 == 15) 360cf43a054SHajimu UMEMOTO printf("\n"); 361cf43a054SHajimu UMEMOTO } 362cf43a054SHajimu UMEMOTO if (len % 16) 3633c62e87aSJun-ichiro itojun Hagino printf("\n"); 3643c62e87aSJun-ichiro itojun Hagino } 3659a4365d0SYoshinobu Inoue 366cf43a054SHajimu UMEMOTO if ((l = send(so, buf, len, 0)) < 0) { 3679a4365d0SYoshinobu Inoue perror("send"); 3689a4365d0SYoshinobu Inoue goto end; 3699a4365d0SYoshinobu Inoue } 3709a4365d0SYoshinobu Inoue 3719a4365d0SYoshinobu Inoue msg = (struct sadb_msg *)rbuf; 3729a4365d0SYoshinobu Inoue do { 3732f4c5de9SHajimu UMEMOTO if ((l = recv(so, rbuf, sizeof(rbuf), 0)) < 0) { 3749a4365d0SYoshinobu Inoue perror("recv"); 3759a4365d0SYoshinobu Inoue goto end; 3769a4365d0SYoshinobu Inoue } 3779a4365d0SYoshinobu Inoue 3782f4c5de9SHajimu UMEMOTO if (PFKEY_UNUNIT64(msg->sadb_msg_len) != l) { 3799a4365d0SYoshinobu Inoue warnx("invalid keymsg length"); 3809a4365d0SYoshinobu Inoue break; 3819a4365d0SYoshinobu Inoue } 3829a4365d0SYoshinobu Inoue 3833c62e87aSJun-ichiro itojun Hagino if (f_verbose) { 3849a4365d0SYoshinobu Inoue kdebug_sadb((struct sadb_msg *)rbuf); 3853c62e87aSJun-ichiro itojun Hagino printf("\n"); 3863c62e87aSJun-ichiro itojun Hagino } 3871e67e310SMateusz Guzik if (postproc(msg) < 0) 3889a4365d0SYoshinobu Inoue break; 3899a4365d0SYoshinobu Inoue } while (msg->sadb_msg_errno || msg->sadb_msg_seq); 3909a4365d0SYoshinobu Inoue 3919a4365d0SYoshinobu Inoue if (f_forever) { 3929a4365d0SYoshinobu Inoue fflush(stdout); 3939a4365d0SYoshinobu Inoue sleep(1); 3949a4365d0SYoshinobu Inoue goto again; 3959a4365d0SYoshinobu Inoue } 3969a4365d0SYoshinobu Inoue 3979a4365d0SYoshinobu Inoue end: 3989a4365d0SYoshinobu Inoue return(0); 3999a4365d0SYoshinobu Inoue } 4009a4365d0SYoshinobu Inoue 4019a4365d0SYoshinobu Inoue int 4021e67e310SMateusz Guzik postproc(struct sadb_msg *msg) 4039a4365d0SYoshinobu Inoue { 4049a4365d0SYoshinobu Inoue 4059a4365d0SYoshinobu Inoue if (msg->sadb_msg_errno != 0) { 4069a4365d0SYoshinobu Inoue char inf[80]; 4072f4c5de9SHajimu UMEMOTO const char *errmsg = NULL; 4089a4365d0SYoshinobu Inoue 4099a4365d0SYoshinobu Inoue if (f_mode == MODE_SCRIPT) 4109a4365d0SYoshinobu Inoue snprintf(inf, sizeof(inf), "The result of line %d: ", lineno); 4119a4365d0SYoshinobu Inoue else 4129a4365d0SYoshinobu Inoue inf[0] = '\0'; 4139a4365d0SYoshinobu Inoue 4149a4365d0SYoshinobu Inoue switch (msg->sadb_msg_errno) { 4159a4365d0SYoshinobu Inoue case ENOENT: 4169a4365d0SYoshinobu Inoue switch (msg->sadb_msg_type) { 4179a4365d0SYoshinobu Inoue case SADB_DELETE: 4189a4365d0SYoshinobu Inoue case SADB_GET: 4199a4365d0SYoshinobu Inoue case SADB_X_SPDDELETE: 4209a4365d0SYoshinobu Inoue errmsg = "No entry"; 4219a4365d0SYoshinobu Inoue break; 4229a4365d0SYoshinobu Inoue case SADB_DUMP: 4239a4365d0SYoshinobu Inoue errmsg = "No SAD entries"; 4249a4365d0SYoshinobu Inoue break; 4259a4365d0SYoshinobu Inoue case SADB_X_SPDDUMP: 4269a4365d0SYoshinobu Inoue errmsg = "No SPD entries"; 4279a4365d0SYoshinobu Inoue break; 4289a4365d0SYoshinobu Inoue } 4299a4365d0SYoshinobu Inoue break; 4309a4365d0SYoshinobu Inoue default: 4319a4365d0SYoshinobu Inoue errmsg = strerror(msg->sadb_msg_errno); 4329a4365d0SYoshinobu Inoue } 4339a4365d0SYoshinobu Inoue printf("%s%s.\n", inf, errmsg); 4349a4365d0SYoshinobu Inoue return(-1); 4359a4365d0SYoshinobu Inoue } 4369a4365d0SYoshinobu Inoue 4379a4365d0SYoshinobu Inoue switch (msg->sadb_msg_type) { 4389a4365d0SYoshinobu Inoue case SADB_GET: 4399a4365d0SYoshinobu Inoue pfkey_sadump(msg); 4409a4365d0SYoshinobu Inoue break; 4419a4365d0SYoshinobu Inoue 4429a4365d0SYoshinobu Inoue case SADB_DUMP: 4439a4365d0SYoshinobu Inoue /* filter out DEAD SAs */ 4449a4365d0SYoshinobu Inoue if (!f_all) { 4459a4365d0SYoshinobu Inoue caddr_t mhp[SADB_EXT_MAX + 1]; 4469a4365d0SYoshinobu Inoue struct sadb_sa *sa; 4479a4365d0SYoshinobu Inoue pfkey_align(msg, mhp); 4489a4365d0SYoshinobu Inoue pfkey_check(mhp); 4499a4365d0SYoshinobu Inoue if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 4509a4365d0SYoshinobu Inoue if (sa->sadb_sa_state == SADB_SASTATE_DEAD) 4519a4365d0SYoshinobu Inoue break; 4529a4365d0SYoshinobu Inoue } 4539a4365d0SYoshinobu Inoue } 4549a4365d0SYoshinobu Inoue if (f_forever) 4559a4365d0SYoshinobu Inoue shortdump(msg); 4569a4365d0SYoshinobu Inoue else 4579a4365d0SYoshinobu Inoue pfkey_sadump(msg); 4589a4365d0SYoshinobu Inoue msg = (struct sadb_msg *)((caddr_t)msg + 4599a4365d0SYoshinobu Inoue PFKEY_UNUNIT64(msg->sadb_msg_len)); 4603c62e87aSJun-ichiro itojun Hagino if (f_verbose) { 4619a4365d0SYoshinobu Inoue kdebug_sadb((struct sadb_msg *)msg); 4623c62e87aSJun-ichiro itojun Hagino printf("\n"); 4633c62e87aSJun-ichiro itojun Hagino } 4649a4365d0SYoshinobu Inoue break; 4659a4365d0SYoshinobu Inoue 4669a4365d0SYoshinobu Inoue case SADB_X_SPDDUMP: 4679a4365d0SYoshinobu Inoue pfkey_spdump(msg); 4689a4365d0SYoshinobu Inoue if (msg->sadb_msg_seq == 0) break; 4699a4365d0SYoshinobu Inoue msg = (struct sadb_msg *)((caddr_t)msg + 4709a4365d0SYoshinobu Inoue PFKEY_UNUNIT64(msg->sadb_msg_len)); 4713c62e87aSJun-ichiro itojun Hagino if (f_verbose) { 4729a4365d0SYoshinobu Inoue kdebug_sadb((struct sadb_msg *)msg); 4733c62e87aSJun-ichiro itojun Hagino printf("\n"); 4743c62e87aSJun-ichiro itojun Hagino } 4759a4365d0SYoshinobu Inoue break; 4769a4365d0SYoshinobu Inoue } 4779a4365d0SYoshinobu Inoue 4789a4365d0SYoshinobu Inoue return(0); 4799a4365d0SYoshinobu Inoue } 4809a4365d0SYoshinobu Inoue 4819a4365d0SYoshinobu Inoue /*------------------------------------------------------------*/ 4822f4c5de9SHajimu UMEMOTO static const char *satype[] = { 4839a4365d0SYoshinobu Inoue NULL, NULL, "ah", "esp" 4849a4365d0SYoshinobu Inoue }; 4852f4c5de9SHajimu UMEMOTO static const char *sastate[] = { 4869a4365d0SYoshinobu Inoue "L", "M", "D", "d" 4879a4365d0SYoshinobu Inoue }; 4882f4c5de9SHajimu UMEMOTO static const char *ipproto[] = { 4899a4365d0SYoshinobu Inoue /*0*/ "ip", "icmp", "igmp", "ggp", "ip4", 4909a4365d0SYoshinobu Inoue NULL, "tcp", NULL, "egp", NULL, 4919a4365d0SYoshinobu Inoue /*10*/ NULL, NULL, NULL, NULL, NULL, 4929a4365d0SYoshinobu Inoue NULL, NULL, "udp", NULL, NULL, 4939a4365d0SYoshinobu Inoue /*20*/ NULL, NULL, "idp", NULL, NULL, 4949a4365d0SYoshinobu Inoue NULL, NULL, NULL, NULL, "tp", 4959a4365d0SYoshinobu Inoue /*30*/ NULL, NULL, NULL, NULL, NULL, 4969a4365d0SYoshinobu Inoue NULL, NULL, NULL, NULL, NULL, 4979a4365d0SYoshinobu Inoue /*40*/ NULL, "ip6", NULL, "rt6", "frag6", 4989a4365d0SYoshinobu Inoue NULL, "rsvp", "gre", NULL, NULL, 4999a4365d0SYoshinobu Inoue /*50*/ "esp", "ah", NULL, NULL, NULL, 5009a4365d0SYoshinobu Inoue NULL, NULL, NULL, "icmp6", "none", 5019a4365d0SYoshinobu Inoue /*60*/ "dst6", 5029a4365d0SYoshinobu Inoue }; 5039a4365d0SYoshinobu Inoue 5049a4365d0SYoshinobu Inoue #define STR_OR_ID(x, tab) \ 505*d94c991fSElyes Haouas (((x) < nitems(tab) && tab[(x)]) ? tab[(x)] : numstr(x)) 5069a4365d0SYoshinobu Inoue 5079a4365d0SYoshinobu Inoue const char * 508e0c0612dSMateusz Guzik numstr(int x) 5099a4365d0SYoshinobu Inoue { 5109a4365d0SYoshinobu Inoue static char buf[20]; 5119a4365d0SYoshinobu Inoue snprintf(buf, sizeof(buf), "#%d", x); 5129a4365d0SYoshinobu Inoue return buf; 5139a4365d0SYoshinobu Inoue } 5149a4365d0SYoshinobu Inoue 5159a4365d0SYoshinobu Inoue void 516e0c0612dSMateusz Guzik shortdump_hdr(void) 5179a4365d0SYoshinobu Inoue { 5189a4365d0SYoshinobu Inoue printf("%-4s %-3s %-1s %-8s %-7s %s -> %s\n", 5199a4365d0SYoshinobu Inoue "time", "p", "s", "spi", "ltime", "src", "dst"); 5209a4365d0SYoshinobu Inoue } 5219a4365d0SYoshinobu Inoue 5229a4365d0SYoshinobu Inoue void 523e0c0612dSMateusz Guzik shortdump(struct sadb_msg *msg) 5249a4365d0SYoshinobu Inoue { 5259a4365d0SYoshinobu Inoue caddr_t mhp[SADB_EXT_MAX + 1]; 5260fe26507SMunechika SUMIKAWA char buf[NI_MAXHOST], pbuf[NI_MAXSERV]; 5279a4365d0SYoshinobu Inoue struct sadb_sa *sa; 5289a4365d0SYoshinobu Inoue struct sadb_address *saddr; 5299a4365d0SYoshinobu Inoue struct sadb_lifetime *lts, *lth, *ltc; 5309a4365d0SYoshinobu Inoue struct sockaddr *s; 5319a4365d0SYoshinobu Inoue u_int t; 5329a4365d0SYoshinobu Inoue time_t cur = time(0); 5339a4365d0SYoshinobu Inoue 5349a4365d0SYoshinobu Inoue pfkey_align(msg, mhp); 5359a4365d0SYoshinobu Inoue pfkey_check(mhp); 5369a4365d0SYoshinobu Inoue 5379a4365d0SYoshinobu Inoue printf("%02lu%02lu", (u_long)(cur % 3600) / 60, (u_long)(cur % 60)); 5389a4365d0SYoshinobu Inoue 5399a4365d0SYoshinobu Inoue printf(" %-3s", STR_OR_ID(msg->sadb_msg_satype, satype)); 5409a4365d0SYoshinobu Inoue 5419a4365d0SYoshinobu Inoue if ((sa = (struct sadb_sa *)mhp[SADB_EXT_SA]) != NULL) { 5429a4365d0SYoshinobu Inoue printf(" %-1s", STR_OR_ID(sa->sadb_sa_state, sastate)); 5439a4365d0SYoshinobu Inoue printf(" %08x", (u_int32_t)ntohl(sa->sadb_sa_spi)); 5449a4365d0SYoshinobu Inoue } else 5459a4365d0SYoshinobu Inoue printf("%-1s %-8s", "?", "?"); 5469a4365d0SYoshinobu Inoue 5479a4365d0SYoshinobu Inoue lts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT]; 5489a4365d0SYoshinobu Inoue lth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; 5499a4365d0SYoshinobu Inoue ltc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; 5509a4365d0SYoshinobu Inoue if (lts && lth && ltc) { 5519a4365d0SYoshinobu Inoue if (ltc->sadb_lifetime_addtime == 0) 5529a4365d0SYoshinobu Inoue t = (u_long)0; 5539a4365d0SYoshinobu Inoue else 5549a4365d0SYoshinobu Inoue t = (u_long)(cur - ltc->sadb_lifetime_addtime); 5559a4365d0SYoshinobu Inoue if (t >= 1000) 5562f4c5de9SHajimu UMEMOTO strlcpy(buf, " big/", sizeof(buf)); 5579a4365d0SYoshinobu Inoue else 5589a4365d0SYoshinobu Inoue snprintf(buf, sizeof(buf), " %3lu/", (u_long)t); 5599a4365d0SYoshinobu Inoue printf("%s", buf); 5609a4365d0SYoshinobu Inoue 5619a4365d0SYoshinobu Inoue t = (u_long)lth->sadb_lifetime_addtime; 5629a4365d0SYoshinobu Inoue if (t >= 1000) 5632f4c5de9SHajimu UMEMOTO strlcpy(buf, "big", sizeof(buf)); 5649a4365d0SYoshinobu Inoue else 5659a4365d0SYoshinobu Inoue snprintf(buf, sizeof(buf), "%-3lu", (u_long)t); 5669a4365d0SYoshinobu Inoue printf("%s", buf); 5679a4365d0SYoshinobu Inoue } else 56833841545SHajimu UMEMOTO printf(" ??\?/???"); /* backslash to avoid trigraph ??/ */ 5699a4365d0SYoshinobu Inoue 5709a4365d0SYoshinobu Inoue printf(" "); 5719a4365d0SYoshinobu Inoue 5729a4365d0SYoshinobu Inoue if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]) != NULL) { 5739a4365d0SYoshinobu Inoue if (saddr->sadb_address_proto) 5749a4365d0SYoshinobu Inoue printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 5759a4365d0SYoshinobu Inoue s = (struct sockaddr *)(saddr + 1); 5769a4365d0SYoshinobu Inoue getnameinfo(s, s->sa_len, buf, sizeof(buf), 5779a4365d0SYoshinobu Inoue pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 5789a4365d0SYoshinobu Inoue if (strcmp(pbuf, "0") != 0) 5799a4365d0SYoshinobu Inoue printf("%s[%s]", buf, pbuf); 5809a4365d0SYoshinobu Inoue else 5819a4365d0SYoshinobu Inoue printf("%s", buf); 5829a4365d0SYoshinobu Inoue } else 5839a4365d0SYoshinobu Inoue printf("?"); 5849a4365d0SYoshinobu Inoue 5859a4365d0SYoshinobu Inoue printf(" -> "); 5869a4365d0SYoshinobu Inoue 5879a4365d0SYoshinobu Inoue if ((saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]) != NULL) { 5889a4365d0SYoshinobu Inoue if (saddr->sadb_address_proto) 5899a4365d0SYoshinobu Inoue printf("%s ", STR_OR_ID(saddr->sadb_address_proto, ipproto)); 5909a4365d0SYoshinobu Inoue 5919a4365d0SYoshinobu Inoue s = (struct sockaddr *)(saddr + 1); 5929a4365d0SYoshinobu Inoue getnameinfo(s, s->sa_len, buf, sizeof(buf), 5939a4365d0SYoshinobu Inoue pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV); 5949a4365d0SYoshinobu Inoue if (strcmp(pbuf, "0") != 0) 5959a4365d0SYoshinobu Inoue printf("%s[%s]", buf, pbuf); 5969a4365d0SYoshinobu Inoue else 5979a4365d0SYoshinobu Inoue printf("%s", buf); 5989a4365d0SYoshinobu Inoue } else 5999a4365d0SYoshinobu Inoue printf("?"); 6009a4365d0SYoshinobu Inoue 6019a4365d0SYoshinobu Inoue printf("\n"); 6029a4365d0SYoshinobu Inoue } 60333841545SHajimu UMEMOTO 60433841545SHajimu UMEMOTO /* From: tcpdump(1):gmt2local.c and util.c */ 60533841545SHajimu UMEMOTO /* 60633841545SHajimu UMEMOTO * Print the timestamp 60733841545SHajimu UMEMOTO */ 60833841545SHajimu UMEMOTO static void 609e0c0612dSMateusz Guzik printdate(void) 61033841545SHajimu UMEMOTO { 61133841545SHajimu UMEMOTO struct timeval tp; 61233841545SHajimu UMEMOTO int s; 61333841545SHajimu UMEMOTO 61433841545SHajimu UMEMOTO if (gettimeofday(&tp, NULL) == -1) { 61533841545SHajimu UMEMOTO perror("gettimeofday"); 61633841545SHajimu UMEMOTO return; 61733841545SHajimu UMEMOTO } 61833841545SHajimu UMEMOTO 61933841545SHajimu UMEMOTO if (f_tflag == 1) { 62033841545SHajimu UMEMOTO /* Default */ 62133841545SHajimu UMEMOTO s = (tp.tv_sec + thiszone ) % 86400; 62233841545SHajimu UMEMOTO (void)printf("%02d:%02d:%02d.%06u ", 62333841545SHajimu UMEMOTO s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tp.tv_usec); 62433841545SHajimu UMEMOTO } else if (f_tflag > 1) { 62533841545SHajimu UMEMOTO /* Unix timeval style */ 62633841545SHajimu UMEMOTO (void)printf("%u.%06u ", 62733841545SHajimu UMEMOTO (u_int32_t)tp.tv_sec, (u_int32_t)tp.tv_usec); 62833841545SHajimu UMEMOTO } 62933841545SHajimu UMEMOTO 63033841545SHajimu UMEMOTO printf("\n"); 63133841545SHajimu UMEMOTO } 63233841545SHajimu UMEMOTO 63333841545SHajimu UMEMOTO /* 63433841545SHajimu UMEMOTO * Returns the difference between gmt and local time in seconds. 63533841545SHajimu UMEMOTO * Use gmtime() and localtime() to keep things simple. 63633841545SHajimu UMEMOTO */ 63733841545SHajimu UMEMOTO int32_t 63833841545SHajimu UMEMOTO gmt2local(time_t t) 63933841545SHajimu UMEMOTO { 64033841545SHajimu UMEMOTO register int dt, dir; 64133841545SHajimu UMEMOTO register struct tm *gmt, *loc; 64233841545SHajimu UMEMOTO struct tm sgmt; 64333841545SHajimu UMEMOTO 64433841545SHajimu UMEMOTO if (t == 0) 64533841545SHajimu UMEMOTO t = time(NULL); 64633841545SHajimu UMEMOTO gmt = &sgmt; 64733841545SHajimu UMEMOTO *gmt = *gmtime(&t); 64833841545SHajimu UMEMOTO loc = localtime(&t); 64933841545SHajimu UMEMOTO dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + 65033841545SHajimu UMEMOTO (loc->tm_min - gmt->tm_min) * 60; 65133841545SHajimu UMEMOTO 65233841545SHajimu UMEMOTO /* 65333841545SHajimu UMEMOTO * If the year or julian day is different, we span 00:00 GMT 65433841545SHajimu UMEMOTO * and must add or subtract a day. Check the year first to 65533841545SHajimu UMEMOTO * avoid problems when the julian day wraps. 65633841545SHajimu UMEMOTO */ 65733841545SHajimu UMEMOTO dir = loc->tm_year - gmt->tm_year; 65833841545SHajimu UMEMOTO if (dir == 0) 65933841545SHajimu UMEMOTO dir = loc->tm_yday - gmt->tm_yday; 66033841545SHajimu UMEMOTO dt += dir * 24 * 60 * 60; 66133841545SHajimu UMEMOTO 66233841545SHajimu UMEMOTO return (dt); 66333841545SHajimu UMEMOTO } 664