CLI: added command autocompletion.
Added storm filtering support.
#include <readline/readline.h>
#include <readline/history.h>
-#include "command.h"
#include "common.h"
+#include "commands.h"
-#define MAXCOM 8
+#define MAXCOM 32
+int cont=1;
-int cont=1;
+
+const struct TreeNode* getSubCom (char **com, int n, int *t) {
+
+ int i;
+ const struct TreeNode *cur, *next;
+
+
+ cur=&coms;
+ for (i=0; i<n; ++i) {
+
+ // we have reached a terminal command, exit
+ if ( cur->sub==NULL ) break;
+
+ // search sub command in sub command array
+ for (next=cur->sub; next->name!=NULL && strcmp(next->name, com[i])!=0; ++next);
+
+ // sub command not found, exit
+ if ( next->name==NULL ) {
+ next=NULL;
+ break;
+ }
+
+ // next command is now the current one
+ cur=next;
+
+ }
+
+ *t=i;
+
+
+ return cur;
+
+}
-static const struct TreeNode rootNode={.sub={
- &com_quit,
- &com_login,
- &com_scan,
- &com_ports,
- &com_password,
- &com_list,
- &com_firmware,
- &com_name,
- NULL
-}};
+const struct TreeNode *compcur;
-void printErrCode (int err) {
+
+
+char* my_generator (const char* text, int state) {
+
+ static int len;
+ static const struct TreeNode *tn;
+ const char *name;
+
+
+ if ( compcur==NULL ) { // sub command not found
+ return NULL;
+ } else if ( state==0 ) {
+ tn=compcur->sub;
+ if ( tn==NULL ) { // terminal command
+ return NULL;
+ }
+ len=strlen(text);
+ }
+
- switch ( err ) {
- case ERR_OK: /*printf("ok\n");*/ break;
- case ERR_NET: printf("network error\n"); break;
- case ERR_NOTLOG: printf("no switch selected\n"); break;
- case ERR_BADPASS: printf("wrong password\n"); break;
- case ERR_BADID: printf("bad switch id\n"); break;
- case ERR_INVARG: printf("invalid argument\n"); break;
- case ERR_TIMEOUT: printf("timeout\n"); break;
- default: printf("unknown status code (%i)\n", err);
+ while ( (name=tn->name)!=NULL ) {
+ ++tn;
+
+ if ( strncmp(name, text, len)==0 ) {
+ return strdup(name);
+ }
+
}
+ return NULL;
+
}
-void displaySwitchTab (const struct swi_attr *sa, int nb) {
+char** my_completion (const char *text, int start, int end UNUSED) {
- int i=0;
+ char **matches=NULL;
+ char *line, *com[MAXCOM];
+ int i, n;
- if ( nb==0 ) {
- printf("no switch found\n");
- return;
- }
+ memset(com, 0, MAXCOM*sizeof(char*));
+ line=strdup(rl_line_buffer);
+ line[start]=0;
+ trim(line, start);
+ n=explode(line, com, MAXCOM);
+ free(line);
- printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n");
+ compcur=getSubCom(com, n, &i);
- for (i=0; i<nb; ++i) {
- printf("%i\t%s\t%s\t\t%s\t%s/", i, ether_ntoa(&sa[i].mac), sa[i].product, sa[i].name, inet_ntoa(sa[i].nc.ip));
- printf("%s\t%s\t%i\t%s\n", inet_ntoa(sa[i].nc.netmask), ( sa[i].nc.dhcp ? "Yes" : "No" ), sa[i].ports, sa[i].firmware);
- }
+ if ( i<n ) compcur=NULL;
+ matches=rl_completion_matches(text, my_generator);
- printf("\nfound %i switch(es)\n", nb);
+ return matches;
}
char *line, *com[MAXCOM];
struct ngadmin *nga=NULL;
struct timeval tv;
- const struct TreeNode *cur, *next, **tab;
+ const struct TreeNode *cur, *next;
int i, n;
ngadmin_setTimeout(nga, &tv);
- rl_bind_key('\t', rl_abort); // disable auto completion
+ //rl_bind_key('\t', rl_abort); // disable auto completion
+ rl_attempted_completion_function=my_completion;
while ( cont ) {
+ //rl_bind_key('\t', rl_complete); // enable auto-complete
+
if ( (line=readline("> "))==NULL ) goto end;
trim(line, strlen(line));
if ( *line!=0 ) add_history(line);
n=explode(line, com, MAXCOM);
free(line);
-
- i=0;
- for (next=&rootNode; i<n; ++i) {
- cur=next;
- for (tab=cur->sub; (next=*tab)!=NULL && strcmp(next->name, com[i])!=0; ++tab);
- if ( next==NULL ) break;
+ if ( n==0 ) {
+ continue;
}
+ cur=getSubCom(com, n, &i);
- if ( i<n ) { // commands left uncompared
+ if ( i<n ) { // commands left unchecked
if ( cur->hasArgs ) { // left "commands" are in fact parameters
- cur->comfunc(cur, n-i, (const char**)&com[i], nga);
- } else {
- if ( i==0 ) {
- printf("unknown command\n");
- } else {
- printf("unknown %s subcommand\n", com[i-1]);
- }
+ cur->comfunc(n-i, (const char**)&com[i], nga);
+ } else if ( i==0 ) { // root command
+ printf("unknown command\n");
+ } else if ( cur->sub==NULL ) { // terminal command without arguments
+ printf("%s as no subcommand and takes no parameter\n", com[i-1]);
+ } else { // intermediate command
+ printf("unknown %s subcommand\n", com[i-1]);
}
} else {
- cur=next;
- if ( cur->comfunc==NULL ) {
+ if ( cur->comfunc==NULL ) { // intermediate command
// print available subcommands
- for (tab=cur->sub; (next=*tab)!=NULL; ++tab) {
+ for (next=cur->sub; next!=NULL && next->name!=NULL; ++next) {
printf("%s ", next->name);
}
printf("\n");
} else { // terminal command
-
- cur->comfunc(cur, 0, NULL, nga);
-
+ cur->comfunc(0, NULL, nga);
}
- }
-
- /*
- if ( n==0 ) {
- // nothing: do nothing
-
- } else if ( strcmp(com[0], "timeout")==0 ) {
- //
}
- */
+
for (i=0; i<MAXCOM; i++) {
if ( com[i]!=NULL ) {
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_firmware_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- const struct swi_attr *sa;
- bool ret=true;
-
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- ret=false;
- goto end;
- }
-
- puts(sa->firmware);
-
-
- end:
-
- return ret;
-
-}
-
-
-
-static bool do_firmware_upgrade (const struct TreeNode *tn UNUSED, int nb, const char **com UNUSED, struct ngadmin *nga) {
-
- const struct swi_attr *sa;
- bool ret=true;
-
-
- if ( nb!=1 ) {
- printf("Usage: firmware upgrade <file>\n");
- ret=false;
- }
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- ret=false;
- goto end;
- }
-
- printf("not implemented yet\n");
-
-
- end:
-
- return ret;
-
-}
-
-
-
-static const struct TreeNode com_firmware_show=COM("show", do_firmware_show, false, NULL);
-static const struct TreeNode com_firmware_upgrade=COM("upgrade", do_firmware_upgrade, true, NULL);
-
-const struct TreeNode com_firmware=COM("firmware", NULL, false, &com_firmware_show, &com_firmware_upgrade, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_list (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int n;
- const struct swi_attr *sa;
-
-
- sa=ngadmin_getSwitchTab(nga, &n);
- displaySwitchTab(sa, n);
-
-
- return true;
-
-}
-
-
-
-const struct TreeNode com_list=COM("list", do_list, false, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_login (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
-
- int i;
-
-
- if ( nb!=1 ) {
- printf("Usage: login <num>\n");
- return false;
- }
-
-
- i=strtol(com[0], NULL, 0);
- i=ngadmin_login(nga, i);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-const struct TreeNode com_login=COM("login", do_login, true, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_name_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- const struct swi_attr *sa;
-
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- return false;
- }
-
- puts(sa->name);
-
-
- return true;
-
-}
-
-
-
-static bool do_name_set (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
-
-
- if ( nb!=1 ) {
- printf("Usage: name set <value>\n");
- return false;
- }
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- return false;
- }
-
- i=ngadmin_setName(nga, com[0]);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-static bool do_name_clear (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
-
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- return false;
- }
-
- i=ngadmin_setName(nga, NULL);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-static struct TreeNode com_name_show=COM("show", do_name_show, false, NULL);
-static struct TreeNode com_name_set=COM("set", do_name_set, true, NULL);
-static struct TreeNode com_name_clear=COM("clear", do_name_clear, false, NULL);
-
-const struct TreeNode com_name=COM("name", NULL, false, &com_name_show, &com_name_set, &com_name_clear, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_password_change (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
-
-
- if ( nb!=1 ) {
- printf("Usage: password set <value>\n");
- return false;
- }
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- return false;
- }
-
- i=ngadmin_changePassword(nga, com[0]);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-static bool do_password_set (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
-
- int i;
-
-
- if ( nb!=1 ) {
- printf("Usage: password set <value>\n");
- return false;
- }
-
- i=ngadmin_setPassword(nga, com[0]);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-
-static const struct TreeNode com_password_change=COM("change", do_password_change, true, NULL);
-static const struct TreeNode com_password_set=COM("set", do_password_set, true, NULL);
-
-const struct TreeNode com_password=COM("password", NULL, false, &com_password_change, &com_password_set, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_ports_state (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
- unsigned char *ports=NULL;
- bool ret=true;
-
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- ret=false;
- goto end;
- }
-
-
- ports=malloc(sa->ports*sizeof(unsigned char));
- if ( (i=ngadmin_getPortsStatus(nga, ports))<0 ) {
- printErrCode(i);
- ret=false;
- goto end;
- }
-
- for (i=0; i<sa->ports; i++) {
- printf("port %i: ", i+1);
- switch ( ports[i] ) {
- case 0: printf("down"); break;
- case SPEED_10: printf("up, 10M"); break;
- case SPEED_100: printf("up, 100M"); break;
- case SPEED_1000: printf("up, 1000M"); break;
- default: printf("unknown (%i)", ports[i]);
- }
- putchar('\n');
- }
-
- end:
- free(ports);
-
-
- return ret;
-
-}
-
-
-
-static bool do_ports_stats_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
- bool ret=true;
- struct port_stats *ps=NULL;
-
-
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
- ret=false;
- goto end;
- }
-
- ps=calloc(sa->ports, sizeof(struct port_stats));
- if ( (i=ngadmin_getPortsStatistics(nga, ps))<0 ) {
- printErrCode(i);
- ret=false;
- goto end;
- }
-
- printf("Port\tReceived\tSent\t\tCRC errors\n");
- for (i=0; i<sa->ports; ++i) {
- printf("%i\t%8llu\t%8llu\t%8llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
- }
-
- end:
- free(ps);
-
-
- return ret;
-
-}
-
-
-
-static bool do_ports_stats_reset (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int i;
-
-
- if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
- printf("must be logged\n");
- return false;
- }
-
- i=ngadmin_resetPortsStatistics(nga);
- printErrCode(i);
-
-
- return true;
-
-}
-
-
-
-static const struct TreeNode com_ports_state=COM("state", do_ports_state, false, NULL);
-
-static const struct TreeNode com_ports_stats_show=COM("show", do_ports_stats_show, false, NULL);
-static const struct TreeNode com_ports_stats_reset=COM("reset", do_ports_stats_reset, false, NULL);
-static const struct TreeNode com_ports_stats=COM("stats", NULL, false, &com_ports_stats_reset, &com_ports_stats_show, NULL);
-
-const struct TreeNode com_ports=COM("ports", NULL, false, &com_ports_state, &com_ports_stats, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_quit (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
-
- cont=0;
-
- return true;
-
-}
-
-
-
-const struct TreeNode com_quit=COM("quit", do_quit, false, NULL);
-
-
-
+++ /dev/null
-
-#include "common.h"
-
-
-
-
-static bool do_scan (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
-
- int i;
- const struct swi_attr *sa;
-
-
- if ( (i=ngadmin_scan(nga))<0 ) {
- printErrCode(i);
- return false;
- }
-
- sa=ngadmin_getSwitchTab(nga, &nb);
- displaySwitchTab(sa, nb);
-
-
- return true;
-
-}
-
-
-
-const struct TreeNode com_scan=COM("scan", do_scan, false, NULL);
-
-
-
+++ /dev/null
-
-#include "command.h"
-
-
-
-
-// ----------------------------
-int trim (char *txt, int start) {
-
- char *p, c;
-
-
- if ( txt==NULL ) {
- return 0;
- }
-
- //for (p=txt; *p!=0; p++);
- p=txt+start;
- for (p--; p>=txt && ( (c=*p)==' ' || c=='\n' ); *p--=0);
-
-
- return p-txt+1;
-
-}
-
-
-
-// --------------------------------------------------------
-int explode (const char *commande, char** tab, int maximum) {
-
- const char *start, *end;
- char c;
- int n=0, len;
-
-
- for (end=commande; ; n++) {
-
- for (start=end; (c=*start)==' ' && c!=0; start++);
- for (end=start; ( (c=*end)!=' ' || n>=maximum-1 ) && c!=0; end++);
-
- if ( (len=end-start)==0 ) {
- break;
- }
-
- tab[n]=malloc(sizeof(char)*(len+1));
- memcpy(tab[n], start, len);
- tab[n][len]=0;
-
- }
-
-
- return n;
-
-}
-
-
+++ /dev/null
-
-#ifndef DEF_COMMAND
-#define DEF_COMMAND
-
-
-#include <stdlib.h>
-#include <string.h>
-
-
-
-//
-int trim (char *txt, int start);
-
-//
-int explode (const char *commande, char** tab, int maximum);
-
-
-
-#endif
-
--- /dev/null
+
+#include "commands.h"
+
+
+
+
+// =============================================================================
+// firmware
+
+
+static bool do_firmware_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+ bool ret=true;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ puts(sa->firmware);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+static bool do_firmware_upgrade (int nb, const char **com UNUSED, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+ bool ret=true;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: firmware upgrade <file>\n");
+ ret=false;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ printf("not implemented yet\n");
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// =============================================================================
+// list
+
+
+static bool do_list (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int n;
+ const struct swi_attr *sa;
+
+
+ sa=ngadmin_getSwitchTab(nga, &n);
+ displaySwitchTab(sa, n);
+
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// login
+
+
+static bool do_login (int nb, const char **com, struct ngadmin *nga) {
+
+ int i;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: login <num>\n");
+ return false;
+ }
+
+
+ i=strtol(com[0], NULL, 0);
+ i=ngadmin_login(nga, i);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// name
+
+
+static bool do_name_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ puts(sa->name);
+
+
+ return true;
+
+}
+
+
+
+static bool do_name_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: name set <value>\n");
+ return false;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_setName(nga, com[0]);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_name_clear (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_setName(nga, NULL);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// password
+
+
+static bool do_password_change (int nb, const char **com, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: password set <value>\n");
+ return false;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_changePassword(nga, com[0]);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_password_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i;
+
+
+ if ( nb!=1 ) {
+ printf("Usage: password set <value>\n");
+ return false;
+ }
+
+ i=ngadmin_setPassword(nga, com[0]);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// ports
+
+
+static bool do_ports_state (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+ unsigned char *ports=NULL;
+ bool ret=true;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc(sa->ports*sizeof(unsigned char));
+ if ( (i=ngadmin_getPortsStatus(nga, ports))<0 ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+ for (i=0; i<sa->ports; i++) {
+ printf("port %i: ", i+1);
+ switch ( ports[i] ) {
+ case 0: printf("down"); break;
+ case SPEED_10: printf("up, 10M"); break;
+ case SPEED_100: printf("up, 100M"); break;
+ case SPEED_1000: printf("up, 1000M"); break;
+ default: printf("unknown (%i)", ports[i]);
+ }
+ putchar('\n');
+ }
+
+ end:
+ free(ports);
+
+
+ return ret;
+
+}
+
+
+
+static bool do_ports_stats_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+
+
+ if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_resetPortsStatistics(nga);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_ports_stats_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+ bool ret=true;
+ struct port_stats *ps=NULL;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ ps=calloc(sa->ports, sizeof(struct port_stats));
+ if ( (i=ngadmin_getPortsStatistics(nga, ps))<0 ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+ printf("Port\tReceived\tSent\t\tCRC errors\n");
+ for (i=0; i<sa->ports; ++i) {
+ printf("%i\t%8llu\t%8llu\t%8llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
+ }
+
+ end:
+ free(ps);
+
+
+ return ret;
+
+}
+
+
+
+// =============================================================================
+// quit
+
+
+static bool do_quit (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+
+ cont=0;
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// scan
+
+
+static bool do_scan (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( (i=ngadmin_scan(nga))<0 ) {
+ printErrCode(i);
+ return false;
+ }
+
+ sa=ngadmin_getSwitchTab(nga, &nb);
+ displaySwitchTab(sa, nb);
+
+
+ return true;
+
+}
+
+
+
+// =============================================================================
+// stormfilt
+
+
+static bool do_stormfilt_enable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_setStormFilterState(nga, 1);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_stormfilt_disable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ i=ngadmin_setStormFilterState(nga, 0);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_stormfilt_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i, *ports=NULL;
+ const struct swi_attr *sa;
+ bool ret=true;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc(sa->ports*sizeof(int));
+ for (i=0; i<sa->ports; ++i) {
+ ports[i]=BITRATE_NOLIMIT;
+ }
+
+ i=ngadmin_setStormFilterValues(nga, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
+static bool do_stormfilt_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i, p, *ports=NULL;
+ const struct swi_attr *sa;
+ bool ret=true;
+
+
+ if ( nb==0 ) {
+ printf("Usage: stormfilt set <port1> <speed1> [<port2> <speed2> ...]\n");
+ ret=false;
+ goto end;
+ }
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc(sa->ports*sizeof(int));
+ for (i=0; i<sa->ports; ++i) {
+ ports[i]=BITRATE_UNSPEC;
+ }
+
+ for (i=0; i<nb; i+=2) {
+ if ( (p=strtol(com[i], NULL, 0))<1 || p>sa->ports ) continue;
+ ports[p-1]=parseBitrate(com[i+1]);
+ }
+
+
+ i=ngadmin_setStormFilterValues(nga, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
+static bool do_stormfilt_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i, s, ret=true, *ports=NULL;
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ if ( (i=ngadmin_getStormFilterState(nga, &s))!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+
+ if ( !s ) {
+ printf("storm filter is disabled\n");
+ goto end;
+ }
+
+ printf("storm filter is enabled\n");
+
+ ports=malloc(sa->ports*sizeof(int));
+ if ( (i=ngadmin_getStormFilterValues(nga, ports))!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+ for (i=0; i<sa->ports; ++i) {
+ printf("port %i: ", i+1);
+ printBitrate(ports[i]);
+ }
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
+// =============================================================================
+
+
+COM_ROOT_START(coms)
+
+ COM_START(firmware)
+ COM_TERM(show, do_firmware_show, false)
+ COM_TERM(upgrade, do_firmware_upgrade, true)
+ COM_END
+
+ COM_TERM(list, do_list, false)
+
+ COM_TERM(login, do_login, true)
+
+ COM_START(name)
+ COM_TERM(show, do_name_show, false)
+ COM_TERM(set, do_name_set, true)
+ COM_TERM(clear, do_name_clear, false)
+ COM_END
+
+ COM_START(password)
+ COM_TERM(change, do_password_change, true)
+ COM_TERM(set, do_password_set, true)
+ COM_END
+
+ COM_START(ports)
+ COM_TERM(state, do_ports_state, false)
+ COM_START(stats)
+ COM_TERM(reset, do_ports_stats_reset, false)
+ COM_TERM(show, do_ports_stats_show, false)
+ COM_END
+ COM_END
+
+ COM_TERM(quit, do_quit, false)
+
+ COM_TERM(scan, do_scan, false)
+
+ COM_START(stormfilt)
+ COM_TERM(enable, do_stormfilt_enable, false)
+ COM_TERM(disable, do_stormfilt_disable, false)
+ COM_TERM(reset, do_stormfilt_reset, false)
+ COM_TERM(set, do_stormfilt_set, true)
+ COM_TERM(show, do_stormfilt_show, false)
+ COM_END
+
+COM_ROOT_END
+
+
+
--- /dev/null
+
+#ifndef DEF_COMMANDS
+#define DEF_COMMANDS
+
+
+#include "common.h"
+
+
+
+
+struct TreeNode {
+ const char *name;
+ bool (* const comfunc)(int, const char**, struct ngadmin*);
+ bool hasArgs;
+ const struct TreeNode *sub;
+};
+
+
+#define COM_ROOT_START(v) const struct TreeNode v={.name="<root>", .comfunc=NULL, .hasArgs=false, .sub=(const struct TreeNode[]){
+#define COM_ROOT_END {.name=NULL, .comfunc=NULL, .hasArgs=false, .sub=NULL}}};
+#define COM_START(nam) {.name=#nam, .comfunc=NULL, .hasArgs=false, .sub=(const struct TreeNode[]){
+#define COM_TERM(nam, func, args) {.name=#nam, .comfunc=func, .hasArgs=args, .sub=NULL},
+#define COM_END {.name=NULL, .comfunc=NULL, .hasArgs=false, .sub=NULL}}},
+
+
+extern const struct TreeNode coms;
+
+
+
+#endif
+
--- /dev/null
+
+#include "common.h"
+
+
+
+
+
+
+
+void printErrCode (int err) {
+
+
+ switch ( err ) {
+ case ERR_OK: /*printf("ok\n");*/ break;
+ case ERR_NET: printf("network error\n"); break;
+ case ERR_NOTLOG: printf("no switch selected\n"); break;
+ case ERR_BADPASS: printf("wrong password\n"); break;
+ case ERR_BADID: printf("bad switch id\n"); break;
+ case ERR_INVARG: printf("invalid argument\n"); break;
+ case ERR_TIMEOUT: printf("timeout\n"); break;
+ default: printf("unknown status code (%i)\n", err);
+ }
+
+
+}
+
+
+
+void printBitrate (int br) {
+
+
+ switch ( br ) {
+ case BITRATE_UNSPEC: printf("unspecified\n"); break;
+ case BITRATE_NOLIMIT: printf("unlimited\n"); break;
+ case BITRATE_512K: printf("512K\n"); break;
+ case BITRATE_1M: printf("1M\n"); break;
+ case BITRATE_2M: printf("2M\n"); break;
+ case BITRATE_4M: printf("4M\n"); break;
+ case BITRATE_8M: printf("8M\n"); break;
+ case BITRATE_16M: printf("16M\n"); break;
+ case BITRATE_32M: printf("32M\n"); break;
+ case BITRATE_64M: printf("64M\n"); break;
+ case BITRATE_128M: printf("128M\n"); break;
+ case BITRATE_256M: printf("256M\n"); break;
+ case BITRATE_512M: printf("512M\n"); break;
+ default: printf("unknown (%i)\n", br);
+ }
+
+
+}
+
+
+struct BrStr {
+ const char *str;
+ int br;
+};
+
+static const struct BrStr bitrates[]={
+ {"nl", BITRATE_NOLIMIT},
+ {"512K", BITRATE_512K},
+ {"1M", BITRATE_1M},
+ {"2M", BITRATE_2M},
+ {"4M", BITRATE_4M},
+ {"8M", BITRATE_8M},
+ {"16M", BITRATE_16M},
+ {"32M", BITRATE_32M},
+ {"64M", BITRATE_64M},
+ {"128M", BITRATE_128M},
+ {"256M", BITRATE_256M},
+ {"512M", BITRATE_512M},
+ {NULL, BITRATE_UNSPEC}
+};
+
+
+int parseBitrate (const char *s) {
+
+ const struct BrStr *b;
+
+
+ for (b=bitrates; b->str!=NULL && strcasecmp(b->str, s)!=0; ++b);
+
+
+ return b->br;
+
+}
+
+
+
+void displaySwitchTab (const struct swi_attr *sa, int nb) {
+
+ int i=0;
+
+
+ if ( nb==0 ) {
+ printf("no switch found\n");
+ return;
+ }
+
+
+ printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n");
+
+ for (i=0; i<nb; ++i) {
+ printf("%i\t%s\t%s\t\t%s\t%s/", i, ether_ntoa(&sa[i].mac), sa[i].product, sa[i].name, inet_ntoa(sa[i].nc.ip));
+ printf("%s\t%s\t%i\t%s\n", inet_ntoa(sa[i].nc.netmask), ( sa[i].nc.dhcp ? "Yes" : "No" ), sa[i].ports, sa[i].firmware);
+ }
+
+ printf("\nfound %i switch(es)\n", nb);
+
+
+}
+
+
+
+// ----------------------------
+int trim (char *txt, int start) {
+
+ char *p, c;
+
+
+ if ( txt==NULL ) {
+ return 0;
+ }
+
+ //for (p=txt; *p!=0; p++);
+ p=txt+start;
+ for (p--; p>=txt && ( (c=*p)==' ' || c=='\n' ); *p--=0);
+
+
+ return p-txt+1;
+
+}
+
+
+
+// --------------------------------------------------------
+int explode (const char *commande, char** tab, int maximum) {
+
+ const char *start, *end;
+ char c;
+ int n=0, len;
+
+
+ for (end=commande; ; n++) {
+
+ for (start=end; (c=*start)==' ' && c!=0; start++);
+ for (end=start; ( (c=*end)!=' ' || n>=maximum-1 ) && c!=0; end++);
+
+ if ( (len=end-start)==0 ) {
+ break;
+ }
+
+ tab[n]=malloc(sizeof(char)*(len+1));
+ memcpy(tab[n], start, len);
+ tab[n][len]=0;
+
+ }
+
+
+ return n;
+
+}
+
+
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <ngadmin.h>
#define UNUSED __attribute__((unused))
-#define COM(nam, func, args, ...) {.name=nam, .comfunc=func, .hasArgs=args, .sub={__VA_ARGS__}}
-
-
-
-struct TreeNode {
- const char *name;
- bool (* const comfunc)(const struct TreeNode*, int, const char**, struct ngadmin*);
- bool hasArgs;
- const struct TreeNode *sub[];
-};
-extern const struct TreeNode com_quit;
-extern const struct TreeNode com_login;
-extern const struct TreeNode com_scan;
-extern const struct TreeNode com_ports;
-extern const struct TreeNode com_password;
-extern const struct TreeNode com_list;
-extern const struct TreeNode com_list;
-extern const struct TreeNode com_firmware;
-extern const struct TreeNode com_name;
-
-
-
void displaySwitchTab (const struct swi_attr *sa, int nb);
void printErrCode (int err);
+void printBitrate (int br);
+int parseBitrate (const char *s);
+
+//
+int trim (char *txt, int start);
+
+//
+int explode (const char *commande, char** tab, int maximum);
#define PRIO_NORM 3
#define PRIO_LOW 4
+#define BITRATE_UNSPEC -1
#define BITRATE_NOLIMIT 0
#define BITRATE_512K 1
#define BITRATE_1M 2
int ngadmin_changePassword (struct ngadmin *nga, const char* pass) EXPORT;
+//
+int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) EXPORT;
+
+
+//
+int ngadmin_setStormFilterState (struct ngadmin *nga, int s) EXPORT;
+
+
+//
+int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) EXPORT;
+
+
+//
+int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) EXPORT;
+
+
#endif
return ret;
-
}
}
+
+// ----------------------------------------------------------
+int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || s==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
+ *s= *(char*)at->data!=0 ;
+ break;
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// ---------------------------------------------------------
+int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
+
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+
+
+ if ( nga==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+ pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// ---------------------------------------------------------------
+int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ ports[i]=ntohl(*(int*)(1+(char*)at->data));
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// ---------------------------------------------------------------------
+int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
+
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+
+ for (i=0; i<nga->current->ports; ++i) {
+ if ( ports[i]>=0 && ports[i]<=11 ) {
+ p=malloc(5);
+ *p=i+1;
+ *(int*)(p+1)=htonl(ports[i]);
+ pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
+ }
+ }
+
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
*v=value;
- return newAttr(attr, 1, v);
+ return newAttr(attr, sizeof(char), v);
+
+}
+
+
+
+// -----------------------------------------------------
+struct attr* newIntAttr (unsigned short attr, int value) {
+
+ int *v=malloc(sizeof(int));
+
+ *v=value;
+
+ return newAttr(attr, sizeof(int), v);
}
//
struct attr* newByteAttr (unsigned short attr, unsigned char value);
+//
+struct attr* newIntAttr (unsigned short attr, int value);
+
//
void freeAttr (struct attr *at);