OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / utils / eroute.c
1 /*
2  * manipulate eroutes
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 eroute_c_version[] = "RCSID $Id: eroute.c,v 1.49 2002/03/08 21:44:04 rgb Exp $";
18
19
20 #include <sys/types.h>
21 #include <linux/types.h> /* new */
22 #include <string.h>
23 #include <errno.h>
24 #include <stdlib.h> /* system(), strtoul() */
25
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <netdb.h>
32
33
34 #include <unistd.h>
35 #include <freeswan.h>
36 #include <signal.h>
37 #include <pfkeyv2.h>
38 #include <pfkey.h>
39 #include "radij.h"
40 #include "ipsec_encap.h"
41 #include "ipsec_netlink.h"
42
43
44 #include <stdio.h>
45 #include <getopt.h>
46
47 char *program_name;
48 char me[] = "ipsec eroute";
49 extern char *optarg;
50 extern int optind, opterr, optopt;
51 char *eroute_af_opt, *said_af_opt, *edst_opt, *spi_opt, *proto_opt, *said_opt, *dst_opt, *src_opt;
52 int action_type = 0;
53
54 extern unsigned int pfkey_lib_debug; /* used by libfreeswan/pfkey_v2_build */
55 int pfkey_sock;
56 fd_set pfkey_socks;
57 uint32_t pfkey_seq = 0;
58
59 static void
60 usage(char* arg)
61 {
62         fprintf(stdout, "usage: %s --{add,addin,replace} --eraf <inet | inet6> --src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask> <SA>\n", arg);
63         fprintf(stdout, "            where <SA> is '--af <inet | inet6> --edst <edst> --spi <spi> --proto <proto>'\n");
64         fprintf(stdout, "                       OR '--said <said>'\n");
65         fprintf(stdout, "                       OR '--said <%%passthrough | %%passthrough4 | %%passthrough6 | %%drop | %%reject | %%trap | %%hold | %%pass>'.\n");
66         fprintf(stdout, "       %s --del --eraf <inet | inet6>--src <src>/<srcmaskbits>|<srcmask> --dst <dst>/<dstmaskbits>|<dstmask>\n", arg);
67         fprintf(stdout, "       %s --clear\n", arg);
68         fprintf(stdout, "       %s --help\n", arg);
69         fprintf(stdout, "       %s --version\n", arg);
70         fprintf(stdout, "       %s\n", arg);
71         fprintf(stdout, "        [ --debug ] is optional to any %s command.\n", arg);
72         fprintf(stdout, "        [ --label <label> ] is optional to any %s command.\n", arg);
73 exit(1);
74 }
75
76 static struct option const longopts[] =
77 {
78         {"dst", 1, 0, 'D'},
79         {"src", 1, 0, 'S'},
80         {"eraf", 1, 0, 'f'},
81         {"add", 0, 0, 'a'},
82         {"addin", 0, 0, 'A'},
83         {"replace", 0, 0, 'r'},
84         {"clear", 0, 0, 'c'},
85         {"del", 0, 0, 'd'},
86         {"af", 1, 0, 'i'},
87         {"edst", 1, 0, 'e'},
88         {"proto", 1, 0, 'p'},
89         {"help", 0, 0, 'h'},
90         {"spi", 1, 0, 's'},
91         {"said", 1, 0, 'I'},
92         {"version", 0, 0, 'v'},
93         {"label", 1, 0, 'l'},
94         {"optionsfrom", 1, 0, '+'},
95         {"debug", 0, 0, 'g'},
96         {0, 0, 0, 0}
97 };
98
99 int
100 main(int argc, char **argv)
101 {
102 /*      int fd; */
103         char *endptr;
104 /*      int ret; */
105         int c, previous = -1;
106         const char* error_s;
107         int debug = 0;
108
109         int error = 0;
110
111         char ipaddr_txt[ADDRTOT_BUF];                
112         struct sadb_ext *extensions[SADB_EXT_MAX + 1];
113         struct sadb_msg *pfkey_msg;
114         ip_address pfkey_address_s_ska;
115         /*struct sockaddr_in pfkey_address_d_ska;*/
116         ip_address pfkey_address_sflow_ska;
117         ip_address pfkey_address_dflow_ska;
118         ip_address pfkey_address_smask_ska;
119         ip_address pfkey_address_dmask_ska;
120
121         ip_said said;
122         ip_subnet s_subnet, d_subnet;
123         int eroute_af = 0;
124         int said_af = 0;
125
126         int argcount = argc;
127
128         program_name = argv[0];
129         eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL;
130
131         while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF) {
132                 switch(c) {
133                 case 'g':
134                         debug = 1;
135                         pfkey_lib_debug = 1;
136                         argcount--;
137                         break;
138                 case 'a':
139                         if(action_type) {
140                                 fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
141                                         program_name);
142                                 exit(1);
143                         }
144                         action_type = EMT_SETEROUTE;
145                         break;
146                 case 'A':
147                         if(action_type) {
148                                 fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
149                                         program_name);
150                                 exit(1);
151                         }
152                         action_type = EMT_INEROUTE;
153                         break;
154                 case 'r':
155                         if(action_type) {
156                                 fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
157                                         program_name);
158                                 exit(1);
159                         }
160                         action_type = EMT_REPLACEROUTE;
161                         break;
162                 case 'c':
163                         if(action_type) {
164                                 fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
165                                         program_name);
166                                 exit(1);
167                         }
168                         action_type = EMT_CLREROUTE;
169                         break;
170                 case 'd':
171                         if(action_type) {
172                                 fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n",
173                                         program_name);
174                                 exit(1);
175                         }
176                         action_type = EMT_DELEROUTE;
177                         break;
178                 case 'e':
179                         if(said_opt) {
180                                 fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n",
181                                         program_name, optarg, said_opt);
182                                 exit (1);
183                         }                               
184                         if(edst_opt) {
185                                 fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n",
186                                         program_name, optarg, edst_opt);
187                                 exit (1);
188                         }                               
189                         error_s = ttoaddr(optarg, 0, said_af, &said.dst);
190                         if(error_s != NULL) {
191                                 fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n",
192                                         program_name, error_s, optarg);
193                                 exit (1);
194                         }
195                         edst_opt = optarg;
196                         break;
197                 case 'h':
198                 case '?':
199                         usage(program_name);
200                         exit(1);
201                 case 's':
202                         if(said_opt) {
203                                 fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n",
204                                         program_name, optarg, said_opt);
205                                 exit (1);
206                         }                               
207                         if(spi_opt) {
208                                 fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n",
209                                         program_name, optarg, spi_opt);
210                                 exit (1);
211                         }                               
212                         said.spi = htonl(strtoul(optarg, &endptr, 0));
213                         if(!(endptr == optarg + strlen(optarg))) {
214                                 fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n",
215                                         program_name, optarg);
216                                 exit (1);
217                         }
218                         if(ntohl(said.spi) < 0x100) {
219                                 fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%lx Must be larger than 0x100.\n",
220                                         program_name, optarg, ntohl(said.spi));
221                                 exit(1);
222                         }
223                         spi_opt = optarg;
224                         break;
225                 case 'p':
226                         if(said_opt) {
227                                 fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n",
228                                         program_name, optarg, said_opt);
229                                 exit (1);
230                         }                               
231                         if(proto_opt) {
232                                 fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n",
233                                         program_name, optarg, proto_opt);
234                                 exit (1);
235                         }
236 #if 0
237                         if(said.proto) {
238                                 fprintf(stderr, "%s: Warning, PROTO parameter redefined:%s\n",
239                                         program_name, optarg);
240                                 exit (1);
241                         }
242 #endif
243                         if(!strcmp(optarg, "ah"))
244                                 said.proto = SA_AH;
245                         if(!strcmp(optarg, "esp"))
246                                 said.proto = SA_ESP;
247                         if(!strcmp(optarg, "tun"))
248                                 said.proto = SA_IPIP;
249                         if(!strcmp(optarg, "comp"))
250                                 said.proto = SA_COMP;
251                         if(said.proto == 0) {
252                                 fprintf(stderr, "%s: Invalid PROTO parameter: %s\n",
253                                         program_name, optarg);
254                                 exit (1);
255                         }
256                         proto_opt = optarg;
257                         break;
258                 case 'I':
259                         if(said_opt) {
260                                 fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n",
261                                         program_name, optarg, said_opt);
262                                 exit (1);
263                         }                               
264                         if(proto_opt) {
265                                 fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n",
266                                         program_name, optarg, proto_opt);
267                                 exit (1);
268                         }
269                         if(edst_opt) {
270                                 fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n",
271                                         program_name, optarg, edst_opt);
272                                 exit (1);
273                         }
274                         if(spi_opt) {
275                                 fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n",
276                                         program_name, optarg, spi_opt);
277                                 exit (1);
278                         }
279                         if(said_af_opt) {
280                                 fprintf(stderr, "%s: Error, address family parameter redefined in SA:%s, already defined as:%s\n",
281                                         program_name, optarg, said_af_opt);
282                                 exit (1);
283                         }
284                         error_s = ttosa(optarg, 0, &said);
285                         if(error_s != NULL) {
286                                 fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n",
287                                         program_name, error_s, optarg);
288                                 exit (1);
289                         } else if(ntohl(said.spi) < 0x100){
290                                 fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n",
291                                         program_name, optarg, said.spi);
292                                 exit(1);
293                         }
294                         said_af = addrtypeof(&said.dst);
295                         said_opt = optarg;
296                         break;
297                 case 'v':
298                         fprintf(stdout, "%s %s\n", me, ipsec_version_code());
299                         fprintf(stdout, "See `ipsec --copyright' for copyright information.\n");
300                         exit(1);
301                 case 'D':
302                         if(dst_opt) {
303                                 fprintf(stderr, "%s: Error, --dst parameter redefined:%s, already defined as:%s\n",
304                                         program_name, optarg, dst_opt);
305                                 exit (1);
306                         }                               
307                         error_s = ttosubnet(optarg, 0, eroute_af, &d_subnet);
308                         if (error_s != NULL) {
309                                 fprintf(stderr, "%s: Error, %s converting --dst argument: %s\n",
310                                         program_name, error_s, optarg);
311                                 exit (1);
312                         }
313                         dst_opt = optarg;
314                         break;
315                 case 'S':
316                         if(src_opt) {
317                                 fprintf(stderr, "%s: Error, --src parameter redefined:%s, already defined as:%s\n",
318                                         program_name, optarg, src_opt);
319                                 exit (1);
320                         }                               
321                         error_s = ttosubnet(optarg, 0, eroute_af, &s_subnet);
322                         if (error_s != NULL) {
323                                 fprintf(stderr, "%s: Error, %s converting --src argument: %s\n",
324                                         program_name, error_s, optarg);
325                                 exit (1);
326                         }
327                         src_opt = optarg;
328                         break;
329                 case 'l':
330                         program_name = malloc(strlen(argv[0])
331                                               + 10 /* update this when changing the sprintf() */
332                                               + strlen(optarg));
333                         sprintf(program_name, "%s --label %s",
334                                 argv[0],
335                                 optarg);
336                         argcount -= 2;
337                         break;
338                 case 'i': /* specifies the address family of the SAID, stored in said_af */
339                         if(said_af_opt) {
340                                 fprintf(stderr, "%s: Error, address family of SAID redefined:%s, already defined as:%s\n",
341                                         program_name, optarg, said_af_opt);
342                                 exit (1);
343                         }                               
344                         if(!strcmp(optarg, "inet"))
345                                 said_af = AF_INET;
346                         if(!strcmp(optarg, "inet6"))
347                                 said_af = AF_INET6;
348                         if(said_af == 0) {
349                                 fprintf(stderr, "%s: Invalid address family parameter for SAID: %s\n",
350                                         program_name, optarg);
351                                 exit (1);
352                         }
353                         said_af_opt = optarg;
354                         break;
355                 case 'f': /* specifies the address family of the eroute, stored in eroute_af */
356                         if(eroute_af_opt) {
357                                 fprintf(stderr, "%s: Error, address family of eroute redefined:%s, already defined as:%s\n",
358                                         program_name, optarg, eroute_af_opt);
359                                 exit (1);
360                         }                               
361                         if(!strcmp(optarg, "inet"))
362                                 eroute_af = AF_INET;
363                         if(!strcmp(optarg, "inet6"))
364                                 eroute_af = AF_INET6;
365                         if(eroute_af == 0) {
366                                 fprintf(stderr, "%s: Invalid address family parameter for eroute: %s\n",
367                                         program_name, optarg);
368                                 exit (1);
369                         }
370                         eroute_af_opt = optarg;
371                         break;
372                 case '+': /* optionsfrom */
373                         optionsfrom(optarg, &argc, &argv, optind, stderr);
374                         /* no return on error */
375                         break;
376                 default:
377                         break;
378                 }
379                 previous = c;
380         }
381
382         if(debug) {
383                 fprintf(stdout, "%s: DEBUG: argc=%d\n", program_name, argc);
384         }
385         
386         if(argcount == 1) {
387                 system("cat /proc/net/ipsec_eroute");
388                 exit(0);
389         }
390
391         /* Sanity checks */
392
393         if(debug) {
394                 fprintf(stdout, "%s: DEBUG: action_type=%d\n", program_name, action_type);
395         }
396
397         switch(action_type) {
398         case EMT_SETEROUTE:
399         case EMT_REPLACEROUTE:
400         case EMT_INEROUTE:
401                 if(!(said_af_opt && edst_opt && spi_opt && proto_opt) && !(said_opt)) {
402                         fprintf(stderr, "%s: add and addin options must have SA specified.\n",
403                                 program_name);
404                         exit(1);
405                 }
406         case EMT_DELEROUTE:
407                 if(!src_opt) {
408                         fprintf(stderr, "%s: Error -- %s option '--src' is required.\n",
409                                 program_name, (action_type == EMT_SETEROUTE) ? "add" : "del");
410                         exit(1);
411                 }
412                 if(!dst_opt) {
413                         fprintf(stderr, "%s: Error -- %s option '--dst' is required.\n",
414                                 program_name, (action_type == EMT_SETEROUTE) ? "add" : "del");
415                         exit(1);
416                 }
417         case EMT_CLREROUTE:
418                 break;
419         default:
420                 fprintf(stderr, "%s: exactly one of '--add', '--addin', '--replace', '--del' or '--clear' options must be specified.\n"
421                         "Try %s --help' for usage information.\n",
422                         program_name, program_name);
423                 exit(1);
424         }
425
426         if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) {
427                 fprintf(stderr, "%s: Trouble openning PF_KEY family socket with error: ",
428                         program_name);
429                 switch(errno) {
430                 case ENOENT:
431                         fprintf(stderr, "device does not exist.  See FreeS/WAN installation procedure.\n");
432                         break;
433                 case EACCES:
434                         fprintf(stderr, "access denied.  ");
435                         if(getuid() == 0) {
436                                 fprintf(stderr, "Check permissions.  Should be 600.\n");
437                         } else {
438                                 fprintf(stderr, "You must be root to open this file.\n");
439                         }
440                         break;
441                 case EUNATCH:
442                         fprintf(stderr, "KLIPS not loaded.\n");
443                         break;
444                 case ENODEV:
445                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
446                         break;
447                 case EBUSY:
448                         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");
449                         break;
450                 case EINVAL:
451                         fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n");
452                         break;
453                 case ENOBUFS:
454                 case ENOMEM:
455                 case ENFILE:
456                         fprintf(stderr, "No kernel memory to allocate socket.\n");
457                         break;
458                 case EMFILE:
459                         fprintf(stderr, "Process file table overflow.\n");
460                         break;
461                 case ESOCKTNOSUPPORT:
462                         fprintf(stderr, "Socket type not supported.\n");
463                         break;
464                 case EPROTONOSUPPORT:
465                         fprintf(stderr, "Protocol version not supported.\n");
466                         break;
467                 case EAFNOSUPPORT:
468                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
469                         break;
470                 default:
471                         fprintf(stderr, "Unknown file open error %d.  Please report as much detail as possible to development team.\n", errno);
472                 }
473                 exit(1);
474         }
475
476         if(debug) {
477                 fprintf(stdout, "%s: DEBUG: PFKEYv2 socket successfully openned=%d.\n", program_name, pfkey_sock);
478         }
479
480         /* Build an SADB_X_ADDFLOW or SADB_X_DELFLOW message to send down. */
481         /* It needs <base, SA, address(SD), flow(SD), mask(SD)> minimum. */
482         pfkey_extensions_init(extensions);
483         if((error = pfkey_msg_hdr_build(&extensions[0],
484                                         (action_type == EMT_SETEROUTE
485                                          || action_type == EMT_REPLACEROUTE
486                                          || action_type == EMT_INEROUTE)
487                                         ? SADB_X_ADDFLOW : SADB_X_DELFLOW,
488                                         proto2satype(said.proto),
489                                         0,
490                                         ++pfkey_seq,
491                                         getpid()))) {
492                 fprintf(stderr, "%s: Trouble building message header, error=%d.\n",
493                         program_name, error);
494                 pfkey_extensions_free(extensions);
495                 exit(1);
496         }
497
498         if(debug) {
499                 fprintf(stdout, "%s: DEBUG: pfkey_msg_hdr_build successfull.\n", program_name);
500         }
501
502         switch(action_type) {
503         case EMT_SETEROUTE:
504         case EMT_REPLACEROUTE:
505         case EMT_INEROUTE:
506         case EMT_CLREROUTE:
507                 if((error = pfkey_sa_build(&extensions[SADB_EXT_SA],
508                                            SADB_EXT_SA,
509                                            said.spi, /* in network order */
510                                            0,
511                                            0,
512                                            0,
513                                            0,
514                                            (action_type == EMT_CLREROUTE) ? SADB_X_SAFLAGS_CLEARFLOW : 0))) {
515                         fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n",
516                                 program_name, error);
517                         pfkey_extensions_free(extensions);
518                         exit(1);
519                 }
520                 if(debug) {
521                         fprintf(stdout, "%s: DEBUG: pfkey_sa_build successful.\n", program_name);
522                 }
523
524         default:
525                 break;
526         }
527
528         switch(action_type) {
529         case EMT_SETEROUTE:
530         case EMT_REPLACEROUTE:
531         case EMT_INEROUTE:
532                 anyaddr(said_af, &pfkey_address_s_ska);
533                 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC],
534                                                 SADB_EXT_ADDRESS_SRC,
535                                                 0,
536                                                 0,
537                                                 sockaddrof(&pfkey_address_s_ska)))) {
538                         addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
539                         fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n",
540                                 program_name, ipaddr_txt, error);
541                         pfkey_extensions_free(extensions);
542                         exit(1);
543                 }
544                 if(debug) {
545                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src.\n", program_name);
546                 }
547
548                 if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST],
549                                                 SADB_EXT_ADDRESS_DST,
550                                                 0,
551                                                 0,
552                                                 sockaddrof(&said.dst)))) {
553                         addrtot(&said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt));
554                         fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n",
555                                 program_name, ipaddr_txt, error);
556                         pfkey_extensions_free(extensions);
557                         exit(1);
558                 }
559                 if(debug) {
560                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst.\n", program_name);
561                 }
562         default:
563                 break;
564         }
565         
566         switch(action_type) {
567         case EMT_SETEROUTE:
568         case EMT_REPLACEROUTE:
569         case EMT_INEROUTE:
570         case EMT_DELEROUTE:
571                 networkof(&s_subnet, &pfkey_address_sflow_ska); /* src flow */
572                 if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_FLOW],
573                                                 SADB_X_EXT_ADDRESS_SRC_FLOW,
574                                                 0,
575                                                 0,
576                                                 sockaddrof(&pfkey_address_sflow_ska)))) {
577                         addrtot(&pfkey_address_sflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
578                         fprintf(stderr, "%s: Trouble building address_sflow extension (%s), error=%d.\n",
579                                 program_name, ipaddr_txt, error);
580                         pfkey_extensions_free(extensions);
581                         exit(1);
582                 }
583                 if(debug) {
584                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src flow.\n", program_name);
585                 }
586         
587                 networkof(&d_subnet, &pfkey_address_dflow_ska); /* dst flow */
588                 if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_FLOW],
589                                                 SADB_X_EXT_ADDRESS_DST_FLOW,
590                                                 0,
591                                                 0,
592                                                 sockaddrof(&pfkey_address_dflow_ska)))) {
593                         addrtot(&pfkey_address_dflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
594                         fprintf(stderr, "%s: Trouble building address_dflow extension (%s), error=%d.\n",
595                                 program_name, ipaddr_txt, error);
596                         pfkey_extensions_free(extensions);
597                         exit(1);
598                 }
599                 if(debug) {
600                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst flow.\n", program_name);
601                 }
602                 
603                 maskof(&s_subnet, &pfkey_address_smask_ska); /* src mask */
604                 if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_MASK],
605                                                 SADB_X_EXT_ADDRESS_SRC_MASK,
606                                                 0,
607                                                 0,
608                                                 sockaddrof(&pfkey_address_smask_ska)))) {
609                         addrtot(&pfkey_address_smask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
610                         fprintf(stderr, "%s: Trouble building address_smask extension (%s), error=%d.\n",
611                                 program_name, ipaddr_txt, error);
612                         pfkey_extensions_free(extensions);
613                         exit(1);
614                 }
615                 if(debug) {
616                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src mask.\n", program_name);
617                 }
618                 
619                 maskof(&d_subnet, &pfkey_address_dmask_ska); /* dst mask */
620                 if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_MASK],
621                                                 SADB_X_EXT_ADDRESS_DST_MASK,
622                                                 0,
623                                                 0,
624                                                 sockaddrof(&pfkey_address_dmask_ska)))) {
625                         addrtot(&pfkey_address_dmask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt));
626                         fprintf(stderr, "%s: Trouble building address_dmask extension (%s), error=%d.\n",
627                                 program_name, ipaddr_txt, error);
628                         pfkey_extensions_free(extensions);
629                         exit(1);
630                 }
631                 if(debug) {
632                         fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst mask.\n", program_name);
633                 }
634         }
635         
636         if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) {
637                 fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n",
638                         program_name, error);
639                 pfkey_extensions_free(extensions);
640                 pfkey_msg_free(&pfkey_msg);
641                 exit(1);
642         }
643         if(debug) {
644                 fprintf(stdout, "%s: DEBUG: pfkey_msg_build successful.\n", program_name);
645         }
646
647         if((error = write(pfkey_sock,
648                           pfkey_msg,
649                           pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) !=
650            pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) {
651                 fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n",
652                         program_name, error, errno);
653                 pfkey_extensions_free(extensions);
654                 pfkey_msg_free(&pfkey_msg);
655                 switch(errno) {
656                 case EINVAL:
657                         fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n");
658                         break;
659                 case ENXIO:
660                         if((action_type == EMT_SETEROUTE) ||
661                            (action_type == EMT_REPLACEROUTE)) {
662                                 fprintf(stderr, "Invalid mask.\n");
663                                 break;
664                         }
665                         if(action_type == EMT_DELEROUTE) {
666                                 fprintf(stderr, "Mask not found.\n");
667                                 break;
668                         }
669                 case EFAULT:
670                         if((action_type == EMT_SETEROUTE) ||
671                            (action_type == EMT_REPLACEROUTE)) {
672                                 fprintf(stderr, "Invalid address.\n");
673                                 break;
674                         }
675                         if(action_type == EMT_DELEROUTE) {
676                                 fprintf(stderr, "Address not found.\n");
677                                 break;
678                         }
679                 case EACCES:
680                         fprintf(stderr, "access denied.  ");
681                         if(getuid() == 0) {
682                                 fprintf(stderr, "Check permissions.  Should be 600.\n");
683                         } else {
684                                 fprintf(stderr, "You must be root to open this file.\n");
685                         }
686                         break;
687                 case EUNATCH:
688                         fprintf(stderr, "KLIPS not loaded.\n");
689                         break;
690                 case EBUSY:
691                         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");
692                         break;
693                 case ENODEV:
694                         fprintf(stderr, "KLIPS not loaded or enabled.\n");
695                         fprintf(stderr, "No device?!?\n");
696                         break;
697                 case ENOBUFS:
698                         fprintf(stderr, "No kernel memory to allocate SA.\n");
699                         break;
700                 case ESOCKTNOSUPPORT:
701                         fprintf(stderr, "Algorithm support not available in the kernel.  Please compile in support.\n");
702                         break;
703                 case EEXIST:
704                         fprintf(stderr, "eroute already in use.  Delete old one first.\n");
705                         break;
706                 case ENOENT:
707                         if((action_type == EMT_INEROUTE)) {
708                                 fprintf(stderr, "non-existant IPIP SA.\n");
709                                 break;
710                         }
711                         fprintf(stderr, "eroute doesn't exist.  Can't delete.\n");
712                         break;
713                 default:
714                         fprintf(stderr, "Unknown socket write error %d.  Please report as much detail as possible to development team.\n", errno);
715                 }
716 /*              fprintf(stderr, "%s: socket write returned errno %d\n",
717                 program_name, errno);*/
718                 exit(1);
719         }
720         if(debug) {
721                 fprintf(stdout, "%s: DEBUG: pfkey write successful.\n", program_name);
722         }
723
724         if(pfkey_msg) {
725                 pfkey_extensions_free(extensions);
726                 pfkey_msg_free(&pfkey_msg);
727         }
728
729         (void) close(pfkey_sock);  /* close the socket */
730
731         if(debug) {
732                 fprintf(stdout, "%s: DEBUG: write ok\n", program_name);
733         }
734
735         exit(0);
736 }
737 /*
738  * $Log: eroute.c,v $
739  * Revision 1.49  2002/03/08 21:44:04  rgb
740  * Update for all GNU-compliant --version strings.
741  *
742  * Revision 1.48  2002/02/15 19:54:11  rgb
743  * Purged dead code.
744  *
745  * Revision 1.47  2001/11/09 01:42:36  rgb
746  * Re-formatted usage text for clarity.
747  *
748  * Revision 1.46  2001/10/02 17:03:45  rgb
749  * Check error return for all "tto*" calls and report errors.  This, in
750  * conjuction with the fix to "tto*" will detect AF not set.
751  *
752  * Revision 1.45  2001/09/07 22:12:27  rgb
753  * Added EAFNOSUPPORT error return explanation for KLIPS not loaded.
754  *
755  * Revision 1.44  2001/07/06 19:49:33  rgb
756  * Renamed EMT_RPLACEROUTE to EMT_REPLACEROUTE for clarity and logical text
757  * searching.
758  * Added EMT_INEROUTE for supporting incoming policy checks.
759  * Added inbound policy checking code for IPIP SAs.
760  *
761  * Revision 1.43  2001/06/15 05:02:05  rgb
762  * Fixed error return messages and codes.
763  *
764  * Revision 1.42  2001/06/14 19:35:14  rgb
765  * Update copyright date.
766  *
767  * Revision 1.41  2001/05/21 02:02:54  rgb
768  * Eliminate 1-letter options.
769  *
770  * Revision 1.40  2001/05/16 04:39:57  rgb
771  * Fix --label option to add to command name rather than replace it.
772  * Fix 'print table' option to ignore --label and --debug options.
773  *
774  * Revision 1.39  2001/02/26 19:59:03  rgb
775  * Added a number of missing ntohl() conversions for debug output.
776  * Implement magic SAs %drop, %reject, %trap, %hold, %pass as part
777  * of the new SPD and to support opportunistic.
778  * Enforced spi > 0x100 requirement, now that pass uses a magic SA.
779  *
780  * Revision 1.38  2000/09/17 18:56:48  rgb
781  * Added IPCOMP support.
782  *
783  * Revision 1.37  2000/09/12 22:36:08  rgb
784  * Gerhard's IPv6 support.
785  * Restructured to remove unused extensions from CLEARFLOW messages.
786  * Added debugging.
787  *
788  * Revision 1.36  2000/09/08 19:17:31  rgb
789  * Removed all references to CONFIG_IPSEC_PFKEYv2.
790  *
791  * Revision 1.35  2000/08/27 01:46:52  rgb
792  * Update copyright dates and remove no longer used resolve_ip().
793  *
794  * Revision 1.34  2000/07/26 03:41:45  rgb
795  * Changed all printf's to fprintf's.  Fixed tncfg's usage to stderr.
796  *
797  * Revision 1.33  2000/07/13 21:54:49  rgb
798  * Remove old cruft from a time when libfreeswan didn't exist and I checked
799  * name lookup errors with the default address.
800  *
801  * Revision 1.32  2000/06/21 16:51:27  rgb
802  * Added no additional argument option to usage text.
803  *
804  * Revision 1.31  2000/03/16 06:40:49  rgb
805  * Hardcode PF_KEYv2 support.
806  *
807  * Revision 1.30  2000/01/22 23:22:46  rgb
808  * Use new function proto2satype().
809  *
810  * Revision 1.29  2000/01/21 09:42:32  rgb
811  * Replace resolve_ip() with atoaddr() from freeswanlib.
812  *
813  * Revision 1.28  2000/01/21 06:22:28  rgb
814  * Changed to AF_ENCAP macro.
815  * Added --debug switch to command line.
816  * Added pfkeyv2 support to completely avoid netlink.
817  *
818  * Revision 1.27  1999/12/07 18:27:10  rgb
819  * Added headers to silence fussy compilers.
820  * Converted local functions to static to limit scope.
821  *
822  * Revision 1.26  1999/11/25 09:07:44  rgb
823  * Fixed printf % escape bug.
824  * Clarified assignment in conditional with parens.
825  *
826  * Revision 1.25  1999/11/23 23:06:26  rgb
827  * Sort out pfkey and freeswan headers, putting them in a library path.
828  *
829  * Revision 1.24  1999/06/10 15:55:14  rgb
830  * Add error return code.
831  *
832  * Revision 1.23  1999/04/15 15:37:27  rgb
833  * Forward check changes from POST1_00 branch.
834  *
835  * Revision 1.19.2.2  1999/04/13 20:58:10  rgb
836  * Add argc==1 --> /proc/net/ipsec_*.
837  *
838  * Revision 1.19.2.1  1999/03/30 17:01:36  rgb
839  * Make main() return type explicit.
840  *
841  * Revision 1.22  1999/04/11 00:12:08  henry
842  * GPL boilerplate
843  *
844  * Revision 1.21  1999/04/06 04:54:37  rgb
845  * Fix/Add RCSID Id: and Log: bits to make PHMDs happy.  This includes
846  * patch shell fixes.
847  *
848  * Revision 1.20  1999/03/17 15:40:54  rgb
849  * Make explicit main() return type of int.
850  *
851  * Revision 1.19  1999/01/26 05:51:01  rgb
852  * Updated to use %passthrough instead of bypass.
853  *
854  * Revision 1.18  1999/01/22 06:34:52  rgb
855  * Update to include SAID command line parameter.
856  * Add IPSEC 'bypass' switch.
857  * Add error-checking.
858  * Cruft clean-out.
859  *
860  * Revision 1.17  1998/11/29 00:52:26  rgb
861  * Add explanation to warning about default source or destination.
862  *
863  * Revision 1.16  1998/11/12 21:08:03  rgb
864  * Add --label option to identify caller from scripts.
865  *
866  * Revision 1.15  1998/10/27 00:33:27  rgb
867  * Make output error text more fatal-sounding.
868  *
869  * Revision 1.14  1998/10/26 01:28:38  henry
870  * use SA_* protocol names, not IPPROTO_*, to avoid compile problems
871  *
872  * Revision 1.13  1998/10/25 02:44:56  rgb
873  * Institute more precise error return codes from eroute commands.
874  *
875  * Revision 1.12  1998/10/19 18:58:55  rgb
876  * Added inclusion of freeswan.h.
877  * a_id structure implemented and used: now includes protocol.
878  *
879  * Revision 1.11  1998/10/09 18:47:29  rgb
880  * Add 'optionfrom' to get more options from a named file.
881  *
882  * Revision 1.10  1998/10/09 04:34:58  rgb
883  * Changed help output from stderr to stdout.
884  * Changed error messages from stdout to stderr.
885  * Added '--replace' option.
886  * Deleted old commented out cruft.
887  *
888  * Revision 1.9  1998/08/18 17:18:13  rgb
889  * Delete old commented out cruft.
890  * Reduce destination and source default subnet to warning, not fatal.
891  *
892  * Revision 1.8  1998/08/05 22:24:45  rgb
893  * Change includes to accomodate RH5.x
894  *
895  * Revision 1.7  1998/07/29 20:49:08  rgb
896  * Change to use 0x-prefixed hexadecimal for spi's.
897  *
898  * Revision 1.6  1998/07/28 00:14:24  rgb
899  * Convert from positional parameters to long options.
900  * Add --clean option.
901  * Add hostname lookup support.
902  *
903  * Revision 1.5  1998/07/14 18:13:28  rgb
904  * Restructured for better argument checking.
905  * Added command to clear the eroute table.
906  *
907  * Revision 1.4  1998/07/09 18:14:10  rgb
908  * Added error checking to IP's and keys.
909  * Made most error messages more specific rather than spamming usage text.
910  * Added more descriptive kernel error return codes and messages.
911  * Converted all spi translations to unsigned.
912  * Removed all invocations of perror.
913  *
914  * Revision 1.3  1998/05/27 18:48:19  rgb
915  * Adding --help and --version directives.
916  *
917  * Revision 1.2  1998/04/13 03:15:29  rgb
918  * Commands are now distinguishable from arguments when invoking usage.
919  *
920  * Revision 1.1.1.1  1998/04/08 05:35:10  henry
921  * RGB's ipsec-0.8pre2.tar.gz ipsec-0.8
922  *
923  * Revision 0.3  1996/11/20 14:51:32  ji
924  * Fixed problems with #include paths.
925  * Changed (incorrect) references to ipsp into ipsec.
926  *
927  * Revision 0.2  1996/11/08 15:45:24  ji
928  * First limited release.
929  *
930  *
931  */