[keystone-rtos/netapi.git] / ti / runtime / netapi / applications / ipsec_offload / config-app / src / cmd_shell.c
1 /*
2 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
3 *
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
15 * distribution.
16 *
17 * Neither the name of Texas Instruments Incorporated nor the names of
18 * its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
35 /* Standard include files */
36 #define _GNU_SOURCE
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <getopt.h>
40 #include <string.h>
42 /* module specific include files */
43 #include <ipsecmgr_ipc.h>
45 #include "cmd_shell_loc.h"
47 /* For debugging */
48 #define DEBUG
49 #define DEBUG1
51 #define OPTION_ID_IF_NAME 1
52 #define OPTION_ID_SP_ID 2
53 #define OPTION_ID_CMD_NAME 3
54 #define OPTION_ID_ESN 4
55 #define OPTION_ID_GTPU_TEID 5
56 #define OPTION_ID_NUM_TEIDS 6
57 #define OPTION_ID_SHARED_SA 7
58 #define OPTION_ID_MAX 8
60 enum cmd_id {
61 CMD_ID_OFFLOAD_SP = 1,
62 CMD_ID_STOP_OFFLOAD,
63 CMD_ID_HELP,
64 CMD_ID_EXIT,
65 CMD_ID_LAST
66 };
68 /* Maximum strlen() of string variables */
69 #define MAX_STR_VAR_SIZE 32
71 /* Maximum number of commands */
72 #define MAX_CMDS CMD_ID_LAST
74 typedef union {
75 unsigned long intval;
76 char strval[MAX_STR_VAR_SIZE];
77 } opt_val_gen_t;
79 typedef struct {
80 opt_val_gen_t value;
81 uint8_t is_valid;
82 } opt_attr_gen_t;
84 static opt_attr_gen_t opt_input_gen[OPTION_ID_MAX];
86 /* Module context */
87 static cmd_shell_ctx_t shell_ctx;
89 static int parse_intval(char* int_str, opt_attr_gen_t *opt_attr) {
90 int i;
91 for (i=0; int_str[i]!= '\0'; i++) int_str[i] = (char) tolower(int_str[i]);
92 if (strncmp("0x", int_str, 2)) {
93 opt_attr->value.intval = strtoul(int_str, (char **)NULL, 10);
94 } else {
95 opt_attr->value.intval = strtoul(int_str, (char **)NULL, 16);
96 }
97 opt_attr->is_valid = 1;
98 return 0;
99 }
101 static int parse_strval(char* str, opt_attr_gen_t *opt_attr) {
103 strncpy(opt_attr->value.strval, str, MAX_STR_VAR_SIZE-1);
104 opt_attr->is_valid = 1;
105 return 0;
106 }
108 static char short_opts[200];
110 #define CMD_NAME_OFFLOAD_SP "offload_sp"
111 #define CMD_DESC_OFFLOAD_SP "Offload an IPSec Policy to Fast Path"
112 #define CMD_MIN_ARGS_OFFLOAD_SP 3
113 #define CMD_SHORT_OPTS_OFFLOAD_SP sprintf(short_opts, "%d:%d:%d%d:%d:",\
114 OPTION_ID_SP_ID, OPTION_ID_IF_NAME, OPTION_ID_ESN,\
115 OPTION_ID_GTPU_TEID, OPTION_ID_NUM_TEIDS,\
116 OPTION_ID_SHARED_SA);
118 static struct option offload_sp_options[] =
119 {
120 {"sp_id", required_argument, 0, OPTION_ID_SP_ID},
121 {"if_name", required_argument, 0, OPTION_ID_IF_NAME},
122 {"esn", no_argument, 0, OPTION_ID_ESN},
123 {"gtpu_teid", required_argument, 0, OPTION_ID_GTPU_TEID},
124 {"num_teids", required_argument, 0, OPTION_ID_NUM_TEIDS},
125 {"shared", no_argument, 0, OPTION_ID_SHARED_SA},
126 {0, 0, 0, 0}
127 };
129 #define CMD_NAME_STOP_OFFLOAD "stop_offload"
130 #define CMD_DESC_STOP_OFFLOAD "Stop Offload of an IPSec Policy"
131 #define CMD_MIN_ARGS_STOP_OFFLOAD 3
132 #define CMD_SHORT_OPTS_STOP_OFFLOAD sprintf(short_opts, "%d:", OPTION_ID_SP_ID);
133 static struct option stop_offload_options[] =
134 {
135 {"sp_id", required_argument, 0, OPTION_ID_SP_ID},
136 {0, 0, 0, 0}
137 };
139 #define CMD_NAME_EXIT "exit"
140 #define CMD_DESC_EXIT "Exit the netcpcfg command shell"
141 #define CMD_MIN_ARGS_EXIT 1
142 #define CMD_SHORT_OPTS_EXIT sprintf(short_opts, "");
143 static struct option exit_options[] =
144 {
145 {0, 0, 0, 0}
146 };
148 #define CMD_NAME_HELP "help"
149 #define CMD_DESC_HELP "Help on available commands"
150 #define CMD_MIN_ARGS_HELP 1
151 #define CMD_SHORT_OPTS_HELP sprintf(short_opts, "%d:", OPTION_ID_CMD_NAME);
152 static struct option help_options[] =
153 {
154 {"cmd", required_argument, 0, OPTION_ID_CMD_NAME},
155 {0, 0, 0, 0}
156 };
158 struct cmd_tbl_s {
159 char *cmd_name;
160 struct option *opt_tbl;
161 char *desc;
162 };
164 struct cmd_tbl_s cmd_table[MAX_CMDS] =
165 {
166 {CMD_NAME_OFFLOAD_SP, offload_sp_options, CMD_DESC_OFFLOAD_SP},
167 {CMD_NAME_STOP_OFFLOAD, stop_offload_options, CMD_DESC_STOP_OFFLOAD},
168 {CMD_NAME_EXIT, exit_options, CMD_DESC_EXIT},
169 {CMD_NAME_HELP, help_options, CMD_DESC_HELP},
170 {0, 0}
171 };
173 static void print_help (char *cmd_name)
174 {
175 int i,j;
177 if (!cmd_name) {
178 printf ("For help on command options type \"%s --cmd <cmd name>\"\n",
179 CMD_NAME_HELP);
180 printf ("Available commands:\n");
182 for (i=0; ((i < MAX_CMDS) && cmd_table[i].cmd_name); i++) {
183 printf (" %s\t%s\n", cmd_table[i].cmd_name, cmd_table[i].desc);
184 }
185 return;
186 }
188 for (i=0; ((i < MAX_CMDS) && (cmd_table[i].cmd_name)); i++) {
189 struct option *opt = cmd_table[i].opt_tbl;
190 if (strcmp(cmd_name, cmd_table[i].cmd_name)) {
191 continue;
192 }
194 printf ("options for \"%s\"\n", cmd_name);
195 for (j=0; opt->name; j++, opt++) {
196 printf (" --%s\n", opt->name);
197 }
198 return;
199 }
201 printf ("No help available for %s\n", cmd_name);
202 return;
203 }
205 static int setargs (char *args, char **argv)
206 {
207 int count = 0;
209 while (isspace(*args)) ++args;
210 while (*args) {
211 if (argv) argv[count] = args;
212 while (*args && !isspace(*args)) ++args;
213 if (argv && *args) *args++ = '\0';
214 while (isspace(*args)) ++args;
215 count++;
216 }
217 return count;
218 }
220 static char **parsedargs(char *args, int *argc)
221 {
222 char **argv = NULL;
223 int argn = 0;
225 if (args && *args
226 && (args = strdup(args))
227 && (argn = setargs(args,NULL))
228 && (argv = malloc((argn+1) * sizeof(char *)))) {
229 *argv++ = args;
230 argn = setargs(args,argv);
231 }
233 if (args && !argv) free(args);
235 *argc = argn;
236 return argv;
237 }
239 static void freeparsedargs(char **argv)
240 {
241 if (argv) {
242 free(argv[-1]);
243 free(argv-1);
244 }
245 }
247 #define COMMAND_LINE_SIZE 400
249 void* cmd_shell (void* args)
250 {
251 char *line = NULL;
252 size_t len = 0;
253 ssize_t read = 0;
254 char cmd[20];
255 int nargs, c, rargs;
256 struct option *long_options;
257 char **av;
258 enum cmd_id cmd_id;
260 memset(&shell_ctx, 0, sizeof(shell_ctx));
261 if (ipsecmgr_ipc_get_user_send_iface(&shell_ctx.ipc_send_if)) {
262 printf ("\ncmd_shell: Failed to get IPC send interface\n");
263 return;
264 }
266 while (1) {
267 memset(opt_input_gen, 0, sizeof(opt_input_gen));
268 cmd_id = 0;
270 printf ("\nIPSECMGR-CFG> ");
272 if (line) free(line);
273 line = malloc(COMMAND_LINE_SIZE);
274 if (line == NULL) {
275 printf("\nError allocating memory");
276 return;
277 }
279 read = getline(&line, &len, stdin);
280 if (read == -1) {
281 printf("\nERROR: reading line");
282 continue;
283 }
284 if (!read) continue;
285 memset(cmd, 0, sizeof(cmd));
286 sscanf(line, "%s", cmd);
288 if ( !strcmp(cmd, "exit"))
289 exit(0);
291 if (!strcmp(cmd, CMD_NAME_OFFLOAD_SP)) {
292 cmd_id = CMD_ID_OFFLOAD_SP;
293 long_options = offload_sp_options;
294 CMD_SHORT_OPTS_OFFLOAD_SP;
295 rargs = CMD_MIN_ARGS_OFFLOAD_SP;
296 } else if (!strcmp(cmd, CMD_NAME_STOP_OFFLOAD)) {
297 cmd_id = CMD_ID_STOP_OFFLOAD;
298 long_options = stop_offload_options;
299 CMD_SHORT_OPTS_STOP_OFFLOAD;
300 rargs = CMD_MIN_ARGS_STOP_OFFLOAD;
301 } else if (!strcmp(cmd, CMD_NAME_HELP)) {
302 cmd_id = CMD_ID_HELP;
303 long_options = help_options;
304 CMD_SHORT_OPTS_HELP;
305 rargs = CMD_MIN_ARGS_HELP;
306 } else {
307 if (strlen(cmd))
308 printf ("Unknown command: %s\n", cmd);
309 continue;
310 }
312 if ((av = parsedargs(line, &nargs)) == NULL) {
313 printf ("error parsing arguments");
314 continue;
315 }
317 if (nargs < rargs) {
318 printf ("Insufficient paramaters for command \"%s\"\n", cmd);
319 print_help (cmd);
320 goto loop_over;
321 }
323 #ifdef DEBUG1
324 {
325 int i;
326 for (i = 0; i < nargs; i++)
327 printf("[%s]\n",av[i]);
328 }
329 #endif
331 optind = 0;
332 while (1) {
333 /* getopt_long stores the option index here. */
334 int option_index = 0;
335 c = getopt_long (nargs, av, short_opts,
336 long_options, &option_index);
338 /* Detect the end of the options. */
339 #ifdef DEBUG1
340 printf("c=%d",c);
341 #endif
342 if (c == -1)
343 break;
345 switch (c)
346 {
348 case OPTION_ID_SP_ID:
349 #ifdef DEBUG
350 printf ("option sp_id with value `%s'\n", optarg);
351 #endif
352 if (parse_intval(optarg, &opt_input_gen[c])) {
353 printf ("Invalid argument for sp_id\n");
354 }
355 break;
357 case OPTION_ID_IF_NAME:
358 #ifdef DEBUG
359 printf ("option if_name with value `%s'\n", optarg);
360 #endif
361 if (parse_strval(optarg, &opt_input_gen[c])) {
362 printf ("Invalid argument for if_name\n");
363 }
364 break;
366 case OPTION_ID_CMD_NAME:
367 #ifdef DEBUG
368 printf ("option cmd with value `%s'\n", optarg);
369 #endif
370 if (parse_strval(optarg, &opt_input_gen[c])) {
371 printf ("Invalid argument for cmd\n");
372 }
373 break;
375 case OPTION_ID_ESN:
376 #ifdef DEBUG
377 printf ("option esn enabled\n");
378 #endif
379 opt_input_gen[c].is_valid = 1;
380 break;
382 case OPTION_ID_GTPU_TEID:
383 #ifdef DEBUG
384 printf ("option gtpu_teid with value `%s'\n", optarg);
385 #endif
386 if (parse_intval(optarg, &opt_input_gen[c])) {
387 printf ("Invalid argument for gtpu_teid\n");
388 }
389 break;
391 case OPTION_ID_NUM_TEIDS:
392 #ifdef DEBUG
393 printf ("option num_teids with value `%s'\n", optarg);
394 #endif
395 if (parse_intval(optarg, &opt_input_gen[c])) {
396 printf ("Invalid argument for num_teids\n");
397 }
398 break;
400 case OPTION_ID_SHARED_SA:
401 #ifdef DEBUG
402 printf ("option shared SA enabled\n");
403 #endif
404 opt_input_gen[c].is_valid = 1;
405 break;
407 default:
408 printf ("unknown option c=%d\n", c);
409 break;
410 }
411 }
412 #ifdef DEBUG1
413 /* Print any remaining command line arguments (not options). */
414 if (optind < nargs)
415 {
416 printf ("non-option elements: ");
417 while (optind < nargs)
418 printf ("%s ", av[optind++]);
419 putchar ('\n');
420 }
421 #endif
423 switch (cmd_id) {
425 case CMD_ID_HELP:
426 {
427 if (!opt_input_gen[OPTION_ID_CMD_NAME].is_valid) {
428 print_help(NULL);
429 } else {
430 print_help(opt_input_gen[OPTION_ID_CMD_NAME].value.strval);
431 }
432 break;
433 }
435 case CMD_ID_OFFLOAD_SP:
436 {
437 ipsecmgr_ipc_offload_sp_req_param_t req;
438 ipsecmgr_ifname_t if_name;
439 ipsecmgr_l5_selector_t l5_selector;
441 if (!opt_input_gen[OPTION_ID_SP_ID].is_valid) {
442 printf ("Mandatory paramater missing: sp_id\n");
443 goto loop_over;
444 }
446 memset(&req, 0, sizeof(req));
447 memset(&if_name, 0, sizeof(if_name));
448 memset(&l5_selector, 0, sizeof(l5_selector));
450 req.trans_id = ++shell_ctx.trans_id;
452 /* sp_id */
453 req.policy_id =
454 (uint32_t)opt_input_gen[OPTION_ID_SP_ID].value.intval;
456 /* if_name */
457 if (opt_input_gen[OPTION_ID_IF_NAME].is_valid) {
458 strcpy(if_name.name,
459 opt_input_gen[OPTION_ID_IF_NAME].value.strval);
460 req.if_name = &if_name;
461 }
463 /* esn */
464 if (opt_input_gen[OPTION_ID_ESN].is_valid) {
465 req.sa_flags |= IPSECMGR_SA_FLAGS_ESN;
466 }
468 /* gtpu_teid */
469 if (opt_input_gen[OPTION_ID_GTPU_TEID].is_valid) {
470 l5_selector.proto = IPSECMGR_L5_PROTO_GTPU;
471 l5_selector.value.gtpu.teid_start =
472 (uint32_t)opt_input_gen[OPTION_ID_GTPU_TEID].value.intval;
473 req.l5_selector = &l5_selector;
474 }
476 /* num_teids */
477 if (opt_input_gen[OPTION_ID_NUM_TEIDS].is_valid) {
478 l5_selector.value.gtpu.teid_end =
479 l5_selector.value.gtpu.teid_start - 1 +
480 (uint32_t)opt_input_gen[OPTION_ID_NUM_TEIDS].value.intval;
481 } else { /* default is 1 TEID */
482 l5_selector.value.gtpu.teid_end =
483 l5_selector.value.gtpu.teid_start;
484 }
486 /* shared tunnel */
487 if (opt_input_gen[OPTION_ID_SHARED_SA].is_valid) {
488 req.sa_flags |= IPSECMGR_SA_FLAGS_SHARED;
489 }
491 if (shell_ctx.ipc_send_if->offload_sp_req(&req)) {
492 printf("%s failed\n", CMD_NAME_OFFLOAD_SP);
493 } else {
494 printf("%s trans_id: 0x%x\n", CMD_NAME_OFFLOAD_SP,
495 shell_ctx.trans_id);
496 }
498 break;
499 }
501 case CMD_ID_STOP_OFFLOAD:
502 {
503 ipsecmgr_ipc_stop_offload_req_param_t req;
505 if (!opt_input_gen[OPTION_ID_SP_ID].is_valid) {
506 printf ("Mandatory paramater missing: sp_id\n");
507 goto loop_over;
508 }
510 memset(&req, 0, sizeof(req));
512 req.trans_id = ++shell_ctx.trans_id;
514 /* sp_id */
515 req.policy_id =
516 (uint32_t)opt_input_gen[OPTION_ID_SP_ID].value.intval;
518 if (shell_ctx.ipc_send_if->stop_offload_req(&req)) {
519 printf("%s failed\n", CMD_NAME_STOP_OFFLOAD);
520 } else {
521 printf("%s trans_id: 0x%x\n", CMD_NAME_STOP_OFFLOAD,
522 shell_ctx.trans_id);
523 }
525 break;
526 }
528 } /* switch cmd_id */
530 loop_over:
531 freeparsedargs(av);
532 }
533 return (void*)(0);
534 }
536 void cmd_shell_offload_sp_rsp
537 (
538 ipsecmgr_ipc_offload_sp_rsp_param_t *rsp
539 )
540 {
541 char resp_str[10] = {0,};
543 printf ("\nRecvd OFFLOAD_SP response:\n");
544 printf (" trans_id:\t0x%x\n", rsp->trans_id);
546 if (rsp->type & RSP_TYPE_ACK) {
547 strcpy(resp_str, "ACK");
548 } else if (rsp->type & RSP_TYPE_DONE) {
549 int slen = strlen(resp_str);
550 if (slen)
551 strcpy(&resp_str[slen], "|DONE");
552 else
553 strcpy(&resp_str[slen], "DONE");
554 }
556 printf (" resp_type:\t(%d) %s\n", rsp->type, resp_str);
557 printf (" result:\t(%d) %s\n", rsp->result,
558 ((rsp->result == RESULT_SUCCESS) ? "SUCCESS":"FAIL"));
560 if (rsp->err_code) {
561 printf (" FP lib retval:\t%d\n", rsp->err_code);
562 }
564 if (rsp->sa_handle)
565 printf (" sa_handle:\t0x%x\n", rsp->sa_handle);
566 if (rsp->sp_handle)
567 printf (" sp_handle:\t0x%x\n", rsp->sp_handle);
569 return;
570 }
572 void cmd_shell_stop_offload_rsp
573 (
574 ipsecmgr_ipc_stop_offload_rsp_param_t *rsp
575 )
576 {
577 char resp_str[10] = {0,};
579 printf ("\nRecvd STOP_OFFLOAD response:\n");
580 printf (" trans_id:\t0x%x\n", rsp->trans_id);
582 if (rsp->type & RSP_TYPE_ACK) {
583 strcpy(resp_str, "ACK");
584 } else if (rsp->type & RSP_TYPE_DONE) {
585 int slen = strlen(resp_str);
586 if (slen)
587 strcpy(&resp_str[slen], "|DONE");
588 else
589 strcpy(&resp_str[slen], "DONE");
590 }
592 printf (" resp_type:\t(%d) %s\n", rsp->type, resp_str);
593 printf (" result:\t(%d) %s\n", rsp->result,
594 ((rsp->result == RESULT_SUCCESS) ? "SUCCESS":"FAIL"));
596 return;
597 }