OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / utils / tncfg.c
1 /*
2  * IPSEC interface configuration
3  * Copyright (C) 1996  John Ioannidis.
4  * Copyright (C) 1998, 1999, 2000, 2001  Richard Guy Briggs.
5  * 
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>.
10  * 
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
14  * for more details.
15  */
16
17 char tncfg_c_version[] = "RCSID $Id: tncfg.c,v 1.28 2002/03/08 21:44:05 rgb Exp $";
18
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h> /* system(), strtoul() */
23 #include <unistd.h> /* getuid() */
24 #include <linux/types.h>
25 #include <sys/ioctl.h> /* ioctl() */
26
27 #include <freeswan.h>
28 #ifdef NET_21 /* from freeswan.h */
29 #include <linux/sockios.h>
30 #include <sys/socket.h>
31 #endif /* NET_21 */ /* from freeswan.h */
32
33 #if 0
34 #include <linux/if.h>
35 #else
36 #include <net/if.h>
37 #endif
38 #include <sys/types.h>
39 #include <errno.h>
40 #include <getopt.h>
41 #include "ipsec_tunnel.h"
42
43 static void
44 usage(char *name)
45 {       
46         fprintf(stdout,"%s --attach --virtual <virtual-device> --physical <physical-device>\n",
47                 name);
48         fprintf(stdout,"%s --detach --virtual <virtual-device>\n",
49                 name);
50         fprintf(stdout,"%s --clear\n",
51                 name);
52         fprintf(stdout,"%s --help\n",
53                 name);
54         fprintf(stdout,"%s --version\n",
55                 name);
56         fprintf(stdout,"%s\n",
57                 name);
58         fprintf(stdout, "        [ --debug ] is optional to any %s command.\n", name);
59         fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", name);
60         exit(1);
61 }
62
63 static struct option const longopts[] =
64 {
65         {"virtual", 1, 0, 'V'},
66         {"physical", 1, 0, 'P'},
67         {"attach", 0, 0, 'a'},
68         {"detach", 0, 0, 'd'},
69         {"clear", 0, 0, 'c'},
70         {"help", 0, 0, 'h'},
71         {"version", 0, 0, 'v'},
72         {"label", 1, 0, 'l'},
73         {"optionsfrom", 1, 0, '+'},
74         {"debug", 0, 0, 'g'},
75         {0, 0, 0, 0}
76 };
77
78 int
79 main(int argc, char *argv[])
80 {
81         struct ifreq ifr;
82         struct ipsectunnelconf *shc=(struct ipsectunnelconf *)&ifr.ifr_data;
83         int s;
84         int c, previous = -1;
85         char *program_name;
86         int debug = 0;
87         int argcount = argc;
88         char me[] = "ipsec tncfg";
89      
90         memset(&ifr, 0, sizeof(ifr));
91         program_name = argv[0];
92
93         while((c = getopt_long_only(argc, argv, ""/*"adchvV:P:l:+:"*/, longopts, 0)) != EOF) {
94                 switch(c) {
95                 case 'g':
96                         debug = 1;
97                         argcount--;
98                         break;
99                 case 'a':
100                         if(shc->cf_cmd) {
101                                 fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",  program_name);
102                                 exit(1);
103                         }
104                         shc->cf_cmd = IPSEC_SET_DEV;
105                         break;
106                 case 'd':
107                         if(shc->cf_cmd) {
108                                 fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",  program_name);
109                                 exit(1);
110                         }
111                         shc->cf_cmd = IPSEC_DEL_DEV;
112                         break;
113                 case 'c':
114                         if(shc->cf_cmd) {
115                                 fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n",  program_name);
116                                 exit(1);
117                         }
118                         shc->cf_cmd = IPSEC_CLR_DEV;
119                         break;
120                 case 'h':
121                         usage(program_name);
122                         break;
123                 case 'v':
124                         if(optarg) {
125                                 fprintf(stderr, "%s: warning; '-v' and '--version' options don't expect arguments, arg '%s' found, perhaps unintended.\n",
126                                         program_name, optarg);
127                         }
128                         fprintf(stdout, "%s %s\n", me, ipsec_version_code());
129                         fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
130                         exit(1);
131                         break;
132                 case 'V':
133                         strcpy(ifr.ifr_name, optarg);
134                         break;
135                 case 'P':
136                         strcpy(shc->cf_name, optarg);
137                         break;
138                 case 'l':
139                         program_name = malloc(strlen(argv[0])
140                                               + 10 /* update this when changing the sprintf() */
141                                               + strlen(optarg));
142                         sprintf(program_name, "%s --label %s",
143                                 argv[0],
144                                 optarg);
145                         argcount -= 2;
146                         break;
147                 case '+': /* optionsfrom */
148                         optionsfrom(optarg, &argc, &argv, optind, stderr);
149                         /* no return on error */
150                         break;
151                 default:
152                         usage(program_name);
153                         break;
154                 }
155                 previous = c;
156         }
157
158         if(argcount == 1) {
159                 system("cat /proc/net/ipsec_tncfg");
160                 exit(0);
161         }
162
163         switch(shc->cf_cmd) {
164         case IPSEC_SET_DEV:
165                 if(!shc->cf_name) {
166                         fprintf(stderr, "%s: physical I/F parameter missing.\n",
167                                 program_name);
168                         exit(1);
169                 }
170         case IPSEC_DEL_DEV:
171                 if(!ifr.ifr_name) {
172                         fprintf(stderr, "%s: virtual I/F parameter missing.\n",
173                                 program_name);
174                         exit(1);
175                 }
176                 break;
177         case IPSEC_CLR_DEV:
178                 strcpy(ifr.ifr_name, "ipsec0");
179                 break;
180         default:
181                 fprintf(stderr, "%s: exactly one of '--attach', '--detach' or '--clear' options must be specified.\n"
182                         "Try %s --help' for usage information.\n",
183                         program_name, program_name);
184                 exit(1);
185         }
186
187         s=socket(AF_INET, SOCK_DGRAM,0);
188         if(s==-1)
189         {
190                 fprintf(stderr, "%s: Socket creation failed -- ", program_name);
191                 switch(errno)
192                 {
193                 case EACCES:
194                         if(getuid()==0)
195                                 fprintf(stderr, "Root denied permission!?!\n");
196                         else
197                                 fprintf(stderr, "Run as root user.\n");
198                         break;
199                 case EPROTONOSUPPORT:
200                         fprintf(stderr, "Internet Protocol not enabled");
201                         break;
202                 case EMFILE:
203                 case ENFILE:
204                 case ENOBUFS:
205                         fprintf(stderr, "Insufficient system resources.\n");
206                         break;
207                 case ENODEV:
208                         fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
209                         break;
210                 default:
211                         fprintf(stderr, "Unknown socket error %d.\n", errno);
212                 }
213                 exit(1);
214         }
215         if(ioctl(s, shc->cf_cmd, &ifr)==-1)
216         {
217                 if(shc->cf_cmd == IPSEC_SET_DEV) {
218                         fprintf(stderr, "%s: Socket ioctl failed on attach -- ", program_name);
219                         switch(errno)
220                         {
221                         case EINVAL:
222                                 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
223                                 break;
224                         case ENODEV:
225                                 fprintf(stderr, "No such device.  Is the virtual device valid?  Is the ipsec module linked into the kernel or loaded as a module?\n");
226                                 break;
227                         case ENXIO:
228                                 fprintf(stderr, "No such device.  Is the physical device valid?\n");
229                                 break;
230                         case EBUSY:
231                                 fprintf(stderr, "Device busy.  Virtual device %s is already attached to a physical device -- Use detach first.\n",
232                                        ifr.ifr_name);
233                                 break;
234                         default:
235                                 fprintf(stderr, "Unknown socket error %d.\n", errno);
236                         }
237                         exit(1);
238                 }
239                 if(shc->cf_cmd == IPSEC_DEL_DEV) {
240                         fprintf(stderr, "%s: Socket ioctl failed on detach -- ", program_name);
241                         switch(errno)
242                         {
243                         case EINVAL:
244                                 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
245                                 break;
246                         case ENODEV:
247                                 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");
248                                 break;
249                         case ENXIO:
250                                 fprintf(stderr, "Device requested is not linked to any physical device.\n");
251                                 break;
252                         default:
253                                 fprintf(stderr, "Unknown socket error %d.\n", errno);
254                         }
255                         exit(1);
256                 }
257                 if(shc->cf_cmd == IPSEC_CLR_DEV) {
258                         fprintf(stderr, "%s: Socket ioctl failed on clear -- ", program_name);
259                         switch(errno)
260                         {
261                         case EINVAL:
262                                 fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
263                                 break;
264                         case ENODEV:
265                                 fprintf(stderr, "Failed.  Is the ipsec module linked into the kernel or loaded as a module?.\n");
266                                 break;
267                         default:
268                                 fprintf(stderr, "Unknown socket error %d.\n", errno);
269                         }
270                         exit(1);
271                 }
272         }
273         exit(0);
274 }
275         
276 /*
277  * $Log: tncfg.c,v $
278  * Revision 1.28  2002/03/08 21:44:05  rgb
279  * Update for all GNU-compliant --version strings.
280  *
281  * Revision 1.27  2001/06/14 19:35:15  rgb
282  * Update copyright date.
283  *
284  * Revision 1.26  2001/05/21 02:02:55  rgb
285  * Eliminate 1-letter options.
286  *
287  * Revision 1.25  2001/05/16 05:07:20  rgb
288  * Fixed --label option in KLIPS manual utils to add the label to the
289  * command name rather than replace it in error text.
290  * Fix 'print table' non-option in KLIPS manual utils to deal with --label
291  * and --debug options.
292  *
293  * Revision 1.24  2000/09/12 13:09:05  rgb
294  * Fixed real/physical discrepancy between tncfg.8 and tncfg.c.
295  *
296  * Revision 1.23  2000/08/27 01:48:30  rgb
297  * Update copyright.
298  *
299  * Revision 1.22  2000/07/26 03:41:46  rgb
300  * Changed all printf's to fprintf's.  Fixed tncfg's usage to stderr.
301  *
302  * Revision 1.21  2000/06/21 16:51:27  rgb
303  * Added no additional argument option to usage text.
304  *
305  * Revision 1.20  2000/01/21 06:26:31  rgb
306  * Added --debug switch to command line.
307  *
308  * Revision 1.19  1999/12/08 20:32:41  rgb
309  * Cleaned out unused cruft.
310  * Changed include file, limiting scope, to avoid conflicts in 2.0.xx
311  * kernels.
312  *
313  * Revision 1.18  1999/12/07 18:27:10  rgb
314  * Added headers to silence fussy compilers.
315  * Converted local functions to static to limit scope.
316  *
317  * Revision 1.17  1999/11/18 04:09:21  rgb
318  * Replaced all kernel version macros to shorter, readable form.
319  *
320  * Revision 1.16  1999/05/25 01:45:36  rgb
321  * Fix version macros for 2.0.x as a module.
322  *
323  * Revision 1.15  1999/05/05 22:02:34  rgb
324  * Add a quick and dirty port to 2.2 kernels by Marc Boucher <marc@mbsi.ca>.
325  *
326  * Revision 1.14  1999/04/15 15:37:28  rgb
327  * Forward check changes from POST1_00 branch.
328  *
329  * Revision 1.10.6.2  1999/04/13 20:58:10  rgb
330  * Add argc==1 --> /proc/net/ipsec_*.
331  *
332  * Revision 1.10.6.1  1999/03/30 17:01:36  rgb
333  * Make main() return type explicit.
334  *
335  * Revision 1.13  1999/04/11 00:12:09  henry
336  * GPL boilerplate
337  *
338  * Revision 1.12  1999/04/06 04:54:39  rgb
339  * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
340  * patch shell fixes.
341  *
342  * Revision 1.11  1999/03/17 15:40:54  rgb
343  * Make explicit main() return type of int.
344  *
345  * Revision 1.10  1998/11/12 21:08:04  rgb
346  * Add --label option to identify caller from scripts.
347  *
348  * Revision 1.9  1998/10/09 18:47:30  rgb
349  * Add 'optionfrom' to get more options from a named file.
350  *
351  * Revision 1.8  1998/10/09 04:36:55  rgb
352  * Changed help output from stderr to stdout.
353  * Deleted old commented out cruft.
354  *
355  * Revision 1.7  1998/08/28 03:15:14  rgb
356  * Add some manual long options to the usage text.
357  *
358  * Revision 1.6  1998/08/05 22:29:00  rgb
359  * Change includes to accomodate RH5.x.
360  * Force long option names.
361  * Add ENXIO error return code to narrow down error reporting.
362  *
363  * Revision 1.5  1998/07/29 21:45:28  rgb
364  * Convert to long option names.
365  *
366  * Revision 1.4  1998/07/09 18:14:11  rgb
367  * Added error checking to IP's and keys.
368  * Made most error messages more specific rather than spamming usage text.
369  * Added more descriptive kernel error return codes and messages.
370  * Converted all spi translations to unsigned.
371  * Removed all invocations of perror.
372  *
373  * Revision 1.3  1998/05/27 18:48:20  rgb
374  * Adding --help and --version directives.
375  *
376  * Revision 1.2  1998/04/23 21:11:39  rgb
377  * Fixed 0 argument usage case to prevent sigsegv.
378  *
379  * Revision 1.1.1.1  1998/04/08 05:35:09  henry
380  * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
381  *
382  * Revision 0.5  1997/06/03 04:31:55  ji
383  * New file.
384  *
385  */