3 * Copyright (C) 1996 John Ioannidis.
4 * Copyright (C) 1997, 1998, 1999, 2000, 2001 Richard Guy Briggs.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 char spigrp_c_version[] = "RCSID $Id: spigrp.c,v 1.41 2002/03/08 21:44:05 rgb Exp $";
20 #include <sys/types.h>
21 #include <linux/types.h> /* new */
24 #include <sys/stat.h> /* open() */
25 #include <fcntl.h> /* open() */
26 #include <stdlib.h> /* system(), strtoul() */
28 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
32 /* #include <linux/ip.h> */
39 #include <linux/autoconf.h> /* CONFIG_IPSEC_PFKEYv2 */
45 #include "ipsec_encap.h"
46 #include "ipsec_netlink.h"
51 char me[] = "ipsec spigrp";
52 extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */
55 uint32_t pfkey_seq = 0;
60 }; /* to store the given saids and their address families in an array */
61 /* XXX: Note that we do *not* check if the address families of all SAID?s are the same.
62 * This can make it possible to group SAs for IPv4 addresses with SAs for
63 * IPv6 addresses (perhaps some kind of IPv4-over-secIPv6 or vice versa).
64 * Do not know, if this is a bug or feature */
69 fprintf(stdout, "usage: Note: position of options and arguments is important!\n");
70 fprintf(stdout, "usage: %s [ --debug ] [ --label <label> ] af1 dst1 spi1 proto1 [ af2 dst2 spi2 proto2 [ af3 dst3 spi3 proto3 [ af4 dst4 spi4 proto4 ] ] ]\n", s);
71 fprintf(stdout, "usage: %s [ --debug ] [ --label <label> ] --said <SA1> [ <SA2> [ <SA3> [ <SA4> ] ] ]\n", s);
72 fprintf(stdout, "usage: %s --help\n", s);
73 fprintf(stdout, "usage: %s --version\n", s);
74 fprintf(stdout, "usage: %s\n", s);
75 fprintf(stdout, " [ --debug ] is optional to any %s command.\n", s);
76 fprintf(stdout, " [ --label <label> ] is optional to any %s command.\n", s);
81 main(int argc, char **argv)
87 const char* error_s = NULL;
88 char ipaddr_txt[ADDRTOT_BUF];
91 struct said_af said_af_array[4];
95 struct sadb_ext *extensions[SADB_EXT_MAX + 1];
96 struct sadb_msg *pfkey_msg;
98 ip_address pfkey_address_s_ska;
101 program_name = argv[0];
102 for(i = 0; i < 4; i++) {
103 memset(&said_af_array[i], 0, sizeof(struct said_af));
106 if(argc > 1 && strcmp(argv[1], "--debug") == 0) {
109 fprintf(stdout, "\"--debug\" option requested.\n");
117 fprintf(stdout, "argc=%d (%d incl. --debug option).\n",
122 if(argc > 1 && strcmp(argv[1], "--label") == 0) {
124 program_name = malloc(strlen(argv[0])
125 + 10 /* update this when changing the sprintf() */
127 sprintf(program_name, "%s --label %s",
131 fprintf(stdout, "using \"%s\" as a label.\n", program_name);
136 fprintf(stderr, "%s: --label option requires an argument.\n",
143 fprintf(stdout, "...After check for --label option.\n");
147 system("cat /proc/net/ipsec_spigrp");
152 fprintf(stdout, "...After check for no option to print /proc/net/ipsec_spigrp.\n");
155 if(strcmp(argv[1], "--help") == 0) {
157 fprintf(stdout, "\"--help\" option requested.\n");
164 fprintf(stdout, "...After check for --help option.\n");
167 if(strcmp(argv[1], "--version") == 0) {
169 fprintf(stdout, "\"--version\" option requested.\n");
171 fprintf(stdout, "%s %s\n", me, ipsec_version_code());
172 fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
177 fprintf(stdout, "...After check for --version option.\n");
180 if(strcmp(argv[1], "--said") == 0) {
182 fprintf(stdout, "processing %d args with --said flag.\n", argc);
188 fprintf(stdout, "...After check for --said option.\n");
192 if (argc < 3 /*|| argc > 5*/) {
193 fprintf(stderr, "expecting 3 or more args with --said, got %d.\n", argc);
199 if ((argc < 5) || (argc > 17) || ((argc % 4) != 1)) {
200 fprintf(stderr, "expecting 5 or more args without --said, got %d.\n", argc);
208 fprintf(stdout, "processing %d nspis.\n", nspis);
211 for(i = 0; i < nspis; i++) {
213 fprintf(stdout, "processing spi #%d.\n", i);
217 error_s = ttosa((const char *)argv[i+2], 0, (ip_said*)&(said_af_array[i].said));
218 if(error_s != NULL) {
219 fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
220 program_name, error_s, argv[i+2]);
223 said_af_array[i].af = addrtypeof(&(said_af_array[i].said.dst));
225 addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
226 fprintf(stdout, "said[%d].dst=%s.\n", i, ipaddr_txt);
229 if(!strcmp(argv[i*4+4], "ah")) {
230 said_af_array[i].said.proto = SA_AH;
232 if(!strcmp(argv[i*4+4], "esp")) {
233 said_af_array[i].said.proto = SA_ESP;
235 if(!strcmp(argv[i*4+4], "tun")) {
236 said_af_array[i].said.proto = SA_IPIP;
238 if(!strcmp(argv[i*4+4], "comp")) {
239 said_af_array[i].said.proto = SA_COMP;
241 if(said_af_array[i].said.proto == 0) {
242 fprintf(stderr, "%s: Badly formed proto: %s\n",
243 program_name, argv[i*4+4]);
246 said_af_array[i].said.spi = htonl(strtoul(argv[i*4+3], &endptr, 0));
247 if(!(endptr == argv[i*4+3] + strlen(argv[i*4+3]))) {
248 fprintf(stderr, "%s: Badly formed spi: %s\n",
249 program_name, argv[i*4+3]);
252 if(!strcmp(argv[i*4+1], "inet")) {
253 said_af_array[i].af = AF_INET;
255 if(!strcmp(argv[i*4+1], "inet6")) {
256 said_af_array[i].af = AF_INET6;
258 if((said_af_array[i].af != AF_INET) && (said_af_array[i].af != AF_INET6)) {
259 fprintf(stderr, "%s: Address family %s not supported\n",
260 program_name, argv[i*4+1]);
263 error_s = ttoaddr(argv[i*4+2], 0, said_af_array[i].af, &(said_af_array[i].said.dst));
264 if(error_s != NULL) {
265 fprintf(stderr, "%s: Error, %s converting %dth address argument:%s\n",
266 program_name, error_s, i, argv[i*4+2]);
271 fprintf(stdout, "SA %d contains: ", i+1);
272 fprintf(stdout, "\n");
273 fprintf(stdout, "proto = %d\n", said_af_array[i].said.proto);
274 fprintf(stdout, "spi = %08x\n", said_af_array[i].said.spi);
275 addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
276 fprintf(stdout, "edst = %s\n", ipaddr_txt);
281 fprintf(stdout, "Opening pfkey socket.\n");
284 if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
285 fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ",
289 fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n");
292 fprintf(stderr, "access denied. ");
294 fprintf(stderr, "Check permissions. Should be 600.\n");
296 fprintf(stderr, "You must be root to open this file.\n");
300 fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
303 fprintf(stderr, "KLIPS not loaded or enabled.\n");
306 fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n");
309 fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
312 fprintf(stderr, "No kernel memory to allocate SA.\n");
314 case ESOCKTNOSUPPORT:
315 fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n");
318 fprintf(stderr, "SA already in use. Delete old one first.\n");
321 fprintf(stderr, "SA does not exist. Cannot delete.\n");
324 fprintf(stderr, "KLIPS not loaded or enabled.\n");
327 fprintf(stderr, "Unknown file open error %d. Please report as much detail as possible to development team.\n", errno);
332 for(i = 0; i < (((nspis - 1) < 2) ? 1 : (nspis - 1)); i++) {
334 fprintf(stdout, "processing %dth pfkey message.\n", i);
337 pfkey_extensions_init(extensions);
338 for(j = 0; j < ((nspis == 1) ? 1 : 2); j++) {
340 fprintf(stdout, "processing %dth said of %dth pfkey message.\n", j, i);
343 /* Build an SADB_X_GRPSA message to send down. */
344 /* It needs <base, SA, SA2, address(D,D2) > minimum. */
346 if((error = pfkey_msg_hdr_build(&extensions[0],
348 proto2satype(said_af_array[i].said.proto),
352 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
353 program_name, error);
354 pfkey_extensions_free(extensions);
359 fprintf(stdout, "setting x_satype proto=%d satype=%d\n",
360 said_af_array[i+j].said.proto,
361 proto2satype(said_af_array[i+j].said.proto)
365 if((error = pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2],
366 proto2satype(said_af_array[i+j].said.proto)
368 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
369 program_name, error);
370 pfkey_extensions_free(extensions);
375 if((error = pfkey_sa_build(&extensions[!j ? SADB_EXT_SA : SADB_X_EXT_SA2],
376 !j ? SADB_EXT_SA : SADB_X_EXT_SA2,
377 said_af_array[i+j].said.spi, /* in network order */
383 fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n",
384 program_name, error);
385 pfkey_extensions_free(extensions);
391 anyaddr(said_af_array[i].af, &pfkey_address_s_ska); /* Is the address family correct ?? */
392 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
393 SADB_EXT_ADDRESS_SRC,
396 sockaddrof(&pfkey_address_s_ska)))) {
397 addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
398 fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n",
399 program_name, ipaddr_txt, error);
400 pfkey_extensions_free(extensions);
405 if((error = pfkey_address_build(&extensions[!j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2],
406 !j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2,
409 sockaddrof(&said_af_array[i+j].said.dst)))) {
410 addrtot(&said_af_array[i+j].said.dst,
411 0, ipaddr_txt, sizeof(ipaddr_txt));
412 fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n",
413 program_name, ipaddr_txt, error);
414 pfkey_extensions_free(extensions);
420 if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
421 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
422 program_name, error);
423 pfkey_extensions_free(extensions);
424 pfkey_msg_free(&pfkey_msg);
428 if((error = write(pfkey_sock,
430 pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) !=
431 pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
432 fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n",
433 program_name, error, errno);
434 pfkey_extensions_free(extensions);
435 pfkey_msg_free(&pfkey_msg);
438 fprintf(stderr, "access denied. ");
440 fprintf(stderr, "Check permissions. Should be 600.\n");
442 fprintf(stderr, "You must be root to open this file.\n");
446 fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
449 fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n");
452 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
455 fprintf(stderr, "KLIPS not loaded or enabled.\n");
456 fprintf(stderr, "No device?!?\n");
459 fprintf(stderr, "No kernel memory to allocate SA.\n");
461 case ESOCKTNOSUPPORT:
462 fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n");
465 fprintf(stderr, "SA already in use. Delete old one first.\n");
468 fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n");
471 fprintf(stderr, "SA does not exist. Cannot delete.\n");
474 fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno);
479 pfkey_extensions_free(extensions);
480 pfkey_msg_free(&pfkey_msg);
484 (void) close(pfkey_sock); /* close the socket */
489 * Revision 1.41 2002/03/08 21:44:05 rgb
490 * Update for all GNU-compliant --version strings.
492 * Revision 1.40 2001/10/02 17:17:17 rgb
493 * Check error return for all "tto*" calls and report errors. This, in
494 * conjuction with the fix to "tto*" will detect AF not set.
496 * Revision 1.39 2001/09/07 22:24:42 rgb
497 * Added EAFNOSUPPORT socket open error code in case KLIPS is not loaded.
499 * Revision 1.38 2001/06/14 19:35:15 rgb
500 * Update copyright date.
502 * Revision 1.37 2001/05/16 05:07:20 rgb
503 * Fixed --label option in KLIPS manual utils to add the label to the
504 * command name rather than replace it in error text.
505 * Fix 'print table' non-option in KLIPS manual utils to deal with --label
506 * and --debug options.
508 * Revision 1.36 2001/01/23 20:24:12 rgb
509 * Fix comment to reflect reality that src is not needed for grouping.
511 * Revision 1.35 2000/09/17 18:56:48 rgb
512 * Added IPCOMP support.
514 * Revision 1.34 2000/09/16 04:56:32 rgb
515 * Added Svenning's ipcomp patch.
517 * Revision 1.33 2000/09/12 22:36:45 rgb
518 * Gerhard's IPv6 support.
520 * Revision 1.32 2000/09/08 19:17:31 rgb
521 * Removed all references to CONFIG_IPSEC_PFKEYv2.
523 * Revision 1.31 2000/08/27 01:46:52 rgb
524 * Update copyright dates and remove no longer used resolve_ip().
526 * Revision 1.30 2000/06/21 16:51:27 rgb
527 * Added no additional argument option to usage text.
529 * Revision 1.29 2000/06/20 22:37:24 rgb
530 * Fixed bug in no-arg invocation that caused a core-dump when it should
531 * have printed out /proc/net/ipsec_spigrp.
532 * Added debug statements.
534 * Revision 1.28 2000/03/16 06:40:50 rgb
535 * Hardcode PF_KEYv2 support.
537 * Revision 1.27 2000/01/25 14:38:52 rgb
538 * Fixed variable declaration bug so it will compile with pfkey off.
540 * Revision 1.26 2000/01/22 23:22:47 rgb
541 * Use new function proto2satype().
543 * Revision 1.25 2000/01/21 09:42:32 rgb
544 * Replace resolve_ip() with atoaddr() from freeswanlib.
546 * Revision 1.24 2000/01/21 06:25:51 rgb
547 * Added pfkeyv2 support to completely avoid netlink.
548 * Added --debug switch to command line.
549 * Added --said processing to command line.
551 * Revision 1.23 1999/12/07 18:30:26 rgb
552 * Added headers to silence fussy compilers.
553 * Converted local functions to static to limit scope.
554 * Removed unused cruft.
555 * Converted main() to prototyped declaration.
557 * Revision 1.22 1999/11/25 09:09:43 rgb
558 * Comment out unused variables.
559 * Clarified assignment in conditional with parens.
561 * Revision 1.21 1999/11/23 23:06:27 rgb
562 * Sort out pfkey and freeswan headers, putting them in a library path.
564 * Revision 1.20 1999/10/16 00:27:14 rgb
567 * Revision 1.19 1999/04/15 15:37:28 rgb
568 * Forward check changes from POST1_00 branch.
570 * Revision 1.15.2.2 1999/04/13 20:58:10 rgb
571 * Add argc==1 --> /proc/net/ipsec_*.
573 * Revision 1.15.2.1 1999/03/30 17:01:36 rgb
574 * Make main() return type explicit.
576 * Revision 1.18 1999/04/11 00:12:09 henry
579 * Revision 1.17 1999/04/06 04:54:39 rgb
580 * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
583 * Revision 1.16 1999/03/17 15:40:54 rgb
584 * Make explicit main() return type of int.
586 * Revision 1.15 1999/01/28 23:20:49 rgb
587 * Replace hard-coded numbers in macros and code with meaningful values
588 * automatically generated from sizeof() and offsetof() to further the
589 * goal of platform independance.
591 * Revision 1.14 1999/01/22 06:36:46 rgb
594 * Revision 1.13 1998/11/12 21:08:04 rgb
595 * Add --label option to identify caller from scripts.
597 * Revision 1.12 1998/10/26 01:28:38 henry
598 * use SA_* protocol names, not IPPROTO_*, to avoid compile problems
600 * Revision 1.11 1998/10/25 02:47:09 rgb
601 * Fix bug in size of stucture passed in from user space for grpspi command.
602 * Added debugging code to find spigrp stucture size mismatch bug.
603 * Convert switch to loop for more efficient coding and redundant code elimination.
605 * Revision 1.10 1998/10/19 18:58:56 rgb
606 * Added inclusion of freeswan.h.
607 * a_id structure implemented and used: now includes protocol.
609 * Revision 1.9 1998/10/09 04:36:32 rgb
610 * Changed help output from stderr to stdout.
611 * Avoid use of argv[0] after first use.
613 * Revision 1.8 1998/08/05 22:24:45 rgb
614 * Change includes to accomodate RH5.x
616 * Revision 1.7 1998/07/29 21:43:17 rgb
617 * Convert to 0x-prefixed spis.
618 * Support dns lookups for hostnames.
620 * Revision 1.6 1998/07/14 18:24:05 rgb
621 * Remove unused skbuff header.
623 * Revision 1.5 1998/07/09 18:14:11 rgb
624 * Added error checking to IP's and keys.
625 * Made most error messages more specific rather than spamming usage text.
626 * Added more descriptive kernel error return codes and messages.
627 * Converted all spi translations to unsigned.
628 * Removed all invocations of perror.
630 * Revision 1.4 1998/06/30 18:04:32 rgb
631 * Fix compiler warning: couldn't find 'struct option' prototype.
633 * Revision 1.3 1998/05/27 18:48:20 rgb
634 * Adding --help and --version directives.
636 * Revision 1.2 1998/05/18 21:14:16 rgb
637 * Modifications to be able to ungroup spi's.
639 * Revision 1.1.1.1 1998/04/08 05:35:09 henry
640 * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
642 * Revision 0.3 1996/11/20 14:51:32 ji
643 * Fixed problems with #include paths.
644 * Changed (incorrect) references to ipsp into ipsec.
646 * Revision 0.2 1996/11/08 15:46:29 ji
647 * First limited release.