2 * @(#) pfkey socket manipulator/observer
4 * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org>
5 * and Michael Richardson <mcr@freeswan.org>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * RCSID $Id: pf_key.c,v 1.5 2002/03/08 21:44:04 rgb Exp $
22 * This program opens a pfkey socket and prints all messages that it sees.
24 * This can be used to diagnose problems.
35 #include <sys/socket.h>
37 #include <sys/types.h>
44 char me[] = "ipsec pf_key";
45 extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */
46 uint32_t pfkey_seq = 0;
52 fprintf(stderr, "%s: Usage: %s [--help]\n"
53 "\tby default listens for AH, ESP, IPIP and IPCOMP\n"
54 "\t--ah listen for AH messages\n"
55 "\t--esp listen for ESP messages\n"
56 "\t--ipip listen for IPIP messages\n"
57 "\t--ipcomp listen for IPCOMP messages\n",
63 pfkey_register(uint8_t satype) {
64 /* for registering SA types that can be negotiated */
66 struct sadb_ext *extensions[SADB_EXT_MAX + 1];
67 struct sadb_msg *pfkey_msg;
69 pfkey_extensions_init(extensions);
70 if((error = pfkey_msg_hdr_build(&extensions[0],
76 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
78 pfkey_extensions_free(extensions);
81 if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
82 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
84 pfkey_extensions_free(extensions);
85 pfkey_msg_free(&pfkey_msg);
88 if(write(pfkey_sock, pfkey_msg,
89 pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) !=
90 pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
91 /* cleanup code here */
92 fprintf(stderr, "%s: Trouble writing to channel PF_KEY.\n", progname);
93 pfkey_extensions_free(extensions);
94 pfkey_msg_free(&pfkey_msg);
97 pfkey_extensions_free(extensions);
98 pfkey_msg_free(&pfkey_msg);
102 main(int argc, char *argv[])
106 unsigned char pfkey_buf[256];
107 struct sadb_msg *msg;
109 static int ah_register;
110 static int esp_register;
111 static int ipip_register;
112 static int ipcomp_register;
114 static struct option long_options[] =
116 {"help", no_argument, 0, 'h'},
117 {"version", no_argument, 0, 'v'},
118 {"ah", no_argument, &ah_register, 1},
119 {"esp", no_argument, &esp_register, 1},
120 {"ipip", no_argument, &ipip_register, 1},
121 {"ipcomp", no_argument, &ipcomp_register, 1},
130 if(strrchr(progname, '/')) {
131 progname=strrchr(progname, '/')+1;
134 while((opt = getopt_long(argc, argv, "hv",
135 long_options, NULL)) != EOF) {
141 fprintf(stdout, "%s %s\n", me, ipsec_version_code());
142 fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
145 /* it was a long option with a flag */
150 if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
151 fprintf(stderr, "%s: failed to open PF_KEY family socket: %s\n",
152 progname, strerror(errno));
156 if(ah_register == 0 &&
159 ipcomp_register==0) {
167 pfkey_register(SADB_SATYPE_AH);
170 pfkey_register(SADB_SATYPE_ESP);
173 pfkey_register(SADB_X_SATYPE_IPIP);
175 if(ipcomp_register) {
176 pfkey_register(SADB_X_SATYPE_COMP);
179 while((readlen = read(pfkey_sock, pfkey_buf, sizeof(pfkey_buf))) > 0) {
180 struct sadb_ext *extensions[SADB_EXT_MAX + 1];
181 msg = (struct sadb_msg *)pfkey_buf;
183 /* first, see if we got enough for an sadb_msg */
184 if(readlen < sizeof(struct sadb_msg)) {
185 printf("%s: runt packet of size: %d (<%d)\n",
186 progname, readlen, sizeof(struct sadb_msg));
190 /* okay, we got enough for a message, print it out */
191 printf("\npfkey v%d msg. type=%d seq=%d len=%d pid=%d errno=%d satype=%d\n",
192 msg->sadb_msg_version,
198 msg->sadb_msg_satype);
200 if(readlen != msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
202 printf("%s: packet size read from socket=%d doesn't equal sadb_msg_len %d * %d; message not decoded\n",
206 IPSEC_PFKEYv2_ALIGN);
210 pfkey_lib_debug = PF_KEY_DEBUG_PARSE_STRUCT;
211 if (pfkey_msg_parse(msg, NULL, extensions, EXT_BITS_OUT)) {
212 printf("%s: unparseable PF_KEY message.\n",
215 printf("%s: parseable PF_KEY message.\n",
224 * Revision 1.5 2002/03/08 21:44:04 rgb
225 * Update for all GNU-compliant --version strings.
227 * Revision 1.4 2001/11/27 05:19:06 mcr
228 * added extra newline between packets.
229 * set pfkey_lib_debug to enum rather than just to "1".
231 * Revision 1.3 2001/11/27 03:35:29 rgb
232 * Added stdlib *again*.
234 * Revision 1.2 2001/11/23 07:23:14 mcr
235 * pulled up klips2 Makefile and pf_key code.
237 * Revision 1.1.2.5 2001/10/23 18:49:12 mcr
238 * renamed man page to section 8.
239 * added --ah, --esp, --ipcomp and --ipip to control which
240 * protocols are printed.
241 * incomplete messages which include at least an sadb header are printed.
243 * Revision 1.1.2.4 2001/10/22 21:50:51 rgb
244 * Added pfkey register for AH, ESP, IPIP and COMP.
246 * Revision 1.1.2.3 2001/10/21 21:51:06 rgb
247 * Bug fixes to get working.
249 * Revision 1.1.2.2 2001/10/20 22:45:31 rgb
250 * Added check for exact length and a call to message parser to get some
251 * idea of the contents of each extension.
253 * Revision 1.1.2.1 2001/10/17 23:25:37 mcr
254 * added "pk_key" program to dump raw kernel pf messages.
255 * (program is still skeletal)
259 * c-file-style: "linux"