2 * IPSEC interface configuration
3 * Copyright (C) 1996 John Ioannidis.
4 * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs.
5 * Copyright (C) 2006 Michael Richardson <mcr@xelerance.com>
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
18 char tncfg_c_version[] = "use ipsec --version instead";
23 #include <stdlib.h> /* system(), strtoul() */
24 #include <unistd.h> /* getuid() */
25 #include <linux/types.h>
26 #include <sys/ioctl.h> /* ioctl() */
29 #ifdef NET_21 /* from openswan.h */
30 #include <linux/sockios.h>
31 #include <sys/socket.h>
32 #endif /* NET_21 */ /* from openswan.h */
39 #include <sys/types.h>
44 #include "socketwrapper.h"
47 #include "openswan/pfkey.h"
48 #include "openswan/pfkeyv2.h"
49 #include "pfkey_help.h"
51 #include "openswan/ipsec_tunnel.h"
58 fprintf(stdout,"%s --create <virtual>\n", name);
59 fprintf(stdout,"%s --delete <virtual>\n", name);
60 fprintf(stdout,"%s --attach --virtual <virtual-device> --physical <physical-device>\n",
62 fprintf(stdout,"%s --detach --virtual <virtual-device>\n",
64 fprintf(stdout,"%s --clear\n",
66 fprintf(stdout,"%s --help\n",
68 fprintf(stdout,"%s --version\n",
70 fprintf(stdout,"%s\n",
72 fprintf(stdout, " [ --debug ] is optional to any %s command.\n", name);
73 fprintf(stdout, " [ --label <label> ] is optional to any %s command.\n", name);
77 static struct option const longopts[] =
79 {"virtual", 1, 0, 'V'},
80 {"physical", 1, 0, 'P'},
81 {"create", required_argument, 0, 'C'},
82 {"delete", required_argument, 0, 'D'},
83 {"attach", 0, 0, 'a'},
84 {"detach", 0, 0, 'd'},
87 {"version", 0, 0, 'v'},
89 {"optionsfrom", 1, 0, '+'},
94 void check_conflict(uint32_t cf_cmd, int createdelete)
96 if(cf_cmd || createdelete) {
97 fprintf(stderr, "%s: exactly one of \n\t'--attach', '--detach', '--create', '--delete' or '--clear'\noptions must be specified.\n",
103 uint32_t pfkey_seq = 0;
105 int createdelete_virtual(int createdelete, char *virtname)
108 struct sadb_ext *extensions[K_SADB_EXT_MAX + 1];
109 struct sadb_msg *pfkey_msg;
111 int io_error, pfkey_sock;
113 if(sscanf(virtname, "mast%d", &vifnum)==1) {
115 } else if(sscanf(virtname, "ipsec%d", &vifnum)==1) {
116 vifnum += IPSECDEV_OFFSET;
121 pfkey_extensions_init(extensions);
123 if((error = pfkey_msg_hdr_build(&extensions[0],
128 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
130 pfkey_extensions_free(extensions);
134 if((error = pfkey_outif_build(&extensions[SADB_X_EXT_PLUMBIF], vifnum))) {
135 fprintf(stderr, "%s: Trouble building outif extension, error=%d.\n",
137 pfkey_extensions_free(extensions);
141 if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
142 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
144 pfkey_extensions_free(extensions);
145 pfkey_msg_free(&pfkey_msg);
149 pfkey_sock = pfkey_open_sock_with_error();
154 io_error = write(pfkey_sock,
156 pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN);
159 if(io_error != (pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) {
160 perror("pfkey write");
167 void exit_tool(int code)
176 main(int argc, char *argv[])
179 struct ipsectunnelconf shc;
183 int createdelete = 0;
187 memset(&ifr, 0, sizeof(ifr));
188 memset(&shc, 0, sizeof(shc));
194 while((c = getopt_long_only(argc, argv, ""/*"adchvV:P:l:+:"*/, longopts, 0)) != EOF) {
201 check_conflict(shc.cf_cmd, createdelete);
202 shc.cf_cmd = IPSEC_SET_DEV;
205 check_conflict(shc.cf_cmd, createdelete);
206 shc.cf_cmd = IPSEC_DEL_DEV;
209 check_conflict(shc.cf_cmd, createdelete);
210 shc.cf_cmd = IPSEC_CLR_DEV;
217 fprintf(stderr, "%s: warning; '-v' and '--version' options don't expect arguments, arg '%s' found, perhaps unintended.\n",
220 fprintf(stdout, "%s, %s\n", progname, tncfg_c_version);
225 check_conflict(shc.cf_cmd, createdelete);
226 createdelete = SADB_X_PLUMBIF;
227 strncat(virtname, optarg, sizeof(virtname)-1);
230 check_conflict(shc.cf_cmd, createdelete);
231 createdelete = SADB_X_UNPLUMBIF;
232 strncat(virtname, optarg, sizeof(virtname)-1);
236 strncpy(ifr.ifr_name, optarg, sizeof(ifr.ifr_name));
239 strncpy(shc.cf_name, optarg, sizeof(shc.cf_name));
242 progname = malloc(strlen(argv[0])
243 + 10 /* update this when changing the sprintf() */
245 sprintf(progname, "%s --label %s",
250 case '+': /* optionsfrom */
251 optionsfrom(optarg, &argc, &argv, optind, stderr);
252 /* no return on error */
260 if ( ((stat ("/proc/net/pfkey", &sts)) == 0) ) {
261 fprintf(stderr, "%s: NETKEY does not support virtual interfaces.\n",progname);
267 if ((stat ("/proc/net/ipsec_tncfg", &sts)) != 0) {
268 fprintf(stderr, "%s: No tncfg - no IPsec support in kernel (are the modules loaded?)\n", progname);
270 ret = system("cat /proc/net/ipsec_tncfg");
271 ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1;
276 /* overlay our struct ipsectunnel onto ifr.ifr_ifru union (hope it fits!) */
277 if (sizeof(ifr.ifr_ifru) < sizeof(shc)) {
278 fprintf(stderr, "%s: Internal error: struct ipsectunnelconf won't fit inside struct ifreq\n",
282 memcpy(&ifr.ifr_ifru.ifru_newname, &shc, sizeof(shc));
284 /* are we creating/deleting a virtual (mastXXX/ipsecXXX) interface? */
286 exit(createdelete_virtual(createdelete, virtname));
291 if(!shc.cf_name[0]) {
292 fprintf(stderr, "%s: physical I/F parameter missing.\n",
297 if(!ifr.ifr_name[0]) {
298 fprintf(stderr, "%s: virtual I/F parameter missing.\n",
304 strncpy(ifr.ifr_name, "ipsec0", sizeof(ifr.ifr_name));
307 fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n"
308 "Try %s --help' for usage information.\n",
313 s=safe_socket(AF_INET, SOCK_DGRAM,0);
316 fprintf(stderr, "%s: Socket creation failed -- ", progname);
321 fprintf(stderr, "Root denied permission!?!\n");
323 fprintf(stderr, "Run as root user.\n");
325 case EPROTONOSUPPORT:
326 fprintf(stderr, "Internet Protocol not enabled");
331 fprintf(stderr, "Insufficient system resources.\n");
334 fprintf(stderr, "No such device. Is the virtual device valid? Is the ipsec module linked into the kernel or loaded as a module?\n");
337 fprintf(stderr, "Unknown socket error %d.\n", errno);
341 if(ioctl(s, shc.cf_cmd, &ifr)==-1)
346 fprintf(stderr, "%s: Socket ioctl failed on attach -- ", progname);
350 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
353 fprintf(stderr, "No such device. Is the virtual device valid? Is the ipsec module linked into the kernel or loaded as a module?\n");
356 fprintf(stderr, "No such device. Is the physical device valid?\n");
359 fprintf(stderr, "Device busy. Virtual device %s is already attached to a physical device -- Use detach first.\n",
363 fprintf(stderr, "Unknown socket error %d.\n", errno);
368 fprintf(stderr, "%s: Socket ioctl failed on detach -- ", progname);
372 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
375 fprintf(stderr, "No such device. Is the virtual device valid? The ipsec module may not be linked into the kernel or loaded as a module.\n");
378 fprintf(stderr, "Device requested is not linked to any physical device.\n");
381 fprintf(stderr, "Unknown socket error %d.\n", errno);
386 fprintf(stderr, "%s: Socket ioctl failed on clear -- ", progname);
390 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
393 fprintf(stderr, "Failed. Is the ipsec module linked into the kernel or loaded as a module?.\n");
396 fprintf(stderr, "Unknown socket error %d.\n", errno);
400 fprintf(stderr, "%s: Socket ioctl failed on unknown operation %u -- %s", progname, (unsigned) shc.cf_cmd, strerror(errno));
409 * Revision 1.33 2005/07/08 02:56:38 paul
410 * gcc4 fixes that were not commited because vault was down
412 * Revision 1.32 2004/04/06 03:05:06 mcr
413 * freeswan->openswan changes.
415 * Revision 1.31 2004/04/04 01:53:50 ken
416 * Use openswan includes
418 * Revision 1.30 2002/04/24 07:55:32 mcr
419 * #include patches and Makefiles for post-reorg compilation.
421 * Revision 1.29 2002/04/24 07:35:41 mcr
422 * Moved from ./klips/utils/tncfg.c,v
424 * Revision 1.28 2002/03/08 21:44:05 rgb
425 * Update for all GNU-compliant --version strings.
427 * Revision 1.27 2001/06/14 19:35:15 rgb
428 * Update copyright date.
430 * Revision 1.26 2001/05/21 02:02:55 rgb
431 * Eliminate 1-letter options.
433 * Revision 1.25 2001/05/16 05:07:20 rgb
434 * Fixed --label option in KLIPS manual utils to add the label to the
435 * command name rather than replace it in error text.
436 * Fix 'print table' non-option in KLIPS manual utils to deal with --label
437 * and --debug options.
439 * Revision 1.24 2000/09/12 13:09:05 rgb
440 * Fixed real/physical discrepancy between tncfg.8 and tncfg.c.
442 * Revision 1.23 2000/08/27 01:48:30 rgb
445 * Revision 1.22 2000/07/26 03:41:46 rgb
446 * Changed all printf's to fprintf's. Fixed tncfg's usage to stderr.
448 * Revision 1.21 2000/06/21 16:51:27 rgb
449 * Added no additional argument option to usage text.
451 * Revision 1.20 2000/01/21 06:26:31 rgb
452 * Added --debug switch to command line.
454 * Revision 1.19 1999/12/08 20:32:41 rgb
455 * Cleaned out unused cruft.
456 * Changed include file, limiting scope, to avoid conflicts in 2.0.xx
459 * Revision 1.18 1999/12/07 18:27:10 rgb
460 * Added headers to silence fussy compilers.
461 * Converted local functions to static to limit scope.
463 * Revision 1.17 1999/11/18 04:09:21 rgb
464 * Replaced all kernel version macros to shorter, readable form.
466 * Revision 1.16 1999/05/25 01:45:36 rgb
467 * Fix version macros for 2.0.x as a module.
469 * Revision 1.15 1999/05/05 22:02:34 rgb
470 * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
472 * Revision 1.14 1999/04/15 15:37:28 rgb
473 * Forward check changes from POST1_00 branch.
475 * Revision 1.10.6.2 1999/04/13 20:58:10 rgb
476 * Add argc==1 --> /proc/net/ipsec_*.
478 * Revision 1.10.6.1 1999/03/30 17:01:36 rgb
479 * Make main() return type explicit.
481 * Revision 1.13 1999/04/11 00:12:09 henry
484 * Revision 1.12 1999/04/06 04:54:39 rgb
485 * Fix/Add RCSID Id: and Log: bits to make PHMDs happy. This includes
488 * Revision 1.11 1999/03/17 15:40:54 rgb
489 * Make explicit main() return type of int.
491 * Revision 1.10 1998/11/12 21:08:04 rgb
492 * Add --label option to identify caller from scripts.
494 * Revision 1.9 1998/10/09 18:47:30 rgb
495 * Add 'optionfrom' to get more options from a named file.
497 * Revision 1.8 1998/10/09 04:36:55 rgb
498 * Changed help output from stderr to stdout.
499 * Deleted old commented out cruft.
501 * Revision 1.7 1998/08/28 03:15:14 rgb
502 * Add some manual long options to the usage text.
504 * Revision 1.6 1998/08/05 22:29:00 rgb
505 * Change includes to accomodate RH5.x.
506 * Force long option names.
507 * Add ENXIO error return code to narrow down error reporting.
509 * Revision 1.5 1998/07/29 21:45:28 rgb
510 * Convert to long option names.
512 * Revision 1.4 1998/07/09 18:14:11 rgb
513 * Added error checking to IP's and keys.
514 * Made most error messages more specific rather than spamming usage text.
515 * Added more descriptive kernel error return codes and messages.
516 * Converted all spi translations to unsigned.
517 * Removed all invocations of perror.
519 * Revision 1.3 1998/05/27 18:48:20 rgb
520 * Adding --help and --version directives.
522 * Revision 1.2 1998/04/23 21:11:39 rgb
523 * Fixed 0 argument usage case to prevent sigsegv.
525 * Revision 1.1.1.1 1998/04/08 05:35:09 henry
526 * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
528 * Revision 0.5 1997/06/03 04:31:55 ji