OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / utils / spi.c
1 /*
2  * All-in-one program to set Security Association parameters
3  * Copyright (C) 1996  John Ioannidis.
4  * Copyright (C) 1997, 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 spi_c_version[] = "RCSID $Id: spi.c,v 1.84 2002/03/08 21:44:04 rgb Exp $";
18
19 #include <asm/types.h>
20 #include <sys/types.h>
21 #include <sys/ioctl.h>
22 /* #include <linux/netdevice.h> */
23 #include <net/if.h>
24 /* #include <linux/types.h> */ /* new */
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <string.h>
28 #include <errno.h>
29
30 /* #include <sys/socket.h> */
31
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 /* #include <linux/ip.h> */
35 #include <netdb.h>
36
37 #include <unistd.h>
38 #include <getopt.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <freeswan.h>
43 #include <signal.h>
44 #include <sys/socket.h>
45 #include <pfkeyv2.h>
46 #include <pfkey.h>
47 #include "ipsec_xform.h"
48
49 /*      
50  *      Manual conn support for ipsec_alg (modular algos).
51  *      Rather ugly to include from pluto dir but avoids
52  *      code duplication.
53  */
54 #ifndef NO_KERNEL_ALG
55 #include "../../pluto/alg_info.h"
56 #include "../../pluto/constants.h"
57 struct connection;
58 #include "../../pluto/kernel_alg.h"
59 #endif /* NO_KERNEL_ALG */
60
61 char *program_name;
62 char me[] = "ipsec spi";
63 int debug = 0;
64 char *command;
65 extern char *optarg;
66 extern int optind, opterr, optopt;
67 char scratch[2];
68 char *iv = NULL, *enckey = NULL, *authkey = NULL;
69 size_t ivlen = 0, enckeylen = 0, authkeylen = 0;
70 ip_address edst, dst, src;
71 int address_family = 0;
72 unsigned char proto = 0;
73 int alg = 0;
74
75 #ifndef NO_KERNEL_ALG
76 /* 
77  *      Manual connection support for modular algos (ipsec_alg) --Juanjo.
78  */
79 #define XF_OTHER_ALG (XF_CLR-1) /* define magic XF_ symbol for alg_info's */
80 #include <assert.h>
81 const char *alg_string = NULL;  /* algorithm string */
82 struct alg_info_esp *alg_info = NULL;   /* algorithm info got from string */
83 struct esp_info *esp_info = NULL;       /* esp info from 1st (only) element */
84 const char *alg_err;            /* auxiliar for parsing errors */
85 int proc_read_ok = 0;           /* /proc/net/pf_key_support read ok */
86 #endif /* NO_KERNEL_ALG */
87
88 int replay_window = 0;
89 char sa[SATOT_BUF];
90
91 extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */
92 int pfkey_sock;
93 fd_set pfkey_socks;
94 uint32_t pfkey_seq = 0;
95 enum life_severity {
96         life_soft = 0,
97         life_hard = 1,
98         life_maxsever = 2
99 };
100 enum life_type {
101         life_alloc = 0,
102         life_bytes = 1,
103         life_addtime = 2,
104         life_usetime = 3,
105         life_packets = 4,
106         life_maxtype = 5
107 };
108
109 #define streql(_a,_b) (!strcmp((_a),(_b)))
110
111 static const char *usage_string = "\
112 Usage:\n\
113         in the following, <SA> is: --af <inet | inet6> --edst <dstaddr> --spi <spi> --proto <proto>\n\
114                                OR: --said <proto><.|:><spi>@<dstaddr>\n\
115                           <life> is: --life <soft|hard>-<allocations|bytes|addtime|usetime|packets>=<value>[,...]\n\
116 spi --clear\n\
117 spi --help\n\
118 spi --version\n\
119 spi\n\
120 spi --del <SA>\n\
121 spi --ip4 <SA> --src <encap-src> --dst <encap-dst>\n\
122 spi --ip6 <SA> --src <encap-src> --dst <encap-dst>\n\
123 spi --ah <algo> <SA> [<life> ][ --replay_window <replay_window> ] --authkey <key>\n\
124         where <algo> is one of: hmac-md5-96 | hmac-sha1-96\n\
125 spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey> --authkey <akey>\n\
126         where <algo> is one of: des-md5-96 | des-sha1-96 | 3des-md5-96 | 3des-sha1-96\n\
127 spi --esp <algo> <SA> [<life> ][ --replay_window <replay-window> ] --enckey <ekey>\n\
128         where <algo> is:        des | 3des\n\
129 spi --comp <algo> <SA>\n\
130         where <algo> is:        deflate | lzs\n\
131 [ --debug ] is optional to any spi command.\n\
132 [ --label <label> ] is optional to any spi command.\n\
133 ";
134
135
136 static void
137 usage(char *s, FILE *f)
138 {
139         /* s argument is actually ignored, at present */
140         fprintf(f, "%s:%s", s, usage_string);
141         exit(-1);
142 }
143
144
145 #ifdef SIGS_FROM_BELOW
146 static void
147 pfkey_sig_handler(int x)
148 {
149         int len;
150         int error = 0;
151 #if 0
152         int i;
153         fd_set l_pfkey_socks;
154 #endif
155         unsigned char buffer[PFKEYv2_MAX_MSGSIZE];
156         struct sadb_ext *extensions_parse[SADB_EXT_MAX + 1];
157         struct sadb_msg *pfkey_msg;
158         
159         /* if(signal.type == SIGIO) } */
160         while(1) {
161 #if 0
162                 memcpy(&l_pfkey_socks, &pfkey_socks, sizeof(pfkey_socks));
163                 
164                 fprintf(stdout, "%s:pfkey_sig_handler: "
165                         "entering select for pfkey_sock=%d.\n",
166                         program_name,
167                         pfkey_sock);
168                 if((i = select(pfkey_sock + 1, &l_pfkey_socks, NULL, NULL, NULL)) < 0) {
169                         fprintf(stderr, "%s:system error:pfkey_sig_handler: "
170                                 "select returned errno:%d.\n",
171                                 program_name,
172                                 errno);
173                         break;
174                 }
175                 if(!i) {
176                         fprintf(stdout, "%s:pfkey_sig_handler: "
177                                 "select returned %d.\n",
178                                 program_name,
179                                 i);
180                         return;
181                 }
182
183                 ret = recvmsg(pfkey_sock,
184                               /* struct msghdr * */msg,
185                               /* unsigned int */flags);
186                 if(ret == -1) {
187                         fprintf(stderr, "%s: pfkey recvmsg failed.\n",
188                                 program_name);
189                         switch(errno) {
190                         case EBADF:
191                         case ENOTCONN:
192                         case ENOTSOCK:
193                         case EWOULDBLOCK:
194                         case EINTR:
195                         case EFAULT:
196                                 fprintf(stderr, "system error:%d\n",
197                                         errno);
198                                 exit(1);
199                         default:
200                                 fprintf(stderr, "unknown error:%d\n",
201                                         errno);
202                                 exit(1);
203                         }
204                 }
205 #endif
206                 fprintf(stdout, "%s:pfkey_sig_handler: "
207                         "entering read for pfkey_sock=%d.\n",
208                         program_name,
209                         pfkey_sock);
210                 if((len = read(pfkey_sock, buffer, sizeof(buffer))) < 0) {
211                         fprintf(stderr, "%s: pfkey read failed.\n",
212                                 program_name);
213                         switch(errno) {
214                         case EBADF:
215                         case ENOTCONN:
216                         case ENOTSOCK:
217                         case EWOULDBLOCK:
218                         case EINTR:
219                         case EFAULT:
220                                 fprintf(stderr, "%s:system error:%d\n",
221                                         program_name,
222                                         errno);
223                                 exit(1);
224                         default:
225                                 fprintf(stderr, "%s:unknown error:%d\n",
226                                         program_name,
227                                         errno);
228                                 exit(1);
229                         }
230                         break;
231                 }
232                 
233                 if(len < sizeof(struct sadb_msg)) {
234                         fprintf(stderr, "%s:system error:pfkey_sig_handler: "
235                                 "read returned only %d octets of a minimum of %d octets for the message header.\n",
236                                 program_name,
237                                 len, sizeof(struct sadb_msg));
238                         break;
239                 }
240                 
241                 fprintf(stdout, "%s:pfkey_sig_handler: "
242                         "read %d octets from pfkey_sock=%d.\n",
243                         program_name,
244                         len, pfkey_sock);
245                 
246                 pfkey_msg = (struct sadb_msg*)buffer;
247
248                 if(pfkey_msg->sadb_msg_version != PF_KEY_V2) {
249                         fprintf(stderr, "system error:pfkey_sig_handler: not PF_KEY_V2 msg.\n");
250                         break;
251                 }
252                 
253                 if(len != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
254                         fprintf(stderr, "system error:pfkey_sig_handler: bogus msg len of %d, not %d byte aligned.\n",
255                                 len, IPSEC_PFKEYv2_ALIGN);
256                         break;
257                 }
258                 
259                 /* XXX when this becomes a lib, keying daemons must be able to receive errors */
260                 if(pfkey_msg->sadb_msg_errno) {
261                         fprintf(stderr, "system error:pfkey_sig_handler: errno set to %d.\n",
262                                 pfkey_msg->sadb_msg_errno);
263                         break;
264                 }
265                 
266                 /* check PID */
267                 if(pfkey_msg->sadb_msg_pid != getpid()) {
268                         fprintf(stderr, "system error:pfkey_sig_handler: pid (%d) does not equal originating process pid (%d).\n",
269                                 pfkey_msg->sadb_msg_pid, getpid());
270                         break;
271                 }
272                 
273                 if(pfkey_msg->sadb_msg_seq != pfkey_seq) {
274                         fprintf(stderr, "system error:pfkey_sig_handler: seq (%d) does not equal original message seq (%d).\n",
275                                 pfkey_msg->sadb_msg_seq, pfkey_seq);
276                         break;
277                 }
278                 
279                 if(pfkey_msg->sadb_msg_reserved) {
280                         fprintf(stderr, "system error:pfkey_sig_handler: reserved field must be zero, set to %d.\n",
281                                 pfkey_msg->sadb_msg_reserved);
282                         break;
283                 }
284                 
285                 if((pfkey_msg->sadb_msg_type > SADB_MAX) || (!pfkey_msg->sadb_msg_type)){
286                         fprintf(stderr, "system error:pfkey_sig_handler: msg type too large or small:%d.\n",
287                                 pfkey_msg->sadb_msg_type);
288                         break;
289                 }
290                 
291                 if((error = pfkey_msg_parse(pfkey_msg, NULL, extensions_parse, EXT_BITS_OUT))) {
292                         fprintf(stderr, "system error:pfkey_sig_handler: pfkey_msg_parse returns %d.\n",
293                                 error);
294                 } else {
295                         fprintf(stdout, "%s:pfkey_sig_handler: return (msg would normally be sent for parsing).\n",
296                                 program_name);
297                 }
298                 break;
299         }
300         return;
301 }
302 #endif /* SIGS_FROM_BELOW */
303
304 int
305 parse_life_options(uint32_t life[life_maxsever][life_maxtype],
306                    char *life_opt[life_maxsever][life_maxtype],
307                    char *optarg)
308 {
309         char *optargp = optarg;
310         char *endptr;
311         
312         do {
313                 int life_severity, life_type;
314                 char *optargt = optargp;
315                 
316                 if(strncmp(optargp, "soft", sizeof("soft")-1) == 0) {
317                         life_severity = life_soft;
318                         optargp += sizeof("soft")-1;
319                 } else if(strncmp(optargp, "hard", sizeof("hard")-1) == 0) {
320                         life_severity = life_hard;
321                         optargp += sizeof("hard")-1;
322                 } else {
323                         fprintf(stderr, "%s: missing lifetime severity in %s, optargt=%p, optargp=%p, sizeof(\"soft\")=%d\n",
324                                 program_name, optargt, optargt, optargp, sizeof("soft"));
325                         usage(program_name, stderr);
326                         return(1);
327                 }
328                 if(debug) {
329                         fprintf(stdout, "%s: debug: life_severity=%d, optargt=%p=\"%s\", optargp=%p=\"%s\", sizeof(\"soft\")=%d\n",
330                                 program_name, life_severity, optargt, optargt, optargp, optargp, sizeof("soft"));
331                 }
332                 if(*(optargp++) != '-') {
333                         fprintf(stderr, "%s: expected '-' after severity of lifetime parameter to --life option.\n",
334                                 program_name);
335                         usage(program_name, stderr);
336                         return(1);
337                 }
338                 if(debug) {
339                         fprintf(stdout, "%s: debug: optargt=%p=\"%s\", optargp=%p=\"%s\", strlen(optargt)=%d, strlen(optargp)=%d, strncmp(optargp, \"addtime\", sizeof(\"addtime\")-1)=%d\n",
340                                 program_name, optargt, optargt, optargp, optargp, strlen(optargt), strlen(optargp), strncmp(optargp, "addtime", sizeof("addtime")-1));
341                 }
342                 if(strncmp(optargp, "allocations", sizeof("allocations")-1) == 0) {
343                         life_type = life_alloc;
344                         optargp += sizeof("allocations")-1;
345                 } else if(strncmp(optargp, "bytes", sizeof("bytes")-1) == 0) {
346                         life_type = life_bytes;
347                         optargp += sizeof("bytes")-1;
348                 } else if(strncmp(optargp, "addtime", sizeof("addtime")-1) == 0) {
349                         life_type = life_addtime;
350                         optargp += sizeof("addtime")-1;
351                 } else if(strncmp(optargp, "usetime", sizeof("usetime")-1) == 0) {
352                         life_type = life_usetime;
353                         optargp += sizeof("usetime")-1;
354                 } else if(strncmp(optargp, "packets", sizeof("packets")-1) == 0) {
355                         life_type = life_packets;
356                         optargp += sizeof("packets")-1;
357                 } else {
358                         fprintf(stderr, "%s: missing lifetime type after '-' in %s\n",
359                                 program_name, optargt);
360                         usage(program_name, stderr);
361                         return(1);
362                 }
363                 if(debug) {
364                         fprintf(stdout, "%s: debug: life_type=%d\n",
365                                 program_name, life_type);
366                 }
367                 if(life_opt[life_severity][life_type] != NULL) {
368                         fprintf(stderr, "%s: Error, lifetime parameter redefined:%s, already defined as:%p\n",
369                                 program_name, optargt, life_opt[life_severity][life_type]);
370                         return(1);
371                 }
372                 if(*(optargp++) != '=') {
373                         fprintf(stderr, "%s: expected '=' after type of lifetime parameter to --life option.\n",
374                                 program_name);
375                         usage(program_name, stderr);
376                         return(1);
377                 }
378                 if(debug) {
379                         fprintf(stdout, "%s: debug: optargt=%p, optargt+strlen(optargt)=%p, optargp=%p, strlen(optargp)=%d\n",
380                                 program_name, optargt, optargt+strlen(optargt), optargp, strlen(optargp));
381                 }
382                 if(strlen(optargp) == 0) {
383                         fprintf(stderr, "%s: expected value after '=' in --life option. optargt=%p, optargt+strlen(optargt)=%p, optargp=%p\n",
384                                 program_name, optargt, optargt+strlen(optargt), optargp);
385                         usage(program_name, stderr);
386                         return(1);
387                 }
388                 life[life_severity][life_type] = strtoul(optargp, &endptr, 0);
389
390                 if(!((endptr == optargp + strlen(optargp)) || (endptr == optargp + strcspn(optargp, ", ")))) {
391                         fprintf(stderr, "%s: Invalid character='%c' at offset %d in lifetime option parameter: '%s', parameter string is %d characters long, %d valid value characters found.\n",
392                                 program_name,
393                                 *endptr, endptr - optarg, optarg, strlen(optarg), strcspn(optargp, ", ") - 1);
394                         return(1);
395                 }
396                 life_opt[life_severity][life_type] = optargt;
397                 if(debug) {
398                         fprintf(stdout, "%s lifetime %s set to %d.\n",
399                                 program_name, optargt, life[life_severity][life_type]);
400                 }
401                 optargp=endptr+1;
402         } while(*endptr==',' || isspace(*endptr));
403         
404         return(0);
405 }
406
407 int
408 pfkey_register(uint8_t satype) {
409         /* for registering SA types that can be negotiated */
410         int error = 0;
411         struct sadb_ext *extensions[SADB_EXT_MAX + 1];
412         struct sadb_msg *pfkey_msg;
413
414         pfkey_extensions_init(extensions);
415         if((error = pfkey_msg_hdr_build(&extensions[0],
416                                         SADB_REGISTER,
417                                         satype,
418                                         0,
419                                         ++pfkey_seq,
420                                         getpid()))) {
421                 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
422                         program_name, error);
423                 pfkey_extensions_free(extensions);
424                 return(1);
425         }
426         if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
427                 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
428                         program_name, error);
429                 pfkey_extensions_free(extensions);
430                 pfkey_msg_free(&pfkey_msg);
431                 return(1);
432         }
433         if(write(pfkey_sock, pfkey_msg,
434                  pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) !=
435            pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
436                 /* cleanup code here */
437                 fprintf(stderr, "%s: Trouble writing to channel PF_KEY.\n", program_name);
438                 pfkey_extensions_free(extensions);
439                 pfkey_msg_free(&pfkey_msg);
440                 return(1);
441         }
442         pfkey_extensions_free(extensions);
443         pfkey_msg_free(&pfkey_msg);
444         
445         return(0);
446 }
447
448 static struct option const longopts[] =
449 {
450         {"ah", 1, 0, 'H'},
451         {"esp", 1, 0, 'P'},
452         {"comp", 1, 0, 'Z'},
453         {"ip4", 0, 0, '4'},
454         {"ip6", 0, 0, '6'},
455         {"del", 0, 0, 'd'},
456
457         {"authkey", 1, 0, 'A'},
458         {"enckey", 1, 0, 'E'},
459         {"edst", 1, 0, 'e'},
460         {"spi", 1, 0, 's'},
461         {"proto", 1, 0, 'p'},
462         {"af", 1, 0, 'a'},
463         {"replay_window", 1, 0, 'w'},
464         {"iv", 1, 0, 'i'},
465         {"dst", 1, 0, 'D'},
466         {"src", 1, 0, 'S'},
467         {"said", 1, 0, 'I'},
468
469         {"help", 0, 0, 'h'},
470         {"version", 0, 0, 'v'},
471         {"clear", 0, 0, 'c'},
472         {"label", 1, 0, 'l'},
473         {"debug", 0, 0, 'g'},
474         {"optionsfrom", 1, 0, '+'},
475         {"life", 1, 0, 'f'},
476         {0, 0, 0, 0}
477 };
478
479 int
480 main(int argc, char *argv[])
481 {
482         char *endptr;
483         __u32 spi = 0;
484         int c, previous = -1;
485 /*      int ret; */
486         ip_said said;
487         size_t sa_len;
488         const char* error_s;
489         char ipaddr_txt[ADDRTOT_BUF];
490         char ipsaid_txt[SATOT_BUF];
491
492         int error = 0;
493         int argcount = argc;
494
495         unsigned char authalg, encryptalg;
496         struct sadb_ext *extensions[SADB_EXT_MAX + 1];
497         struct sadb_msg *pfkey_msg;
498         char *iv_opt, *akey_opt, *ekey_opt, *alg_opt, *edst_opt, *spi_opt, *proto_opt, *af_opt, *said_opt, *dst_opt, *src_opt;
499 #if 0
500         ip_address pfkey_address_p_ska;
501         ip_address pfkey_ident_s_ska;
502         ip_address pfkey_ident_d_ska;
503 #endif
504         uint32_t life[life_maxsever][life_maxtype];
505         char *life_opt[life_maxsever][life_maxtype];
506         
507         program_name = argv[0];
508         memset(&said, 0, sizeof(said));
509         iv_opt = akey_opt = ekey_opt = alg_opt = edst_opt = spi_opt = proto_opt = af_opt = said_opt = dst_opt = src_opt = NULL;
510         {
511                 int i,j;
512                 for(i = 0; i < life_maxsever; i++) {
513                         for(j = 0; j < life_maxtype; j++) {
514                                 life_opt[i][j] = NULL;
515                                 life[i][j] = 0;
516                         }
517                 }
518         }
519
520         while((c = getopt_long(argc, argv, ""/*"H:P:Z:46dcA:E:e:s:a:w:i:D:S:hvgl:+:f:"*/, longopts, 0)) != EOF) {
521                 switch(c) {
522                 case 'g':
523                         debug = 1;
524                         pfkey_lib_debug = 1;
525                         argcount--;
526                         break;
527                 case 'l':
528                         program_name = malloc(strlen(argv[0])
529                                               + 10 /* update this when changing the sprintf() */
530                                               + strlen(optarg));
531                         sprintf(program_name, "%s --label %s",
532                                 argv[0],
533                                 optarg);
534                         argcount -= 2;
535                         break;
536                 case 'H':
537                         if(alg) {
538                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
539                                         program_name);
540                                 exit(1);
541                         }
542                         if       (!strcmp(optarg, "hmac-md5-96")) {
543                                 alg = XF_AHHMACMD5;
544                         } else if(!strcmp(optarg, "hmac-sha1-96")) {
545                                 alg = XF_AHHMACSHA1;
546                         } else {
547                                 fprintf(stderr, "%s: Unknown authentication algorithm '%s' follows '--ah' option.\n",
548                                         program_name, optarg);
549                                 exit(1);
550                         }
551                         if(debug) {
552                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
553                         }
554                         alg_opt = optarg;
555                         break;
556                 case 'P':
557                         if(alg) {
558                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
559                                         program_name);
560                                 exit(1);
561                         }
562                         if       (!strcmp(optarg, "3des-md5-96")) {
563                                 alg = XF_ESP3DESMD596;
564                         } else if(!strcmp(optarg, "3des-sha1-96")) {
565                                 alg = XF_ESP3DESSHA196;
566                         } else if(!strcmp(optarg, "3des")) {
567                                 alg = XF_ESP3DES;
568                         } else if(!strcmp(optarg, "des-md5-96")) {
569                                 alg = XF_ESPDESMD596;
570                         } else if(!strcmp(optarg, "des-sha1-96")) {
571                                 alg = XF_ESPDESSHA196;
572                         } else if(!strcmp(optarg, "des")) {
573                                 alg = XF_ESPDES;
574 #ifndef NO_KERNEL_ALG
575                         } else if((alg_info=alg_info_esp_create_from_str(optarg, &alg_err))) {
576                                 int esp_ealg_id, esp_aalg_id;
577                                 alg = XF_OTHER_ALG;
578                                 if (alg_info->alg_info_cnt>1) {
579                                         fprintf(stderr, "%s: Invalid encryption algorithm '%s' "
580                                                 "follows '--esp' option: lead too many(%d) "
581                                                 "transforms\n",
582                                                 program_name, optarg, alg_info->alg_info_cnt);
583                                         exit(1);
584                                 }
585                                 alg_string=optarg;
586                                 esp_info=&alg_info->esp[0];
587                                 if (debug) {
588                                         fprintf(stdout, "%s: alg_info: cnt=%d ealg[0]=%d aalg[0]=%d\n",
589                                                 program_name, 
590                                                 alg_info->alg_info_cnt,
591                                                 esp_info->encryptalg,
592                                                 esp_info->authalg);
593                                 }
594                                 esp_ealg_id=esp_info->esp_ealg_id;
595                                 esp_aalg_id=esp_info->esp_aalg_id;
596                                 if (kernel_alg_proc_read()==0) {
597                                         proc_read_ok++;
598                                         if (!kernel_alg_esp_enc_ok(esp_ealg_id, 0, 0))
599                                         {
600                                                 fprintf(stderr, "%s: ESP encryptalg=%d (\"%s\") "
601                                                                 "not present\n",
602                                                         program_name,
603                                                         esp_ealg_id,
604                                                         enum_name(&esp_transformid_names, esp_ealg_id));
605                                                 exit(1);
606                                         }
607                                         if (!kernel_alg_esp_auth_ok(esp_aalg_id, 0))
608                                         {
609                                                 fprintf(stderr, "%s: ESP authalg=%d (\"%s\")"
610                                                                 "not present\n",
611                                                         program_name,
612                                                         esp_aalg_id,
613                                                         enum_name(&auth_alg_names, esp_aalg_id));
614                                                 exit(1);
615                                         }
616                                 }
617 #endif /* NO_KERNEL_ALG */
618                         } else {
619                                 fprintf(stderr, "%s: Invalid encryption algorithm '%s' follows '--esp' option.\n",
620                                         program_name, optarg);
621                                 exit(1);
622                         }
623                         if(debug) {
624                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
625                         }
626                         alg_opt = optarg;
627                         break;
628                 case 'Z':
629                         if(alg) {
630                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
631                                         program_name);
632                                 exit(1);
633                         }
634                         if (!strcmp(optarg, "deflate")) {
635                                 alg = XF_COMPDEFLATE;
636                         } else if (!strcmp(optarg, "lzs")) {
637                                 alg = XF_COMPLZS;
638                         } else {
639                                 fprintf(stderr, "%s: Unknown compression algorithm '%s' follows '--comp' option.\n",
640                                         program_name, optarg);
641                                 exit(1);
642                         }
643                         if(debug) {
644                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
645                         }
646                         alg_opt = optarg;
647                         break;
648                 case '4':
649                         if(alg) {
650                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n",
651                                         program_name);
652                                 exit(1);
653                         }
654                         alg = XF_IP4;
655                         address_family = AF_INET;
656                         if(debug) {
657                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
658                         }
659                         alg_opt = optarg;
660                         break;
661                 case '6':
662                         if(alg) {
663                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n",
664                                         program_name);
665                                 exit(1);
666                         }
667                         alg = XF_IP6;
668                         address_family = AF_INET6;
669                         if(debug) {
670                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
671                         }
672                         alg_opt = optarg;
673                         break;
674                 case 'd':
675                         if(alg) {
676                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
677                                         program_name);
678                                 exit(1);
679                         }
680                         alg = XF_DEL;
681                         if(debug) {
682                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
683                         }
684                         alg_opt = optarg;
685                         break;
686                 case 'c':
687                         if(alg) {
688                                 fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear'  options permitted.\n",
689                                         program_name);
690                                 exit(1);
691                         }
692                         alg = XF_CLR;
693                         if(debug) {
694                                 fprintf(stdout, "Algorithm %d selected.\n", alg);
695                         }
696                         alg_opt = optarg;
697                         break;
698                 case 'e':
699                         if(said_opt) {
700                                 fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n",
701                                         program_name, optarg, said_opt);
702                                 exit (1);
703                         }                               
704                         if(edst_opt) {
705                                 fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n",
706                                         program_name, optarg, edst_opt);
707                                 exit (1);
708                         }
709                         error_s = ttoaddr(optarg, 0, address_family, &edst);
710                         if(error_s != NULL) {
711                                 if(error_s) {
712                                         fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n",
713                                                 program_name, error_s, optarg);
714                                         exit (1);
715                                 }
716                         }
717                         edst_opt = optarg;
718                         if(debug) {
719                                 addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
720                                 fprintf(stdout, "edst=%s.\n", ipaddr_txt);
721                         }
722                         break;
723                 case 's':
724                         if(said_opt) {
725                                 fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n",
726                                         program_name, optarg, said_opt);
727                                 exit (1);
728                         }                               
729                         if(spi_opt) {
730                                 fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n",
731                                         program_name, optarg, spi_opt);
732                                 exit (1);
733                         }                               
734                         spi = strtoul(optarg, &endptr, 0);
735                         if(!(endptr == optarg + strlen(optarg))) {
736                                 fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n",
737                                         program_name, optarg);
738                                 exit (1);
739                         }
740                         if(spi < 0x100) {
741                                 fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n",
742                                         program_name, optarg, spi);
743                                 exit(1);
744                         }
745                         spi_opt = optarg;
746                         break;
747                 case 'p':
748                         if(said_opt) {
749                                 fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n",
750                                         program_name, optarg, said_opt);
751                                 exit (1);
752                         }                               
753                         if(proto_opt) {
754                                 fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n",
755                                         program_name, optarg, proto_opt);
756                                 exit (1);
757                         }
758                         if(!strcmp(optarg, "ah"))
759                                 proto = SA_AH;
760                         if(!strcmp(optarg, "esp"))
761                                 proto = SA_ESP;
762                         if(!strcmp(optarg, "tun"))
763                                 proto = SA_IPIP;
764                         if(!strcmp(optarg, "comp"))
765                                 proto = SA_COMP;
766                         if(proto == 0) {
767                                 fprintf(stderr, "%s: Invalid PROTO parameter: %s\n",
768                                         program_name, optarg);
769                                 exit (1);
770                         }
771                         proto_opt = optarg;
772                         break;
773                 case 'a':
774                         if(said_opt) {
775                                 fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined in SA:%s\n",
776                                         program_name, optarg, said_opt);
777                                 exit (1);
778                         }                               
779                         if(af_opt) {
780                                 fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined as:%s\n",
781                                         program_name, optarg, af_opt);
782                                 exit (1);
783                         }
784                         if(strcmp(optarg, "inet") == 0) {
785                                 address_family = AF_INET;
786                                 /* currently we ensure that all addresses belong to the same address family */
787                                 anyaddr(address_family, &dst);
788                                 anyaddr(address_family, &edst);
789                                 anyaddr(address_family, &src);
790                         }
791                         if(strcmp(optarg, "inet6") == 0) {
792                                 address_family = AF_INET6;
793                                 /* currently we ensure that all addresses belong to the same address family */
794                                 anyaddr(address_family, &dst);
795                                 anyaddr(address_family, &edst);
796                                 anyaddr(address_family, &src);
797                         }
798                         if((strcmp(optarg, "inet") != 0) && (strcmp(optarg, "inet6") != 0)) {
799                                 fprintf(stderr, "%s: Invalid ADDRESS FAMILY parameter: %s.\n",
800                                         program_name, optarg);
801                                 exit (1);
802                         }
803                         af_opt = optarg;
804                         break;
805                 case 'I':
806                         if(said_opt) {
807                                 fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n",
808                                         program_name, optarg, said_opt);
809                                 exit (1);
810                         }                               
811                         if(proto_opt) {
812                                 fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n",
813                                         program_name, optarg, proto_opt);
814                                 exit (1);
815                         }
816                         if(edst_opt) {
817                                 fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n",
818                                         program_name, optarg, edst_opt);
819                                 exit (1);
820                         }
821                         if(spi_opt) {
822                                 fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n",
823                                         program_name, optarg, spi_opt);
824                                 exit (1);
825                         }
826                         error_s = ttosa(optarg, 0, &said);
827                         if(error_s != NULL) {
828                                 fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
829                                         program_name, error_s, optarg);
830                                 exit (1);
831                         }
832                         if(debug) {
833                                 satot(&said, 0, ipsaid_txt, sizeof(ipsaid_txt));
834                                 fprintf(stdout, "said=%s.\n", ipsaid_txt);
835                         }
836                         /* init the src and dst with the same address family */
837                         if(address_family == 0) {
838                                 address_family = addrtypeof(&said.dst);
839                         } else if(address_family != addrtypeof(&said.dst)) {
840                                 fprintf(stderr, "%s: Error, specified address family (%d) is different that of SAID: %s\n",
841                                         program_name, address_family, optarg);
842                                 exit (1);
843                         }
844                         anyaddr(address_family, &dst);
845                         anyaddr(address_family, &edst);
846                         anyaddr(address_family, &src);
847                         said_opt = optarg;
848                         break;
849                 case 'A':
850                         if(optarg[0] == '0') {
851                                 switch(optarg[1]) {
852                                 case 't':
853                                 case 'x':
854                                 case 's':
855                                         break;
856                                 default:
857                                         fprintf(stderr, "%s: Authentication key must have a '0x', '0t' or '0s' prefix to select the format: %s\n",
858                                                 program_name, optarg);
859                                         exit(1);
860                                 }
861                         }
862                         authkeylen = atodata(optarg, 0, NULL, 0);
863                         if(!authkeylen) {
864                                 fprintf(stderr, "%s: unknown format or syntax error in authentication key: %s\n",
865                                         program_name, optarg);
866                                 exit (1);
867                         }
868                         authkey = malloc(authkeylen);
869                         if(authkey == NULL) {
870                                 fprintf(stderr, "%s: Memory allocation error.\n", program_name);
871                                 exit(1);
872                         }
873                         memset(authkey, 0, authkeylen);
874                         authkeylen = atodata(optarg, 0, authkey, authkeylen);
875                         akey_opt = optarg;
876                         break;
877                 case 'E':
878                         if(optarg[0] == '0') {
879                                 switch(optarg[1]) {
880                                 case 't':
881                                 case 'x':
882                                 case 's':
883                                         break;
884                                 default:
885                                         fprintf(stderr, "%s: Encryption key must have a '0x', '0t' or '0s' prefix to select the format: %s\n",
886                                                 program_name, optarg);
887                                         exit(1);
888                                 }
889                         }
890                         enckeylen = atodata(optarg, 0, NULL, 0);
891                         if(!enckeylen) {
892                                 fprintf(stderr, "%s: unknown format or syntax error in encryption key: %s\n",
893                                         program_name, optarg);
894                                 exit (1);
895                         }
896                         enckey = malloc(enckeylen);
897                         if(enckey == NULL) {
898                                 fprintf(stderr, "%s: Memory allocation error.\n", program_name);
899                                 exit(1);
900                         }
901                         memset(enckey, 0, enckeylen);
902                         enckeylen = atodata(optarg, 0, enckey, enckeylen);
903                         ekey_opt = optarg;
904                         break;
905                 case 'w':
906                         replay_window = strtoul(optarg, &endptr, 0);
907                         if(!(endptr == optarg + strlen(optarg))) {
908                                 fprintf(stderr, "%s: Invalid character in replay_window parameter: %s\n",
909                                         program_name, optarg);
910                                 exit (1);
911                         }
912                         if((replay_window < 0x1) || (replay_window > 64)) {
913                                 fprintf(stderr, "%s: Failed -- Illegal window size: arg=%s, replay_window=%d, must be 1 <= size <= 64.\n",
914                                         program_name, optarg, replay_window);
915                                 exit(1);
916                         }
917                         break;
918                 case 'i':
919                         if(optarg[0] == '0') {
920                                 switch(optarg[1]) {
921                                 case 't':
922                                 case 'x':
923                                 case 's':
924                                         break;
925                                 default:
926                                         fprintf(stderr, "%s: IV must have a '0x', '0t' or '0s' prefix to select the format, found '%c'.\n",
927                                                 program_name, optarg[1]);
928                                         exit(1);
929                                 }
930                         }
931                         ivlen = atodata(optarg, 0, NULL, 0);
932                         if(!ivlen) {
933                                 fprintf(stderr, "%s: unknown format or syntax error in IV: %s\n",
934                                         program_name, optarg);
935                                 exit (1);
936                         }
937                         iv = malloc(ivlen);
938                         if(iv == NULL) {
939                                 fprintf(stderr, "%s: Memory allocation error.\n", program_name);
940                                 exit(1);
941                         }
942                         memset(iv, 0, ivlen);
943                         ivlen = atodata(optarg, 0, iv, ivlen);
944                         iv_opt = optarg;
945                         break;
946                 case 'D':
947                         if(dst_opt) {
948                                 fprintf(stderr, "%s: Error, DST parameter redefined:%s, already defined as:%s\n",
949                                         program_name, optarg, dst_opt);
950                                 exit (1);
951                         }                               
952                         error_s = ttoaddr(optarg, 0, address_family, &dst);
953                         if(error_s != NULL) {
954                                 fprintf(stderr, "%s: Error, %s converting --dst argument:%s\n",
955                                         program_name, error_s, optarg);
956                                 exit (1);
957                         }
958                         dst_opt = optarg;
959                         if(debug) {
960                                 addrtot(&dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
961                                 fprintf(stdout, "dst=%s.\n", ipaddr_txt);
962                         }
963                         break;
964                 case 'S':
965                         if(src_opt) {
966                                 fprintf(stderr, "%s: Error, SRC parameter redefined:%s, already defined as:%s\n",
967                                         program_name, optarg, src_opt);
968                                 exit (1);
969                         }                               
970                         error_s = ttoaddr(optarg, 0, address_family, &src);
971                         if(error_s != NULL) {
972                                 fprintf(stderr, "%s: Error, %s converting --src argument:%s\n",
973                                         program_name, error_s, optarg);
974                                 exit (1);
975                         }
976                         src_opt = optarg;
977                         if(debug) {
978                                 addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
979                                 fprintf(stdout, "src=%s.\n", ipaddr_txt);
980                         }
981                         break;
982                 case 'h':
983                         usage(program_name, stdout);
984                         exit(0);
985                 case '?':
986                         usage(program_name, stderr);
987                         exit(1);
988                 case 'v':
989                         fprintf(stdout, "%s %s\n", me, ipsec_version_code());
990                         fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
991                         exit(1);
992                 case '+': /* optionsfrom */
993                         optionsfrom(optarg, &argc, &argv, optind, stderr);
994                         /* no return on error */
995                         break;
996                 case 'f':
997                         if(parse_life_options(life,
998                                            life_opt,
999                                            optarg) != 0) {
1000                                 exit(1);
1001                         };
1002                         break;
1003                 default:
1004                         fprintf(stderr, "%s: unrecognized option '%c', update option processing.\n",
1005                                 program_name, c);
1006                         exit(1);
1007                 }
1008                 previous = c;
1009         }
1010         if(debug) {
1011                 fprintf(stdout, "All options processed.\n");
1012         }
1013
1014         if(argcount == 1) {
1015                 system("cat /proc/net/ipsec_spi");
1016                 exit(0);
1017         }
1018
1019         switch(alg) {
1020 #ifndef NO_KERNEL_ALG
1021         case XF_OTHER_ALG: 
1022                 /* validate keysizes */
1023                 if (proc_read_ok) {
1024                        const struct sadb_alg *alg_p;
1025                        int keylen, minbits, maxbits;
1026                        alg_p=kernel_alg_sadb_alg_get(SADB_SATYPE_ESP,SADB_EXT_SUPPORTED_ENCRYPT, 
1027                                        esp_info->encryptalg);
1028                        assert(alg_p);
1029                        keylen=enckeylen * 8;
1030
1031                        if (alg_p->sadb_alg_id==ESP_3DES) {
1032                                maxbits=minbits=alg_p->sadb_alg_minbits * 8 /7;
1033                        } else {
1034                                minbits=alg_p->sadb_alg_minbits;
1035                                maxbits=alg_p->sadb_alg_maxbits;
1036                        }
1037                        /* 
1038                         * if explicit keylen told in encrypt algo, eg "aes128"
1039                         * check actual keylen "equality"
1040                         */
1041                        if (esp_info->esp_ealg_keylen &&
1042                                esp_info->esp_ealg_keylen!=keylen) {
1043                                fprintf(stderr, "%s: invalid encryption keylen=%d, "
1044                                                "required %d by encrypt algo string=\"%s\"\n",
1045                                        program_name, 
1046                                        keylen,
1047                                        esp_info->esp_ealg_keylen,
1048                                        alg_string);
1049                                exit(1);
1050
1051                        }
1052                        /* thanks DES for this sh*t */
1053
1054                        if (minbits > keylen || maxbits < keylen) {
1055                                fprintf(stderr, "%s: invalid encryption keylen=%d, "
1056                                                "must be between %d and %d bits\n",
1057                                                program_name, 
1058                                                keylen, minbits, maxbits);
1059                                exit(1);
1060                        }
1061                        alg_p=kernel_alg_sadb_alg_get(SADB_SATYPE_ESP,SADB_EXT_SUPPORTED_AUTH, 
1062                                        esp_info->authalg);
1063                        assert(alg_p);
1064                        keylen=authkeylen * 8;
1065                        minbits=alg_p->sadb_alg_minbits;
1066                        maxbits=alg_p->sadb_alg_maxbits;
1067                        if (minbits > keylen || maxbits < keylen) {
1068                                fprintf(stderr, "%s: invalid auth keylen=%d, "
1069                                                "must be between %d and %d bits\n",
1070                                                program_name, 
1071                                                keylen, minbits, maxbits);
1072                                exit(1);
1073                        }
1074
1075                 }
1076 #endif /* NO_KERNEL_ALG */
1077         case XF_IP4:
1078         case XF_IP6:
1079         case XF_DEL:
1080         case XF_AHHMACMD5:
1081         case XF_AHHMACSHA1:
1082         case XF_ESPDESMD596:
1083         case XF_ESPDESSHA196:
1084         case XF_ESP3DESMD596:
1085         case XF_ESP3DESSHA196:
1086         case XF_ESPNULLMD596:
1087         case XF_ESPNULLSHA196:
1088         case XF_ESPDES:
1089         case XF_ESP3DES:
1090         case XF_COMPDEFLATE:
1091         case XF_COMPLZS:
1092                 if(!said_opt) {
1093                         if(isanyaddr(&edst)) {
1094                                 fprintf(stderr, "%s: SA destination not specified.\n",
1095                                         program_name);
1096                                 exit(1);
1097                         }
1098                         if(!spi) {
1099                                 fprintf(stderr, "%s: SA SPI not specified.\n",
1100                                         program_name);
1101                                 exit(1);
1102                         }
1103                         if(!proto) {
1104                                 fprintf(stderr, "%s: SA PROTO not specified.\n",
1105                                         program_name);
1106                                 exit(1);
1107                         }
1108                         initsaid(&edst, htonl(spi), proto, &said);
1109                 } else {
1110                         proto = said.proto;
1111                         spi = ntohl(said.spi);
1112                         edst = said.dst;
1113                 }
1114                 if((address_family != 0) && (address_family != addrtypeof(&said.dst))) {
1115                         fprintf(stderr, "%s: Defined address family and address family of SA missmatch.\n",
1116                                 program_name);
1117                         exit(1);
1118                 }
1119                 sa_len = satot(&said, 0, sa, sizeof(sa));
1120
1121                 if(debug) {
1122                         fprintf(stdout, "SA valid.\n");
1123                 }
1124                 break;
1125         case XF_CLR:
1126                 break;
1127         default:
1128                 fprintf(stderr, "%s: No action chosen.  See '%s --help' for usage.\n",
1129                         program_name, program_name);
1130                 exit(1);
1131         }
1132
1133         switch(alg) {
1134         case XF_CLR:
1135         case XF_DEL:
1136         case XF_IP4:
1137         case XF_IP6:
1138         case XF_AHHMACMD5:
1139         case XF_AHHMACSHA1:
1140         case XF_ESPDESMD596:
1141         case XF_ESPDESSHA196:
1142         case XF_ESP3DESMD596:
1143         case XF_ESP3DESSHA196:
1144         case XF_ESPNULLMD596:
1145         case XF_ESPNULLSHA196:
1146         case XF_ESPDES:
1147         case XF_ESP3DES:
1148         case XF_COMPDEFLATE:
1149         case XF_COMPLZS:
1150 #ifndef NO_KERNEL_ALG
1151         case XF_OTHER_ALG:
1152 #endif /* NO_KERNEL_ALG */
1153                 break;
1154         default:
1155                 fprintf(stderr, "%s: No action chosen.  See '%s --help' for usage.\n",
1156                         program_name, program_name);
1157                 exit(1);
1158         }
1159         if(debug) {
1160                 fprintf(stdout, "Algorithm ok.\n");
1161         }
1162
1163         if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
1164                 fprintf(stderr, "%s: Trouble openning PF_KEY family socket with error: ",
1165                         program_name);
1166                 switch(errno) {
1167                 case ENOENT:
1168                         fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
1169                         break;
1170                 case EACCES:
1171                         fprintf(stderr, "access denied.  ");
1172                         if(getuid() == 0) {
1173                                 fprintf(stderr, "Check permissions.  Should be 600.\n");
1174                         } else {
1175                                 fprintf(stderr, "You must be root to open this file.\n");
1176                         }
1177                         break;
1178                 case EUNATCH:
1179                         fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
1180                         break;
1181                 case ENODEV:
1182                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
1183                         break;
1184                 case EBUSY:
1185                         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");
1186                         break;
1187                 case EINVAL:
1188                         fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
1189                         break;
1190                 case ENOBUFS:
1191                         fprintf(stderr, "No kernel memory to allocate SA.\n");
1192                         break;
1193                 case ESOCKTNOSUPPORT:
1194                         fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
1195                         break;
1196                 case EEXIST:
1197                         fprintf(stderr, "SA already in use.  Delete old one first.\n");
1198                         break;
1199                 case ENXIO:
1200                         fprintf(stderr, "SA does not exist.  Cannot delete.\n");
1201                         break;
1202                 case EAFNOSUPPORT:
1203                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
1204                         break;
1205                 default:
1206                         fprintf(stderr, "Unknown file open error %d.  Please report as much detail as possible to development team.\n", errno);
1207                 }
1208                 exit(1);
1209         }
1210
1211 #ifdef SIGS_FROM_BELOW
1212         {
1213                 struct sigaction sig_act;
1214                 int sig_act_err;
1215                 memset(&sig_act, 0, sizeof(sig_act));
1216
1217                 sig_act.sa_handler = pfkey_sig_handler;
1218                 sigemptyset(&sig_act.sa_mask);
1219                 sig_act.sa_flags = SA_RESTART;
1220
1221                 sig_act_err = sigaction(SIGIO, &sig_act, NULL);
1222                 if(sig_act_err < 0) {
1223                         fprintf(stderr, "Signal handler registration error.\n", sig_act_err);
1224                         exit(1);
1225                 }
1226         }
1227 #endif /* SIGS_FROM_BELOW */
1228         
1229 #ifdef MANUAL_IS_NOT_ABLE_TO_NEGOTIATE
1230         /* for registering SA types that can be negotiated */
1231         if(pfkey_register(SADB_SATYPE_AH) != 0) {
1232                 exit(1);
1233         }
1234         if(pfkey_register(SADB_SATYPE_ESP)) != 0) {
1235                 exit(1);
1236         }
1237         if(pfkey_register(SADB_X_SATYPE_IPIP)) != 0) {
1238                 exit(1);
1239         }
1240         if(pfkey_register(SADB_X_SATYPE_COMP)) != 0) {
1241                 exit(1);
1242         }
1243 #endif /* MANUAL_IS_NOT_ABLE_TO_NEGOTIATE */
1244
1245         /* Build an SADB_ADD message to send down. */
1246         /* It needs <base, SA, address(SD), key(AE)> minimum. */
1247         /*   Lifetime(HS) could be added before addresses. */
1248         pfkey_extensions_init(extensions);
1249         if(debug) {
1250                 fprintf(stdout, "%s: extensions=%p &extensions=%p extensions[0]=%p &extensions[0]=%p cleared.\n",
1251                         program_name,
1252                         extensions,
1253                         &extensions,
1254                         extensions[0],
1255                         &extensions[0]);
1256         }
1257         if((error = pfkey_msg_hdr_build(&extensions[0],
1258                                         (alg == XF_DEL ? SADB_DELETE : alg == XF_CLR ? SADB_FLUSH : SADB_ADD),
1259                                         proto2satype(proto),
1260                                         0,
1261                             ++pfkey_seq,
1262                             getpid()))) {
1263                 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
1264                         program_name, error);
1265                 pfkey_extensions_free(extensions);
1266                 exit(1);
1267         }
1268         if(debug) {
1269                 fprintf(stdout, "%s: extensions=%p &extensions=%p extensions[0]=%p &extensions[0]=%p set w/msghdr.\n",
1270                         program_name,
1271                         extensions,
1272                         &extensions,
1273                         extensions[0],
1274                         &extensions[0]);
1275         }
1276         if(debug) {
1277                 fprintf(stdout, "%s: base message assembled.\n", program_name);
1278         }
1279         
1280         switch(alg) {
1281         case XF_AHHMACMD5:
1282         case XF_ESPDESMD596:
1283         case XF_ESP3DESMD596:
1284                 authalg = SADB_AALG_MD5HMAC;
1285                 break;
1286         case XF_AHHMACSHA1:
1287         case XF_ESPDESSHA196:
1288         case XF_ESP3DESSHA196:
1289                 authalg = SADB_AALG_SHA1HMAC;
1290                 break;
1291 #ifndef NO_KERNEL_ALG
1292         case XF_OTHER_ALG:
1293                 authalg= esp_info->authalg;
1294                 if(debug) {
1295                         fprintf(stdout, "%s: debug: authalg=%d\n",
1296                                 program_name, authalg);
1297                 }
1298                 break;
1299 #endif /* NO_KERNEL_ALG */
1300         case XF_ESPDESMD5:
1301         case XF_ESP3DESMD5:
1302         default:
1303                 authalg = SADB_AALG_NONE;
1304         }
1305         switch(alg) {
1306         case XF_ESPDES:
1307         case XF_ESPDESMD596:
1308         case XF_ESPDESSHA196:
1309                 encryptalg = SADB_EALG_DESCBC;
1310                 break;
1311         case XF_ESP3DES:
1312         case XF_ESP3DESMD596:
1313         case XF_ESP3DESSHA196:
1314                 encryptalg = SADB_EALG_3DESCBC;
1315                 break;
1316         case XF_COMPDEFLATE:
1317                 encryptalg = SADB_X_CALG_DEFLATE;
1318                 break;
1319         case XF_COMPLZS:
1320                 encryptalg = SADB_X_CALG_LZS;
1321                 break;
1322 #ifndef NO_KERNEL_ALG
1323         case XF_OTHER_ALG:
1324                 encryptalg= esp_info->encryptalg;
1325                 if(debug) {
1326                         fprintf(stdout, "%s: debug: encryptalg=%d\n",
1327                                 program_name, encryptalg);
1328                 }
1329                 break;
1330 #endif /* NO_KERNEL_ALG */
1331         default:
1332                 encryptalg = SADB_EALG_NONE;
1333         }
1334         if(!(alg == XF_CLR /* IE: pfkey_msg->sadb_msg_type == SADB_FLUSH */)) {
1335                 if((error = pfkey_sa_build(&extensions[SADB_EXT_SA],
1336                                            SADB_EXT_SA,
1337                                            htonl(spi), /* in network order */
1338                                            replay_window,
1339                                            SADB_SASTATE_MATURE,
1340                                            authalg,
1341                                            encryptalg,
1342                                            0))) {
1343                         fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n",
1344                                 program_name, error);
1345                         pfkey_extensions_free(extensions);
1346                         exit(1);
1347                 }
1348                 if(debug) {
1349                         fprintf(stdout, "%s: extensions[0]=%p previously set with msg_hdr.\n",
1350                                 program_name,
1351                                 extensions[0]);
1352                 }
1353                 if(debug) {
1354                         fprintf(stdout, "%s: assembled SA extension, pfkey msg authalg=%d encalg=%d.\n",
1355                                 program_name,
1356                                 authalg,
1357                                 encryptalg);
1358                 }
1359                 
1360 #if 1 /* def PFKEY_LIFETIME */
1361                 if(debug) {
1362                         int i,j;
1363                         for(i = 0; i < life_maxsever; i++) {
1364                                 for(j = 0; j < life_maxtype; j++) {
1365                                         fprintf(stdout, "i=%d, j=%d, life_opt[%d][%d]=%p, life[%d][%d]=%d\n",
1366                                                 i, j, i, j, life_opt[i][j], i, j, life[i][j]);
1367                                 }
1368                         }
1369                 }
1370                 if(life_opt[life_soft][life_alloc] != NULL ||
1371                    life_opt[life_soft][life_bytes] != NULL ||
1372                    life_opt[life_soft][life_addtime] != NULL ||
1373                    life_opt[life_soft][life_usetime] != NULL ||
1374                    life_opt[life_soft][life_packets] != NULL) {
1375                         if((error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_SOFT],
1376                                                          SADB_EXT_LIFETIME_SOFT,
1377                                                          life[life_soft][life_alloc],/*-1,*/            /*allocations*/
1378                                                          life[life_soft][life_bytes],/*-1,*/            /*bytes*/
1379                                                          life[life_soft][life_addtime],/*-1,*/          /*addtime*/
1380                                                          life[life_soft][life_usetime],/*-1,*/          /*usetime*/
1381                                                          life[life_soft][life_packets]/*-1*/))) {       /*packets*/
1382                                 fprintf(stderr, "%s: Trouble building lifetime_s extension, error=%d.\n",
1383                                         program_name, error);
1384                                 pfkey_extensions_free(extensions);
1385                                 exit(1);
1386                         }
1387                         if(debug) {
1388                                 fprintf(stdout, "%s: lifetime_s extension assembled.\n",
1389                                         program_name);
1390                         }
1391                 }
1392
1393                 if(life_opt[life_hard][life_alloc] != NULL ||
1394                    life_opt[life_hard][life_bytes] != NULL ||
1395                    life_opt[life_hard][life_addtime] != NULL ||
1396                    life_opt[life_hard][life_usetime] != NULL ||
1397                    life_opt[life_hard][life_packets] != NULL) {
1398                         if((error = pfkey_lifetime_build(&extensions[SADB_EXT_LIFETIME_HARD],
1399                                                          SADB_EXT_LIFETIME_HARD,
1400                                                          life[life_hard][life_alloc],/*-1,*/            /*allocations*/
1401                                                          life[life_hard][life_bytes],/*-1,*/            /*bytes*/
1402                                                          life[life_hard][life_addtime],/*-1,*/          /*addtime*/
1403                                                          life[life_hard][life_usetime],/*-1,*/          /*usetime*/
1404                                                          life[life_hard][life_packets]/*-1*/))) {       /*packets*/
1405                                 fprintf(stderr, "%s: Trouble building lifetime_h extension, error=%d.\n",
1406                                         program_name, error);
1407                                 pfkey_extensions_free(extensions);
1408                                 exit(1);
1409                         }
1410                         if(debug) {
1411                                 fprintf(stdout, "%s: lifetime_h extension assembled.\n",
1412                                         program_name);
1413                         }
1414                 }
1415 #endif /* PFKEY_LIFETIME */
1416                 
1417                 if(debug) {
1418                         addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
1419                         fprintf(stdout, "%s: assembling address_s extension (%s).\n",
1420                                 program_name, ipaddr_txt);
1421                 }
1422         
1423                 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
1424                                                 SADB_EXT_ADDRESS_SRC,
1425                                                 0,
1426                                                 0,
1427                                                 sockaddrof(&src)))) {
1428                         addrtot(&src, 0, ipaddr_txt, sizeof(ipaddr_txt));
1429                         fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n",
1430                                 program_name, ipaddr_txt, error);
1431                         pfkey_extensions_free(extensions);
1432                         exit(1);
1433                 }
1434                 if(debug) {
1435                         ip_address temp_addr;
1436                         
1437                         switch(address_family) {
1438                                 case AF_INET:
1439                                         initaddr((const unsigned char *)&(((struct sockaddr_in*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_SRC])) + 1))->sin_addr),
1440                                                 sockaddrlenof(&src), address_family, &temp_addr);
1441                                         break;
1442                                 case AF_INET6:
1443                                         initaddr((const unsigned char *)&(((struct sockaddr_in6*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_SRC])) + 1))->sin6_addr),
1444                                                 sockaddrlenof(&src), address_family, &temp_addr);
1445                                         break;
1446                                 default:
1447                                         fprintf(stdout, "%s: unknown address family (%d).\n",
1448                                                 program_name, address_family);
1449                                         exit(1);
1450                         }
1451                         addrtot(&temp_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
1452                         fprintf(stdout, "%s: address_s extension assembled (%s).\n",
1453                                 program_name, ipaddr_txt);
1454                 }
1455         
1456                 if(debug) {
1457                         addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
1458                         fprintf(stdout, "%s: assembling address_d extension (%s).\n",
1459                                 program_name, ipaddr_txt);
1460                 }
1461         
1462                 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
1463                                                 SADB_EXT_ADDRESS_DST,
1464                                                 0,
1465                                                 0,
1466                                                 sockaddrof(&edst)))) {
1467                         addrtot(&edst, 0, ipaddr_txt, sizeof(ipaddr_txt));
1468                         fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n",
1469                                 program_name, ipaddr_txt, error);
1470                         pfkey_extensions_free(extensions);
1471                         exit(1);
1472                 }
1473                 if(debug) {
1474                         ip_address temp_addr;
1475                         switch(address_family) {
1476                                 case AF_INET:
1477                                         initaddr((const unsigned char *)&(((struct sockaddr_in*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_DST])) + 1))->sin_addr),
1478                                                 4, address_family, &temp_addr);
1479                                         break;
1480                                 case AF_INET6:
1481                                         initaddr((const unsigned char *)&(((struct sockaddr_in6*)( ((struct sadb_address*)(extensions[SADB_EXT_ADDRESS_DST])) + 1))->sin6_addr),
1482                                                 16, address_family, &temp_addr);
1483                                         break;
1484                                 default:
1485                                         fprintf(stdout, "%s: unknown address family (%d).\n",
1486                                                 program_name, address_family);
1487                                         exit(1);
1488                         }
1489                         addrtot(&temp_addr, 0, ipaddr_txt, sizeof(ipaddr_txt));
1490                         fprintf(stdout, "%s: address_d extension assembled (%s).\n",
1491                                 program_name, ipaddr_txt);
1492                 }
1493
1494 #if PFKEY_PROXY
1495                 anyaddr(address_family, &pfkey_address_p_ska);
1496                 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_PROXY],
1497                                                 SADB_EXT_ADDRESS_PROXY,
1498                                                 0,
1499                                                 0,
1500                                                 sockaddrof(&pfkey_address_p_ska)))) {
1501                         fprintf(stderr, "%s: Trouble building address_p extension, error=%d.\n",
1502                                 program_name, error);
1503                         pfkey_extensions_free(extensions);
1504                         exit(1);
1505                 }
1506                 if(debug) {
1507                         fprintf(stdout, "%s: address_p extension assembled.\n", program_name);
1508                 }
1509 #endif /* PFKEY_PROXY */
1510                 
1511                 switch(alg) {
1512                 case XF_AHHMACMD5:
1513                 case XF_ESPDESMD596:
1514                 case XF_ESP3DESMD596:
1515                 case XF_AHHMACSHA1:
1516                 case XF_ESPDESSHA196:
1517                 case XF_ESP3DESSHA196:
1518 #ifndef NO_KERNEL_ALG
1519                 case XF_OTHER_ALG:
1520 #endif /* NO_KERNEL_ALG */
1521                         if((error = pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH],
1522                                                     SADB_EXT_KEY_AUTH,
1523                                                     authkeylen * 8,
1524                                                     authkey))) {
1525                                 fprintf(stderr, "%s: Trouble building key_a extension, error=%d.\n",
1526                                         program_name, error);
1527                                 pfkey_extensions_free(extensions);
1528                                 exit(1);
1529                         }
1530                         if(debug) {
1531                                 fprintf(stdout, "%s: key_a extension assembled.\n",
1532                                         program_name);
1533                         }
1534                         break;
1535                 default:
1536                         break;
1537                 }
1538                 
1539                 switch(alg) {
1540                 case XF_ESPDES:
1541                 case XF_ESPDESMD596:
1542                 case XF_ESPDESSHA196:
1543                 case XF_ESP3DES:
1544                 case XF_ESP3DESMD596:
1545                 case XF_ESP3DESSHA196:
1546 #ifndef NO_KERNEL_ALG
1547                 case XF_OTHER_ALG:
1548 #endif /* NO_KERNEL_ALG */
1549                         if((error = pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT],
1550                                                     SADB_EXT_KEY_ENCRYPT,
1551                                                     enckeylen * 8,
1552                                                     enckey))) {
1553                                 fprintf(stderr, "%s: Trouble building key_e extension, error=%d.\n",
1554                                         program_name, error);
1555                                 pfkey_extensions_free(extensions);
1556                                 exit(1);
1557                         }
1558                         if(debug) {
1559                                 fprintf(stdout, "%s: key_e extension assembled.\n",
1560                                         program_name);
1561                         }
1562                         break;
1563                 default:
1564                         break;
1565                 }
1566                 
1567 #ifdef PFKEY_IDENT /* GG: looks wierd, not touched */
1568                 if((pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_SRC],
1569                                       SADB_EXT_IDENTITY_SRC,
1570                                       SADB_IDENTTYPE_PREFIX,
1571                                       0,
1572                                       strlen(pfkey_ident_s_ska),
1573                                       pfkey_ident_s_ska))) {
1574                         fprintf(stderr, "%s: Trouble building ident_s extension, error=%d.\n",
1575                                 program_name, error);
1576                         pfkey_extensions_free(extensions);
1577                         exit(1);
1578                 }
1579                 if(subnettoa(addr, mask, format, pfkey_ident_s_ska,
1580                              sizeof(pfkey_ident_s_ska) ) !=
1581                    sizeof(pfkey_ident_s_ska) ) {
1582                         exit (1);
1583                 }
1584                 
1585                 if((error = pfkey_ident_build(&extensions[SADB_EXT_IDENTITY_DST],
1586                                               SADB_EXT_IDENTITY_DST,
1587                                               SADB_IDENTTYPE_PREFIX,
1588                                               0,
1589                                               strlen(pfkey_ident_d_ska),
1590                                               pfkey_ident_d_ska))) {
1591                         fprintf(stderr, "%s: Trouble building ident_d extension, error=%d.\n",
1592                                 program_name, error);
1593                         pfkey_extensions_free(extensions);
1594                         exit(1);
1595                 }
1596                 if(subnettoa(addr, mask, format, pfkey_ident_d_ska,
1597                              sizeof(pfkey_ident_d_ska) ) !=
1598                    sizeof(pfkey_ident_d_ska) ) {
1599                         exit (1);
1600                 }
1601
1602                 if(debug) {
1603                         fprintf(stdout, "%s: ident extensions assembled.\n",
1604                                 program_name);
1605                 }
1606 #endif /* PFKEY_IDENT */
1607         }
1608         
1609         if(debug) {
1610                 fprintf(stdout, "%s: assembling pfkey msg....\n",
1611                         program_name);
1612         }
1613         if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
1614                 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
1615                         program_name, error);
1616                 pfkey_extensions_free(extensions);
1617                 pfkey_msg_free(&pfkey_msg);
1618                 exit(1);
1619         }
1620         if(debug) {
1621                 fprintf(stdout, "%s: assembled.\n",
1622                         program_name);
1623         }
1624         if(debug) {
1625                 fprintf(stdout, "%s: writing pfkey msg.\n",
1626                         program_name);
1627         }
1628         if((error = write(pfkey_sock,
1629                           pfkey_msg,
1630                           pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) !=
1631            pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
1632                 fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n",
1633                         program_name, error, errno);
1634                 pfkey_extensions_free(extensions);
1635                 pfkey_msg_free(&pfkey_msg);
1636                 switch(errno) {
1637                 case EACCES:
1638                         fprintf(stderr, "access denied.  ");
1639                         if(getuid() == 0) {
1640                                 fprintf(stderr, "Check permissions.  Should be 600.\n");
1641                         } else {
1642                                 fprintf(stderr, "You must be root to open this file.\n");
1643                         }
1644                         break;
1645                 case EUNATCH:
1646                         fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n");
1647                         break;
1648                 case EBUSY:
1649                         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");
1650                         break;
1651                 case EINVAL:
1652                         fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
1653                         break;
1654                 case ENODEV:
1655                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
1656                         fprintf(stderr, "No device?!?\n");
1657                         break;
1658                 case ENOBUFS:
1659                         fprintf(stderr, "No kernel memory to allocate SA.\n");
1660                         break;
1661                 case ESOCKTNOSUPPORT:
1662                         fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
1663                         break;
1664                 case EEXIST:
1665                         fprintf(stderr, "SA already in use.  Delete old one first.\n");
1666                         break;
1667                 case ENOENT:
1668                         fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
1669                         break;
1670                 case ENXIO:
1671                 case ESRCH:
1672                         fprintf(stderr, "SA does not exist.  Cannot delete.\n");
1673                         break;
1674                 default:
1675                         fprintf(stderr, "Unknown socket write error %d.  Please report as much detail as possible to development team.\n", errno);
1676                 }
1677 /*              fprintf(stderr, "%s: socket write returned errno %d\n",
1678                 program_name, errno);*/
1679                 exit(1);
1680         }
1681         if(debug) {
1682                 fprintf(stdout, "%s: pfkey command written to socket.\n",
1683                         program_name);
1684         }
1685         
1686 #if 0 /* use write() rather than sendmsg() */
1687         error = sendmsg(/* int */pfkey_sock,
1688                 /* const void* */msg,
1689                 /* int */len,
1690                 /* unsigned int flags MSG_OOB|MSG_DONTROUTE */ 0);
1691         if( error == -1 ) {
1692                 fprintf(stderr, "%s: pfkey sendmsg failed.\n",
1693                         program_name);
1694                 switch(errno) {
1695                         case EINVAL:
1696                                 fprintf(stderr, "bad data error, since this should not happen, advise the maintainer.\n");
1697                                 exit(1);
1698                         case EBADF:
1699                         case ENOTSOCK:
1700                         case EFAULT:
1701                         case EMSGSIZE:
1702                         case EWOULDBLOCK:
1703                         case ENOBUFS:
1704                                 fprintf(stderr, "system error:%d\n", error);
1705                                 exit(1);
1706                         default:
1707                                 fprintf(stderr, "unknown error:%d\n", error);
1708                                 exit(1);
1709                 }
1710         }
1711 #endif
1712
1713 #if 0
1714         sleep (1); /* wait for errors to come back through signal handling */
1715         read(pfkey_sock, &pfkey_buf, sizeof(pfkey_msg) );
1716         fprintf(stdout, "%s: pfkey_buf read.\n", program_name);
1717         /* fprintf(stdout, "%s: press a key to close pfkey socket.\n", program_name); */
1718         /* getchar(); */ /* RGB wait for keystroke to exit (debug) */
1719         fprintf(stdout, "%s: sleeping 2 seconds to allow return messages.\n", program_name);
1720         sleep(1); /* wait for errors to come back through signal handling */
1721         fprintf(stdout, "%s: pfkey_sig_handler called.\n", program_name);
1722         pfkey_sig_handler(0); /* solicit upmsg */
1723 #endif
1724         if(pfkey_msg) {
1725                 pfkey_extensions_free(extensions);
1726                 pfkey_msg_free(&pfkey_msg);
1727         }
1728         if(debug) {
1729                 fprintf(stdout, "%s: pfkey message buffer freed.\n",
1730                         program_name);
1731         }
1732         (void) close(pfkey_sock);  /* close the socket */
1733         if(authkey) {
1734                 memset((caddr_t)authkey, 0, authkeylen);
1735                 free(authkey);
1736         }
1737         if(enckey) {
1738                 memset((caddr_t)enckey, 0, enckeylen);
1739                 free(enckey);
1740         }
1741         if(iv) {
1742                 memset((caddr_t)iv, 0, ivlen);
1743                 free(iv);
1744         }
1745         exit(0);
1746 }
1747
1748 /*
1749  * $Log: spi.c,v $
1750  * Revision 1.84  2002/03/08 21:44:04  rgb
1751  * Update for all GNU-compliant --version strings.
1752  *
1753  * Revision 1.83  2002/02/20 00:01:53  rgb
1754  * Cleaned out unused code.
1755  *
1756  * Revision 1.82  2001/11/09 02:16:37  rgb
1757  * Fixed bug that erroneously required explicit af parameter for --said.
1758  * Fixed missing SA message on delete.
1759  *
1760  * Revision 1.81  2001/11/06 20:18:47  rgb
1761  * Added lifetime parameters.
1762  *
1763  * Revision 1.80  2001/10/25 06:57:10  rgb
1764  * Added space as legal delimiter in lifetime parameter list.
1765  *
1766  * Revision 1.79  2001/10/24 03:23:55  rgb
1767  * Moved lifetime option parsing to a seperate function and allowed for
1768  * comma-seperated lists of lifetime parameters.
1769  * Moved SATYPE registrations to a seperate function.
1770  *
1771  * Revision 1.78  2001/10/22 19:49:35  rgb
1772  * Added lifetime parameter capabilities.
1773  *
1774  * Revision 1.77  2001/10/02 17:17:17  rgb
1775  * Check error return for all "tto*" calls and report errors.  This, in
1776  * conjuction with the fix to "tto*" will detect AF not set.
1777  *
1778  * Revision 1.76  2001/09/08 21:13:35  rgb
1779  * Added pfkey ident extension support for ISAKMPd. (NetCelo)
1780  *
1781  * Revision 1.75  2001/09/07 22:24:42  rgb
1782  * Added EAFNOSUPPORT socket open error code in case KLIPS is not loaded.
1783  *
1784  * Revision 1.74  2001/06/14 19:35:14  rgb
1785  * Update copyright date.
1786  *
1787  * Revision 1.73  2001/05/30 08:14:05  rgb
1788  * Removed vestiges of esp-null transforms.
1789  *
1790  * Revision 1.72  2001/05/21 02:02:55  rgb
1791  * Eliminate 1-letter options.
1792  *
1793  * Revision 1.71  2001/05/16 05:07:20  rgb
1794  * Fixed --label option in KLIPS manual utils to add the label to the
1795  * command name rather than replace it in error text.
1796  * Fix 'print table' non-option in KLIPS manual utils to deal with --label
1797  * and --debug options.
1798  *
1799  * Revision 1.70  2000/11/06 04:36:57  rgb
1800  * Display conversion on replay_window failure.
1801  * Don't register SATYPEs for manual.
1802  *
1803  * Revision 1.69  2000/09/28 00:37:20  rgb
1804  * Swapped order of pfkey_registration of IPCOMP and IPIP.
1805  *
1806  * Revision 1.68  2000/09/17 18:56:48  rgb
1807  * Added IPCOMP support.
1808  *
1809  * Revision 1.67  2000/09/12 22:36:45  rgb
1810  * Gerhard's IPv6 support.
1811  *
1812  * Revision 1.66  2000/09/08 19:17:31  rgb
1813  * Removed all references to CONFIG_IPSEC_PFKEYv2.
1814  *
1815  * Revision 1.65  2000/08/30 05:34:54  rgb
1816  * Minor clean-up.
1817  *
1818  * Revision 1.64  2000/08/27 01:50:51  rgb
1819  * Update copyright dates and fix replay window endian bug.
1820  *
1821  * Revision 1.63  2000/08/18 21:19:27  rgb
1822  * Removed no longer used resolve_ip() code.
1823  *
1824  * Revision 1.62  2000/08/01 14:51:53  rgb
1825  * Removed _all_ remaining traces of DES.
1826  *
1827  * Revision 1.61  2000/07/26 20:48:42  rgb
1828  * Fixed typo that caused compile failure.
1829  *
1830  * Revision 1.60  2000/07/26 03:41:46  rgb
1831  * Changed all printf's to fprintf's.  Fixed tncfg's usage to stderr.
1832  *
1833  * Revision 1.59  2000/06/21 16:51:27  rgb
1834  * Added no additional argument option to usage text.
1835  *
1836  * Revision 1.58  2000/03/16 06:40:49  rgb
1837  * Hardcode PF_KEYv2 support.
1838  *
1839  * Revision 1.57  2000/01/22 23:22:46  rgb
1840  * Use new function proto2satype().
1841  *
1842  * Revision 1.56  2000/01/21 09:42:32  rgb
1843  * Replace resolve_ip() with atoaddr() from freeswanlib.
1844  *
1845  * Revision 1.55  2000/01/21 06:24:57  rgb
1846  * Blasted any references in usage and code to deleted algos.
1847  * Removed DES usage.
1848  * Changed usage of memset on extensions to pfkey_extensions_init().
1849  *
1850  * Revision 1.54  1999/12/29 21:17:41  rgb
1851  * Changed pfkey_msg_build() I/F to include a struct sadb_msg**
1852  * parameter for cleaner manipulation of extensions[] and to guard
1853  * against potential memory leaks.
1854  * Changed the I/F to pfkey_msg_free() for the same reason.
1855  *
1856  * Revision 1.53  1999/12/10 17:35:37  rgb
1857  * Added address debugging.
1858  * Fixed undetected spi followed by said sanity check bug.
1859  * Fixed unset spi and edst using said bug.
1860  *
1861  * Revision 1.52  1999/12/09 23:13:53  rgb
1862  * Added argument to pfkey_sa_build() to do eroutes.
1863  *
1864  * Revision 1.51  1999/12/07 18:29:13  rgb
1865  * Converted local functions to static to limit scope.
1866  * Removed unused cruft.
1867  * Changed types to unsigned to quiet compiler.
1868  * Cleaned up compiler directives.
1869  *
1870  * Revision 1.50  1999/12/01 22:19:04  rgb
1871  * Change pfkey_sa_build to accept an SPI in network byte order.
1872  * Minor reformatting.
1873  * Close socket after cleanup.
1874  * Moved pfkey_lib_debug variable into the library.
1875  *
1876  * Revision 1.49  1999/11/27 11:53:56  rgb
1877  * Fix pfkey_v2_parse calls.
1878  * Add argument to pfkey_msg_parse() for direction.
1879  * Move parse-after-build check inside pfkey_msg_build().
1880  *
1881  * Revision 1.48  1999/11/25 19:05:12  rgb
1882  * Add parser calls to parse newly built message and disabled signal
1883  * handler.
1884  * Zapped all manual pfkey assignment code in favour of build library
1885  * calls.
1886  * Clean out other unused code.
1887  *
1888  * Revision 1.47  1999/11/25 09:08:46  rgb
1889  * Turn debug compiler directive into command line switch.
1890  * Fix unused argument bug in usage.
1891  * Delete unused variables and code.
1892  * Add default to alg switch to catch algo not set.
1893  * Added error return checking from pfkey_build routines.
1894  * Clarified assignment in conditional with parens.
1895  * Fixed extension pointer bugs passing args to pfkey_build routines.
1896  *
1897  * Revision 1.46  1999/11/24 17:22:25  rgb
1898  * Fix PFKEY_BUILD_LIB compiler directives.
1899  * Fix bug in memset(extensions) size argument.
1900  * Fix bug in extensions type and calling style.
1901  * Fix PFKEY_BUILD_LIB ifdef boundary bug.
1902  *
1903  * Revision 1.45  1999/11/23 23:11:18  rgb
1904  * Added pfkey_v2_build calls.
1905  * Sort out pfkey and freeswan headers, putting them in a library path.
1906  * Corrected a couple of bugs in as-yet-inactive code.
1907  * Clarified indention of pfkey_msg assembly code.
1908  *
1909  * Revision 1.44  1999/11/18 04:56:07  rgb
1910  * Change expected signal type comment.
1911  * Add signal handler degugging code.
1912  * Temporarily remove select() code for signal debugging.
1913  * Fix minor sequence number bug.
1914  *
1915  * Revision 1.43  1999/10/27 20:01:01  rgb
1916  * Enabled the signal handler.
1917  * Changed pfkey_seq from post-increment to pre-increment.
1918  *
1919  * Revision 1.42  1999/10/16 00:26:34  rgb
1920  * Add to pfkey lifetime support.
1921  * Attempt to add pfkey socket receive support.
1922  * Change to more intuitive name of pfkey socket variable.
1923  *
1924  * Revision 1.41  1999/07/08 19:18:33  rgb
1925  * Shut off debugging by default.
1926  *
1927  * Revision 1.40  1999/06/10 16:12:53  rgb
1928  * Add autoconf to use pfkey.
1929  * Add error return code description.
1930  *
1931  * Revision 1.39  1999/04/29 15:26:54  rgb
1932  * Debug pfkey support.
1933  * Add debugging instrumentation.
1934  * Add error return code checks.
1935  * Add support for DELETE and CLR messages.
1936  * Add support for IPPROTO_IPIP.
1937  * Copy in src address.
1938  * Set sin_zero properly.
1939  * Add ident_d support(untested).
1940  * Fix msg header copy length bug.
1941  * Add kludge to support FLUSH.
1942  *
1943  * Revision 1.38  1999/04/15 15:37:28  rgb
1944  * Forward check changes from POST1_00 branch.
1945  *
1946  * Revision 1.34.2.2  1999/04/13 20:58:10  rgb
1947  * Add argc==1 --> /proc/net/ipsec_*.
1948  *
1949  * Revision 1.34.2.1  1999/03/30 17:07:04  rgb
1950  * Make main() return type explicit.
1951  * Add pfkey code.
1952  * OOO window size htons bugfix.
1953  *
1954  * Revision 1.37  1999/04/11 00:12:08  henry
1955  * GPL boilerplate
1956  *
1957  * Revision 1.36  1999/04/06 04:54:38  rgb
1958  * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
1959  * patch shell fixes.
1960  *
1961  * Revision 1.35  1999/03/17 15:40:07  rgb
1962  * Make explicit main() return type of int.
1963  * Fix memory clear bug in spi.c.
1964  *
1965  * Revision 1.34  1999/02/16 05:20:49  rgb
1966  * Fix memory clear bugs just prior to normal exit that were causing ipsec
1967  * manual scripts to fail and potentially leaving large core files.
1968  *
1969  * Revision 1.33  1999/02/09 00:13:16  rgb
1970  * Fix replay window htonl bug.
1971  *
1972  * Revision 1.32  1999/01/22 06:35:54  rgb
1973  * 64-bit clean-up.
1974  * Added algorithm switch code.
1975  * Removed IV requirement, now an option (kept code for back-compat).
1976  * Cruft clean-out.
1977  * Add error-checking.
1978  * Removed PFKEY code, will re-add later.
1979  *
1980  * Revision 1.31  1998/11/12 21:08:04  rgb
1981  * Add --label option to identify caller from scripts.
1982  *
1983  * Revision 1.30  1998/11/11 18:34:12  rgb
1984  * Fixed #includes for RH5.1.
1985  *
1986  * Revision 1.29  1998/11/11 07:14:18  rgb
1987  * #include cleanup to hopefully compile under RH5.1.
1988  *
1989  * Revision 1.28  1998/11/10 05:34:11  rgb
1990  * Add support for SA direction flag.
1991  * Add more specific error output messages.
1992  *
1993  * Revision 1.27  1998/10/27 00:31:12  rgb
1994  * Set replay structure flag to 0 (not used).
1995  *
1996  * Revision 1.26  1998/10/26 01:28:38  henry
1997  * use SA_* protocol names, not IPPROTO_*, to avoid compile problems
1998  *
1999  * Revision 1.25  1998/10/25 02:45:39  rgb
2000  * Change program to program_name to bring in line with other utils.
2001  * Added debugging code to find null proto bug, premature exit on hex info bug.
2002  * Fixed premature exit on hex info bug.
2003  *
2004  * Revision 1.24  1998/10/22 06:34:16  rgb
2005  * Fixed bad stucture pointer.
2006  * Fixed unknown var (cut and paste error).
2007  *
2008  * Revision 1.23  1998/10/19 18:56:24  rgb
2009  * Added inclusion of freeswan.h.
2010  * sa_id structure implemented and used: now includes protocol.
2011  * Start to add some inactive pfkey2 code.
2012  *
2013  * Revision 1.22  1998/10/09 18:47:30  rgb
2014  * Add 'optionfrom' to get more options from a named file.
2015  *
2016  * Revision 1.21  1998/10/09 04:36:03  rgb
2017  * Standardise on '-96' notation for AH transforms.
2018  *
2019  * Revision 1.20  1998/09/03 01:29:32  henry
2020  * improve atodata()-failed error messages a bit
2021  *
2022  * Revision 1.19  1998/09/02 03:14:33  henry
2023  * no point in printing zero lengths used as error returns
2024  *
2025  * Revision 1.18  1998/09/02 03:12:08  henry
2026  * --help output goes on stdout, not stderr
2027  *
2028  * Revision 1.17  1998/09/01 19:50:50  henry
2029  * fix operator-precedence bug that often messed up --ah SPI creation
2030  * minor cleanup
2031  *
2032  * Revision 1.16  1998/08/28 03:14:12  rgb
2033  * Simplify/Clarify usage text.
2034  *
2035  * Revision 1.15  1998/08/12 00:16:46  rgb
2036  * Removed a lot of old cruft that was commented out.
2037  * Updated usage text.
2038  * Added config options for new xforms.
2039  *
2040  * Revision 1.14  1998/08/05 22:24:45  rgb
2041  * Change includes to accomodate RH5.x
2042  *
2043  * Revision 1.13  1998/07/29 21:41:17  rgb
2044  * Fix spi bug, add hexadecimal value entry debugging.
2045  *
2046  * Revision 1.12  1998/07/28 00:14:24  rgb
2047  * Convert from positional parameters to long options.
2048  * Add --clean option.
2049  * Add hostname lookup support.
2050  *
2051  * Revision 1.11  1998/07/14 18:15:55  rgb
2052  * Fix undetected bug using AH-SHA1 with manual keying:  The key was
2053  * truncated by the data structure used to get it to the kernel.
2054  *
2055  * Revision 1.10  1998/07/09 18:14:11  rgb
2056  * Added error checking to IP's and keys.
2057  * Made most error messages more specific rather than spamming usage text.
2058  * Added more descriptive kernel error return codes and messages.
2059  * Converted all spi translations to unsigned.
2060  * Removed all invocations of perror.
2061  *
2062  * Revision 1.9  1998/06/30 18:04:31  rgb
2063  * Fix compiler warning: couldn't find 'struct option' prototype.
2064  *
2065  * Revision 1.8  1998/06/11 05:40:04  rgb
2066  * Make usage text more concise WRT replay window sizes and defaults.
2067  * Make error reporting more concise WRT exact IV and key lengths supported
2068  * and their units.
2069  *
2070  * Revision 1.7  1998/06/08 17:54:58  rgb
2071  * Fixed string escape code in usage.
2072  *
2073  * Revision 1.6  1998/06/05 02:22:49  rgb
2074  * Clarify usage text and update for key splitting and i/r removal.
2075  * Require keys of exact length.
2076  *
2077  * Revision 1.5  1998/05/27 20:54:11  rgb
2078  * Added --help and --version directives.  Separated auth and encr keys.
2079  *
2080  * Revision 1.4  1998/05/18 21:12:13  rgb
2081  * Clean up debugging code, clean up after keys, cleaner options setting.
2082  *
2083  * Revision 1.3  1998/05/06 03:37:11  rgb
2084  * Fixed incorrect signed interpretation of command line spi to unsigned long.
2085  * It prevented deletion of ~spi values generated by pluto.
2086  *
2087  * Revision 1.2  1998/05/01 23:34:01  rgb
2088  * Clarified the usage text.
2089  *
2090  * Revision 1.1.1.1  1998/04/08 05:35:10  henry
2091  * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
2092  *
2093  * Revision 0.5  1997/06/03 04:31:55  ji
2094  * Added esp 3des-md5-96
2095  *
2096  * Revision 0.4  1997/01/15 01:37:54  ji
2097  * New program in this release, replaces set* programs.
2098  *
2099  *
2100  */