OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / utils / pf_key.c
1 /*
2  * @(#) pfkey socket manipulator/observer
3  *
4  * Copyright (C) 2001  Richard Guy Briggs  <rgb@freeswan.org>
5  *                 and Michael Richardson  <mcr@freeswan.org>
6  * 
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>.
11  * 
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
15  * for more details.
16  *
17  * RCSID $Id: pf_key.c,v 1.5 2002/03/08 21:44:04 rgb Exp $
18  *
19  */
20
21 /* 
22  * This program opens a pfkey socket and prints all messages that it sees.
23  *
24  * This can be used to diagnose problems.
25  *
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <getopt.h>
33 #include <errno.h>
34
35 #include <sys/socket.h>
36
37 #include <sys/types.h>
38 #include <stdint.h>
39 #include <freeswan.h>
40 #include <pfkeyv2.h>
41 #include <pfkey.h>
42
43 char *progname;
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;
47 int pfkey_sock;
48
49 static void
50 Usage(char *progname)
51 {
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",
58                 progname, progname);
59         exit(1);
60 }
61
62 void
63 pfkey_register(uint8_t satype) {
64         /* for registering SA types that can be negotiated */
65         int error = 0;
66         struct sadb_ext *extensions[SADB_EXT_MAX + 1];
67         struct sadb_msg *pfkey_msg;
68
69         pfkey_extensions_init(extensions);
70         if((error = pfkey_msg_hdr_build(&extensions[0],
71                                         SADB_REGISTER,
72                                         satype,
73                                         0,
74                                         ++pfkey_seq,
75                                         getpid()))) {
76                 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
77                         progname, error);
78                 pfkey_extensions_free(extensions);
79                 exit(1);
80         }
81         if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
82                 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
83                         progname, error);
84                 pfkey_extensions_free(extensions);
85                 pfkey_msg_free(&pfkey_msg);
86                 exit(1);
87         }
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);
95                 exit(1);
96         }
97         pfkey_extensions_free(extensions);
98         pfkey_msg_free(&pfkey_msg);
99 }
100
101 int
102 main(int argc, char *argv[])
103 {
104         int opt;
105         int readlen;
106         unsigned char pfkey_buf[256];
107         struct sadb_msg *msg;
108
109         static int ah_register;
110         static int esp_register;
111         static int ipip_register;
112         static int ipcomp_register;
113
114         static struct option long_options[] =
115         {
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},
122         };
123
124         ah_register   = 0;
125         esp_register  = 0;
126         ipip_register = 0;
127         ipcomp_register=0;
128         
129         progname = argv[0];
130         if(strrchr(progname, '/')) {
131                 progname=strrchr(progname, '/')+1;
132         }
133         
134         while((opt = getopt_long(argc, argv, "hv",
135                                  long_options, NULL)) !=  EOF) {
136                 switch(opt) {
137                 case 'h':
138                         Usage(progname);
139                         break;
140                 case 'v':
141                         fprintf(stdout, "%s %s\n", me, ipsec_version_code());
142                         fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
143                         exit(0);
144                 case '0':
145                         /* it was a long option with a flag */
146                         break;
147                 }
148         }
149         
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));
153                 exit(1);
154         }
155
156         if(ah_register == 0 &&
157            esp_register== 0 &&
158            ipip_register==0 &&
159            ipcomp_register==0) {
160                 ah_register=1;
161                 esp_register=1;
162                 ipip_register=1;
163                 ipcomp_register=1;
164         }
165
166         if(ah_register) {
167                 pfkey_register(SADB_SATYPE_AH);
168         }
169         if(esp_register) {
170                 pfkey_register(SADB_SATYPE_ESP);
171         }
172         if(ipip_register) {
173                 pfkey_register(SADB_X_SATYPE_IPIP);
174         }
175         if(ipcomp_register) {
176                 pfkey_register(SADB_X_SATYPE_COMP);
177         }
178
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;
182                 
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));
187                         continue;
188                 }
189                 
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,
193                        msg->sadb_msg_type,
194                        msg->sadb_msg_seq,
195                        msg->sadb_msg_len,
196                        msg->sadb_msg_pid,
197                        msg->sadb_msg_errno,
198                        msg->sadb_msg_satype);
199                 
200                 if(readlen != msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)
201                 {
202                         printf("%s: packet size read from socket=%d doesn't equal sadb_msg_len %d * %d; message not decoded\n",
203                                progname,
204                                readlen, 
205                                msg->sadb_msg_len,
206                                IPSEC_PFKEYv2_ALIGN);
207                         continue;
208                 }
209                 
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",
213                                progname);
214                 } else {
215                         printf("%s: parseable PF_KEY message.\n",
216                                progname);
217                 }
218         }
219         exit(0);
220 }
221         
222 /*
223  * $Log: pf_key.c,v $
224  * Revision 1.5  2002/03/08 21:44:04  rgb
225  * Update for all GNU-compliant --version strings.
226  *
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".
230  *
231  * Revision 1.3  2001/11/27 03:35:29  rgb
232  * Added stdlib *again*.
233  *
234  * Revision 1.2  2001/11/23 07:23:14  mcr
235  *      pulled up klips2 Makefile and pf_key code.
236  *
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.
242  *
243  * Revision 1.1.2.4  2001/10/22 21:50:51  rgb
244  * Added pfkey register for AH, ESP, IPIP and COMP.
245  *
246  * Revision 1.1.2.3  2001/10/21 21:51:06  rgb
247  * Bug fixes to get working.
248  *
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.
252  *
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)
256  *
257  *
258  * Local variables:
259  * c-file-style: "linux"
260  * End:
261  *
262  */