Resolve NETAPI library coverity warnings.
[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 */
37 #ifndef _GNU_SOURCE
38 #define _GNU_SOURCE
39 #endif
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <getopt.h>
44 #include <string.h>
46 /* module specific include files */
47 #include <ipsecmgr_ipc.h>
49 #include "cmd_shell_loc.h"
51 /* For debugging */
52 #define  DEBUG
53 #define DEBUG1
55 #define OPTION_ID_IF_NAME       1
56 #define OPTION_ID_SP_ID         2
57 #define OPTION_ID_CMD_NAME      3
58 #define OPTION_ID_ESN           4
59 #define OPTION_ID_GTPU_TEID     5
60 #define OPTION_ID_NUM_TEIDS     6
61 #define OPTION_ID_SHARED_SA     7
62 #define OPTION_ID_MAX           8
64 enum cmd_id {
65     CMD_ID_OFFLOAD_SP   = 1,
66     CMD_ID_STOP_OFFLOAD,
67     CMD_ID_HELP,
68     CMD_ID_EXIT,
69     CMD_ID_LAST
70 };
72 /* Maximum strlen() of string variables */
73 #define MAX_STR_VAR_SIZE   32
75 /* Maximum number of commands */
76 #define MAX_CMDS    CMD_ID_LAST
78 typedef union {
79     unsigned long   intval;
80     char            strval[MAX_STR_VAR_SIZE];
81 } opt_val_gen_t;
82     
83 typedef struct {
84     opt_val_gen_t   value;
85     uint8_t         is_valid;
86 } opt_attr_gen_t;
87  
88 static opt_attr_gen_t opt_input_gen[OPTION_ID_MAX];
90 /* Module context */
91 static cmd_shell_ctx_t shell_ctx;
93 static int parse_intval(char* int_str, opt_attr_gen_t *opt_attr) {
94     int i;
95     for (i=0; int_str[i]!= '\0'; i++) int_str[i] = (char) tolower(int_str[i]);
96     if (strncmp("0x", int_str, 2)) {
97         opt_attr->value.intval = strtoul(int_str, (char **)NULL, 10);
98     } else {
99         opt_attr->value.intval = strtoul(int_str, (char **)NULL, 16);
100     }
101     opt_attr->is_valid = 1;
102     return 0;
105 static int parse_strval(char* str, opt_attr_gen_t *opt_attr) {
107     strncpy(opt_attr->value.strval, str, MAX_STR_VAR_SIZE-1);
108     opt_attr->is_valid = 1;
109     return 0;
112 #define CMD_SHORT_OPTS_LEN 200
113 static char short_opts[CMD_SHORT_OPTS_LEN];
115 #define CMD_NAME_OFFLOAD_SP   "offload_sp"
116 #define CMD_DESC_OFFLOAD_SP   "Offload an IPSec Policy to Fast Path"
117 #define CMD_MIN_ARGS_OFFLOAD_SP    3
118 #define CMD_SHORT_OPTS_OFFLOAD_SP snprintf(short_opts,CMD_SHORT_OPTS_LEN, "%d:%d:%d%d:%d:",\
119                            OPTION_ID_SP_ID, OPTION_ID_IF_NAME, OPTION_ID_ESN,\
120                            OPTION_ID_GTPU_TEID, OPTION_ID_NUM_TEIDS,\
121                            OPTION_ID_SHARED_SA);
123 static struct option offload_sp_options[] =
125     {"sp_id",  required_argument, 0, OPTION_ID_SP_ID},
126     {"if_name", required_argument, 0, OPTION_ID_IF_NAME},
127     {"esn", no_argument, 0, OPTION_ID_ESN},
128     {"gtpu_teid", required_argument, 0, OPTION_ID_GTPU_TEID},
129     {"num_teids", required_argument, 0, OPTION_ID_NUM_TEIDS},
130     {"shared", no_argument, 0, OPTION_ID_SHARED_SA},
131     {0, 0, 0, 0}
132 };
134 #define CMD_NAME_STOP_OFFLOAD   "stop_offload"
135 #define CMD_DESC_STOP_OFFLOAD   "Stop Offload of an IPSec Policy"
136 #define CMD_MIN_ARGS_STOP_OFFLOAD   3
137 #define CMD_SHORT_OPTS_STOP_OFFLOAD snprintf(short_opts,CMD_SHORT_OPTS_LEN, "%d:", OPTION_ID_SP_ID);
138 static struct option stop_offload_options[] =
140     {"sp_id",  required_argument, 0, OPTION_ID_SP_ID},
141     {0, 0, 0, 0}
142 };
144 #define CMD_NAME_EXIT   "exit"
145 #define CMD_DESC_EXIT   "Exit the netcpcfg command shell"
146 #define CMD_MIN_ARGS_EXIT    1
147 #define CMD_SHORT_OPTS_EXIT snprintf(short_opts,CMD_SHORT_OPTS_LEN, ""); 
148 static struct option exit_options[] =
150     {0, 0, 0, 0}
151 };
153 #define CMD_NAME_HELP       "help"
154 #define CMD_DESC_HELP       "Help on available commands"
155 #define CMD_MIN_ARGS_HELP   1
156 #define CMD_SHORT_OPTS_HELP snprintf(short_opts,CMD_SHORT_OPTS_LEN, "%d:", OPTION_ID_CMD_NAME); 
157 static struct option help_options[] =
159     {"cmd",  required_argument, 0, OPTION_ID_CMD_NAME},
160     {0, 0, 0, 0}
161 };
163 struct cmd_tbl_s {
164     char            *cmd_name;
165     struct option   *opt_tbl;
166     char            *desc;
167 };
169 struct cmd_tbl_s cmd_table[MAX_CMDS] = 
171     {CMD_NAME_OFFLOAD_SP, offload_sp_options, CMD_DESC_OFFLOAD_SP},
172     {CMD_NAME_STOP_OFFLOAD, stop_offload_options, CMD_DESC_STOP_OFFLOAD},
173     {CMD_NAME_EXIT, exit_options, CMD_DESC_EXIT},
174     {CMD_NAME_HELP, help_options, CMD_DESC_HELP},
175     {0, 0}
176 };
178 static void print_help (char *cmd_name)
180     int i,j;
182     if (!cmd_name) {
183         printf ("For help on command options type \"%s --cmd <cmd name>\"\n",
184                 CMD_NAME_HELP);
185         printf ("Available commands:\n");
187         for (i=0; ((i < MAX_CMDS) && cmd_table[i].cmd_name); i++) {
188             printf ("    %s\t%s\n", cmd_table[i].cmd_name, cmd_table[i].desc);
189         }
190         return;
191     }
193     for (i=0; ((i < MAX_CMDS) && (cmd_table[i].cmd_name)); i++) {
194         struct option *opt = cmd_table[i].opt_tbl;
195         if (strcmp(cmd_name, cmd_table[i].cmd_name)) {
196             continue;
197         }
199         printf ("options for \"%s\"\n", cmd_name);
200         for (j=0; opt->name; j++, opt++) {
201             printf ("    --%s\n", opt->name);
202         }
203         return;
204     }
206     printf ("No help available for %s\n", cmd_name);
207     return;
210 static int setargs (char *args, char **argv)
212     int count = 0;
214     while (isspace(*args)) ++args;
215     while (*args) {
216         if (argv) argv[count] = args;
217         while (*args && !isspace(*args)) ++args;
218         if (argv && *args) *args++ = '\0';
219         while (isspace(*args)) ++args;
220         count++;
221     }
222     return count;
225 static char **parsedargs(char *args, int *argc)
227     char **argv = NULL;
228     int    argn = 0;
230     if (args && *args
231         && (args = strdup(args))
232         && (argn = setargs(args,NULL))
233         && (argv = malloc((argn+1) * sizeof(char *)))) {
234           *argv++ = args;
235           argn = setargs(args,argv);
236     }
238     //if (args && !argv) free(args);
240     *argc = argn;
241     return argv;
244 static void freeparsedargs(char **argv)
246     if (argv) {
247         free(argv[-1]);
248         free(argv-1);
249     } 
252 #define COMMAND_LINE_SIZE 400
253      
254 void* cmd_shell (void* args)
256     char *line = NULL;
257     size_t len = 0;
258     ssize_t read = 0;
259     char cmd[COMMAND_LINE_SIZE];
260     int nargs, c, rargs;
261     struct option *long_options; 
262     char **av;
263     enum cmd_id  cmd_id;
265     memset(&shell_ctx, 0, sizeof(shell_ctx));
266     if (ipsecmgr_ipc_get_user_send_iface(&shell_ctx.ipc_send_if)) {
267         printf ("\ncmd_shell: Failed to get IPC send interface\n");
268         return (void*)(0);
269     }
271     while (1) {
272         memset(opt_input_gen, 0, sizeof(opt_input_gen));
273         cmd_id = 0;
275         printf ("\nIPSECMGR-CFG> ");
277         if (line) free(line);
278         line = malloc(COMMAND_LINE_SIZE);
279         if (line == NULL) {
280             printf("\nError allocating memory");
281             return (void*)(0);
282         }
284         read = getline(&line, &len, stdin);
285         if ((read == -1) || (read > COMMAND_LINE_SIZE)) {
286             printf("\nERROR: reading line");
287             continue;
288         }
289         if (!read) continue;
290         memset(cmd, 0, sizeof(cmd));
291         sscanf(line, "%s", cmd);
293         if ( !strcmp(cmd, "exit"))
294             exit(0);
296         if (!strcmp(cmd, CMD_NAME_OFFLOAD_SP)) {
297             cmd_id = CMD_ID_OFFLOAD_SP;
298             long_options = offload_sp_options; 
299             CMD_SHORT_OPTS_OFFLOAD_SP;
300             rargs = CMD_MIN_ARGS_OFFLOAD_SP;
301         } else if (!strcmp(cmd, CMD_NAME_STOP_OFFLOAD)) {
302             cmd_id = CMD_ID_STOP_OFFLOAD;
303             long_options = stop_offload_options; 
304             CMD_SHORT_OPTS_STOP_OFFLOAD;
305             rargs = CMD_MIN_ARGS_STOP_OFFLOAD;
306         } else if (!strcmp(cmd, CMD_NAME_HELP)) {
307             cmd_id = CMD_ID_HELP;
308             long_options = help_options; 
309             CMD_SHORT_OPTS_HELP;
310             rargs = CMD_MIN_ARGS_HELP;
311         } else {
312             if (strlen(cmd))
313                 printf ("Unknown command: %s\n", cmd);
314             continue;
315         }
317         if ((av = parsedargs(line, &nargs)) == NULL) {
318             printf ("error parsing arguments\n");
319             continue;
320         }
322         if (nargs < rargs) {
323             printf ("Insufficient paramaters for command \"%s\"\n", cmd);
324             print_help (cmd);
325             goto loop_over;
326         }
328 #ifdef DEBUG1
329         {
330             int i;
331             for (i = 0; i < nargs; i++)
332             printf("[%s]\n",av[i]);
333         }
334 #endif
335                 
336         optind = 0;
337         while (1) {
338             /* getopt_long stores the option index here. */
339             int option_index = 0;
340             c = getopt_long (nargs, av, short_opts,
341                         long_options, &option_index);
342      
343             /* Detect the end of the options. */
344 #ifdef DEBUG1
345                         printf("c=%d",c);
346 #endif
347             if (c == -1)
348                 break;
350             switch (c)
351             {
353                 case OPTION_ID_SP_ID:
354 #ifdef DEBUG
355                 printf ("option sp_id with value `%s'\n", optarg);
356 #endif
357                 if (parse_intval(optarg, &opt_input_gen[c])) {
358                     printf ("Invalid argument for sp_id\n");
359                 }
360                 break;
362                 case OPTION_ID_IF_NAME:
363 #ifdef DEBUG
364                 printf ("option if_name with value `%s'\n", optarg);
365 #endif
366                 if (parse_strval(optarg, &opt_input_gen[c])) {
367                     printf ("Invalid argument for if_name\n");
368                 }
369                 break;
371                 case OPTION_ID_CMD_NAME:
372 #ifdef DEBUG
373                 printf ("option cmd with value `%s'\n", optarg);
374 #endif
375                 if (parse_strval(optarg, &opt_input_gen[c])) {
376                     printf ("Invalid argument for cmd\n");
377                 }
378                 break;
380                 case OPTION_ID_ESN:
381 #ifdef DEBUG
382                 printf ("option esn enabled\n");
383 #endif
384                 opt_input_gen[c].is_valid = 1;
385                 break;
387                 case OPTION_ID_GTPU_TEID:
388 #ifdef DEBUG
389                 printf ("option gtpu_teid with value `%s'\n", optarg);
390 #endif
391                 if (parse_intval(optarg, &opt_input_gen[c])) {
392                     printf ("Invalid argument for gtpu_teid\n");
393                 }
394                 break;
396                 case OPTION_ID_NUM_TEIDS:
397 #ifdef DEBUG
398                 printf ("option num_teids with value `%s'\n", optarg);
399 #endif
400                 if (parse_intval(optarg, &opt_input_gen[c])) {
401                     printf ("Invalid argument for num_teids\n");
402                 }
403                 break;
405                 case OPTION_ID_SHARED_SA:
406 #ifdef DEBUG
407                 printf ("option shared SA enabled\n");
408 #endif
409                 opt_input_gen[c].is_valid = 1;
410                 break;
412                 default:
413                 printf ("unknown option c=%d\n", c);
414                 break;
415             }
416         }
417 #ifdef DEBUG1
418     /* Print any remaining command line arguments (not options). */
419     if (optind < nargs)
420     {
421         printf ("non-option elements: ");
422         while (optind < nargs)
423             printf ("%s ", av[optind++]);
424         putchar ('\n');
425     }
426 #endif
428     switch (cmd_id) {
430         case CMD_ID_HELP:
431         {
432             if (!opt_input_gen[OPTION_ID_CMD_NAME].is_valid) {
433                 print_help(NULL);
434             } else {
435                 print_help(opt_input_gen[OPTION_ID_CMD_NAME].value.strval);
436             }
437             break;
438         }
440         case CMD_ID_OFFLOAD_SP:
441         {
442             ipsecmgr_ipc_offload_sp_req_param_t req;
443             ipsecmgr_ifname_t if_name;
444             ipsecmgr_l5_selector_t l5_selector;
446             if (!opt_input_gen[OPTION_ID_SP_ID].is_valid) {
447                 printf ("Mandatory paramater missing: sp_id\n");
448                 goto loop_over;
449             }
451             memset(&req, 0, sizeof(req));
452             memset(&if_name, 0, sizeof(if_name));
453             memset(&l5_selector, 0, sizeof(l5_selector));
455             req.trans_id = ++shell_ctx.trans_id;
457             /* sp_id */
458             req.policy_id =
459                     (uint32_t)opt_input_gen[OPTION_ID_SP_ID].value.intval;
461             /* if_name */
462             if (opt_input_gen[OPTION_ID_IF_NAME].is_valid) {
463                 strcpy(if_name.name,
464                        opt_input_gen[OPTION_ID_IF_NAME].value.strval);
465                 req.if_name = &if_name;
466             }
468             /* esn */
469             if (opt_input_gen[OPTION_ID_ESN].is_valid) {
470                 req.sa_flags |= IPSECMGR_SA_FLAGS_ESN;
471             }
473             /* gtpu_teid */
474             if (opt_input_gen[OPTION_ID_GTPU_TEID].is_valid) {
475                 l5_selector.proto = IPSECMGR_L5_PROTO_GTPU;
476                 l5_selector.value.gtpu.teid_start =
477                     (uint32_t)opt_input_gen[OPTION_ID_GTPU_TEID].value.intval;
478                 req.l5_selector = &l5_selector;
479             }
481             /* num_teids */
482             if (opt_input_gen[OPTION_ID_NUM_TEIDS].is_valid) {
483                 l5_selector.value.gtpu.teid_end =
484                     l5_selector.value.gtpu.teid_start - 1 +
485                     (uint32_t)opt_input_gen[OPTION_ID_NUM_TEIDS].value.intval;
486             } else { /* default is 1 TEID */
487                 l5_selector.value.gtpu.teid_end =
488                     l5_selector.value.gtpu.teid_start;
489             }
491             /* shared tunnel */
492             if (opt_input_gen[OPTION_ID_SHARED_SA].is_valid) {
493                 req.sa_flags |= IPSECMGR_SA_FLAGS_SHARED;
494             }
496             if (shell_ctx.ipc_send_if->offload_sp_req(&req)) {
497                 printf("%s failed\n", CMD_NAME_OFFLOAD_SP);
498             } else {
499                 printf("%s trans_id: 0x%x\n", CMD_NAME_OFFLOAD_SP,
500                        shell_ctx.trans_id);
501             }
503             break;
504         }
506         case CMD_ID_STOP_OFFLOAD:
507         {
508             ipsecmgr_ipc_stop_offload_req_param_t req;
510             if (!opt_input_gen[OPTION_ID_SP_ID].is_valid) {
511                 printf ("Mandatory paramater missing: sp_id\n");
512                 goto loop_over;
513             }
515             memset(&req, 0, sizeof(req));
517             req.trans_id = ++shell_ctx.trans_id;
519             /* sp_id */
520             req.policy_id =
521                     (uint32_t)opt_input_gen[OPTION_ID_SP_ID].value.intval;
523             if (shell_ctx.ipc_send_if->stop_offload_req(&req)) {
524                 printf("%s failed\n", CMD_NAME_STOP_OFFLOAD);
525             } else {
526                 printf("%s trans_id: 0x%x\n", CMD_NAME_STOP_OFFLOAD,
527                        shell_ctx.trans_id);
528             }
530             break;
531         }
533     } /* switch cmd_id */
535 loop_over:
536         freeparsedargs(av);
537     }
538     return (void*)(0);
541 void cmd_shell_offload_sp_rsp
543     ipsecmgr_ipc_offload_sp_rsp_param_t *rsp
546     char resp_str[10] = {0,};
548     printf ("\nRecvd OFFLOAD_SP response:\n");
549     printf ("  trans_id:\t0x%x\n", rsp->trans_id);
551     if (rsp->type & RSP_TYPE_ACK) {
552         strcpy(resp_str, "ACK");
553     } else if (rsp->type & RSP_TYPE_DONE) {
554         int slen = strlen(resp_str);
555         if (slen)
556             strcpy(&resp_str[slen], "|DONE");
557         else
558             strcpy(&resp_str[slen], "DONE");
559     } 
561     printf ("  resp_type:\t(%d) %s\n", rsp->type, resp_str);
562     printf ("  result:\t(%d) %s\n", rsp->result,
563             ((rsp->result == RESULT_SUCCESS) ? "SUCCESS":"FAIL"));
565     if (rsp->err_code) {
566         printf ("  FP lib retval:\t%d\n", rsp->err_code);
567     }
569     if (rsp->sa_handle) 
570         printf ("  sa_handle:\t0x%x\n", rsp->sa_handle);
571     if (rsp->sp_handle) 
572         printf ("  sp_handle:\t0x%x\n", rsp->sp_handle);
574     return;
577 void cmd_shell_stop_offload_rsp
579     ipsecmgr_ipc_stop_offload_rsp_param_t *rsp
582     char resp_str[10] = {0,};
584     printf ("\nRecvd STOP_OFFLOAD response:\n");
585     printf ("  trans_id:\t0x%x\n", rsp->trans_id);
587     if (rsp->type & RSP_TYPE_ACK) {
588         strcpy(resp_str, "ACK");
589     } else if (rsp->type & RSP_TYPE_DONE) {
590         int slen = strlen(resp_str);
591         if (slen)
592             strcpy(&resp_str[slen], "|DONE");
593         else
594             strcpy(&resp_str[slen], "DONE");
595     } 
597     printf ("  resp_type:\t(%d) %s\n", rsp->type, resp_str);
598     printf ("  result:\t(%d) %s\n", rsp->result,
599             ((rsp->result == RESULT_SUCCESS) ? "SUCCESS":"FAIL"));
601     return;