Print this page
5007142 Add ntohll and htonll to sys/byteorder.h
6717509 Need to use bswap/bswapq for byte swap of 64-bit integer on x32/x64
PSARC 2008/474
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/cmd-inet/usr.sbin/ipsecutils/ikeadm.c
+++ new/usr/src/cmd/cmd-inet/usr.sbin/ipsecutils/ikeadm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 *
21 21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
22 22 * Use is subject to license terms.
23 23 */
24 24
25 -#pragma ident "%Z%%M% %I% %E% SMI"
26 -
27 25 #include <unistd.h>
28 26 #include <stdio.h>
29 27 #include <stdarg.h>
30 28 #include <stdlib.h>
31 29 #include <sys/sysconf.h>
32 30 #include <string.h>
33 31 #include <strings.h>
34 32 #include <libintl.h>
35 33 #include <locale.h>
36 34 #include <ctype.h>
37 35 #include <time.h>
38 36 #include <sys/sysmacros.h>
39 37 #include <sys/stat.h>
40 38 #include <sys/mman.h>
41 39 #include <fcntl.h>
42 40 #include <sys/socket.h>
43 41 #include <netdb.h>
44 42 #include <errno.h>
45 43 #include <assert.h>
46 44 #include <netinet/in.h>
47 45 #include <arpa/inet.h>
48 46 #include <door.h>
49 47 #include <setjmp.h>
50 48
51 49 #include <ipsec_util.h>
52 50 #include <ikedoor.h>
53 51
54 52 static int doorfd = -1;
55 53
56 54 /*
57 55 * These are additional return values for the command line parsing
58 56 * function (parsecmd()). They are specific to this utility, but
59 57 * need to share the same space as the IKE_SVC_* defs, without conflicts.
60 58 * So they're defined relative to the end of that range.
61 59 */
62 60 #define IKEADM_HELP_GENERAL IKE_SVC_MAX + 1
63 61 #define IKEADM_HELP_GET IKE_SVC_MAX + 2
64 62 #define IKEADM_HELP_SET IKE_SVC_MAX + 3
65 63 #define IKEADM_HELP_ADD IKE_SVC_MAX + 4
66 64 #define IKEADM_HELP_DEL IKE_SVC_MAX + 5
67 65 #define IKEADM_HELP_DUMP IKE_SVC_MAX + 6
68 66 #define IKEADM_HELP_FLUSH IKE_SVC_MAX + 7
69 67 #define IKEADM_HELP_READ IKE_SVC_MAX + 8
70 68 #define IKEADM_HELP_WRITE IKE_SVC_MAX + 9
71 69 #define IKEADM_HELP_HELP IKE_SVC_MAX + 10
72 70 #define IKEADM_EXIT IKE_SVC_MAX + 11
73 71
74 72 static void
75 73 command_complete(int s)
76 74 {
77 75 if (interactive) {
78 76 longjmp(env, 1);
79 77 } else {
80 78 exit(s);
81 79 }
82 80 }
83 81
84 82 static void
85 83 usage()
86 84 {
87 85 if (!interactive) {
88 86 (void) fprintf(stderr, gettext("Usage:\t"
89 87 "ikeadm [ -hnp ] cmd obj [cmd-specific options]\n"));
90 88 (void) fprintf(stderr, gettext(" \tikeadm help\n"));
91 89 }
92 90
93 91 command_complete(1);
94 92 }
95 93
96 94 static void
97 95 print_help()
98 96 {
99 97 (void) printf(gettext("Valid commands and objects:\n"));
100 98 (void) printf(
101 99 "\tget debug|priv|stats|p1|rule|preshared|defaults [%s]\n",
102 100 gettext("identifier"));
103 101 (void) printf("\tset priv %s\n", gettext("level"));
104 102 (void) printf("\tset debug %s [%s]\n",
105 103 gettext("level"), gettext("filename"));
106 104 (void) printf("\tadd rule|preshared {%s}|%s\n",
107 105 gettext("definition"), gettext("filename"));
108 106 (void) printf("\tdel p1|rule|preshared %s\n", gettext("identifier"));
109 107 (void) printf("\tdump p1|rule|preshared\n");
110 108 (void) printf("\tflush p1\n");
111 109 (void) printf("\tread rule|preshared [%s]\n", gettext("filename"));
112 110 (void) printf("\twrite rule|preshared %s\n", gettext("filename"));
113 111 (void) printf(
114 112 "\thelp [get|set|add|del|dump|flush|read|write|help]\n");
115 113 (void) printf("\texit %s\n", gettext("exit the program"));
116 114 (void) printf("\tquit %s\n", gettext("exit the program"));
117 115 (void) printf("\n");
118 116
119 117 command_complete(0);
120 118 }
121 119
122 120 static void
123 121 print_get_help()
124 122 {
125 123 (void) printf(
126 124 gettext("This command gets information from in.iked.\n\n"));
127 125 (void) printf(gettext("Objects that may be retrieved include:\n"));
128 126 (void) printf("\tdebug\t\t");
129 127 (void) printf(gettext("the current debug level\n"));
130 128 (void) printf("\tpriv\t\t");
131 129 (void) printf(gettext("the current privilege level\n"));
132 130 (void) printf("\tstats\t\t");
133 131 (void) printf(gettext("current usage statistics\n"));
134 132 (void) printf("\tp1\t\t");
135 133 (void) printf(gettext("a phase 1 SA, identified by\n"));
136 134 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
137 135 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n"));
138 136 (void) printf("\trule\t\t");
139 137 (void) printf(gettext("a phase 1 rule, identified by its label\n"));
140 138 (void) printf("\tpreshared\t");
141 139 (void) printf(gettext("a preshared key, identified by\n"));
142 140 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
143 141 (void) printf(gettext("\t\t\t local_id remote_id\n"));
144 142 (void) printf("\n");
145 143
146 144 command_complete(0);
147 145 }
148 146
149 147 static void
150 148 print_set_help()
151 149 {
152 150 (void) printf(gettext("This command sets values in in.iked.\n\n"));
153 151 (void) printf(gettext("Objects that may be set include:\n"));
154 152 (void) printf("\tdebug\t\t");
155 153 (void) printf(gettext("change the debug level\n"));
156 154 (void) printf("\tpriv\t\t");
157 155 (void) printf(
158 156 gettext("change the privilege level (may only be lowered)\n"));
159 157 (void) printf("\n");
160 158
161 159 command_complete(0);
162 160 }
163 161
164 162 static void
165 163 print_add_help()
166 164 {
167 165 (void) printf(
168 166 gettext("This command adds items to in.iked's tables.\n\n"));
169 167 (void) printf(gettext("Objects that may be set include:\n"));
170 168 (void) printf("\trule\t\t");
171 169 (void) printf(gettext("a phase 1 policy rule\n"));
172 170 (void) printf("\tpreshared\t");
173 171 (void) printf(gettext("a preshared key\n"));
174 172 (void) printf(
175 173 gettext("\nObjects may be entered on the command-line, as a\n"));
176 174 (void) printf(
177 175 gettext("series of keywords and tokens contained in curly\n"));
178 176 (void) printf(
179 177 gettext("braces ('{', '}'); or the name of a file containing\n"));
180 178 (void) printf(gettext("the object definition may be provided.\n\n"));
181 179 (void) printf(
182 180 gettext("For security purposes, preshared keys may only be\n"));
183 181 (void) printf(
184 182 gettext("entered on the command-line if ikeadm is running in\n"));
185 183 (void) printf(gettext("interactive mode.\n"));
186 184 (void) printf("\n");
187 185
188 186 command_complete(0);
189 187 }
190 188
191 189 static void
192 190 print_del_help()
193 191 {
194 192 (void) printf(
195 193 gettext("This command deletes an item from in.iked's tables.\n\n"));
196 194 (void) printf(gettext("Objects that may be deleted include:\n"));
197 195 (void) printf("\tp1\t\t");
198 196 (void) printf(gettext("a phase 1 SA, identified by\n"));
199 197 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
200 198 (void) printf(gettext("\t\t\t init_cookie resp_cookie\n"));
201 199 (void) printf("\trule\t\t");
202 200 (void) printf(gettext("a phase 1 rule, identified by its label\n"));
203 201 (void) printf("\tpreshared\t");
204 202 (void) printf(gettext("a preshared key, identified by\n"));
205 203 (void) printf(gettext("\t\t\t local_ip remote_ip OR\n"));
206 204 (void) printf(gettext("\t\t\t local_id remote_id\n"));
207 205 (void) printf("\n");
208 206
209 207 command_complete(0);
210 208 }
211 209
212 210 static void
213 211 print_dump_help()
214 212 {
215 213 (void) printf(
216 214 gettext("This command dumps one of in.iked's tables.\n\n"));
217 215 (void) printf(gettext("Tables that may be dumped include:\n"));
218 216 (void) printf("\tp1\t\t");
219 217 (void) printf(gettext("all phase 1 SAs\n"));
220 218 (void) printf("\trule\t\t");
221 219 (void) printf(gettext("all phase 1 rules\n"));
222 220 (void) printf("\tpreshared\t");
223 221 (void) printf(gettext("all preshared keys\n"));
224 222 (void) printf("\n");
225 223
226 224 command_complete(0);
227 225 }
228 226
229 227 static void
230 228 print_flush_help()
231 229 {
232 230 (void) printf(
233 231 gettext("This command clears one of in.iked's tables.\n\n"));
234 232 (void) printf(gettext("Tables that may be flushed include:\n"));
235 233 (void) printf("\tp1\t\t");
236 234 (void) printf(gettext("all phase 1 SAs\n"));
237 235 (void) printf("\n");
238 236
239 237 command_complete(0);
240 238 }
241 239
242 240 static void
243 241 print_read_help()
244 242 {
245 243 (void) printf(
246 244 gettext("This command reads a new configuration file into\n"));
247 245 (void) printf(
248 246 gettext("in.iked, discarding the old configuration info.\n\n"));
249 247 (void) printf(gettext("Sets of data that may be read include:\n"));
250 248 (void) printf("\trule\t\t");
251 249 (void) printf(gettext("all phase 1 rules\n"));
252 250 (void) printf("\tpreshared\t");
253 251 (void) printf(gettext("all preshared keys\n\n"));
254 252 (void) printf(
255 253 gettext("A filename may be provided to specify a source file\n"));
256 254 (void) printf(gettext("other than the default.\n"));
257 255 (void) printf("\n");
258 256
259 257 command_complete(0);
260 258 }
261 259
262 260 static void
263 261 print_write_help()
264 262 {
265 263 (void) printf(
266 264 gettext("This command writes in.iked's current configuration\n"));
267 265 (void) printf(gettext("out to a config file.\n\n"));
268 266 (void) printf(gettext("Sets of data that may be written include:\n"));
269 267 (void) printf("\trule\t\t");
270 268 (void) printf(gettext("all phase 1 rules\n"));
271 269 (void) printf("\tpreshared\t");
272 270 (void) printf(gettext("all preshared keys\n\n"));
273 271 (void) printf(
274 272 gettext("A filename must be provided to specify the file to\n"));
275 273 (void) printf(gettext("which the information should be written.\n"));
276 274 (void) printf("\n");
277 275
278 276 command_complete(0);
279 277 }
280 278
281 279 static void
282 280 print_help_help()
283 281 {
284 282 (void) printf(
285 283 gettext("This command provides information about commands.\n\n"));
286 284 (void) printf(
287 285 gettext("The 'help' command alone provides a list of valid\n"));
288 286 (void) printf(
289 287 gettext("commands, along with the valid objects for each.\n"));
290 288 (void) printf(
291 289 gettext("'help' followed by a valid command name provides\n"));
292 290 (void) printf(gettext("further information about that command.\n"));
293 291 (void) printf("\n");
294 292
295 293 command_complete(0);
296 294 }
297 295
298 296 /*PRINTFLIKE1*/
299 297 static void
300 298 message(char *fmt, ...)
301 299 {
302 300 va_list ap;
303 301 char msgbuf[BUFSIZ];
304 302
305 303 va_start(ap, fmt);
306 304 (void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
307 305 (void) fprintf(stderr, gettext("ikeadm: %s\n"), msgbuf);
308 306 va_end(ap);
309 307 }
310 308
311 309 static int
312 310 open_door(void)
313 311 {
314 312 if (doorfd >= 0)
315 313 (void) close(doorfd);
316 314 doorfd = open(DOORNM, O_RDWR);
317 315 return (doorfd);
318 316 }
319 317
320 318 static ike_service_t *
321 319 ikedoor_call(char *reqp, int size, door_desc_t *descp, int ndesc)
322 320 {
323 321 door_arg_t arg;
324 322 int retries = 0;
325 323
326 324 arg.data_ptr = reqp;
327 325 arg.data_size = size;
328 326 arg.desc_ptr = descp;
329 327 arg.desc_num = ndesc;
330 328 arg.rbuf = (char *)NULL;
331 329 arg.rsize = 0;
332 330
333 331 retry:
334 332 if (door_call(doorfd, &arg) < 0) {
335 333 if ((errno == EBADF) && ((++retries < 2) &&
336 334 (open_door() >= 0)))
337 335 goto retry;
338 336 (void) fprintf(stderr,
339 337 gettext("Unable to communicate with in.iked\n"));
340 338 Bail("door_call failed");
341 339 }
342 340
343 341 if ((ndesc > 0) && (descp->d_attributes & DOOR_RELEASE) &&
344 342 ((errno == EBADF) || (errno == EFAULT))) {
345 343 /* callers assume passed fds will be closed no matter what */
346 344 (void) close(descp->d_data.d_desc.d_descriptor);
347 345 }
348 346
349 347 /* LINTED E_BAD_PTR_CAST_ALIGN */
350 348 return ((ike_service_t *)arg.rbuf);
351 349 }
352 350
353 351 /*
354 352 * Parsing functions
355 353 */
356 354
357 355 /* stolen from ipseckey.c, with a second tier added */
358 356 static int
359 357 parsecmd(char *cmdstr, char *objstr)
360 358 {
361 359 #define MAXOBJS 10
362 360 struct objtbl {
363 361 char *obj;
364 362 int token;
365 363 };
366 364 static struct cmdtbl {
367 365 char *cmd;
368 366 int null_obj_token;
↓ open down ↓ |
332 lines elided |
↑ open up ↑ |
369 367 struct objtbl objt[MAXOBJS];
370 368 } table[] = {
371 369 {"get", IKE_SVC_ERROR, {
372 370 {"debug", IKE_SVC_GET_DBG},
373 371 {"priv", IKE_SVC_GET_PRIV},
374 372 {"stats", IKE_SVC_GET_STATS},
375 373 {"p1", IKE_SVC_GET_P1},
376 374 {"rule", IKE_SVC_GET_RULE},
377 375 {"preshared", IKE_SVC_GET_PS},
378 376 {"defaults", IKE_SVC_GET_DEFS},
379 - {NULL, IKE_SVC_ERROR},
377 + {NULL, IKE_SVC_ERROR}
380 378 }
381 379 },
382 380 {"set", IKE_SVC_ERROR, {
383 381 {"debug", IKE_SVC_SET_DBG},
384 382 {"priv", IKE_SVC_SET_PRIV},
385 - {NULL, IKE_SVC_ERROR},
383 + {NULL, IKE_SVC_ERROR}
386 384 }
387 385 },
388 386 {"add", IKE_SVC_ERROR, {
389 387 {"rule", IKE_SVC_NEW_RULE},
390 388 {"preshared", IKE_SVC_NEW_PS},
391 - {NULL, IKE_SVC_ERROR},
389 + {NULL, IKE_SVC_ERROR}
392 390 }
393 391 },
394 392 {"del", IKE_SVC_ERROR, {
395 393 {"p1", IKE_SVC_DEL_P1},
396 394 {"rule", IKE_SVC_DEL_RULE},
397 395 {"preshared", IKE_SVC_DEL_PS},
398 - {NULL, IKE_SVC_ERROR},
396 + {NULL, IKE_SVC_ERROR}
399 397 }
400 398 },
401 399 {"dump", IKE_SVC_ERROR, {
402 400 {"p1", IKE_SVC_DUMP_P1S},
403 401 {"rule", IKE_SVC_DUMP_RULES},
404 402 {"preshared", IKE_SVC_DUMP_PS},
405 - {NULL, IKE_SVC_ERROR},
403 + {NULL, IKE_SVC_ERROR}
406 404 }
407 405 },
408 406 {"flush", IKE_SVC_ERROR, {
409 407 {"p1", IKE_SVC_FLUSH_P1S},
410 - {NULL, IKE_SVC_ERROR},
408 + {NULL, IKE_SVC_ERROR}
411 409 }
412 410 },
413 411 {"read", IKE_SVC_ERROR, {
414 412 {"rule", IKE_SVC_READ_RULES},
415 413 {"preshared", IKE_SVC_READ_PS},
416 - {NULL, IKE_SVC_ERROR},
414 + {NULL, IKE_SVC_ERROR}
417 415 }
418 416 },
419 417 {"write", IKE_SVC_ERROR, {
420 418 {"rule", IKE_SVC_WRITE_RULES},
421 419 {"preshared", IKE_SVC_WRITE_PS},
422 - {NULL, IKE_SVC_ERROR},
420 + {NULL, IKE_SVC_ERROR}
423 421 }
424 422 },
425 423 {"help", IKEADM_HELP_GENERAL, {
426 424 {"get", IKEADM_HELP_GET},
427 425 {"set", IKEADM_HELP_SET},
428 426 {"add", IKEADM_HELP_ADD},
429 427 {"del", IKEADM_HELP_DEL},
430 428 {"dump", IKEADM_HELP_DUMP},
431 429 {"flush", IKEADM_HELP_FLUSH},
432 430 {"read", IKEADM_HELP_READ},
433 431 {"write", IKEADM_HELP_WRITE},
434 432 {"help", IKEADM_HELP_HELP},
435 - {NULL, IKE_SVC_ERROR},
433 + {NULL, IKE_SVC_ERROR}
436 434 }
437 435 },
438 436 {"exit", IKEADM_EXIT, {
439 - {NULL, IKE_SVC_ERROR},
437 + {NULL, IKE_SVC_ERROR}
440 438 }
441 439 },
442 440 {"quit", IKEADM_EXIT, {
443 - {NULL, IKE_SVC_ERROR},
441 + {NULL, IKE_SVC_ERROR}
444 442 }
445 443 },
446 444 {"dbg", IKE_SVC_ERROR, {
447 445 {"rbdump", IKE_SVC_DBG_RBDUMP},
448 - {NULL, IKE_SVC_ERROR},
446 + {NULL, IKE_SVC_ERROR}
449 447 }
450 448 },
451 449 {NULL, IKE_SVC_ERROR, {
452 - {NULL, IKE_SVC_ERROR},
450 + {NULL, IKE_SVC_ERROR}
453 451 }
454 - },
452 + }
455 453 };
456 454 struct cmdtbl *ct = table;
457 455 struct objtbl *ot;
458 456
459 457 if (cmdstr == NULL) {
460 458 return (IKE_SVC_ERROR);
461 459 }
462 460
463 461 while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
464 462 ct++;
465 463 ot = ct->objt;
466 464
467 465 if (ct->cmd == NULL) {
468 466 message(gettext("Unrecognized command '%s'"), cmdstr);
469 467 return (ot->token);
470 468 }
471 469
472 470 if (objstr == NULL) {
473 471 return (ct->null_obj_token);
474 472 }
475 473
476 474 while (ot->obj != NULL && strcmp(ot->obj, objstr) != 0)
477 475 ot++;
478 476
479 477 if (ot->obj == NULL)
480 478 message(gettext("Unrecognized object '%s'"), objstr);
481 479
482 480 return (ot->token);
483 481 }
484 482
485 483 /*
486 484 * Parsing functions:
487 485 * Parse command-line identification info. All return -1 on failure,
488 486 * or the number of cmd-line args "consumed" on success (though argc
489 487 * and argv params are not actually modified).
490 488 */
491 489
492 490 static int
493 491 parse_label(int argc, char **argv, char *label)
494 492 {
495 493 if ((argc < 1) || (argv == NULL))
496 494 return (-1);
497 495
498 496 if (strlcpy(label, argv[0], MAX_LABEL_LEN) >= MAX_LABEL_LEN)
499 497 return (-1);
500 498
501 499 return (1);
502 500 }
503 501
504 502 /*
505 503 * Parse an address off the command line. In the hpp param, either
506 504 * return a hostent pointer (caller frees) or a pointer to a dummy_he_t
507 505 * (must also be freed by the caller; both cases are handled by the
508 506 * macro FREE_HE). The new getipnodebyname() call does the Right Thing
509 507 * (TM), even with raw addresses (colon-separated IPv6 or dotted decimal
510 508 * IPv4).
511 509 * (mostly stolen from ipseckey.c, though some tweaks were made
512 510 * to better serve our purposes here.)
513 511 */
514 512
515 513 typedef struct {
516 514 struct hostent he;
517 515 char *addtl[2];
518 516 } dummy_he_t;
519 517
520 518 static int
521 519 parse_addr(int argc, char **argv, struct hostent **hpp)
522 520 {
523 521 int hp_errno;
524 522 struct hostent *hp = NULL;
525 523 dummy_he_t *dhp;
526 524 char *addr1;
527 525
528 526 if ((argc < 1) || (argv == NULL) || (argv[0] == NULL))
529 527 return (-1);
530 528
531 529 if (!nflag) {
532 530 /*
533 531 * Try name->address first. Assume AF_INET6, and
534 532 * get IPV4s, plus IPv6s iff IPv6 is configured.
535 533 */
536 534 hp = getipnodebyname(argv[0], AF_INET6, AI_DEFAULT | AI_ALL,
537 535 &hp_errno);
538 536 } else {
539 537 /*
540 538 * Try a normal address conversion only. malloc a
541 539 * dummy_he_t to construct a fake hostent. Caller
542 540 * will know to free this one using free_he().
543 541 */
544 542 dhp = (dummy_he_t *)malloc(sizeof (dummy_he_t));
545 543 addr1 = (char *)malloc(sizeof (struct in6_addr));
546 544 if (inet_pton(AF_INET6, argv[0], addr1) == 1) {
547 545 dhp->he.h_addr_list = dhp->addtl;
548 546 dhp->addtl[0] = addr1;
549 547 dhp->addtl[1] = NULL;
550 548 hp = &dhp->he;
551 549 dhp->he.h_addrtype = AF_INET6;
552 550 dhp->he.h_length = sizeof (struct in6_addr);
553 551 } else if (inet_pton(AF_INET, argv[0], addr1) == 1) {
554 552 dhp->he.h_addr_list = dhp->addtl;
555 553 dhp->addtl[0] = addr1;
556 554 dhp->addtl[1] = NULL;
557 555 hp = &dhp->he;
558 556 dhp->he.h_addrtype = AF_INET;
559 557 dhp->he.h_length = sizeof (struct in_addr);
560 558 } else {
561 559 hp = NULL;
562 560 }
563 561 }
564 562
565 563 *hpp = hp;
566 564
567 565 if (hp == NULL) {
568 566 message(gettext("Unknown address %s."), argv[0]);
569 567 return (-1);
570 568 }
571 569
572 570 return (1);
573 571 }
574 572
575 573 /*
576 574 * Free a dummy_he_t structure that was malloc'd in parse_addr().
577 575 * Unfortunately, callers of parse_addr don't want to know about
578 576 * dummy_he_t structs, so all they have is a pointer to the struct
579 577 * hostent; so that's what's passed in. To manage this, we make
580 578 * the assumption that the struct hostent is the first field in
581 579 * the dummy_he_t, and therefore a pointer to it is a pointer to
582 580 * the dummy_he_t.
583 581 */
584 582 static void
585 583 free_he(struct hostent *hep)
586 584 {
587 585 dummy_he_t *p = (dummy_he_t *)hep;
588 586
589 587 assert(p != NULL);
590 588
591 589 if (p->addtl[0])
592 590 free(p->addtl[0]);
593 591 if (p->addtl[1])
594 592 free(p->addtl[1]);
595 593
596 594 free(p);
597 595 }
598 596
599 597 #define FREE_HE(x) \
600 598 if (nflag) \
601 599 free_he(x); \
602 600 else \
603 601 freehostent(x)
604 602
605 603 static void
606 604 headdr2sa(char *hea, struct sockaddr_storage *sa, int len)
607 605 {
608 606 struct sockaddr_in *sin;
609 607 struct sockaddr_in6 *sin6;
610 608
611 609 if (len == sizeof (struct in6_addr)) {
612 610 /* LINTED E_BAD_PTR_CAST_ALIGN */
613 611 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)hea)) {
614 612 sin = (struct sockaddr_in *)sa;
615 613 (void) memset(sin, 0, sizeof (*sin));
616 614 /* LINTED E_BAD_PTR_CAST_ALIGN */
617 615 IN6_V4MAPPED_TO_INADDR((struct in6_addr *)hea,
618 616 &sin->sin_addr);
619 617 sin->sin_family = AF_INET;
620 618 } else {
621 619 sin6 = (struct sockaddr_in6 *)sa;
622 620 (void) memset(sin6, 0, sizeof (*sin6));
623 621 (void) memcpy(&sin6->sin6_addr, hea,
624 622 sizeof (struct in6_addr));
625 623 sin6->sin6_family = AF_INET6;
626 624 }
627 625 } else {
628 626 sin = (struct sockaddr_in *)sa;
629 627 (void) memset(sin, 0, sizeof (*sin));
630 628 (void) memcpy(&sin->sin_addr, hea, sizeof (struct in_addr));
631 629 sin->sin_family = AF_INET;
632 630 }
633 631 }
634 632
635 633 /*
636 634 * The possible ident-type keywords that might be used on the command
637 635 * line. This is a superset of the ones supported by ipseckey, those
638 636 * in the ike config file, and those in ike.preshared.
639 637 */
640 638 static keywdtab_t idtypes[] = {
641 639 /* ip, ipv4, and ipv6 are valid for preshared keys... */
642 640 {SADB_IDENTTYPE_RESERVED, "ip"},
643 641 {SADB_IDENTTYPE_RESERVED, "ipv4"},
644 642 {SADB_IDENTTYPE_RESERVED, "ipv6"},
645 643 {SADB_IDENTTYPE_PREFIX, "prefix"},
646 644 {SADB_IDENTTYPE_PREFIX, "ipv4-prefix"},
647 645 {SADB_IDENTTYPE_PREFIX, "ipv6-prefix"},
648 646 {SADB_IDENTTYPE_PREFIX, "subnet"},
649 647 {SADB_IDENTTYPE_PREFIX, "subnetv4"},
650 648 {SADB_IDENTTYPE_PREFIX, "subnetv6"},
651 649 {SADB_IDENTTYPE_FQDN, "fqdn"},
652 650 {SADB_IDENTTYPE_FQDN, "dns"},
653 651 {SADB_IDENTTYPE_FQDN, "domain"},
654 652 {SADB_IDENTTYPE_FQDN, "domainname"},
655 653 {SADB_IDENTTYPE_USER_FQDN, "user_fqdn"},
656 654 {SADB_IDENTTYPE_USER_FQDN, "mbox"},
657 655 {SADB_IDENTTYPE_USER_FQDN, "mailbox"},
658 656 {SADB_X_IDENTTYPE_DN, "dn"},
659 657 {SADB_X_IDENTTYPE_DN, "asn1dn"},
660 658 {SADB_X_IDENTTYPE_GN, "gn"},
661 659 {SADB_X_IDENTTYPE_GN, "asn1gn"},
662 660 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv4-range"},
663 661 {SADB_X_IDENTTYPE_ADDR_RANGE, "ipv6-range"},
664 662 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev4"},
665 663 {SADB_X_IDENTTYPE_ADDR_RANGE, "rangev6"},
666 664 {SADB_X_IDENTTYPE_KEY_ID, "keyid"},
667 665 {NULL, 0}
668 666 };
669 667
670 668 static int
671 669 parse_idtype(char *type, uint16_t *idnum)
672 670 {
673 671 keywdtab_t *idp;
674 672
675 673 if (type == NULL)
676 674 return (-1);
677 675
678 676 for (idp = idtypes; idp->kw_str != NULL; idp++) {
679 677 if (strcasecmp(idp->kw_str, type) == 0) {
680 678 if (idnum != NULL)
681 679 *idnum = idp->kw_tag;
682 680 return (1);
683 681 }
684 682 }
685 683
686 684 return (-1);
687 685 }
688 686
689 687 /*
690 688 * The sadb_ident_t is malloc'd, since its length varies;
691 689 * so the caller must free() it when done with the data.
692 690 */
693 691 static int
694 692 parse_ident(int argc, char **argv, sadb_ident_t **idpp)
695 693 {
696 694 int alloclen, consumed;
697 695 sadb_ident_t *idp;
698 696 if ((argc < 2) || (argv == NULL) || (argv[0] == NULL) ||
699 697 (argv[1] == NULL))
700 698 return (-1);
701 699
702 700 alloclen = sizeof (sadb_ident_t) + IKEDOORROUNDUP(strlen(argv[1]) + 1);
703 701 *idpp = idp = (sadb_ident_t *)malloc(alloclen);
704 702 if (idp == NULL)
705 703 Bail("parsing identity");
706 704
707 705 if ((consumed = parse_idtype(argv[0], &idp->sadb_ident_type)) < 0) {
708 706 message(gettext("unknown identity type %s."), argv[0]);
709 707 return (-1);
710 708 }
711 709
712 710 idp->sadb_ident_len = SADB_8TO64(alloclen);
713 711 idp->sadb_ident_reserved = 0;
714 712 idp->sadb_ident_id = 0;
715 713
716 714 /* now copy in identity param */
717 715 (void) strlcpy((char *)(idp + 1), argv[1],
718 716 alloclen - (sizeof (sadb_ident_t)));
719 717
720 718 return (++consumed);
721 719 }
722 720
723 721 static int
724 722 parse_cky(int argc, char **argv, uint64_t *ckyp)
725 723 {
726 724 u_longlong_t arg;
727 725
728 726 if ((argc < 1) || (argv[0] == NULL))
729 727 return (-1);
730 728
731 729 errno = 0;
732 730 arg = strtoull(argv[0], NULL, 0);
733 731 if (errno != 0) {
734 732 message(gettext("failed to parse cookie %s."), argv[0]);
735 733 return (-1);
736 734 }
737 735
738 736 *ckyp = (uint64_t)arg;
739 737
740 738 return (1);
741 739 }
742 740
743 741 static int
744 742 parse_addr_pr(int argc, char **argv, struct hostent **h1pp,
745 743 struct hostent **h2pp)
746 744 {
747 745 int rtn, consumed = 0;
748 746
749 747 if ((rtn = parse_addr(argc, argv, h1pp)) < 0) {
750 748 return (-1);
751 749 }
752 750 consumed = rtn;
753 751 argc -= rtn;
754 752 argv += rtn;
755 753
756 754 if ((rtn = parse_addr(argc, argv, h2pp)) < 0) {
757 755 FREE_HE(*h1pp);
758 756 return (-1);
759 757 }
760 758 consumed += rtn;
761 759
762 760 return (consumed);
763 761 }
764 762
765 763 /*
766 764 * The sadb_ident_ts are malloc'd, since their length varies;
767 765 * so the caller must free() them when done with the data.
768 766 */
769 767 static int
770 768 parse_ident_pr(int argc, char **argv, sadb_ident_t **id1pp,
771 769 sadb_ident_t **id2pp)
772 770 {
773 771 int rtn, consumed = 0;
774 772
775 773 if ((rtn = parse_ident(argc, argv, id1pp)) < 0) {
776 774 return (-1);
777 775 }
778 776 consumed = rtn;
779 777 argc -= rtn;
780 778 argv += rtn;
781 779
782 780 (*id1pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
783 781
784 782 if ((rtn = parse_ident(argc, argv, id2pp)) < 0) {
785 783 free(*id1pp);
786 784 return (-1);
787 785 }
788 786 consumed += rtn;
789 787
790 788 (*id2pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
791 789
792 790 return (consumed);
793 791 }
794 792
795 793 static int
796 794 parse_cky_pr(int argc, char **argv, ike_cky_pr_t *cpr)
797 795 {
798 796 int rtn, consumed = 0;
799 797
800 798 if ((rtn = parse_cky(argc, argv, &cpr->cky_i)) < 0) {
801 799 return (-1);
802 800 }
803 801 consumed = rtn;
804 802 argc -= rtn;
805 803 argv += rtn;
806 804
807 805 if ((rtn = parse_cky(argc, argv, &cpr->cky_r)) < 0) {
808 806 return (-1);
809 807 }
810 808 consumed += rtn;
811 809
812 810 return (consumed);
813 811 }
814 812
815 813 /*
816 814 * Preshared key field types...used for parsing preshared keys that
817 815 * have been entered on the command line. The code to parse preshared
818 816 * keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is
819 817 * mostly duplicated from in.iked's readps.c.
820 818 */
821 819 #define PSFLD_LOCID 1
822 820 #define PSFLD_LOCIDTYPE 2
823 821 #define PSFLD_REMID 3
824 822 #define PSFLD_REMIDTYPE 4
825 823 #define PSFLD_MODE 5
826 824 #define PSFLD_KEY 6
827 825
828 826 static keywdtab_t psfldtypes[] = {
829 827 {PSFLD_LOCID, "localid"},
830 828 {PSFLD_LOCIDTYPE, "localidtype"},
831 829 {PSFLD_REMID, "remoteid"},
832 830 {PSFLD_REMIDTYPE, "remoteidtype"},
833 831 {PSFLD_MODE, "ike_mode"},
834 832 {PSFLD_KEY, "key"},
835 833 {NULL, 0}
836 834 };
837 835
838 836 static int
839 837 parse_psfldid(char *type, uint16_t *idnum)
840 838 {
841 839 keywdtab_t *pfp;
842 840
843 841 if (type == NULL)
844 842 return (-1);
845 843
846 844 for (pfp = psfldtypes; pfp->kw_str != NULL; pfp++) {
847 845 if (strcasecmp(pfp->kw_str, type) == 0) {
848 846 if (idnum != NULL)
849 847 *idnum = pfp->kw_tag;
850 848 return (1);
851 849 }
852 850 }
853 851
854 852 return (-1);
855 853 }
856 854
857 855 static keywdtab_t ikemodes[] = {
858 856 {IKE_XCHG_IDENTITY_PROTECT, "main"},
859 857 {IKE_XCHG_AGGRESSIVE, "aggressive"},
860 858 {IKE_XCHG_IP_AND_AGGR, "both"},
861 859 {NULL, 0}
862 860 };
863 861
864 862 static int
865 863 parse_ikmtype(char *mode, uint16_t *modenum)
866 864 {
867 865 keywdtab_t *ikmp;
868 866
869 867 if (mode == NULL)
870 868 return (-1);
871 869
872 870 for (ikmp = ikemodes; ikmp->kw_str != NULL; ikmp++) {
873 871 if (strcasecmp(ikmp->kw_str, mode) == 0) {
874 872 if (modenum != NULL)
875 873 *modenum = ikmp->kw_tag;
876 874 return (1);
877 875 }
878 876 }
879 877
880 878 return (-1);
881 879 }
882 880
883 881 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
884 882 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
885 883
886 884 static uint8_t *
887 885 parse_key(char *input, uint_t *keybuflen, uint_t *lbits)
888 886 {
889 887 uint8_t *keyp, *keybufp;
890 888 uint_t i, hexlen = 0, bits, alloclen;
891 889
892 890 for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
893 891 hexlen++;
894 892
895 893 if (input[i] == '\0') {
896 894 bits = 0;
897 895 } else {
898 896 /* Have /nn. */
899 897 input[i] = '\0';
900 898 if (sscanf((input + i + 1), "%u", &bits) != 1)
901 899 return (NULL);
902 900
903 901 /* hexlen is in nibbles */
904 902 if (((bits + 3) >> 2) > hexlen)
905 903 return (NULL);
906 904
907 905 /*
908 906 * Adjust hexlen down if user gave us too small of a bit
909 907 * count.
910 908 */
911 909 if ((hexlen << 2) > bits + 3) {
912 910 hexlen = (bits + 3) >> 2;
913 911 input[hexlen] = '\0';
914 912 }
915 913 }
916 914
917 915 /*
918 916 * Allocate. Remember, hexlen is in nibbles.
919 917 */
920 918
921 919 alloclen = (hexlen/2 + (hexlen & 0x1));
922 920 keyp = malloc(alloclen);
923 921
924 922 if (keyp == NULL)
925 923 return (NULL);
926 924
927 925 keybufp = keyp;
928 926 *keybuflen = alloclen;
929 927 if (bits == 0)
930 928 *lbits = (hexlen + (hexlen & 0x1)) << 2;
931 929 else
932 930 *lbits = bits;
933 931
934 932 /*
935 933 * Read in nibbles. Read in odd-numbered as shifted high.
936 934 * (e.g. 123 becomes 0x1230).
937 935 */
938 936 for (i = 0; input[i] != '\0'; i += 2) {
939 937 boolean_t second = (input[i + 1] != '\0');
940 938
941 939 if (!isxdigit(input[i]) ||
942 940 (!isxdigit(input[i + 1]) && second)) {
943 941 free(keyp);
944 942 return (NULL);
945 943 }
946 944 *keyp = (hd2num(input[i]) << 4);
947 945 if (second)
948 946 *keyp |= hd2num(input[i + 1]);
949 947 else
950 948 break; /* out of for loop. */
951 949 keyp++;
952 950 }
953 951
954 952 /* zero the remaining bits if we're a non-octet amount. */
955 953 if (bits & 0x7)
956 954 *((input[i] == '\0') ? keyp - 1 : keyp) &=
957 955 0xff << (8 - (bits & 0x7));
958 956 return (keybufp);
959 957 }
960 958
961 959 /*
962 960 * the ike_ps_t struct (plus trailing data) will be allocated here,
963 961 * so it will need to be freed by the caller.
964 962 */
965 963 static int
966 964 parse_ps(int argc, char **argv, ike_ps_t **presharedpp, int *len)
967 965 {
968 966 uint_t c = 0, locidlen, remidlen, keylen, keybits;
969 967 uint_t a_locidtotal = 0, a_remidtotal = 0;
970 968 char *locid, *remid;
971 969 uint8_t *keyp = NULL;
972 970 uint16_t fldid, locidtype, remidtype, mtype;
973 971 struct hostent *loche = NULL, *remhe = NULL;
974 972 ike_ps_t *psp = NULL;
975 973 sadb_ident_t *sidp;
976 974 boolean_t whacked = B_FALSE;
977 975
978 976 if ((argv[c] == NULL) || (argv[c][0] != '{'))
979 977 return (-1);
980 978 if (argv[c][1] != 0) {
981 979 /* no space between '{' and first token */
982 980 argv[c]++;
983 981 } else {
984 982 c++;
985 983 }
986 984 if ((argv[argc - 1][strlen(argv[argc - 1]) - 1] == '}') &&
987 985 (argv[argc - 1][0] != '}')) {
988 986 /*
989 987 * whack '}' without a space before it or parsers break.
990 988 * Remember this trailing character for later
991 989 */
992 990 argv[argc - 1][strlen(argv[argc - 1]) - 1] = '\0';
993 991 whacked = B_TRUE;
994 992 }
995 993
996 994 while ((c < argc) && (argv[c] != NULL) && (argv[c][0] != '}')) {
997 995 if ((argv[c + 1] == NULL) || (argv[c + 1][0] == '}'))
998 996 goto bail;
999 997 if (parse_psfldid(argv[c++], &fldid) < 0)
1000 998 goto bail;
1001 999 switch (fldid) {
1002 1000 case PSFLD_LOCID:
1003 1001 locid = argv[c++];
1004 1002 locidlen = strlen(locid) + 1;
1005 1003 break;
1006 1004 case PSFLD_LOCIDTYPE:
1007 1005 if (parse_idtype(argv[c++], &locidtype) < 0)
1008 1006 goto bail;
1009 1007 break;
1010 1008 case PSFLD_REMID:
1011 1009 remid = argv[c++];
1012 1010 remidlen = strlen(remid) + 1;
1013 1011 break;
1014 1012 case PSFLD_REMIDTYPE:
1015 1013 if (parse_idtype(argv[c++], &remidtype) < 0)
1016 1014 goto bail;
1017 1015 break;
1018 1016 case PSFLD_MODE:
1019 1017 if (parse_ikmtype(argv[c++], &mtype) < 0)
1020 1018 goto bail;
1021 1019 break;
1022 1020 case PSFLD_KEY:
1023 1021 keyp = parse_key(argv[c++], &keylen, &keybits);
1024 1022 if (keyp == NULL)
1025 1023 goto bail;
1026 1024 break;
1027 1025 }
1028 1026 }
1029 1027
1030 1028 /* Make sure the line was terminated with '}' */
1031 1029 if (argv[c] == NULL) {
1032 1030 if (!whacked)
1033 1031 goto bail;
1034 1032 } else if (argv[c][0] != '}') {
1035 1033 goto bail;
1036 1034 }
1037 1035
1038 1036 /*
1039 1037 * make sure we got all the required fields. If no idtype, assume
1040 1038 * ip addr; if that translation fails, we'll catch the error then.
1041 1039 */
1042 1040 if (locid == NULL || remid == NULL || keyp == NULL || mtype == 0)
1043 1041 goto bail;
1044 1042
1045 1043 /* figure out the size buffer we need */
1046 1044 *len = sizeof (ike_ps_t);
1047 1045 if (locidtype != SADB_IDENTTYPE_RESERVED) {
1048 1046 a_locidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + locidlen);
1049 1047 *len += a_locidtotal;
1050 1048 }
1051 1049 if (remidtype != SADB_IDENTTYPE_RESERVED) {
1052 1050 a_remidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + remidlen);
1053 1051 *len += a_remidtotal;
1054 1052 }
1055 1053 *len += keylen;
1056 1054
1057 1055 psp = malloc(*len);
1058 1056 if (psp == NULL)
1059 1057 goto bail;
1060 1058 (void) memset(psp, 0, *len);
1061 1059
1062 1060 psp->ps_ike_mode = mtype;
1063 1061
1064 1062 psp->ps_localid_off = sizeof (ike_ps_t);
1065 1063 if (locidtype == SADB_IDENTTYPE_RESERVED) {
1066 1064 /*
1067 1065 * this is an ip address, store in the sockaddr field;
1068 1066 * we won't use an sadb_ident_t.
1069 1067 */
1070 1068 psp->ps_localid_len = 0;
1071 1069 if (parse_addr(1, &locid, &loche) < 0)
1072 1070 goto bail;
1073 1071 if (loche->h_addr_list[1] != NULL) {
1074 1072 message(gettext("preshared key identifier cannot "
1075 1073 "match multiple IP addresses"));
1076 1074 goto bail;
1077 1075 }
1078 1076 headdr2sa(loche->h_addr_list[0], &psp->ps_ipaddrs.loc_addr,
1079 1077 loche->h_length);
1080 1078 FREE_HE(loche);
1081 1079 } else {
1082 1080 psp->ps_localid_len = sizeof (sadb_ident_t) + locidlen;
1083 1081 sidp = (sadb_ident_t *)((int)psp + psp->ps_localid_off);
1084 1082 sidp->sadb_ident_len = psp->ps_localid_len;
1085 1083 sidp->sadb_ident_type = locidtype;
1086 1084 (void) strlcpy((char *)(sidp + 1), locid, a_locidtotal);
1087 1085 }
1088 1086
1089 1087 psp->ps_remoteid_off = psp->ps_localid_off + a_locidtotal;
1090 1088 if (remidtype == SADB_IDENTTYPE_RESERVED) {
1091 1089 /*
1092 1090 * this is an ip address, store in the sockaddr field;
1093 1091 * we won't use an sadb_ident_t.
1094 1092 */
1095 1093 psp->ps_remoteid_len = 0;
1096 1094 if (parse_addr(1, &remid, &remhe) < 0)
1097 1095 goto bail;
1098 1096 if (remhe->h_addr_list[1] != NULL) {
1099 1097 message(gettext("preshared key identifier cannot "
1100 1098 "match multiple IP addresses"));
1101 1099 goto bail;
1102 1100 }
1103 1101 headdr2sa(remhe->h_addr_list[0], &psp->ps_ipaddrs.rem_addr,
1104 1102 remhe->h_length);
1105 1103 FREE_HE(remhe);
1106 1104 } else {
1107 1105 /* make sure we have at least 16-bit alignment */
1108 1106 if (remidlen & 0x1)
1109 1107 remidlen++;
1110 1108 psp->ps_remoteid_len = sizeof (sadb_ident_t) + remidlen;
1111 1109 sidp = (sadb_ident_t *)((int)psp + psp->ps_remoteid_off);
1112 1110 sidp->sadb_ident_len = psp->ps_remoteid_len;
1113 1111 sidp->sadb_ident_type = remidtype;
1114 1112 (void) strlcpy((char *)(sidp + 1), remid, a_remidtotal);
1115 1113 }
1116 1114
1117 1115 psp->ps_key_off = psp->ps_remoteid_off + a_remidtotal;
1118 1116 psp->ps_key_len = keylen;
1119 1117 psp->ps_key_bits = keybits;
1120 1118 (void) memcpy((uint8_t *)((int)psp + psp->ps_key_off), keyp, keylen);
1121 1119
1122 1120 *presharedpp = psp;
1123 1121
1124 1122 return (c);
1125 1123
1126 1124 bail:
1127 1125 if (loche != NULL)
1128 1126 FREE_HE(loche);
1129 1127 if (remhe != NULL)
1130 1128 FREE_HE(remhe);
↓ open down ↓ |
666 lines elided |
↑ open up ↑ |
1131 1129 if (keyp != NULL)
1132 1130 free(keyp);
1133 1131 if (psp != NULL)
1134 1132 free(psp);
1135 1133
1136 1134 *presharedpp = NULL;
1137 1135
1138 1136 return (-1);
1139 1137 }
1140 1138
1141 -/* stolen from libdhcputil (dhcp_inittab.c) */
1142 -static uint64_t
1143 -ike_ntohll(uint64_t nll)
1144 -{
1145 -#ifdef _LITTLE_ENDIAN
1146 - return ((uint64_t)ntohl(nll & 0xffffffff) << 32 | ntohl(nll >> 32));
1147 -#else
1148 - return (nll);
1149 -#endif
1150 -}
1151 -
1152 1139 /*
1153 1140 * Printing functions
1154 1141 *
1155 1142 * A potential point of confusion here is that the ikeadm-specific string-
1156 1143 * producing functions do not match the ipsec_util.c versions in style: the
1157 1144 * ikeadm-specific functions return a string (and are named foostr), while
1158 1145 * the ipsec_util.c functions actually print the string to the file named
1159 1146 * in the second arg to the function (and are named dump_foo).
1160 1147 *
1161 - * The reason for this is that in the context of the ikeadm output, it
1162 - * seemed like the localization of the text would be more straightforward
1163 - * (and could more easily accomodate non-english grammar!) if more complete
1164 - * phrases were being translated, rather than a bit of a phrase followed by
1165 - * a call to dump_foo() followed by more of the phrase.
1148 + * Localization for ikeadm seems more straightforward when complete
1149 + * phrases are translated rather than: a part of a phrase, a call to
1150 + * dump_foo(), and more of the phrase. It could also accommodate
1151 + * non-English grammar more easily.
1166 1152 */
1167 1153
1168 1154 static char *
1169 1155 errstr(int err)
1170 1156 {
1171 1157 static char rtn[MAXLINESIZE];
1172 1158
1173 1159 switch (err) {
1174 1160 case IKE_ERR_NO_OBJ:
1175 1161 return (gettext("No data returned"));
1176 1162 case IKE_ERR_NO_DESC:
1177 1163 return (gettext("No destination provided"));
1178 1164 case IKE_ERR_ID_INVALID:
1179 1165 return (gettext("Id info invalid"));
1180 1166 case IKE_ERR_LOC_INVALID:
1181 1167 return (gettext("Destination invalid"));
1182 1168 case IKE_ERR_CMD_INVALID:
1183 1169 return (gettext("Command invalid"));
1184 1170 case IKE_ERR_DATA_INVALID:
1185 1171 return (gettext("Supplied data invalid"));
1186 1172 case IKE_ERR_CMD_NOTSUP:
1187 1173 return (gettext("Unknown command"));
1188 1174 case IKE_ERR_REQ_INVALID:
1189 1175 return (gettext("Request invalid"));
1190 1176 case IKE_ERR_NO_PRIV:
1191 1177 return (gettext("Not allowed at current privilege level"));
1192 1178 case IKE_ERR_SYS_ERR:
1193 1179 return (gettext("System error"));
1194 1180 case IKE_ERR_DUP_IGNORED:
1195 1181 return (gettext("One or more duplicate entries ignored"));
1196 1182 default:
1197 1183 (void) snprintf(rtn, MAXLINESIZE,
1198 1184 gettext("<unknown error %d>"), err);
1199 1185 return (rtn);
1200 1186 }
1201 1187 }
1202 1188
1203 1189 static char *
1204 1190 dbgstr(int bit)
1205 1191 {
1206 1192 static char rtn[MAXLINESIZE];
1207 1193
1208 1194 switch (bit) {
1209 1195 case D_CERT:
1210 1196 return (gettext("Certificate management"));
1211 1197 case D_KEY:
1212 1198 return (gettext("Key management"));
1213 1199 case D_OP:
1214 1200 return (gettext("Operational"));
1215 1201 case D_P1:
1216 1202 return (gettext("Phase 1 SA creation"));
1217 1203 case D_P2:
1218 1204 return (gettext("Phase 2 SA creation"));
1219 1205 case D_PFKEY:
1220 1206 return (gettext("PF_KEY interface"));
1221 1207 case D_POL:
1222 1208 return (gettext("Policy management"));
1223 1209 case D_PROP:
1224 1210 return (gettext("Proposal construction"));
1225 1211 case D_DOOR:
1226 1212 return (gettext("Door interface"));
1227 1213 case D_CONFIG:
1228 1214 return (gettext("Config file processing"));
1229 1215 default:
1230 1216 (void) snprintf(rtn, MAXLINESIZE,
1231 1217 gettext("<unknown flag 0x%x>"), bit);
1232 1218 return (rtn);
1233 1219 }
1234 1220 }
1235 1221
1236 1222 static char *
1237 1223 privstr(int priv)
1238 1224 {
1239 1225 static char rtn[MAXLINESIZE];
1240 1226
1241 1227 switch (priv) {
1242 1228 case IKE_PRIV_MINIMUM:
1243 1229 return (gettext("base privileges"));
1244 1230 case IKE_PRIV_MODKEYS:
1245 1231 return (gettext("access to preshared key information"));
1246 1232 case IKE_PRIV_KEYMAT:
1247 1233 return (gettext("access to keying material"));
1248 1234 default:
1249 1235 (void) snprintf(rtn, MAXLINESIZE,
1250 1236 gettext("<unknown level %d>"), priv);
1251 1237 return (rtn);
1252 1238 }
1253 1239 }
1254 1240
1255 1241 static char *
1256 1242 xchgstr(int xchg)
1257 1243 {
1258 1244 static char rtn[MAXLINESIZE];
1259 1245
1260 1246 switch (xchg) {
1261 1247 case IKE_XCHG_NONE:
1262 1248 return (gettext("<unspecified>"));
1263 1249 case IKE_XCHG_BASE:
1264 1250 return (gettext("base"));
1265 1251 case IKE_XCHG_IDENTITY_PROTECT:
1266 1252 return (gettext("main mode (identity protect)"));
1267 1253 case IKE_XCHG_AUTH_ONLY:
1268 1254 return (gettext("authentication only"));
1269 1255 case IKE_XCHG_AGGRESSIVE:
1270 1256 return (gettext("aggressive mode"));
1271 1257 case IKE_XCHG_IP_AND_AGGR:
1272 1258 return (gettext("main and aggressive mode"));
1273 1259 case IKE_XCHG_ANY:
1274 1260 return (gettext("any mode"));
1275 1261 default:
1276 1262 (void) snprintf(rtn, MAXLINESIZE,
1277 1263 gettext("<unknown %d>"), xchg);
1278 1264 return (rtn);
1279 1265 }
1280 1266 }
1281 1267
1282 1268 static char *
1283 1269 statestr(int state)
1284 1270 {
1285 1271 static char rtn[MAXLINESIZE];
1286 1272
1287 1273 switch (state) {
1288 1274 case IKE_SA_STATE_INIT:
1289 1275 return (gettext("INITIALIZING"));
1290 1276 case IKE_SA_STATE_SENT_SA:
1291 1277 return (gettext("SENT FIRST MSG (SA)"));
1292 1278 case IKE_SA_STATE_SENT_KE:
1293 1279 return (gettext("SENT SECOND MSG (KE)"));
1294 1280 case IKE_SA_STATE_SENT_LAST:
1295 1281 return (gettext("SENT FINAL MSG"));
1296 1282 case IKE_SA_STATE_DONE:
1297 1283 return (gettext("ACTIVE"));
1298 1284 case IKE_SA_STATE_DELETED:
1299 1285 return (gettext("DELETED"));
1300 1286 case IKE_SA_STATE_INVALID:
1301 1287 return (gettext("<invalid>"));
1302 1288 default:
1303 1289 (void) snprintf(rtn, MAXLINESIZE,
1304 1290 gettext("<unknown %d>"), state);
1305 1291 return (rtn);
1306 1292 }
1307 1293 }
1308 1294
1309 1295 static char *
1310 1296 authmethstr(int meth)
1311 1297 {
1312 1298 static char rtn[MAXLINESIZE];
1313 1299
1314 1300 switch (meth) {
1315 1301 case IKE_AUTH_METH_PRE_SHARED_KEY:
1316 1302 return (gettext("pre-shared key"));
1317 1303 case IKE_AUTH_METH_DSS_SIG:
1318 1304 return (gettext("DSS signatures"));
1319 1305 case IKE_AUTH_METH_RSA_SIG:
1320 1306 return (gettext("RSA signatures"));
1321 1307 case IKE_AUTH_METH_RSA_ENCR:
1322 1308 return (gettext("RSA Encryption"));
1323 1309 case IKE_AUTH_METH_RSA_ENCR_REVISED:
1324 1310 return (gettext("Revised RSA Encryption"));
1325 1311 default:
1326 1312 (void) snprintf(rtn, MAXLINESIZE,
1327 1313 gettext("<unknown %d>"), meth);
1328 1314 return (rtn);
1329 1315 }
1330 1316 }
1331 1317
1332 1318 static char *
1333 1319 prfstr(int prf)
1334 1320 {
1335 1321 static char rtn[MAXLINESIZE];
1336 1322
1337 1323 switch (prf) {
1338 1324 case IKE_PRF_NONE:
1339 1325 return (gettext("<none/unavailable>"));
1340 1326 case IKE_PRF_HMAC_MD5:
1341 1327 return ("HMAC MD5");
1342 1328 case IKE_PRF_HMAC_SHA1:
1343 1329 return ("HMAC SHA1");
1344 1330 case IKE_PRF_HMAC_SHA256:
1345 1331 return ("HMAC SHA256");
1346 1332 case IKE_PRF_HMAC_SHA384:
1347 1333 return ("HMAC SHA384");
1348 1334 case IKE_PRF_HMAC_SHA512:
1349 1335 return ("HMAC SHA512");
1350 1336 default:
1351 1337 (void) snprintf(rtn, MAXLINESIZE,
1352 1338 gettext("<unknown %d>"), prf);
1353 1339 return (rtn);
1354 1340 }
1355 1341 }
1356 1342
1357 1343 static char *
1358 1344 dhstr(int grp)
1359 1345 {
1360 1346 static char rtn[MAXLINESIZE];
1361 1347
1362 1348 switch (grp) {
1363 1349 case 0:
1364 1350 return (gettext("<unavailable>"));
1365 1351 case IKE_GRP_DESC_MODP_768:
1366 1352 return (gettext("768-bit MODP (group 1)"));
1367 1353 case IKE_GRP_DESC_MODP_1024:
1368 1354 return (gettext("1024-bit MODP (group 2)"));
1369 1355 case IKE_GRP_DESC_EC2N_155:
1370 1356 return (gettext("EC2N group on GP[2^155]"));
1371 1357 case IKE_GRP_DESC_EC2N_185:
1372 1358 return (gettext("EC2N group on GP[2^185]"));
1373 1359 case IKE_GRP_DESC_MODP_1536:
1374 1360 return (gettext("1536-bit MODP (group 5)"));
1375 1361 case IKE_GRP_DESC_MODP_2048:
1376 1362 return (gettext("2048-bit MODP (group 14)"));
1377 1363 case IKE_GRP_DESC_MODP_3072:
1378 1364 return (gettext("3072-bit MODP (group 15)"));
1379 1365 case IKE_GRP_DESC_MODP_4096:
1380 1366 return (gettext("4096-bit MODP (group 16)"));
1381 1367 case IKE_GRP_DESC_MODP_6144:
1382 1368 return (gettext("6144-bit MODP (group 17)"));
1383 1369 case IKE_GRP_DESC_MODP_8192:
1384 1370 return (gettext("8192-bit MODP (group 18)"));
1385 1371 default:
↓ open down ↓ |
210 lines elided |
↑ open up ↑ |
1386 1372 (void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp);
1387 1373 return (rtn);
1388 1374 }
1389 1375 }
1390 1376
1391 1377 static void
1392 1378 print_hdr(char *prefix, ike_p1_hdr_t *hdrp)
1393 1379 {
1394 1380 (void) printf(
1395 1381 gettext("%s Cookies: Initiator 0x%llx Responder 0x%llx\n"),
1396 - prefix, ike_ntohll(hdrp->p1hdr_cookies.cky_i),
1397 - ike_ntohll(hdrp->p1hdr_cookies.cky_r));
1382 + prefix, ntohll(hdrp->p1hdr_cookies.cky_i),
1383 + ntohll(hdrp->p1hdr_cookies.cky_r));
1398 1384 (void) printf(gettext("%s The local host is the %s.\n"), prefix,
1399 1385 hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder"));
1400 1386 (void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix,
1401 1387 hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg));
1402 1388 (void) printf(gettext("%s Current state is %s"), prefix,
1403 1389 statestr(hdrp->p1hdr_state));
1404 1390 (void) printf("\n");
1405 1391 }
1406 1392
1407 1393 static void
1408 1394 print_lt_limits(char *prefix, ike_p1_xform_t *xfp)
1409 1395 {
1410 1396 (void) printf(gettext("%s Lifetime limits:\n"), prefix);
1411 1397 (void) printf(gettext("%s %u seconds; %u kbytes protected; "),
1412 1398 prefix, xfp->p1xf_max_secs, xfp->p1xf_max_kbytes);
1413 1399 (void) printf(gettext("%u keymat provided.\n"), xfp->p1xf_max_keyuses);
1414 1400 }
1415 1401
1416 1402 #define LT_USAGE_LEN 16 /* 1 uint64 + 2 uint32s */
1417 1403 static void
1418 1404 print_lt_usage(char *prefix, ike_p1_stats_t *sp)
1419 1405 {
1420 1406 time_t scratch;
1421 1407 char tbuf[TBUF_SIZE];
1422 1408
1423 1409 (void) printf(gettext("%s Current usage:\n"), prefix);
1424 1410 scratch = (time_t)sp->p1stat_start;
1425 1411 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0)
1426 1412 (void) strlcpy(tbuf, gettext("<time conversion failed>"),
1427 1413 TBUF_SIZE);
1428 1414 (void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf);
1429 1415 (void) printf(gettext("%s %u kbytes protected; %u keymat provided.\n"),
1430 1416 prefix, sp->p1stat_kbytes, sp->p1stat_keyuses);
1431 1417 }
1432 1418
1433 1419 static void
1434 1420 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes)
1435 1421 {
1436 1422 (void) printf(gettext("%s Authentication method: %s"), prefix,
1437 1423 authmethstr(xfp->p1xf_auth_meth));
1438 1424 (void) printf(gettext("\n%s Encryption alg: "), prefix);
1439 1425 (void) dump_ealg(xfp->p1xf_encr_alg, stdout);
1440 1426 if (xfp->p1xf_encr_low_bits != 0) {
1441 1427 (void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits,
1442 1428 xfp->p1xf_encr_high_bits);
1443 1429 } else if ((xfp->p1xf_encr_low_bits == 0) &&
1444 1430 (xfp->p1xf_encr_high_bits != 0)) {
1445 1431 /*
1446 1432 * High bits is a placeholder for
1447 1433 * negotiated algorithm strength
1448 1434 */
1449 1435 (void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits);
1450 1436 }
1451 1437 (void) printf(gettext("; Authentication alg: "));
1452 1438 (void) dump_aalg(xfp->p1xf_auth_alg, stdout);
1453 1439 (void) printf("\n%s ", prefix);
1454 1440 if (xfp->p1xf_prf != 0)
1455 1441 (void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf));
1456 1442 (void) printf(gettext("Oakley Group: %s\n"),
1457 1443 dhstr(xfp->p1xf_dh_group));
1458 1444 if (xfp->p1xf_pfs == 0) {
1459 1445 (void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix);
1460 1446 } else {
1461 1447 (void) printf(gettext(
1462 1448 "%s Phase 2 PFS is required (Oakley Group: %s)\n"),
1463 1449 prefix, dhstr(xfp->p1xf_pfs));
1464 1450 }
1465 1451
1466 1452 if (print_lifetimes)
1467 1453 print_lt_limits(prefix, xfp);
1468 1454 }
1469 1455
1470 1456 static void
1471 1457 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp,
1472 1458 int statlen)
1473 1459 {
1474 1460 time_t current, remain, exp;
1475 1461 char tbuf[TBUF_SIZE];
1476 1462
1477 1463 current = time(NULL);
1478 1464
1479 1465 print_lt_limits(prefix, xfp);
1480 1466
1481 1467 /*
1482 1468 * make sure the stats struct we've been passed is as big
1483 1469 * as we expect it to be. The usage stats are at the end,
1484 1470 * so anything less than the size we expect won't work.
1485 1471 */
1486 1472 if (statlen >= sizeof (ike_p1_stats_t)) {
1487 1473 print_lt_usage(prefix, sp);
1488 1474 } else {
1489 1475 return;
1490 1476 }
1491 1477
1492 1478 (void) printf(gettext("%s Expiration info:\n"), prefix);
1493 1479
1494 1480 if (xfp->p1xf_max_kbytes != 0)
1495 1481 (void) printf(gettext("%s %u more bytes can be protected.\n"),
1496 1482 prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes);
1497 1483
1498 1484 if (xfp->p1xf_max_keyuses != 0)
1499 1485 (void) printf(gettext("%s Keying material can be provided "
1500 1486 "%u more times.\n"), prefix,
1501 1487 xfp->p1xf_max_keyuses - sp->p1stat_keyuses);
1502 1488
1503 1489 if (xfp->p1xf_max_secs != 0) {
1504 1490 exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs;
1505 1491 remain = exp - current;
1506 1492 if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0)
1507 1493 (void) strlcpy(tbuf,
1508 1494 gettext("<time conversion failed>"), TBUF_SIZE);
1509 1495 /*
1510 1496 * The SA may have expired but still exist because libike
1511 1497 * has not freed it yet.
1512 1498 */
1513 1499 if (remain > 0)
1514 1500 (void) printf(gettext(
1515 1501 "%s SA expires in %lu seconds, at %s\n"),
1516 1502 prefix, remain, tbuf);
1517 1503 else
1518 1504 (void) printf(gettext("%s SA Expired at %s\n"),
1519 1505 prefix, tbuf);
1520 1506 }
1521 1507 }
1522 1508
1523 1509 /* used to verify structure lengths... */
1524 1510 #define COUNTER_32BIT 4
1525 1511 #define COUNTER_PAIR 8
1526 1512
1527 1513 static void
1528 1514 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen,
1529 1515 boolean_t print_lifetimes)
1530 1516 {
1531 1517 if (statlen < COUNTER_PAIR)
1532 1518 return;
1533 1519 (void) printf(gettext("%s %u Quick Mode SAs created; "), prefix,
1534 1520 sp->p1stat_new_qm_sas);
1535 1521 (void) printf(gettext("%u Quick Mode SAs deleted\n"),
1536 1522 sp->p1stat_del_qm_sas);
1537 1523 statlen -= COUNTER_PAIR;
1538 1524
1539 1525 if ((print_lifetimes) && (statlen >= LT_USAGE_LEN))
1540 1526 print_lt_usage(prefix, sp);
1541 1527 }
1542 1528
1543 1529 static void
1544 1530 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen)
1545 1531 {
1546 1532 /*
1547 1533 * Don't try to break this one up; it's either all or nothing!
1548 1534 */
1549 1535 if (errlen < sizeof (ike_p1_errors_t))
1550 1536 return;
1551 1537
1552 1538 (void) printf(gettext("%s %u RX errors: "), prefix,
1553 1539 errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx);
1554 1540 (void) printf(gettext("%u decryption, %u hash, %u other\n"),
1555 1541 errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx);
1556 1542 (void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx);
1557 1543 }
1558 1544
1559 1545 static void
1560 1546 print_addr_range(char *prefix, ike_addr_pr_t *pr)
1561 1547 {
1562 1548 boolean_t range = B_TRUE;
1563 1549 struct sockaddr_storage *beg, *end;
1564 1550 struct sockaddr_in *bsin, *esin;
1565 1551 struct sockaddr_in6 *bsin6, *esin6;
1566 1552
1567 1553 beg = &pr->beg_iprange;
1568 1554 end = &pr->end_iprange;
1569 1555
1570 1556 if (beg->ss_family != end->ss_family) {
1571 1557 (void) printf(gettext("%s invalid address range\n"), prefix);
1572 1558 return;
1573 1559 }
1574 1560
1575 1561 switch (beg->ss_family) {
1576 1562 case AF_INET:
1577 1563 bsin = (struct sockaddr_in *)beg;
1578 1564 esin = (struct sockaddr_in *)end;
1579 1565 if ((uint32_t)bsin->sin_addr.s_addr ==
1580 1566 (uint32_t)esin->sin_addr.s_addr)
1581 1567 range = B_FALSE;
1582 1568 break;
1583 1569 case AF_INET6:
1584 1570 bsin6 = (struct sockaddr_in6 *)beg;
1585 1571 esin6 = (struct sockaddr_in6 *)end;
1586 1572 if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr))
1587 1573 range = B_FALSE;
1588 1574 break;
1589 1575 default:
1590 1576 (void) printf(gettext("%s invalid address range\n"), prefix);
1591 1577 return;
1592 1578 }
1593 1579
1594 1580 (void) printf("%s ", prefix);
1595 1581 (void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag);
1596 1582 if (range) {
1597 1583 (void) printf(" - ");
1598 1584 (void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout,
1599 1585 nflag);
1600 1586 }
1601 1587 (void) printf("\n");
1602 1588
1603 1589 }
1604 1590
1605 1591 /*
1606 1592 * used to tell printing function if info should be identified
1607 1593 * as belonging to initiator, responder, or neither
1608 1594 */
1609 1595 #define IS_INITIATOR 1
1610 1596 #define IS_RESPONDER 2
1611 1597 #define DONT_PRINT_INIT 3
1612 1598
1613 1599 static void
1614 1600 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr)
1615 1601 {
1616 1602 (void) printf(gettext("%s Address"), prefix);
1617 1603
1618 1604 if (init_instr != DONT_PRINT_INIT)
1619 1605 (void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ?
1620 1606 gettext("Initiator") : gettext("Responder"));
1621 1607 else
1622 1608 (void) printf(":\n");
1623 1609
1624 1610 (void) printf("%s ", prefix);
1625 1611 (void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag);
1626 1612 }
1627 1613
1628 1614 static void
1629 1615 print_id(char *prefix, sadb_ident_t *idp, int init_instr)
1630 1616 {
1631 1617 boolean_t canprint;
1632 1618
1633 1619 switch (init_instr) {
1634 1620 case IS_INITIATOR:
1635 1621 (void) printf(gettext("%s Initiator identity, "), prefix);
1636 1622 break;
1637 1623 case IS_RESPONDER:
1638 1624 (void) printf(gettext("%s Responder identity, "), prefix);
1639 1625 break;
1640 1626 case DONT_PRINT_INIT:
1641 1627 (void) printf(gettext("%s Identity, "), prefix);
1642 1628 break;
1643 1629 default:
1644 1630 (void) printf(gettext("<invalid identity>\n"));
1645 1631 return;
1646 1632 }
1647 1633 (void) printf(gettext("uid=%d, type "), idp->sadb_ident_id);
1648 1634 canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL);
1649 1635 if (canprint) {
1650 1636 (void) printf("\n%s %s\n", prefix, (char *)(idp + 1));
1651 1637 } else {
1652 1638 (void) printf(gettext("\n%s "), prefix);
1653 1639 print_asn1_name(stdout,
1654 1640 (const unsigned char *)(idp + 1),
1655 1641 SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t));
1656 1642 }
1657 1643 }
1658 1644
1659 1645 static void
1660 1646 print_idspec(char *prefix, char *idp, int icnt, int ecnt)
1661 1647 {
1662 1648 int i;
1663 1649
1664 1650 (void) printf(gettext("%s Identity descriptors:\n"), prefix);
1665 1651
1666 1652 for (i = 0; i < icnt; i++) {
1667 1653 if (i == 0)
1668 1654 (void) printf(gettext("%s Includes:\n"), prefix);
1669 1655 (void) printf("%s %s\n", prefix, idp);
1670 1656 idp += strlen(idp) + 1;
1671 1657 }
1672 1658
1673 1659 for (i = 0; i < ecnt; i++) {
1674 1660 if (i == 0)
1675 1661 (void) printf(gettext("%s Excludes:\n"), prefix);
1676 1662 (void) printf("%s %s\n", prefix, idp);
1677 1663 idp += strlen(idp) + 1;
1678 1664 }
1679 1665 }
1680 1666
1681 1667 static void
1682 1668 print_keys(char *prefix, ike_p1_key_t *keyp, int size)
1683 1669 {
1684 1670 uint32_t *curp;
1685 1671 ike_p1_key_t *p;
1686 1672 int ssize;
1687 1673
1688 1674 curp = (uint32_t *)keyp;
1689 1675
1690 1676 ssize = sizeof (ike_p1_key_t);
1691 1677
1692 1678 while ((intptr_t)curp - (intptr_t)keyp < size) {
1693 1679 size_t p1klen, len;
1694 1680
1695 1681 p = (ike_p1_key_t *)curp;
1696 1682 p1klen = p->p1key_len;
1697 1683 len = p1klen - ssize;
1698 1684
1699 1685 p1klen = roundup(p1klen, sizeof (ike_p1_key_t));
1700 1686 if (p1klen < ssize) {
1701 1687 (void) printf(gettext("Short key\n"));
1702 1688 break;
1703 1689 }
1704 1690
1705 1691 switch (p->p1key_type) {
1706 1692 case IKE_KEY_PRESHARED:
1707 1693 (void) printf(gettext("%s Pre-shared key (%d bytes): "),
1708 1694 prefix, len);
1709 1695 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1710 1696 stdout);
1711 1697 break;
1712 1698 case IKE_KEY_SKEYID:
1713 1699 (void) printf(gettext("%s SKEYID (%d bytes): "),
1714 1700 prefix, len);
1715 1701 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1716 1702 stdout);
1717 1703 break;
1718 1704 case IKE_KEY_SKEYID_D:
1719 1705 (void) printf(gettext("%s SKEYID_d (%d bytes): "),
1720 1706 prefix, len);
1721 1707 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1722 1708 stdout);
1723 1709 break;
1724 1710 case IKE_KEY_SKEYID_A:
1725 1711 (void) printf(gettext("%s SKEYID_a (%d bytes): "),
1726 1712 prefix, len);
1727 1713 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1728 1714 stdout);
1729 1715 break;
1730 1716 case IKE_KEY_SKEYID_E:
1731 1717 (void) printf(gettext("%s SKEYID_e (%d bytes): "),
1732 1718 prefix, len);
1733 1719 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1734 1720 stdout);
1735 1721 break;
1736 1722 case IKE_KEY_ENCR:
1737 1723 (void) printf(gettext("%s Encryption key (%d bytes): "),
1738 1724 prefix, len);
1739 1725 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1740 1726 stdout);
1741 1727 break;
1742 1728 case IKE_KEY_IV:
1743 1729 (void) printf(
1744 1730 gettext("%s Initialization vector (%d bytes): "),
1745 1731 prefix, len);
1746 1732 (void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len),
1747 1733 stdout);
1748 1734 break;
1749 1735 default:
1750 1736 (void) printf(gettext("%s Unidentified key info %p %d"),
1751 1737 prefix, p, p1klen);
1752 1738 }
1753 1739 (void) printf("\n");
1754 1740 assert(IS_P2ALIGNED(p1klen, 8));
1755 1741 curp += (p1klen >> 2);
1756 1742 }
1757 1743 }
1758 1744
1759 1745 static void
1760 1746 print_p1(ike_p1_sa_t *p1)
1761 1747 {
1762 1748 ike_p1_stats_t *sp;
1763 1749 ike_p1_errors_t *ep;
1764 1750 ike_p1_key_t *kp;
1765 1751 sadb_ident_t *lidp, *ridp;
1766 1752 int lstat, rstat;
1767 1753
1768 1754 (void) printf("\n");
1769 1755 print_hdr("IKESA:", &p1->p1sa_hdr);
1770 1756 print_xform("XFORM:", &p1->p1sa_xform, B_FALSE);
1771 1757
1772 1758 if (p1->p1sa_hdr.p1hdr_isinit) {
1773 1759 lstat = IS_INITIATOR;
1774 1760 rstat = IS_RESPONDER;
1775 1761 } else {
1776 1762 lstat = IS_RESPONDER;
1777 1763 rstat = IS_INITIATOR;
1778 1764 }
1779 1765 print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat);
1780 1766 print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat);
1781 1767
1782 1768 /*
1783 1769 * the stat len might be 0; but still make the call
1784 1770 * to print_lifetime() to pick up the xform info
1785 1771 */
1786 1772 sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off);
1787 1773 print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len);
1788 1774
1789 1775 if (p1->p1sa_stat_len > 0) {
1790 1776 print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE);
1791 1777 }
1792 1778
1793 1779 if (p1->p1sa_error_len > 0) {
1794 1780 ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off);
1795 1781 print_errs("ERRS: ", ep, p1->p1sa_error_len);
1796 1782 }
1797 1783
1798 1784 if (p1->p1sa_localid_len > 0) {
1799 1785 lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off);
1800 1786 print_id("LOCID:", lidp, lstat);
1801 1787 }
1802 1788
1803 1789 if (p1->p1sa_remoteid_len > 0) {
1804 1790 ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off);
1805 1791 print_id("REMID:", ridp, rstat);
1806 1792 }
1807 1793
1808 1794 if (p1->p1sa_key_len > 0) {
1809 1795 kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off);
1810 1796 print_keys("KEY: ", kp, p1->p1sa_key_len);
1811 1797 }
1812 1798 }
1813 1799
1814 1800 static void
1815 1801 print_ps(ike_ps_t *ps)
1816 1802 {
1817 1803 sadb_ident_t *lidp, *ridp;
1818 1804 uint8_t *keyp;
1819 1805
1820 1806 (void) printf("\n");
1821 1807
1822 1808 (void) printf(gettext("PSKEY: For %s exchanges\n"),
1823 1809 xchgstr(ps->ps_ike_mode));
1824 1810
1825 1811 if (ps->ps_key_len > 0) {
1826 1812 keyp = (uint8_t *)((int)(ps) + ps->ps_key_off);
1827 1813 (void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "),
1828 1814 ps->ps_key_len);
1829 1815 (void) dump_key(keyp, ps->ps_key_bits, stdout);
1830 1816 (void) printf("\n");
1831 1817 }
1832 1818
1833 1819 /*
1834 1820 * We get *either* and address or an ident, never both. So if
1835 1821 * the ident is there, don't try printing an address.
1836 1822 */
1837 1823 if (ps->ps_localid_len > 0) {
1838 1824 lidp = (sadb_ident_t *)
1839 1825 ((int)(ps) + ps->ps_localid_off);
1840 1826 print_id("LOCID:", lidp, DONT_PRINT_INIT);
1841 1827 } else {
1842 1828 print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT);
1843 1829 }
1844 1830
1845 1831 if (ps->ps_remoteid_len > 0) {
1846 1832 ridp = (sadb_ident_t *)
1847 1833 ((int)(ps) + ps->ps_remoteid_off);
1848 1834 print_id("REMID:", ridp, DONT_PRINT_INIT);
1849 1835 } else {
1850 1836 print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT);
1851 1837 }
1852 1838 }
1853 1839
1854 1840 #define PREFIXLEN 16
1855 1841
1856 1842 static void
1857 1843 print_rule(ike_rule_t *rp)
1858 1844 {
1859 1845 char prefix[PREFIXLEN];
1860 1846 int i;
1861 1847 ike_p1_xform_t *xfp;
1862 1848 ike_addr_pr_t *lipp, *ripp;
1863 1849 char *lidp, *ridp;
1864 1850
1865 1851 (void) printf("\n");
1866 1852 (void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"),
1867 1853 rp->rule_label, rp->rule_kmcookie);
1868 1854 (void) printf(gettext("GLOBL: local_idtype="));
1869 1855 (void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL);
1870 1856 (void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode));
1871 1857 (void) printf(gettext(
1872 1858 "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
1873 1859 rp->rule_p1_nonce_len, rp->rule_p2_nonce_len,
1874 1860 (rp->rule_p2_pfs) ? gettext("true") : gettext("false"),
1875 1861 rp->rule_p2_pfs);
1876 1862 (void) printf(
1877 1863 gettext("GLOBL: p2_lifetime=%u seconds, p2_softlife=%u seconds\n"),
1878 1864 rp->rule_p2_lifetime_secs, rp->rule_p2_softlife_secs);
1879 1865 (void) printf(
1880 1866 gettext("GLOBL: p2_lifetime_kb=%u seconds,"
1881 1867 " p2_softlife_kb=%u seconds\n"),
1882 1868 rp->rule_p2_lifetime_kb, rp->rule_p2_softlife_kb);
1883 1869
1884 1870 if (rp->rule_locip_cnt > 0) {
1885 1871 (void) printf(gettext("LOCIP: IP address range(s):\n"));
1886 1872 lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off);
1887 1873 for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) {
1888 1874 print_addr_range("LOCIP:", lipp);
1889 1875 }
1890 1876 }
1891 1877
1892 1878 if (rp->rule_remip_cnt > 0) {
1893 1879 (void) printf(gettext("REMIP: IP address range(s):\n"));
1894 1880 ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off);
1895 1881 for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) {
1896 1882 print_addr_range("REMIP:", ripp);
1897 1883 }
1898 1884 }
1899 1885
1900 1886 if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) {
1901 1887 lidp = (char *)((int)rp + rp->rule_locid_off);
1902 1888 print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt,
1903 1889 rp->rule_locid_exclcnt);
1904 1890 }
1905 1891
1906 1892 if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) {
1907 1893 ridp = (char *)((int)rp + rp->rule_remid_off);
1908 1894 print_idspec("REMID:", ridp, rp->rule_remid_inclcnt,
1909 1895 rp->rule_remid_exclcnt);
1910 1896 }
1911 1897
1912 1898 if (rp->rule_xform_cnt > 0) {
1913 1899 (void) printf(gettext("XFRMS: Available Transforms:\n"));
1914 1900 xfp = (ike_p1_xform_t *)((int)rp + rp->rule_xform_off);
1915 1901 for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) {
1916 1902 (void) snprintf(prefix, PREFIXLEN, "XF %2u:", i);
1917 1903 print_xform(prefix, xfp, B_TRUE);
1918 1904 }
1919 1905 }
1920 1906 }
1921 1907
1922 1908 #undef PREFIXLEN
1923 1909
1924 1910 #define PRSACNTS(init, resp) \
1925 1911 (void) printf(gettext("initiator: %10u responder: %10u\n"), \
1926 1912 (init), (resp))
1927 1913
1928 1914 static void
1929 1915 print_stats(ike_stats_t *sp, int len)
1930 1916 {
1931 1917 /*
1932 1918 * before printing each line, make sure the structure we were
1933 1919 * given is big enough to include the fields needed.
1934 1920 */
1935 1921 if (len < COUNTER_PAIR)
1936 1922 return;
1937 1923 (void) printf(gettext("Phase 1 SA counts:\n"));
1938 1924 (void) printf(gettext("Current: "));
1939 1925 PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current);
1940 1926 len -= COUNTER_PAIR;
1941 1927
1942 1928 if (len < COUNTER_PAIR)
1943 1929 return;
1944 1930 (void) printf(gettext("Total: "));
1945 1931 PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total);
1946 1932 len -= COUNTER_PAIR;
1947 1933
1948 1934 if (len < COUNTER_PAIR)
1949 1935 return;
1950 1936 (void) printf(gettext("Attempted: "));
1951 1937 PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts);
1952 1938 len -= COUNTER_PAIR;
1953 1939
1954 1940 if (len < (COUNTER_PAIR + COUNTER_32BIT))
1955 1941 return;
1956 1942 (void) printf(gettext("Failed: "));
1957 1943 PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail,
1958 1944 sp->st_resp_p1_fail);
1959 1945 (void) printf(
1960 1946 gettext(" initiator fails include %u time-out(s)\n"),
1961 1947 sp->st_init_p1_noresp);
1962 1948
1963 1949 if (len < PATH_MAX)
1964 1950 return;
1965 1951 if (*(sp->st_pkcs11_libname) != '\0')
1966 1952 (void) printf(gettext("PKCS#11 library linked in from %s\n"),
1967 1953 sp->st_pkcs11_libname);
1968 1954 }
1969 1955
1970 1956 static void
1971 1957 print_defaults(char *label, char *description, char *unit, boolean_t kbytes,
1972 1958 uint_t current, uint_t def)
1973 1959 {
1974 1960 (void) printf("%-18s%-10s%14u%s%-10s%-26s\n", label,
1975 1961 (current != def) ? gettext("config") : gettext("default"),
1976 1962 (current != def) ? current : def, (kbytes) ? "K " : " ",
1977 1963 unit, description);
1978 1964 }
1979 1965
1980 1966 /*
1981 1967 * Print out defaults used by in.iked, the argument is a buffer containing
1982 1968 * two ike_defaults_t's, the first contains the hard coded defaults, the second
1983 1969 * contains the actual values used. If these differ, then the defaults have been
1984 1970 * changed via a config file entry. Note that "-" indicates this default
1985 1971 * is not tunable.
1986 1972 */
1987 1973 static void
1988 1974 do_print_defaults(ike_defaults_t *dp)
1989 1975 {
1990 1976 ike_defaults_t *ddp;
1991 1977 ddp = (ike_defaults_t *)(dp + 1);
1992 1978
1993 1979 (void) printf(gettext("\nGlobal defaults. Some values can be"
1994 1980 " over-ridden on a per rule basis.\n\n"));
1995 1981
1996 1982 (void) printf("%-18s%-10s%-16s%-10s%-26s\n\n",
1997 1983 gettext("Token:"), gettext("Source:"), gettext("Value:"),
1998 1984 gettext("Unit:"), gettext("Description:"));
1999 1985
2000 1986 print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"),
2001 1987 gettext("seconds"), B_FALSE, ddp->rule_p1_lifetime_secs,
2002 1988 dp->rule_p1_lifetime_secs);
2003 1989
2004 1990 print_defaults("-", gettext("minimum phase 1 lifetime"),
2005 1991 gettext("seconds"), B_FALSE, ddp->rule_p1_minlife,
2006 1992 dp->rule_p1_minlife);
2007 1993
2008 1994 print_defaults("p1_nonce_len", gettext("phase 1 nonce length"),
2009 1995 gettext("bytes"), B_FALSE, ddp->rule_p1_nonce_len,
2010 1996 dp->rule_p1_nonce_len);
2011 1997
2012 1998 print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"),
2013 1999 gettext("seconds"), B_FALSE, ddp->rule_p2_lifetime_secs,
2014 2000 dp->rule_p2_lifetime_secs);
2015 2001
2016 2002 print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"),
2017 2003 gettext("seconds"), B_FALSE, ddp->rule_p2_softlife_secs,
2018 2004 dp->rule_p2_softlife_secs);
2019 2005
2020 2006 print_defaults("-", gettext("system phase 2 lifetime"),
2021 2007 gettext("seconds"), B_FALSE, ddp->sys_p2_lifetime_secs,
2022 2008 dp->sys_p2_lifetime_secs);
2023 2009
2024 2010 print_defaults("-", gettext("system phase 2 soft lifetime"),
2025 2011 gettext("seconds"), B_FALSE, ddp->sys_p2_softlife_secs,
2026 2012 dp->sys_p2_softlife_secs);
2027 2013
2028 2014 print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"),
2029 2015 gettext("bytes"), B_TRUE, ddp->rule_p2_lifetime_kb,
2030 2016 dp->rule_p2_lifetime_kb);
2031 2017
2032 2018 print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"),
2033 2019 gettext("bytes"), B_TRUE, ddp->rule_p2_softlife_kb,
2034 2020 dp->rule_p2_softlife_kb);
2035 2021
2036 2022 print_defaults("-", gettext("system phase 2 lifetime"),
2037 2023 gettext("bytes"), B_FALSE, ddp->sys_p2_lifetime_bytes,
2038 2024 dp->sys_p2_lifetime_bytes);
2039 2025
2040 2026 print_defaults("-", gettext("system phase 2 soft lifetime"),
2041 2027 gettext("bytes"), B_FALSE, ddp->sys_p2_softlife_bytes,
2042 2028 dp->sys_p2_softlife_bytes);
2043 2029
2044 2030 print_defaults("-", gettext("minimum phase 2 lifetime"),
2045 2031 gettext("seconds"), B_FALSE, ddp->rule_p2_minlife,
2046 2032 dp->rule_p2_minlife);
2047 2033
2048 2034 print_defaults("p2_nonce_len", gettext("phase 2 nonce length"),
2049 2035 gettext("bytes"), B_FALSE, ddp->rule_p2_nonce_len,
2050 2036 dp->rule_p2_nonce_len);
2051 2037
2052 2038 print_defaults("-", gettext("default phase 2 lifetime"),
2053 2039 gettext("seconds"), B_FALSE, ddp->rule_p2_def_minlife,
2054 2040 dp->rule_p2_def_minlife);
2055 2041
2056 2042 print_defaults("-", gettext("minimum phase 2 soft delta"),
2057 2043 gettext("seconds"), B_FALSE, ddp->rule_p2_minsoft,
2058 2044 dp->rule_p2_minsoft);
2059 2045
2060 2046 print_defaults("p2_pfs", gettext("phase 2 PFS"),
2061 2047 " ", B_FALSE, ddp->rule_p2_pfs, dp->rule_p2_pfs);
2062 2048
2063 2049 print_defaults("max_certs", gettext("max certificates"),
2064 2050 " ", B_FALSE, ddp->rule_max_certs, dp->rule_max_certs);
2065 2051
2066 2052 print_defaults("-", gettext("IKE port number"),
2067 2053 " ", B_FALSE, ddp->rule_ike_port, dp->rule_ike_port);
2068 2054
2069 2055 print_defaults("-", gettext("NAT-T port number"),
2070 2056 " ", B_FALSE, ddp->rule_natt_port, dp->rule_natt_port);
2071 2057 }
2072 2058
2073 2059 static void
2074 2060 print_categories(int level)
2075 2061 {
2076 2062 int mask;
2077 2063
2078 2064 if (level == 0) {
2079 2065 (void) printf(gettext("No debug categories enabled.\n"));
2080 2066 return;
2081 2067 }
2082 2068
2083 2069 (void) printf(gettext("Debug categories enabled:"));
2084 2070 for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) {
2085 2071 if (level & mask)
2086 2072 (void) printf("\n\t%s", dbgstr(mask));
2087 2073 }
2088 2074 (void) printf("\n");
2089 2075 }
2090 2076
2091 2077 /*PRINTFLIKE2*/
2092 2078 static void
2093 2079 ikeadm_err_exit(ike_err_t *err, char *fmt, ...)
2094 2080 {
2095 2081 va_list ap;
2096 2082 char bailbuf[BUFSIZ];
2097 2083
2098 2084 va_start(ap, fmt);
2099 2085 (void) vsnprintf(bailbuf, BUFSIZ, fmt, ap);
2100 2086 va_end(ap);
2101 2087 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2102 2088 bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ?
2103 2089 gettext("<unknown error>") : strerror(err->ike_err_unix));
2104 2090 } else {
2105 2091 bail_msg("%s: %s", bailbuf, (err == NULL) ?
2106 2092 gettext("<unknown error>") : errstr(err->ike_err));
2107 2093 }
2108 2094 }
2109 2095
2110 2096 /*PRINTFLIKE2*/
2111 2097 static void
2112 2098 ikeadm_err_msg(ike_err_t *err, char *fmt, ...)
2113 2099 {
2114 2100 va_list ap;
2115 2101 char mbuf[BUFSIZ];
2116 2102
2117 2103 va_start(ap, fmt);
2118 2104 (void) vsnprintf(mbuf, BUFSIZ, fmt, ap);
2119 2105 va_end(ap);
2120 2106 if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2121 2107 message("%s: %s", mbuf, (err->ike_err_unix == 0) ?
2122 2108 gettext("<unknown error>") :
2123 2109 ((err->ike_err_unix == EEXIST) ?
2124 2110 gettext("Duplicate entry") :
2125 2111 strerror(err->ike_err_unix)));
2126 2112 } else {
2127 2113 message("%s: %s", mbuf, (err == NULL) ?
2128 2114 gettext("<unknown error>") : errstr(err->ike_err));
2129 2115 }
2130 2116 }
2131 2117
2132 2118
2133 2119 /*
2134 2120 * Command functions
2135 2121 */
2136 2122
2137 2123 /*
2138 2124 * Exploit the fact that ike_dbg_t and ike_priv_t have identical
2139 2125 * formats in the following two functions.
2140 2126 */
2141 2127 static void
2142 2128 do_getvar(int cmd)
2143 2129 {
2144 2130 ike_service_t req, *rtn;
2145 2131 ike_dbg_t *dreq;
2146 2132 char *varname;
2147 2133
2148 2134 switch (cmd) {
2149 2135 case IKE_SVC_GET_DBG:
2150 2136 varname = gettext("debug");
2151 2137 break;
2152 2138 case IKE_SVC_GET_PRIV:
2153 2139 varname = gettext("privilege");
2154 2140 break;
2155 2141 default:
2156 2142 bail_msg(gettext("unrecognized get command (%d)"), cmd);
2157 2143 }
2158 2144
2159 2145 dreq = &req.svc_dbg;
2160 2146 dreq->cmd = cmd;
2161 2147 dreq->dbg_level = 0;
2162 2148
2163 2149 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0);
2164 2150
2165 2151 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2166 2152 ikeadm_err_exit(&rtn->svc_err,
2167 2153 gettext("error getting %s level"), varname);
2168 2154 }
2169 2155 dreq = &rtn->svc_dbg;
2170 2156 (void) printf(gettext("Current %s level is 0x%x"),
2171 2157 varname, dreq->dbg_level);
2172 2158
2173 2159 if (cmd == IKE_SVC_GET_DBG) {
2174 2160 (void) printf("\n");
2175 2161 print_categories(dreq->dbg_level);
2176 2162 } else {
2177 2163 (void) printf(gettext(", %s enabled\n"),
2178 2164 privstr(dreq->dbg_level));
2179 2165 }
2180 2166 }
2181 2167
2182 2168 static void
2183 2169 do_setvar(int cmd, int argc, char **argv)
2184 2170 {
2185 2171 ike_service_t req, *rtn;
2186 2172 ike_dbg_t *dreq;
2187 2173 door_desc_t *descp = NULL, desc;
2188 2174 int fd, ndesc = 0;
2189 2175 uint32_t reqlevel;
2190 2176 char *varname;
2191 2177
2192 2178 if (argc < 1)
2193 2179 Bail("unspecified level");
2194 2180 reqlevel = strtoul(argv[0], NULL, 0);
2195 2181
2196 2182 switch (cmd) {
2197 2183 case IKE_SVC_SET_DBG:
2198 2184 if (argc > 2)
2199 2185 Bail("Too many arguments to \"set debug\"");
2200 2186 varname = gettext("debug");
2201 2187 if (reqlevel == 0) {
2202 2188 /* check for a string... */
2203 2189 reqlevel = parsedbgopts(argv[0]);
2204 2190 }
2205 2191 if (reqlevel == D_INVALID)
2206 2192 bail_msg(gettext("Bad debug flag: %s"), argv[0]);
2207 2193 break;
2208 2194 case IKE_SVC_SET_PRIV:
2209 2195 if (argc > 1)
2210 2196 Bail("Too many arguments to \"set priv\"");
2211 2197
2212 2198 varname = gettext("privilege");
2213 2199 if (reqlevel == 0) {
2214 2200 /* check for a string... */
2215 2201 reqlevel = privstr2num(argv[0]);
2216 2202 }
2217 2203 if (reqlevel > IKE_PRIV_MAXIMUM)
2218 2204 bail_msg(gettext("Bad privilege flag: %s"), argv[0]);
2219 2205 break;
2220 2206 default:
2221 2207 bail_msg(gettext("unrecognized set command (%d)"), cmd);
2222 2208 }
2223 2209
2224 2210 dreq = &req.svc_dbg;
2225 2211 dreq->cmd = cmd;
2226 2212 dreq->dbg_level = reqlevel;
2227 2213
2228 2214 if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) {
2229 2215 fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND,
2230 2216 S_IRUSR | S_IWUSR);
2231 2217 if (fd < 0)
2232 2218 Bail("open debug file");
2233 2219 desc.d_data.d_desc.d_descriptor = fd;
2234 2220 desc.d_attributes = DOOR_DESCRIPTOR;
2235 2221 descp = &desc;
2236 2222 ndesc = 1;
2237 2223 }
2238 2224
2239 2225 rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc);
2240 2226
2241 2227 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2242 2228 ikeadm_err_exit(&rtn->svc_err,
2243 2229 gettext("error setting %s level"), varname);
2244 2230 }
2245 2231 dreq = &rtn->svc_dbg;
2246 2232 (void) printf(
2247 2233 gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
2248 2234 varname, dreq->dbg_level, reqlevel);
2249 2235
2250 2236 if (cmd == IKE_SVC_SET_DBG) {
2251 2237 print_categories(reqlevel);
2252 2238 } else {
2253 2239 (void) printf(gettext("New privilege level 0x%x enables %s\n"),
2254 2240 reqlevel, privstr(reqlevel));
2255 2241 }
2256 2242 }
2257 2243
2258 2244 static void
2259 2245 do_getstats(int cmd)
2260 2246 {
2261 2247 ike_service_t *rtn;
2262 2248 ike_statreq_t sreq, *sreqp;
2263 2249 ike_stats_t *sp;
2264 2250
2265 2251 sreq.cmd = cmd;
2266 2252
2267 2253 rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0);
2268 2254 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2269 2255 ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats"));
2270 2256 }
2271 2257
2272 2258 sreqp = &rtn->svc_stats;
2273 2259 sp = (ike_stats_t *)(sreqp + 1);
2274 2260 print_stats(sp, sreqp->stat_len);
2275 2261 }
2276 2262
2277 2263 static void
2278 2264 do_getdefs(int cmd)
2279 2265 {
2280 2266 ike_service_t *rtn;
2281 2267 ike_defreq_t dreq, *dreqp;
2282 2268 ike_defaults_t *dp;
2283 2269
2284 2270 dreq.cmd = cmd;
2285 2271
2286 2272 rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0);
2287 2273 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2288 2274 ikeadm_err_exit(&rtn->svc_err,
2289 2275 gettext("error getting defaults"));
2290 2276 }
2291 2277
2292 2278 dreqp = &rtn->svc_defaults;
2293 2279 dp = (ike_defaults_t *)(dreqp + 1);
2294 2280
2295 2281 /*
2296 2282 * Before printing each line, make sure the structure we were
2297 2283 * given is big enough to include the fields needed.
2298 2284 * Silently bail out of there is a version mismatch.
2299 2285 */
2300 2286 if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t))
2301 2287 + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) {
2302 2288 return;
2303 2289 }
2304 2290 do_print_defaults(dp);
2305 2291 }
2306 2292
2307 2293 static void
2308 2294 do_dump(int cmd)
2309 2295 {
2310 2296 char *name;
2311 2297 ike_service_t req, *rtn;
2312 2298 ike_dump_t *dreq, *dump;
2313 2299
2314 2300 switch (cmd) {
2315 2301 case IKE_SVC_DUMP_P1S:
2316 2302 name = gettext("phase 1 SA info");
2317 2303 break;
2318 2304 case IKE_SVC_DUMP_RULES:
2319 2305 name = gettext("policy rules");
2320 2306 break;
2321 2307 case IKE_SVC_DUMP_PS:
2322 2308 name = gettext("preshared keys");
2323 2309 break;
2324 2310 default:
2325 2311 bail_msg(gettext("unrecognized dump command (%d)"), cmd);
2326 2312 }
2327 2313
2328 2314 dreq = &req.svc_dump;
2329 2315 dreq->cmd = cmd;
2330 2316 dreq->dump_len = 0;
2331 2317 dreq->dump_next = 0;
2332 2318 do {
2333 2319 rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t),
2334 2320 NULL, 0);
2335 2321 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2336 2322 if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2337 2323 /* no entries to print */
2338 2324 break;
2339 2325 }
2340 2326 ikeadm_err_exit(&rtn->svc_err,
2341 2327 gettext("error getting %s"), name);
2342 2328 }
2343 2329 dump = &rtn->svc_dump;
2344 2330
2345 2331 switch (cmd) {
2346 2332 case IKE_SVC_DUMP_P1S:
2347 2333 print_p1((ike_p1_sa_t *)(dump + 1));
2348 2334 break;
2349 2335 case IKE_SVC_DUMP_RULES:
2350 2336 print_rule((ike_rule_t *)(dump + 1));
2351 2337 break;
2352 2338 case IKE_SVC_DUMP_PS:
2353 2339 print_ps((ike_ps_t *)(dump + 1));
2354 2340 break;
2355 2341 }
2356 2342
2357 2343 dreq->dump_next = dump->dump_next;
2358 2344
2359 2345 (void) munmap((char *)rtn, dump->dump_len);
2360 2346
2361 2347 } while (dreq->dump_next);
2362 2348
2363 2349 (void) printf(gettext("\nCompleted dump of %s\n"), name);
2364 2350 }
2365 2351
2366 2352 static void
2367 2353 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name)
2368 2354 {
2369 2355 int totallen;
2370 2356 char *p;
2371 2357 ike_service_t *reqp, *rtnp;
2372 2358 ike_get_t *getp;
2373 2359 boolean_t getcmd;
2374 2360
2375 2361 getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) ||
2376 2362 (cmd == IKE_SVC_GET_PS));
2377 2363
2378 2364 /*
2379 2365 * WARNING: to avoid being redundant, this code takes advantage
2380 2366 * of the fact that the ike_get_t and ike_del_t structures are
2381 2367 * identical (only the field names differ, their function and
2382 2368 * size are the same). If for some reason those structures
2383 2369 * change, this code will need to be re-written to accomodate
2384 2370 * that difference.
2385 2371 */
2386 2372 totallen = sizeof (ike_get_t) + idlen;
2387 2373 if ((reqp = (ike_service_t *)malloc(totallen)) == NULL)
2388 2374 Bail("malloc(id)");
2389 2375
2390 2376 getp = &reqp->svc_get;
2391 2377 getp->cmd = cmd;
2392 2378 getp->get_len = totallen;
2393 2379 getp->get_idtype = idtype;
2394 2380 p = (char *)(getp + 1);
2395 2381
2396 2382 (void) memcpy(p, idp, idlen);
2397 2383
2398 2384 rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0);
2399 2385 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2400 2386 if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2401 2387 message(gettext("Could not find requested %s."), name);
2402 2388 } else {
2403 2389 ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"),
2404 2390 (getcmd) ? gettext("getting") : gettext("deleting"),
2405 2391 name);
2406 2392 }
2407 2393 free(reqp);
2408 2394 return;
2409 2395 }
2410 2396 getp = &rtnp->svc_get;
2411 2397
2412 2398 if (getcmd) {
2413 2399 switch (cmd) {
2414 2400 case IKE_SVC_GET_P1:
2415 2401 print_p1((ike_p1_sa_t *)(getp + 1));
2416 2402 break;
2417 2403 case IKE_SVC_GET_PS:
2418 2404 print_ps((ike_ps_t *)(getp + 1));
2419 2405 break;
2420 2406 case IKE_SVC_GET_RULE:
2421 2407 print_rule((ike_rule_t *)(getp + 1));
2422 2408 break;
2423 2409 }
2424 2410 } else {
2425 2411 message(gettext("Successfully deleted selected %s."), name);
2426 2412 }
2427 2413
2428 2414 (void) munmap((char *)rtnp, getp->get_len);
2429 2415 free(reqp);
2430 2416 }
2431 2417
2432 2418 static void
2433 2419 do_getdel(int cmd, int argc, char **argv)
2434 2420 {
2435 2421 int idlen, idtype = 0, i, j;
2436 2422 int bytelen1, bytelen2;
2437 2423 char *name, *idp, *p, *p1, *p2;
2438 2424 ike_addr_pr_t apr;
2439 2425 ike_cky_pr_t cpr;
2440 2426 sadb_ident_t *sid1p, *sid2p;
2441 2427 struct hostent *he1p, *he2p;
2442 2428 char label[MAX_LABEL_LEN];
2443 2429
2444 2430 if ((argc < 1) || (argv[0] == NULL)) {
2445 2431 Bail("not enough identification info");
2446 2432 }
2447 2433
2448 2434 switch (cmd) {
2449 2435 case IKE_SVC_GET_P1:
2450 2436 case IKE_SVC_DEL_P1:
2451 2437 name = gettext("phase 1 SA");
2452 2438 /*
2453 2439 * The first token must either be an address (or hostname)
2454 2440 * or a cookie. We require cookies to be entered as hex
2455 2441 * numbers, beginning with 0x; so if our token starts with
2456 2442 * that, it's a cookie.
2457 2443 */
2458 2444 if (strncmp(argv[0], "0x", 2) == 0) {
2459 2445 if (parse_cky_pr(argc, argv, &cpr) >= 0) {
2460 2446 idtype = IKE_ID_CKY_PAIR;
2461 2447 idlen = sizeof (ike_cky_pr_t);
2462 2448 idp = (char *)&cpr;
2463 2449 }
2464 2450 } else {
2465 2451 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2466 2452 idtype = IKE_ID_ADDR_PAIR;
2467 2453 idlen = sizeof (ike_addr_pr_t);
2468 2454 }
2469 2455 }
2470 2456 break;
2471 2457
2472 2458 case IKE_SVC_GET_RULE:
2473 2459 case IKE_SVC_DEL_RULE:
2474 2460 name = gettext("policy rule");
2475 2461 if (parse_label(argc, argv, label) >= 0) {
2476 2462 idtype = IKE_ID_LABEL;
2477 2463 idlen = MAX_LABEL_LEN;
2478 2464 idp = label;
2479 2465 }
2480 2466 break;
2481 2467
2482 2468 case IKE_SVC_GET_PS:
2483 2469 case IKE_SVC_DEL_PS:
2484 2470 name = gettext("preshared key");
2485 2471 /*
2486 2472 * The first token must either be an address or an ident
2487 2473 * type. Check for an ident type to determine which it is.
2488 2474 */
2489 2475 if (parse_idtype(argv[0], NULL) >= 0) {
2490 2476 if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) {
2491 2477 idtype = IKE_ID_IDENT_PAIR;
2492 2478 idlen = SADB_64TO8(sid1p->sadb_ident_len) +
2493 2479 SADB_64TO8(sid2p->sadb_ident_len);
2494 2480 }
2495 2481 } else {
2496 2482 if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2497 2483 idtype = IKE_ID_ADDR_PAIR;
2498 2484 idlen = sizeof (ike_addr_pr_t);
2499 2485 }
2500 2486 }
2501 2487 break;
2502 2488
2503 2489 default:
2504 2490 bail_msg(gettext("unrecognized get/del command (%d)"), cmd);
2505 2491 }
2506 2492
2507 2493 switch (idtype) {
2508 2494 case IKE_ID_ADDR_PAIR:
2509 2495 /*
2510 2496 * we might have exploding addrs here; do every possible
2511 2497 * combination.
2512 2498 */
2513 2499 i = 0;
2514 2500 j = 0;
2515 2501 while ((p1 = he1p->h_addr_list[i++]) != NULL) {
2516 2502 headdr2sa(p1, &apr.loc_addr, he1p->h_length);
2517 2503
2518 2504 while ((p2 = he2p->h_addr_list[j++]) != NULL) {
2519 2505 headdr2sa(p2, &apr.rem_addr, he2p->h_length);
2520 2506 do_getdel_doorcall(cmd, idlen, idtype,
2521 2507 (char *)&apr, name);
2522 2508 }
2523 2509 }
2524 2510 FREE_HE(he1p);
2525 2511 FREE_HE(he2p);
2526 2512 break;
2527 2513
2528 2514 case IKE_ID_IDENT_PAIR:
2529 2515 bytelen1 = SADB_64TO8(sid1p->sadb_ident_len);
2530 2516 bytelen2 = SADB_64TO8(sid2p->sadb_ident_len);
2531 2517 if (idlen != bytelen1 + bytelen2)
2532 2518 Bail("ident syntax error");
2533 2519 idp = p = (char *)malloc(idlen);
2534 2520 if (p == NULL)
2535 2521 Bail("malloc(id)");
2536 2522 (void) memcpy(p, (char *)sid1p, bytelen1);
2537 2523 p += bytelen1;
2538 2524 (void) memcpy(p, (char *)sid2p, bytelen2);
2539 2525 do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2540 2526 free(idp);
2541 2527 free(sid1p);
2542 2528 free(sid2p);
2543 2529 break;
2544 2530
2545 2531 case IKE_ID_CKY_PAIR:
2546 2532 case IKE_ID_LABEL:
2547 2533 do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2548 2534 break;
2549 2535
2550 2536 case 0:
2551 2537 default:
2552 2538 bail_msg(gettext("invalid %s identification\n"), name);
2553 2539 }
2554 2540 }
2555 2541
2556 2542 /*
2557 2543 * Copy source into target, inserting an escape character ('\') before
2558 2544 * any quotes that appear. Return true on success, false on failure.
2559 2545 */
2560 2546 static boolean_t
2561 2547 escapequotes(char *target, char *source, int tlen)
2562 2548 {
2563 2549 int s, t, len = strlen(source) + 1;
2564 2550
2565 2551 if (tlen < len)
2566 2552 return (B_FALSE);
2567 2553
2568 2554 for (s = 0, t = 0; s < len && t < tlen; s++) {
2569 2555 if (source[s] == '\"')
2570 2556 target[t++] = '\\';
2571 2557 target[t++] = source[s];
2572 2558 }
2573 2559
2574 2560 if ((t == tlen) && (s < len))
2575 2561 return (B_FALSE);
2576 2562
2577 2563 return (B_TRUE);
2578 2564 }
2579 2565
2580 2566 /*
2581 2567 * Return true if the arg following the given keyword should
2582 2568 * be in quotes (i.e. is a string), false if not.
2583 2569 */
2584 2570 static boolean_t
2585 2571 quotedfield(char *keywd)
2586 2572 {
2587 2573 if ((strncmp(keywd, "label", strlen("label") + 1) == 0) ||
2588 2574 (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) ||
2589 2575 (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0))
2590 2576 return (B_TRUE);
2591 2577
2592 2578 return (B_FALSE);
2593 2579 }
2594 2580
2595 2581 static void
2596 2582 do_new(int cmd, int argc, char **argv)
2597 2583 {
2598 2584 ike_service_t *rtn;
2599 2585 ike_new_t new, *newp = NULL;
2600 2586 door_desc_t desc, *descp = NULL;
2601 2587 int i, fd, ndesc = 0, buflen;
2602 2588 char *name, tmpfilepath[32];
2603 2589 FILE *tmpfile;
2604 2590
2605 2591 switch (cmd) {
2606 2592 case IKE_SVC_NEW_PS:
2607 2593 name = gettext("preshared key");
2608 2594 break;
2609 2595 case IKE_SVC_NEW_RULE:
2610 2596 name = gettext("policy rule");
2611 2597 break;
2612 2598 default:
2613 2599 bail_msg(gettext("unrecognized new command (%d)"), cmd);
2614 2600 }
2615 2601
2616 2602 if (argc == 1) {
2617 2603 /* We've been given a file to read from */
2618 2604 fd = open(argv[0], O_RDONLY);
2619 2605 if (fd < 0)
2620 2606 Bail("open source file");
2621 2607
2622 2608 desc.d_data.d_desc.d_descriptor = fd;
2623 2609 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2624 2610 descp = &desc;
2625 2611 ndesc = 1;
2626 2612
2627 2613 new.cmd = cmd;
2628 2614 new.new_len = 0;
2629 2615 newp = &new;
2630 2616 buflen = sizeof (ike_new_t);
2631 2617
2632 2618 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) {
2633 2619 /*
2634 2620 * This is an alternative to using the tmpfile method
2635 2621 * for preshared keys. It means we're duplicating the
2636 2622 * parsing effort that happens in readps.c; but it
2637 2623 * does avoid having the key sitting in a file.
2638 2624 */
2639 2625 ike_ps_t *psp;
2640 2626 int pslen;
2641 2627
2642 2628 /*
2643 2629 * must be in interactive mode; don't want keys in
2644 2630 * the process args.
2645 2631 */
2646 2632 if (!interactive)
2647 2633 Bail("Must be in interactive mode to add key info.");
2648 2634 if (parse_ps(argc, argv, &psp, &pslen) < 0) {
2649 2635 errno = 0;
2650 2636 Bail("invalid preshared key definition");
2651 2637 }
2652 2638 newp = malloc(sizeof (ike_new_t) + pslen);
2653 2639 if (newp == NULL)
2654 2640 Bail("alloc pskey");
2655 2641 newp->cmd = cmd;
2656 2642 newp->new_len = sizeof (ike_new_t) + pslen;
2657 2643 (void) memcpy((char *)(newp + 1), psp, pslen);
2658 2644 buflen = newp->new_len;
2659 2645 /* parse_ps allocated the ike_ps_t buffer; free it now */
2660 2646 free(psp);
2661 2647
2662 2648 } else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) {
2663 2649 /*
2664 2650 * We've been given the item in argv. However, parsing
2665 2651 * rules can get more than a little messy, and in.iked
2666 2652 * already has a great parser for this stuff! So don't
2667 2653 * fool around with trying to do the parsing here. Just
2668 2654 * write it out to a tempfile, and send the fd to in.iked.
2669 2655 *
2670 2656 * We could conceivably do this for preshared keys,
2671 2657 * rather than duplicating the parsing effort; but that
2672 2658 * would mean the key would be written out to a file,
2673 2659 * which isn't such a good idea.
2674 2660 */
2675 2661 boolean_t doquotes = B_FALSE;
2676 2662 int rtn;
2677 2663
2678 2664 if ((argv[0][0] != '{') ||
2679 2665 (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}'))
2680 2666 bail_msg(gettext("improperly formatted %s"), name);
2681 2667
2682 2668 /* attempt to use a fairly unpredictable file name... */
2683 2669 (void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime());
2684 2670 fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL,
2685 2671 S_IRUSR | S_IWUSR);
2686 2672 if (fd < 0)
2687 2673 Bail("cannot open tmpfile");
2688 2674
2689 2675 /* and make it inaccessible asap */
2690 2676 if (unlink(tmpfilepath) < 0) {
2691 2677 (void) close(fd);
2692 2678 Bail("tmpfile error");
2693 2679 }
2694 2680
2695 2681 tmpfile = fdopen(fd, "w");
2696 2682 if (tmpfile == NULL) {
2697 2683 (void) close(fd);
2698 2684 Bail("cannot write to tmpfile");
2699 2685 }
2700 2686
2701 2687 for (i = 0; i < argc; i++) {
2702 2688 /*
2703 2689 * We have to do some gyrations with our string here,
2704 2690 * to properly handle quotes. There are two issues:
2705 2691 * - some of the fields of a rule may have embedded
2706 2692 * whitespace, and thus must be quoted on the cmd
2707 2693 * line. The shell removes the quotes, and gives
2708 2694 * us a single argv string; but we need to put the
2709 2695 * quotes back in when we write the string out to
2710 2696 * file. The doquotes boolean is set when we
2711 2697 * process a keyword which will be followed by a
2712 2698 * string value (so the NEXT argv element will be
2713 2699 * quoted).
2714 2700 * - there might be a quote character in a field,
2715 2701 * that was escaped on the cmdline. The shell
2716 2702 * removes the escape char, and leaves the quote
2717 2703 * in the string it gives us. We need to put the
2718 2704 * escape char back in before writing to file.
2719 2705 */
2720 2706 char field[MAXLINESIZE];
2721 2707 if (!escapequotes(field, argv[i], MAXLINESIZE))
2722 2708 Bail("write to tmpfile failed (arg too big)");
2723 2709 if (doquotes) {
2724 2710 rtn = fprintf(tmpfile, "\"%s\"\n", field);
2725 2711 doquotes = B_FALSE;
2726 2712 } else {
2727 2713 rtn = fprintf(tmpfile, "%s\n", field);
2728 2714 }
2729 2715 if (rtn < 0)
2730 2716 Bail("write to tmpfile failed");
2731 2717 /*
2732 2718 * check if this is a keyword identifying
2733 2719 * a field that needs to be quoted.
2734 2720 */
2735 2721 doquotes = quotedfield(argv[i]);
2736 2722 }
2737 2723 if (fflush(tmpfile) == EOF)
2738 2724 Bail("write to tmpfile failed");
2739 2725 /* rewind so that the daemon will get the beginning */
2740 2726 rewind(tmpfile);
2741 2727
2742 2728 desc.d_data.d_desc.d_descriptor = fd;
2743 2729 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2744 2730 descp = &desc;
2745 2731 ndesc = 1;
2746 2732
2747 2733 new.cmd = cmd;
2748 2734 new.new_len = 0;
2749 2735 newp = &new;
2750 2736 buflen = sizeof (ike_new_t);
2751 2737
2752 2738 } else {
2753 2739 /* not enough information! */
2754 2740 bail_msg(gettext("missing %s description or file name"), name);
2755 2741 }
2756 2742
2757 2743 rtn = ikedoor_call((char *)newp, buflen, descp, ndesc);
2758 2744
2759 2745 if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2760 2746 ikeadm_err_msg(&rtn->svc_err,
2761 2747 gettext("error creating new %s"), name);
2762 2748 } else {
2763 2749 message(gettext("Successfully created new %s."), name);
2764 2750 }
2765 2751 }
2766 2752
2767 2753 static void
2768 2754 do_flush(int cmd)
2769 2755 {
2770 2756 ike_service_t *rtnp;
2771 2757 ike_flush_t flush;
2772 2758
2773 2759 if (cmd != IKE_SVC_FLUSH_P1S) {
2774 2760 bail_msg(gettext("unrecognized flush command (%d)."), cmd);
2775 2761 }
2776 2762
2777 2763 flush.cmd = cmd;
2778 2764
2779 2765 rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0);
2780 2766 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2781 2767 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
2782 2768 }
2783 2769 message(gettext("Successfully flushed P1 SAs."));
2784 2770 }
2785 2771
2786 2772 static void
2787 2773 do_rw(int cmd, int argc, char **argv)
2788 2774 {
2789 2775 ike_service_t *rtnp;
2790 2776 ike_rw_t rw;
2791 2777 door_desc_t desc, *descp = NULL;
2792 2778 int oflag, omode, fd, ndesc = 0;
2793 2779 char *op, *obj = NULL;
2794 2780 boolean_t writing = B_FALSE;
2795 2781
2796 2782 switch (cmd) {
2797 2783 case IKE_SVC_READ_PS:
2798 2784 obj = gettext("preshared key");
2799 2785 /* FALLTHRU */
2800 2786 case IKE_SVC_READ_RULES:
2801 2787 if (obj == NULL)
2802 2788 obj = gettext("policy rule");
2803 2789 op = gettext("read");
2804 2790 oflag = O_RDONLY;
2805 2791 omode = 0;
2806 2792 break;
2807 2793
2808 2794 case IKE_SVC_WRITE_PS:
2809 2795 obj = gettext("preshared key");
2810 2796 /* FALLTHRU */
2811 2797 case IKE_SVC_WRITE_RULES:
2812 2798 if (obj == NULL)
2813 2799 obj = gettext("policy rule");
2814 2800 op = gettext("write");
2815 2801 oflag = O_RDWR | O_CREAT | O_EXCL;
2816 2802 omode = S_IRUSR | S_IWUSR;
2817 2803
2818 2804 /* for write commands, dest location must be specified */
2819 2805 if (argc < 1) {
2820 2806 bail_msg(gettext("destination location required "
2821 2807 "to write %ss"), obj);
2822 2808 }
2823 2809 writing = B_TRUE;
2824 2810 break;
2825 2811
2826 2812 default:
2827 2813 bail_msg(gettext("unrecognized read/write command (%d)."), cmd);
2828 2814 }
2829 2815
2830 2816 rw.cmd = cmd;
2831 2817
2832 2818 if (argc >= 1) {
2833 2819 rw.rw_loc = IKE_RW_LOC_USER_SPEC;
2834 2820 fd = open(argv[0], oflag, omode);
2835 2821 if (fd < 0)
2836 2822 Bail("open user-specified file");
2837 2823
2838 2824 desc.d_data.d_desc.d_descriptor = fd;
2839 2825 desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2840 2826 descp = &desc;
2841 2827 ndesc = 1;
2842 2828 } else {
2843 2829 rw.rw_loc = IKE_RW_LOC_DEFAULT;
2844 2830 }
2845 2831
2846 2832 rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc);
2847 2833 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2848 2834 /*
2849 2835 * Need to remove the target file in the
2850 2836 * case of a failed write command.
2851 2837 */
2852 2838 if (writing) {
2853 2839 /*
2854 2840 * argv[0] must be valid if we're writing; we
2855 2841 * exit before setting this boolean if not.
2856 2842 */
2857 2843 (void) unlink(argv[0]);
2858 2844 (void) close(fd);
2859 2845
2860 2846 if ((rtnp != NULL) &&
2861 2847 (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2862 2848 message(gettext("No %s information to write."),
2863 2849 obj);
2864 2850 return;
2865 2851 }
2866 2852 }
2867 2853 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op);
2868 2854 }
2869 2855 message(gettext("Completed %s of %s configuration information."),
2870 2856 op, obj);
2871 2857 }
2872 2858
2873 2859 static void
2874 2860 do_rbdump()
2875 2861 {
2876 2862 ike_cmd_t req;
2877 2863 ike_service_t *rtnp;
2878 2864
2879 2865 req.cmd = IKE_SVC_DBG_RBDUMP;
2880 2866
2881 2867 rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0);
2882 2868 if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2883 2869 ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
2884 2870 }
2885 2871 message(gettext("Successfully dumped rulebase; check iked dbg"));
2886 2872 }
2887 2873
2888 2874 #define REQ_ARG_CNT 1
2889 2875
2890 2876 /*ARGSUSED*/
2891 2877 static void
2892 2878 parseit(int argc, char **argv, char *notused, boolean_t notused_either)
2893 2879 {
2894 2880 int cmd, cmd_obj_args = 1;
2895 2881 char *cmdstr, *objstr;
2896 2882
2897 2883 if (interactive) {
2898 2884 if (argc == 0)
2899 2885 return;
2900 2886 }
2901 2887
2902 2888 if (argc < REQ_ARG_CNT) {
2903 2889 usage();
2904 2890 }
2905 2891
2906 2892 cmdstr = argv[0];
2907 2893 if (argc > REQ_ARG_CNT) {
2908 2894 cmd_obj_args++;
2909 2895 objstr = argv[1];
2910 2896 } else {
2911 2897 objstr = NULL;
2912 2898 }
2913 2899 cmd = parsecmd(cmdstr, objstr);
2914 2900
2915 2901 /* skip over args specifying command/object */
2916 2902 argc -= cmd_obj_args;
2917 2903 argv += cmd_obj_args;
2918 2904
2919 2905 switch (cmd) {
2920 2906 case IKE_SVC_GET_DEFS:
2921 2907 do_getdefs(cmd);
2922 2908 break;
2923 2909 case IKE_SVC_GET_DBG:
2924 2910 case IKE_SVC_GET_PRIV:
2925 2911 do_getvar(cmd);
2926 2912 break;
2927 2913 case IKE_SVC_GET_STATS:
2928 2914 do_getstats(cmd);
2929 2915 break;
2930 2916 case IKE_SVC_SET_DBG:
2931 2917 case IKE_SVC_SET_PRIV:
2932 2918 do_setvar(cmd, argc, argv);
2933 2919 break;
2934 2920 case IKE_SVC_DUMP_P1S:
2935 2921 case IKE_SVC_DUMP_RULES:
2936 2922 case IKE_SVC_DUMP_PS:
2937 2923 do_dump(cmd);
2938 2924 break;
2939 2925 case IKE_SVC_GET_P1:
2940 2926 case IKE_SVC_GET_RULE:
2941 2927 case IKE_SVC_GET_PS:
2942 2928 case IKE_SVC_DEL_P1:
2943 2929 case IKE_SVC_DEL_RULE:
2944 2930 case IKE_SVC_DEL_PS:
2945 2931 do_getdel(cmd, argc, argv);
2946 2932 break;
2947 2933 case IKE_SVC_NEW_RULE:
2948 2934 case IKE_SVC_NEW_PS:
2949 2935 do_new(cmd, argc, argv);
2950 2936 break;
2951 2937 case IKE_SVC_FLUSH_P1S:
2952 2938 do_flush(cmd);
2953 2939 break;
2954 2940 case IKE_SVC_READ_RULES:
2955 2941 case IKE_SVC_READ_PS:
2956 2942 case IKE_SVC_WRITE_RULES:
2957 2943 case IKE_SVC_WRITE_PS:
2958 2944 do_rw(cmd, argc, argv);
2959 2945 break;
2960 2946 case IKEADM_HELP_GENERAL:
2961 2947 print_help();
2962 2948 break;
2963 2949 case IKEADM_HELP_GET:
2964 2950 print_get_help();
2965 2951 break;
2966 2952 case IKEADM_HELP_SET:
2967 2953 print_set_help();
2968 2954 break;
2969 2955 case IKEADM_HELP_ADD:
2970 2956 print_add_help();
2971 2957 break;
2972 2958 case IKEADM_HELP_DEL:
2973 2959 print_del_help();
2974 2960 break;
2975 2961 case IKEADM_HELP_DUMP:
2976 2962 print_dump_help();
2977 2963 break;
2978 2964 case IKEADM_HELP_FLUSH:
2979 2965 print_flush_help();
2980 2966 break;
2981 2967 case IKEADM_HELP_READ:
2982 2968 print_read_help();
2983 2969 break;
2984 2970 case IKEADM_HELP_WRITE:
2985 2971 print_write_help();
2986 2972 break;
2987 2973 case IKEADM_HELP_HELP:
2988 2974 print_help_help();
2989 2975 break;
2990 2976 case IKEADM_EXIT:
2991 2977 if (interactive)
2992 2978 exit(0);
2993 2979 break;
2994 2980 case IKE_SVC_DBG_RBDUMP:
2995 2981 do_rbdump();
2996 2982 break;
2997 2983 case IKE_SVC_ERROR:
2998 2984 usage();
2999 2985 default:
3000 2986 exit(0);
3001 2987 }
3002 2988 }
3003 2989
3004 2990 int
3005 2991 main(int argc, char **argv)
3006 2992 {
3007 2993 char ch;
3008 2994
3009 2995 (void) setlocale(LC_ALL, "");
3010 2996 #if !defined(TEXT_DOMAIN)
3011 2997 #define TEXT_DOMAIN "SYS_TEST"
3012 2998 #endif
3013 2999 (void) textdomain(TEXT_DOMAIN);
3014 3000
3015 3001 while ((ch = getopt(argc, argv, "hpn")) != EOF) {
3016 3002 switch (ch) {
3017 3003 case 'h':
3018 3004 print_help();
3019 3005 return (0);
3020 3006 case 'p':
3021 3007 pflag = B_TRUE;
3022 3008 break;
3023 3009 case 'n':
3024 3010 nflag = B_TRUE;
3025 3011 break;
3026 3012 default:
3027 3013 usage();
3028 3014 }
3029 3015 }
3030 3016 argc -= optind;
3031 3017 argv += optind;
3032 3018
3033 3019 if (open_door() < 0) {
3034 3020 (void) fprintf(stderr,
3035 3021 gettext("Unable to communicate with in.iked\n"));
3036 3022 Bail("open_door failed");
3037 3023 }
3038 3024
3039 3025 if (*argv == NULL) {
3040 3026 /* no cmd-line args, do interactive mode */
3041 3027 do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit);
3042 3028 }
3043 3029
3044 3030 parseit(argc, argv, NULL, B_FALSE);
3045 3031
3046 3032 return (0);
3047 3033 }
↓ open down ↓ |
1640 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX