918c549429f41619a96a3f2f8251834ba090382c
[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;
78     
79 typedef struct {
80     opt_val_gen_t   value;
81     uint8_t         is_valid;
82 } opt_attr_gen_t;
83  
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;
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[] =
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[] =
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[] =
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[] =
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] = 
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)
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;
205 static int setargs (char *args, char **argv)
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;
220 static char **parsedargs(char *args, int *argc)
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;
239 static void freeparsedargs(char **argv)
241     if (argv) {
242         free(argv[-1]);
243         free(argv-1);
244     } 
247 #define COMMAND_LINE_SIZE 400
248      
249 void* cmd_shell (void* args)
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
330                 
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);
337      
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);
536 void cmd_shell_offload_sp_rsp
538     ipsecmgr_ipc_offload_sp_rsp_param_t *rsp
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;
572 void cmd_shell_stop_offload_rsp
574     ipsecmgr_ipc_stop_offload_rsp_param_t *rsp
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;