From 47fbfc0635ef174f71047d75c328f8e848e6a02d Mon Sep 17 00:00:00 2001 From: darkcoven Date: Tue, 29 Nov 2011 12:00:00 +0100 Subject: [PATCH] CLI: separated commands by category in different files. Added support for reading VLAN 802.1q values. Dissector: changed code structure. Dissector: added checks of packet structure. Dissector: added dissect support for most request types. --- cli/com_bitrate.c | 121 ++++ cli/com_cabletest.c | 53 ++ cli/com_defaults.c | 35 ++ cli/com_firmware.c | 56 ++ cli/com_igmp.c | 72 +++ cli/com_list.c | 20 + cli/com_login.c | 26 + cli/com_mirror.c | 132 ++++ cli/com_name.c | 70 +++ cli/com_netconf.c | 80 +++ cli/com_password.c | 51 ++ cli/com_ports.c | 105 ++++ cli/com_qos.c | 154 +++++ cli/com_quit.c | 14 + cli/com_restart.c | 35 ++ cli/com_scan.c | 25 + cli/com_stormfilter.c | 144 +++++ cli/com_tree.c | 42 ++ cli/com_vlan.c | 177 ++++++ cli/commands.c | 1366 ++--------------------------------------- lib/ngadmin.h | 6 +- lib/src/network.c | 34 +- lib/src/ngadmin.c | 81 ++- nsdp.lua | 230 +++++-- 24 files changed, 1747 insertions(+), 1382 deletions(-) create mode 100644 cli/com_bitrate.c create mode 100644 cli/com_cabletest.c create mode 100644 cli/com_defaults.c create mode 100644 cli/com_firmware.c create mode 100644 cli/com_igmp.c create mode 100644 cli/com_list.c create mode 100644 cli/com_login.c create mode 100644 cli/com_mirror.c create mode 100644 cli/com_name.c create mode 100644 cli/com_netconf.c create mode 100644 cli/com_password.c create mode 100644 cli/com_ports.c create mode 100644 cli/com_qos.c create mode 100644 cli/com_quit.c create mode 100644 cli/com_restart.c create mode 100644 cli/com_scan.c create mode 100644 cli/com_stormfilter.c create mode 100644 cli/com_tree.c create mode 100644 cli/com_vlan.c diff --git a/cli/com_bitrate.c b/cli/com_bitrate.c new file mode 100644 index 0000000..94afad8 --- /dev/null +++ b/cli/com_bitrate.c @@ -0,0 +1,121 @@ + +#include "commands.h" + + + +// helper function to analyse bitrate speed specifications +static int bitrate_analyse (int nb, const char **com, int *ports) { + + int i=0, s; + + + while ( i SPEEDSPEC [ SPEEDSPEC ...]\n"); + printf("SPEEDSPEC: [inout ] [in ] [out ]\n"); + ret=false; + goto end; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + ports=malloc(2*sa->ports*sizeof(int)); + + // get defaults if present + if ( strcmp(com[k], "all")==0 ) { + ++k; + k+=bitrate_analyse(nb-k, &com[k], defs); + } + + // apply defaults + for (i=0; iports; ++i) { + memcpy(&ports[2*i], defs, sizeof(defs)); + } + + // get ports specifics + while ( k=0 && pports ) { + k+=bitrate_analyse(nb-k, &com[k], &ports[2*p]); + } + } + + // send it to the switch + i=ngadmin_setBitrateLimits(nga, ports); + printErrCode(i); + + + end: + free(ports); + + return ret; + +} + + + +bool do_bitrate_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + int i, ret=true, *ports=NULL; + const struct swi_attr *sa; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + + ports=malloc(2*sa->ports*sizeof(int)); + if ( (i=ngadmin_getBitrateLimits(nga, ports))!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + for (i=0; iports; ++i) { + printf("port %i: in %s, out %s\n", i+1, bitrates[ports[2*i+0]], bitrates[ports[2*i+1]]); + } + + end: + free(ports); + + return ret; + +} + + + diff --git a/cli/com_cabletest.c b/cli/com_cabletest.c new file mode 100644 index 0000000..521ada9 --- /dev/null +++ b/cli/com_cabletest.c @@ -0,0 +1,53 @@ + +#include "commands.h" + + + +bool do_cabletest (int nb, const char **com, struct ngadmin *nga) { + + bool ret=true; + const struct swi_attr *sa; + struct cabletest *ct=NULL; + int i, j=0, k=0; + + + if ( nb<1 ) { + printf("Usage: cabletest [ ...]\n"); + goto end; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + ct=malloc(sa->ports*sizeof(struct cabletest)); + memset(ct, 0, sa->ports*sizeof(struct cabletest)); + + while ( k=1 && ct[j].port<=sa->ports ) ++j; + } + + i=ngadmin_cabletest(nga, ct, j); + if ( i<0 ) { + printErrCode(i); + ret=false; + goto end; + } + + + for (i=0; ifirmware); + + + end: + + return ret; + +} + + + +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 \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; + +} + + + diff --git a/cli/com_igmp.c b/cli/com_igmp.c new file mode 100644 index 0000000..efe39b8 --- /dev/null +++ b/cli/com_igmp.c @@ -0,0 +1,72 @@ + +#include "commands.h" + + + +bool do_igmp_set (int nb, const char **com, struct ngadmin *nga) { + + int i; + struct igmp_conf ic; + + + if ( nb!=4 ) { + printf("Usage: igmp set \n"); + return false; + } + + if ( ngadmin_getCurrentSwitch(nga)==NULL ) { + printf("must be logged\n"); + return false; + } + + ic.enable=strtol(com[0], NULL, 0); + ic.vlan=strtol(com[1], NULL, 0); + ic.validate=strtol(com[2], NULL, 0); + ic.block=strtol(com[3], NULL, 0); + + i=ngadmin_setIGMPConf(nga, &ic); + printErrCode(i); + + + return true; + +} + + + +bool do_igmp_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + int i; + const struct swi_attr *sa; + struct igmp_conf ic; + bool ret=true; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + i=ngadmin_getIGMPConf(nga, &ic); + if ( i!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + + printf("IGMP snooping enabled: %s\n", ic.enable ? "yes" : "no" ); + printf("IGMP snooping vlan: %u\n", ic.vlan); + printf("Validate IGMPv3 headers: %s\n", ic.validate ? "yes" : "no" ); + printf("Block unknown multicast addresses: %s\n", ic.block ? "yes" : "no" ); + + + + end: + + return ret; + +} + + diff --git a/cli/com_list.c b/cli/com_list.c new file mode 100644 index 0000000..9630f76 --- /dev/null +++ b/cli/com_list.c @@ -0,0 +1,20 @@ + +#include "commands.h" + + + +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; + +} + + diff --git a/cli/com_login.c b/cli/com_login.c new file mode 100644 index 0000000..dfd0a92 --- /dev/null +++ b/cli/com_login.c @@ -0,0 +1,26 @@ + +#include "commands.h" + + + +bool do_login (int nb, const char **com, struct ngadmin *nga) { + + int i; + + + if ( nb!=1 ) { + printf("Usage: login \n"); + return false; + } + + + i=strtol(com[0], NULL, 0); + i=ngadmin_login(nga, i); + printErrCode(i); + + + return true; + +} + + diff --git a/cli/com_mirror.c b/cli/com_mirror.c new file mode 100644 index 0000000..67cbb04 --- /dev/null +++ b/cli/com_mirror.c @@ -0,0 +1,132 @@ + +#include "commands.h" + + + + +bool do_mirror_disable (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_setMirror(nga, NULL); + printErrCode(i); + + + return true; + +} + + + +bool do_mirror_set (int nb, const char **com, struct ngadmin *nga) { + + const struct swi_attr *sa; + char *ports=NULL; + bool ret=true; + int i, k=0; + + + if ( nb<3 ) { + printf("Usage: mirror set clone [ ...]\n"); + goto end; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + + ports=malloc((sa->ports+1)*sizeof(char)); + memset(ports, 0, sa->ports+1); + + ports[0]=strtol(com[k++], NULL, 0); + if ( ports[0]<1 || ports[0]>sa->ports || strcasecmp(com[k++], "clone")!=0 ) { + printf("syntax error\n"); + ret=false; + goto end; + } + + + while ( ksa->ports ) { + printf("port out of range\n"); + ret=false; + goto end; + } else if ( i==ports[0] ) { + printf("destination port cannot be in port list\n"); + ret=false; + goto end; + } + ports[i]=1; + } + + + i=ngadmin_setMirror(nga, ports); + printErrCode(i); + + + end: + free(ports); + + return ret; + +} + + + +bool do_mirror_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + const struct swi_attr *sa; + char *ports=NULL; + int i; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + return false; + } + + + ports=malloc((sa->ports+1)*sizeof(char)); + + i=ngadmin_getMirror(nga, ports); + if ( i!=ERR_OK ) { + printErrCode(i); + goto end; + } + + if ( ports[0]==0 ) { + printf("port mirroring is disabled\n"); + goto end; + } + + printf("destination: %i\n", ports[0]); + printf("ports: "); + for (i=1; i<=sa->ports; ++i) { + if ( ports[i] ) { + printf("%i ", i); + } + } + printf("\n"); + + + + end: + free(ports); + + return true; + +} + + + diff --git a/cli/com_name.c b/cli/com_name.c new file mode 100644 index 0000000..e561724 --- /dev/null +++ b/cli/com_name.c @@ -0,0 +1,70 @@ + +#include "commands.h" + + + +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; + +} + + + +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 \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; + +} + + + +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; + +} + + diff --git a/cli/com_netconf.c b/cli/com_netconf.c new file mode 100644 index 0000000..e4838b8 --- /dev/null +++ b/cli/com_netconf.c @@ -0,0 +1,80 @@ + +#include "commands.h" + + + +bool do_netconf_set (int nb, const char **com, struct ngadmin *nga) { + + int i, k; + const struct swi_attr *sa; + struct net_conf nc; + bool ret=true; + + + if ( nb==0 ) { + printf("Usage: netconf set [dhcp yes|no] [ip ] [mask ] [gw ]\n"); + return false; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + return false; + } + + + memset(&nc, 0, sizeof(struct net_conf)); + + for (k=0; k\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; + +} + + + +bool do_password_set (int nb, const char **com, struct ngadmin *nga) { + + int i; + + + if ( nb!=1 ) { + printf("Usage: password set \n"); + return false; + } + + i=ngadmin_setPassword(nga, com[0]); + printErrCode(i); + + + return true; + +} + + + diff --git a/cli/com_ports.c b/cli/com_ports.c new file mode 100644 index 0000000..baa8c8f --- /dev/null +++ b/cli/com_ports.c @@ -0,0 +1,105 @@ + +#include "commands.h" + + + +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; iports; 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; + +} + + + +bool do_ports_statistics_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; + +} + + + +bool do_ports_statistics_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\tCRC errors\n"); + for (i=0; iports; ++i) { + printf("% 4i%12llu%12llu%14llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc); + } + + end: + free(ps); + + + return ret; + +} + + + diff --git a/cli/com_qos.c b/cli/com_qos.c new file mode 100644 index 0000000..cd61741 --- /dev/null +++ b/cli/com_qos.c @@ -0,0 +1,154 @@ + +#include "commands.h" + + + + +bool do_qos_mode (int nb, const char **com, struct ngadmin *nga) { + + int i, s, ret=true; + const struct swi_attr *sa; + + + if ( nb==0 ) { + printf("Usage: qos mode port|802.1p\n"); + goto end; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + + if ( strcasecmp(com[0], "port")==0 ) { + s=QOS_PORT; + } else if ( strcasecmp(com[0], "802.1p")==0 ) { + s=QOS_DOT; + } else { + printf("Unknown QOS mode\n"); + ret=false; + goto end; + } + + + i=ngadmin_setQOSMode(nga, s); + printErrCode(i); + + + end: + + return ret; + +} + + + +bool do_qos_set (int nb, const char **com, struct ngadmin *nga) { + + int i, p; + const struct swi_attr *sa; + bool ret=true; + char d=PRIO_UNSPEC, *ports=NULL; + + + if ( nb<2 ) { + printf("Usage: qos set (all )|( [ ...])\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(char)); + + if ( strcmp(com[0], "all")==0 ) { + d=parsePrio(com[1]); + com+=2; + nb-=2; + } + + for (i=0; iports; ++i) { + ports[i]=d; + } + + for (i=0; isa->ports ) continue; + ports[p-1]=parsePrio(com[i+1]); + } + + + i=ngadmin_setQOSValues(nga, ports); + printErrCode(i); + + + end: + free(ports); + + return ret; + +} + + + +bool do_qos_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + int i, s=0, ret=true; + const struct swi_attr *sa; + char *ports=NULL; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + if ( (i=ngadmin_getQOSMode(nga, &s))!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + + printf("QOS mode: "); + + if ( s==QOS_DOT ) { + printf("802.1p\n"); + goto end; + } else if ( s!=QOS_PORT ) { + printf("unknown (%i)\n", s); + goto end; + } + + printf("port based\n"); + + ports=malloc(sa->ports*sizeof(char)); + + if ( (i=ngadmin_getQOSValues(nga, ports))!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + for (i=0; iports; ++i) { + printf("port %i: %s\n", i+1, prio[(int)ports[i]]); + } + + + end: + free(ports); + + return ret; + +} + + + + diff --git a/cli/com_quit.c b/cli/com_quit.c new file mode 100644 index 0000000..64c7824 --- /dev/null +++ b/cli/com_quit.c @@ -0,0 +1,14 @@ + +#include "commands.h" + + + +bool do_quit (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { + + cont=0; + + return true; + +} + + diff --git a/cli/com_restart.c b/cli/com_restart.c new file mode 100644 index 0000000..8ad5845 --- /dev/null +++ b/cli/com_restart.c @@ -0,0 +1,35 @@ + +#include "commands.h" + + + +bool do_restart (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { + + int i, ret=true; + const struct swi_attr *sa; + char line[16]; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + + printf("The switch will be restarted. Continue ? [y/N]: "); + fflush(stdout); + + if ( fgets(line, sizeof(line), stdin)!=NULL && strcasecmp(line, "y\n")==0 ) { + i=ngadmin_restart(nga); + printErrCode(i); + } + + + end: + + return ret; + +} + + diff --git a/cli/com_scan.c b/cli/com_scan.c new file mode 100644 index 0000000..98744ff --- /dev/null +++ b/cli/com_scan.c @@ -0,0 +1,25 @@ + +#include "commands.h" + + + +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; + +} + + diff --git a/cli/com_stormfilter.c b/cli/com_stormfilter.c new file mode 100644 index 0000000..88afdae --- /dev/null +++ b/cli/com_stormfilter.c @@ -0,0 +1,144 @@ + +#include "commands.h" + + + +bool do_stormfilter_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; + +} + + + +bool do_stormfilter_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; + +} + + + +bool do_stormfilter_set (int nb, const char **com, struct ngadmin *nga) { + + int i, d=BITRATE_UNSPEC, p, *ports=NULL; + const struct swi_attr *sa; + bool ret=true; + + + if ( nb<2 ) { + printf("Usage: stormfilt set (all )|( [ ...])\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)); + + if ( strcmp(com[0], "all")==0 ) { + d=parseBitrate(com[1]); + com+=2; + nb-=2; + } + + for (i=0; iports; ++i) { + ports[i]=d; + } + + for (i=0; isa->ports ) continue; + ports[p-1]=parseBitrate(com[i+1]); + } + + + i=ngadmin_setStormFilterValues(nga, ports); + printErrCode(i); + + + end: + free(ports); + + return ret; + +} + + + +bool do_stormfilter_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; iports; ++i) { + printf("port %i: %s\n", i+1, bitrates[ports[i]]); + } + + end: + free(ports); + + return ret; + +} + + + diff --git a/cli/com_tree.c b/cli/com_tree.c new file mode 100644 index 0000000..200ac41 --- /dev/null +++ b/cli/com_tree.c @@ -0,0 +1,42 @@ + +#include "commands.h" + + + + +static void display_node (const struct TreeNode *tn, int depth) { + + int i; + const struct TreeNode *s; + + + for (i=0; iname); + + if ( tn->sub==NULL ) return; + + for (s=tn->sub; s->name!=NULL; ++s) { + display_node(s, depth+1); + } + + +} + + + +bool do_tree (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { + + + display_node(&coms, 0); + + + return true; + +} + + + + diff --git a/cli/com_vlan.c b/cli/com_vlan.c new file mode 100644 index 0000000..14be784 --- /dev/null +++ b/cli/com_vlan.c @@ -0,0 +1,177 @@ + +#include "commands.h" + + + + +static char vlan_char (int t) { + + switch ( t ) { + case VLAN_TAGGED: return 'T'; + case VLAN_UNTAGGED: return 'U'; + case VLAN_NO: return ' '; + default: return '?'; + } + +} + + + +bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga) { + + unsigned short vl=0, *vlans=NULL; + unsigned char *ports=NULL; + const struct swi_attr *sa; + int i, j, n=16; + bool ret=true; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + if ( nb>0 ) { + vl=strtoul(com[0], NULL, 0); + } + + + ports=malloc(sa->ports*n*sizeof(unsigned char)); + + if ( vl==0 ) { + vlans=malloc(n*sizeof(unsigned short)); + ports=malloc(sa->ports*n*sizeof(unsigned char)); + i=ngadmin_getVLANDotAllConf(nga, vlans, ports, &n); + } else { + ports=malloc(sa->ports*sizeof(unsigned char)); + i=ngadmin_getVLANDotConf(nga, vl, ports); + } + + if ( i!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + + printf("Ports configuration: \n"); + printf("VLAN\t"); + for (i=1; i<=sa->ports; ++i) { + printf("%i\t", i); + } + putchar('\n'); + + if ( vl==0 ) { + + for (i=0; iports; ++j) { + printf("%c\t", vlan_char(ports[i*sa->ports+j])); + } + putchar('\n'); + } + + } else { + + printf("%u\t", vl); + for (j=0; jports; ++j) { + printf("%c\t", vlan_char(ports[j])); + } + putchar('\n'); + + } + + + end: + free(vlans); + free(ports); + + + return ret; + +} + + + +bool do_vlan_mode_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + int i, t, ret=true; + + + if ( ngadmin_getCurrentSwitch(nga)==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + if ( (i=ngadmin_getVLANType(nga, &t))!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + printf("VLAN type: "); + switch ( t ) { + case VLAN_DISABLED: printf("disabled\n"); break; + case VLAN_PORT_BASIC: printf("port basic\n"); break; + case VLAN_PORT_ADV: printf("port advanced\n"); break; + case VLAN_DOT_BASIC: printf("802.1Q basic\n"); break; + case VLAN_DOT_ADV:printf("802.1Q advanced\n");break; + default: printf("unknown (%i)\n", t); + } + + + end: + + return ret; + +} + + + +bool do_vlan_pvid_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { + + unsigned short *ports=NULL; + const struct swi_attr *sa; + int i; + bool ret=true; + + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + ports=malloc(sa->ports*sizeof(unsigned short)); + i=ngadmin_getPVID(nga, ports); + if ( i!=ERR_OK ) { + printErrCode(i); + ret=false; + goto end; + } + + + printf("PVID: \n"); + printf("Port\t"); + for (i=1; i<=sa->ports; ++i) { + printf("%i\t", i); + } + putchar('\n'); + + printf("VLAN\t"); + for (i=0; iports; ++i) { + printf("%u\t", ports[i]); + } + putchar('\n'); + + + end: + free(ports); + + return ret; + +} + + diff --git a/cli/commands.c b/cli/commands.c index b26d2fd..70740b2 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -4,1369 +4,101 @@ -// ============================================================================= // bitrate +bool do_bitrate_set (int nb, const char **com, struct ngadmin *nga); +bool do_bitrate_show (int nb, const char **com, struct ngadmin *nga); -// helper function to analyse bitrate speed specifications -static int bitrate_analyse (int nb, const char **com, int *ports) { - - int i=0, s; - - - while ( i SPEEDSPEC [ SPEEDSPEC ...]\n"); - printf("SPEEDSPEC: [inout ] [in ] [out ]\n"); - ret=false; - goto end; - } - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - ports=malloc(2*sa->ports*sizeof(int)); - - // get defaults if present - if ( strcmp(com[k], "all")==0 ) { - ++k; - k+=bitrate_analyse(nb-k, &com[k], defs); - } - - // apply defaults - for (i=0; iports; ++i) { - memcpy(&ports[2*i], defs, sizeof(defs)); - } - - // get ports specifics - while ( k=0 && pports ) { - k+=bitrate_analyse(nb-k, &com[k], &ports[2*p]); - } - } - - // send it to the switch - i=ngadmin_setBitrateLimits(nga, ports); - printErrCode(i); - - - end: - free(ports); - - return ret; - -} - - - -static bool do_bitrate_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { - - int i, ret=true, *ports=NULL; - const struct swi_attr *sa; - - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - - ports=malloc(2*sa->ports*sizeof(int)); - if ( (i=ngadmin_getBitrateLimits(nga, ports))!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - for (i=0; iports; ++i) { - printf("port %i: in %s, out %s\n", i+1, bitrates[ports[2*i+0]], bitrates[ports[2*i+1]]); - } - - end: - free(ports); - - return ret; - -} - - - -// ============================================================================= // cabletest +bool do_cabletest (int nb, const char **com, struct ngadmin *nga); -static bool do_cabletest (int nb, const char **com, struct ngadmin *nga) { - - bool ret=true; - const struct swi_attr *sa; - struct cabletest *ct=NULL; - int i, j=0, k=0; - - - if ( nb<1 ) { - printf("Usage: cabletest [ ...]\n"); - goto end; - } - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - ct=malloc(sa->ports*sizeof(struct cabletest)); - memset(ct, 0, sa->ports*sizeof(struct cabletest)); - - while ( k=1 && ct[j].port<=sa->ports ) ++j; - } - - i=ngadmin_cabletest(nga, ct, j); - if ( i<0 ) { - printErrCode(i); - ret=false; - goto end; - } - - - for (i=0; ifirmware); - - - 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 \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; - -} - - - -// ============================================================================= // igmp +bool do_igmp_set (int nb, const char **com, struct ngadmin *nga); +bool do_igmp_show (int nb, const char **com, struct ngadmin *nga); -static bool do_igmp_set (int nb, const char **com, struct ngadmin *nga) { - - int i; - struct igmp_conf ic; - - - if ( nb!=4 ) { - printf("Usage: igmp set \n"); - return false; - } - - if ( ngadmin_getCurrentSwitch(nga)==NULL ) { - printf("must be logged\n"); - return false; - } - - ic.enable=strtol(com[0], NULL, 0); - ic.vlan=strtol(com[1], NULL, 0); - ic.validate=strtol(com[2], NULL, 0); - ic.block=strtol(com[3], NULL, 0); - - i=ngadmin_setIGMPConf(nga, &ic); - printErrCode(i); - - - return true; - -} - - - -static bool do_igmp_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { - - int i; - const struct swi_attr *sa; - struct igmp_conf ic; - bool ret=true; - - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - i=ngadmin_getIGMPConf(nga, &ic); - if ( i!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - - printf("IGMP snooping enabled: %s\n", ic.enable ? "yes" : "no" ); - printf("IGMP snooping vlan: %u\n", ic.vlan); - printf("Validate IGMPv3 headers: %s\n", ic.validate ? "yes" : "no" ); - printf("Block unknown multicast addresses: %s\n", ic.block ? "yes" : "no" ); - - - - end: - - return ret; - -} - - - -// ============================================================================= // list +bool do_list (int nb, const char **com, struct ngadmin *nga); -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 +bool do_login (int nb, const char **com, struct ngadmin *nga); -static bool do_login (int nb, const char **com, struct ngadmin *nga) { - - int i; - - - if ( nb!=1 ) { - printf("Usage: login \n"); - return false; - } - - - i=strtol(com[0], NULL, 0); - i=ngadmin_login(nga, i); - printErrCode(i); - - - return true; - -} - - - -// ============================================================================= // mirror +bool do_mirror_disable (int nb, const char **com, struct ngadmin *nga); +bool do_mirror_set (int nb, const char **com, struct ngadmin *nga); +bool do_mirror_show (int nb, const char **com, struct ngadmin *nga); -static bool do_mirror_disable (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_setMirror(nga, NULL); - printErrCode(i); - - - return true; - -} - - - -static bool do_mirror_set (int nb, const char **com, struct ngadmin *nga) { - - const struct swi_attr *sa; - char *ports=NULL; - bool ret=true; - int i, k=0; - - - if ( nb<3 ) { - printf("Usage: mirror set clone [ ...]\n"); - goto end; - } - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - - ports=malloc((sa->ports+1)*sizeof(char)); - memset(ports, 0, sa->ports+1); - - ports[0]=strtol(com[k++], NULL, 0); - if ( ports[0]<1 || ports[0]>sa->ports || strcasecmp(com[k++], "clone")!=0 ) { - printf("syntax error\n"); - ret=false; - goto end; - } - - - while ( ksa->ports ) { - printf("port out of range\n"); - ret=false; - goto end; - } else if ( i==ports[0] ) { - printf("destination port cannot be in port list\n"); - ret=false; - goto end; - } - ports[i]=1; - } - - - i=ngadmin_setMirror(nga, ports); - printErrCode(i); - - - end: - free(ports); - - return ret; - -} - - - -static bool do_mirror_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { - - const struct swi_attr *sa; - char *ports=NULL; - int i; - - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - return false; - } - - - ports=malloc((sa->ports+1)*sizeof(char)); - - i=ngadmin_getMirror(nga, ports); - if ( i!=ERR_OK ) { - printErrCode(i); - goto end; - } - - if ( ports[0]==0 ) { - printf("port mirroring is disabled\n"); - goto end; - } - - printf("destination: %i\n", ports[0]); - printf("ports: "); - for (i=1; i<=sa->ports; ++i) { - if ( ports[i] ) { - printf("%i ", i); - } - } - printf("\n"); - - - - end: - free(ports); - - return true; - -} - - - -// ============================================================================= // name +bool do_name_show (int nb, const char **com, struct ngadmin *nga); +bool do_name_set (int nb, const char **com, struct ngadmin *nga); +bool do_name_clear (int nb, const char **com, struct ngadmin *nga); -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 \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; - -} - - - -// ============================================================================= // netconf +bool do_netconf_set (int nb, const char **com, struct ngadmin *nga); -static bool do_netconf_set (int nb, const char **com, struct ngadmin *nga) { - - int i, k; - const struct swi_attr *sa; - struct net_conf nc; - bool ret=true; - - - if ( nb==0 ) { - printf("Usage: netconf set [dhcp yes|no] [ip ] [mask ] [gw ]\n"); - return false; - } - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - return false; - } - - - memset(&nc, 0, sizeof(struct net_conf)); - - for (k=0; k\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 \n"); - return false; - } - - i=ngadmin_setPassword(nga, com[0]); - printErrCode(i); - - - return true; - -} - - - -// ============================================================================= // ports +bool do_ports_state (int nb, const char **com, struct ngadmin *nga); +bool do_ports_statistics_reset (int nb, const char **com, struct ngadmin *nga); +bool do_ports_statistics_show (int nb, const char **com, struct ngadmin *nga); -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; iports; 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_statistics_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_statistics_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\tCRC errors\n"); - for (i=0; iports; ++i) { - printf("% 4i%12llu%12llu%14llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc); - } - - end: - free(ps); - - - return ret; - -} - - - - -// ============================================================================= // qos +bool do_qos_mode (int nb, const char **com, struct ngadmin *nga); +bool do_qos_set (int nb, const char **com, struct ngadmin *nga); +bool do_qos_show (int nb, const char **com, struct ngadmin *nga); - -static bool do_qos_mode (int nb, const char **com, struct ngadmin *nga) { - - int i, s, ret=true; - const struct swi_attr *sa; - - - if ( nb==0 ) { - printf("Usage: qos mode port|802.1p\n"); - goto end; - } - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - - if ( strcasecmp(com[0], "port")==0 ) { - s=QOS_PORT; - } else if ( strcasecmp(com[0], "802.1p")==0 ) { - s=QOS_DOT; - } else { - printf("Unknown QOS mode\n"); - ret=false; - goto end; - } - - - i=ngadmin_setQOSMode(nga, s); - printErrCode(i); - - - end: - - return ret; - -} - - - -static bool do_qos_set (int nb, const char **com, struct ngadmin *nga) { - - int i, p; - const struct swi_attr *sa; - bool ret=true; - char d=PRIO_UNSPEC, *ports=NULL; - - - if ( nb<2 ) { - printf("Usage: qos set (all )|( [ ...])\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(char)); - - if ( strcmp(com[0], "all")==0 ) { - d=parsePrio(com[1]); - com+=2; - nb-=2; - } - - for (i=0; iports; ++i) { - ports[i]=d; - } - - for (i=0; isa->ports ) continue; - ports[p-1]=parsePrio(com[i+1]); - } - - - i=ngadmin_setQOSValues(nga, ports); - printErrCode(i); - - - end: - free(ports); - - return ret; - -} - - - -static bool do_qos_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { - - int i, s=0, ret=true; - const struct swi_attr *sa; - char *ports=NULL; - - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - if ( (i=ngadmin_getQOSMode(nga, &s))!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - - printf("QOS mode: "); - - if ( s==QOS_DOT ) { - printf("802.1p\n"); - goto end; - } else if ( s!=QOS_PORT ) { - printf("unknown (%i)\n", s); - goto end; - } - - printf("port based\n"); - - ports=malloc(sa->ports*sizeof(char)); - - if ( (i=ngadmin_getQOSValues(nga, ports))!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - for (i=0; iports; ++i) { - printf("port %i: %s\n", i+1, prio[(int)ports[i]]); - } - - - end: - free(ports); - - return ret; - -} - - - -// ============================================================================= // quit +bool do_quit (int nb, const char **com, struct ngadmin *nga); -static bool do_quit (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { - - cont=0; - - return true; - -} - - - -// ============================================================================= // restart +bool do_restart (int nb, const char **com, struct ngadmin *nga); -static bool do_restart (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { - - int i, ret=true; - const struct swi_attr *sa; - char line[16]; - - - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - - printf("The switch will be restarted. Continue ? [y/N]: "); - fflush(stdout); - - if ( fgets(line, sizeof(line), stdin)!=NULL && strcasecmp(line, "y\n")==0 ) { - i=ngadmin_restart(nga); - printErrCode(i); - } - - - end: - - return ret; - -} - - - -// ============================================================================= // scan +bool do_scan (int nb, const char **com, struct ngadmin *nga); -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; - -} - - - -// ============================================================================= // stormfilter +bool do_stormfilter_enable (int nb, const char **com, struct ngadmin *nga); +bool do_stormfilter_disable (int nb, const char **com, struct ngadmin *nga); +bool do_stormfilter_set (int nb, const char **com, struct ngadmin *nga); +bool do_stormfilter_show (int nb, const char **com, struct ngadmin *nga); -static bool do_stormfilter_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_stormfilter_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_stormfilter_set (int nb, const char **com, struct ngadmin *nga) { - - int i, d=BITRATE_UNSPEC, p, *ports=NULL; - const struct swi_attr *sa; - bool ret=true; - - - if ( nb<2 ) { - printf("Usage: stormfilt set (all )|( [ ...])\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)); - - if ( strcmp(com[0], "all")==0 ) { - d=parseBitrate(com[1]); - com+=2; - nb-=2; - } - - for (i=0; iports; ++i) { - ports[i]=d; - } - - for (i=0; isa->ports ) continue; - ports[p-1]=parseBitrate(com[i+1]); - } - - - i=ngadmin_setStormFilterValues(nga, ports); - printErrCode(i); - - - end: - free(ports); - - return ret; - -} - - - -static bool do_stormfilter_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; iports; ++i) { - printf("port %i: %s\n", i+1, bitrates[ports[i]]); - } - - end: - free(ports); - - return ret; - -} - - - -// ============================================================================= // tree +bool do_tree (int nb, const char **com, struct ngadmin *nga); -static void display_node (const struct TreeNode *tn, int depth) { - - int i; - const struct TreeNode *s; - - - for (i=0; iname); - - if ( tn->sub==NULL ) return; - - for (s=tn->sub; s->name!=NULL; ++s) { - display_node(s, depth+1); - } - - -} - - -static bool do_tree (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) { - - - display_node(&coms, 0); - - - return true; - -} - - - -// ============================================================================= // vlan +bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga); +bool do_vlan_mode_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga); +bool do_vlan_pvid_show (int nb, const char **com, struct ngadmin *nga); -static char vlan_char (int t) { - - switch ( t ) { - case VLAN_TAGGED: return 'T'; - case VLAN_UNTAGGED: return 'U'; - case VLAN_NO: return ' '; - default: return '?'; - } - -} - - -static bool print_vlan_pvid (struct ngadmin *nga) { - - unsigned short *ports=NULL; - const struct swi_attr *sa; - int i; - bool ret=true; - - - sa=ngadmin_getCurrentSwitch(nga); - - ports=malloc(sa->ports*sizeof(unsigned short)); - i=ngadmin_getPVID(nga, ports); - if ( i!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - - printf("PVID: \n"); - printf("Port\t"); - for (i=1; i<=sa->ports; ++i) { - printf("%i\t", i); - } - putchar('\n'); - - printf("VLAN\t"); - for (i=0; iports; ++i) { - printf("%u\t", ports[i]); - } - putchar('\n'); - - - end: - free(ports); - - return ret; - -} - - -static bool print_vlan_dot_adv (struct ngadmin *nga) { - - char buffer[512], *b=buffer; - const struct swi_attr *sa; - int i, t; - - - sa=ngadmin_getCurrentSwitch(nga); - - t=sizeof(buffer); - i=ngadmin_getVLANDotConf(nga, buffer, &t); - if ( i!=ERR_OK ) { - printErrCode(i); - return false; - } - - printf("Ports configuration: \n"); - printf("VLAN\t"); - for (i=1; i<=sa->ports; ++i) { - printf("%i\t", i); - } - putchar('\n'); - - while ( b-bufferports; ++i) { - printf("%c\t", vlan_char(*b++)); - } - putchar('\n'); - } - - - return true; - -} - - -static bool do_vlan_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) { - - int i, t, ret=true; - - - if ( ngadmin_getCurrentSwitch(nga)==NULL ) { - printf("must be logged\n"); - ret=false; - goto end; - } - - if ( (i=ngadmin_getVLANType(nga, &t))!=ERR_OK ) { - printErrCode(i); - ret=false; - goto end; - } - - - printf("VLAN type: "); - switch ( t ) { - case VLAN_DISABLED: printf("disabled\n"); break; - case VLAN_PORT_BASIC: printf("port basic\n"); break; - case VLAN_PORT_ADV: printf("port advanced\n"); break; - case VLAN_DOT_BASIC: printf("802.1Q basic\n"); break; - - case VLAN_DOT_ADV: - printf("802.1Q advanced\n\n"); - ret=print_vlan_dot_adv(nga); - putchar('\n'); - ret=print_vlan_pvid(nga); - break; - - default: printf("unknown (%i)\n", t); - } - - - - end: - - return ret; - -} - - - -// ============================================================================= - +// commands structure COM_ROOT_START(coms) COM_START(bitrate) @@ -1443,8 +175,28 @@ COM_ROOT_START(coms) COM_TERM(tree, do_tree, false) COM_START(vlan) - COM_TERM(show, do_vlan_show, false) - COM_TERM(mode, NULL, true) + COM_START(802.1q) + COM_START(port) + COM_TERM(add, NULL, true) + COM_TERM(del, NULL, true) + COM_END + COM_TERM(show, do_vlan_8021q_show, true) + COM_START(vlan) + COM_TERM(add, NULL, true) + COM_TERM(del, NULL, true) + COM_TERM(flush, NULL, true) + COM_END + COM_END + COM_START(mode) + COM_TERM(set, NULL, true) + COM_TERM(show, do_vlan_mode_show, false) + COM_END + COM_START(port) + COM_END + COM_START(pvid) + COM_TERM(set, NULL, true) + COM_TERM(show, do_vlan_pvid_show, false) + COM_END COM_END COM_ROOT_END diff --git a/lib/ngadmin.h b/lib/ngadmin.h index d7d6702..adaddfe 100644 --- a/lib/ngadmin.h +++ b/lib/ngadmin.h @@ -252,7 +252,11 @@ int ngadmin_getVLANType (struct ngadmin *nga, int *t) EXPORT; // -int ngadmin_getVLANDotConf (struct ngadmin *nga, char *buf, int *len) EXPORT; +int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) EXPORT; + + +// +int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) EXPORT; // diff --git a/lib/src/network.c b/lib/src/network.c index 52837d0..77012ea 100644 --- a/lib/src/network.c +++ b/lib/src/network.c @@ -218,6 +218,24 @@ int recvNgPacket (struct ngadmin *nga, char code, unsigned short *error, unsigne +int checkErrorCode (unsigned short err, unsigned short attr_error) { + + + if ( err==0x0700 && attr_error==ATTR_PASSWORD ) { + return ERR_BADPASS; + } + + if ( err==0x0500 ) { + return ERR_INVARG; + } + + + return ERR_OK; + +} + + + // ---------------------------------------------- int readRequest (struct ngadmin *nga, List *attr) { @@ -243,14 +261,12 @@ int readRequest (struct ngadmin *nga, List *attr) { goto end; } - if ( err==0x0700 && attr_error==ATTR_PASSWORD ) { - ret=ERR_BADPASS; - goto end; - } + // check error code + ret=checkErrorCode(err, attr_error); - end: + end: return ret; @@ -295,12 +311,8 @@ int writeRequest (struct ngadmin *nga, List *attr) { goto end; } - if ( err==0x0700 && attr_error==ATTR_PASSWORD ) { - ret=ERR_BADPASS; - goto end; - } - - // err==0x0500 + // check error code + ret=checkErrorCode(err, attr_error); end: diff --git a/lib/src/ngadmin.c b/lib/src/ngadmin.c index 3393080..f1dee3e 100644 --- a/lib/src/ngadmin.c +++ b/lib/src/ngadmin.c @@ -268,7 +268,10 @@ int ngadmin_login (struct ngadmin *nga, int id) { attr=createEmptyList(); pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password))); - if ( (ret=readRequest(nga, attr))!=ERR_OK ) { + if ( (ret=readRequest(nga, attr))==ERR_OK ) { + // login succeeded + // TODO: if keep broadcasting is disabled, connect() the UDP socket so icmp errors messages (port unreachable, TTL exceeded in transit, ...)can be received + } else { // login failed nga->current=NULL; } @@ -959,7 +962,7 @@ int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) { ATTR_IGMP_BLOCK_UNK ATTR_IGMP_VALID_V3 - Apparently, read-querying theses attributes at the same time causes the switch to reply garbage. + Apparently, read-querying these attributes at the same time causes the switch to reply garbage. Here we are forced to do like the official win app and send a separate request for each attribute. */ @@ -1211,26 +1214,26 @@ int ngadmin_getVLANType (struct ngadmin *nga, int *t) { -// ------------------------------------------------------------------ -int ngadmin_getVLANDotConf (struct ngadmin *nga, char *buf, int *len) { +// ------------------------------------------------------------------------------------------------------ +int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) { List *attr; ListNode *ln; struct attr *at; struct swi_attr *sa; int ret=ERR_OK, total, i; - char *b=buf, *p=NULL; + char *p=NULL; - if ( nga==NULL || buf==NULL || len==NULL || *len<=0 ) { + if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) { return ERR_INVARG; } else if ( (sa=nga->current)==NULL ) { return ERR_NOTLOG; } - total=*len; - *len=0; + total=*nb; + *nb=0; attr=createEmptyList(); pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF)); @@ -1242,15 +1245,65 @@ int ngadmin_getVLANDotConf (struct ngadmin *nga, char *buf, int *len) { for (ln=attr->first; ln!=NULL; ln=ln->next) { at=ln->data; p=at->data; - if ( *len+2+sa->ports>total ) break; // no more room + if ( *nb>=sa->ports ) break; // no more room if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) { - *(unsigned short*)b=ntohs(*(unsigned short*)p);b+=2; for (i=1; i<=sa->ports; ++i) { - if ( (p[3]>>(sa->ports-i))&1 ) *b++=VLAN_TAGGED; // tagged - else if ( (p[2]>>(sa->ports-i))&1 ) *b++=VLAN_UNTAGGED; // untagged - else *b++=VLAN_NO; + if ( (p[3]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_TAGGED; // tagged + else if ( (p[2]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_UNTAGGED; // untagged + else ports[i-1]=VLAN_NO; } - *len+=2+sa->ports; + *vlans++=ntohs(*(unsigned short*)p); + ports+=sa->ports; + ++*nb; + } + } + + + end: + destroyList(attr, (void(*)(void*))freeAttr); + + return ret; + +} + + + +// ---------------------------------------------------------------------------------------- +int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) { + + List *attr; + ListNode *ln; + struct attr *at; + struct swi_attr *sa; + int ret=ERR_OK, i; + char *p=NULL; + + + if ( nga==NULL || ports==NULL ) { + return ERR_INVARG; + } else if ( (sa=nga->current)==NULL ) { + return ERR_NOTLOG; + } + + + + attr=createEmptyList(); + pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan)); + if ( (ret=readRequest(nga, attr))!=ERR_OK ) { + goto end; + } + + + for (ln=attr->first; ln!=NULL; ln=ln->next) { + at=ln->data; + p=at->data; + if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) { + for (i=1; i<=sa->ports; ++i) { + if ( (p[3]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_TAGGED; // tagged + else if ( (p[2]>>(sa->ports-i))&1 ) ports[i-1]=VLAN_UNTAGGED; // untagged + else ports[i-1]=VLAN_NO; + } + break; } } diff --git a/nsdp.lua b/nsdp.lua index 11475ce..bbd3933 100644 --- a/nsdp.lua +++ b/nsdp.lua @@ -1,5 +1,6 @@ p_nsdp=Proto("nsdp", "Netgear Switch Description Protocol") + local f_version=ProtoField.uint8("nsdp.version", "Version", base.DEC) local f_code=ProtoField.uint8("nsdp.code", "Operation Code", base.DEC) local f_error=ProtoField.uint8("nsdp.error", "Error Code", base.DEC) @@ -8,34 +9,14 @@ local f_clientmac=ProtoField.ether("nsdp.clientmac", "Client MAC") local f_switchmac=ProtoField.ether("nsdp.switchmac", "Switch MAC") local f_seqnum=ProtoField.uint32("nsdp.seqnum", "Sequence Number", base.DEC) -local f_attr=ProtoField.uint16("", "Attribute", base.HEX) -local f_attr_code=ProtoField.uint16("", "Attribute Code", base.HEX) -local f_attr_length=ProtoField.uint16("", "Attribute Length", base.DEC) -local f_attr_data=ProtoField.bytes("", "Attribute Data") - -local f_attr_product=ProtoField.string("", "Product") -local f_attr_name=ProtoField.string("", "Name") -local f_attr_mac=ProtoField.ether("", "MAC") -local f_attr_ip=ProtoField.ipv4("", "IP") -local f_attr_mask=ProtoField.ipv4("", "Mask") -local f_attr_gateway=ProtoField.ipv4("", "Gateway") -local f_attr_newpassword=ProtoField.string("", "New Password") -local f_attr_password=ProtoField.string("", "Password") -local f_attr_dhcp=ProtoField.bool("", "DHCP") -local f_attr_firmver=ProtoField.string("", "Firmare Version") -local f_attr_portscount=ProtoField.uint8("", "Ports Count", base.DEC) -local f_attr_port=ProtoField.uint8("", "Port", base.DEC) -local f_attr_port_status=ProtoField.uint8("", "Port Status", base.DEC) - p_nsdp.fields={ - f_version, f_code, f_error, f_errattr, f_clientmac, f_switchmac, f_seqnum, - f_attr, f_attr_code, f_attr_length, f_attr_data, - f_attr_product, f_attr_name, f_attr_mac, f_attr_ip, f_attr_mask, f_attr_gateway, f_attr_newpassword, f_attr_password, f_attr_portscount, - f_attr_dhcp, f_attr_port, f_attr_port_status, f_attr_firmver + f_version, f_code, f_error, f_errattr, f_clientmac, f_switchmac, f_seqnum } + + local op_codes={ [1]="Read Request", [2]="Read Reply", @@ -58,40 +39,179 @@ local status_codes={ } +local bitrates_codes={ + [0]="unlimited", + [1]="512K", + [2]="1M", + [3]="2M", + [4]="4M", + [5]="8M", + [6]="16M", + [7]="32M", + [8]="64M", + [9]="128M", + [10]="256M", + [11]="512M" +} + + +local vlan_type_codes={ + [1]="port basic", + [2]="port advanced", + [3]="802.1Q basic", + [4]="802.1Q advanced" +} + + +local qos_type_codes={ + [1]="port based", + [2]="802.1p" +} + + +local prio_codes={ + [1]="high", + [2]="medium", + [3]="normal", + [4]="low" +} + + +local function dissect_port_statistics (buffer, offset, subtree) + + subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint())) + subtree:add(buffer(offset+4+1+8*0, 8), "Received:", tostring(buffer(offset+4+1+8*0, 8):uint64())) + subtree:add(buffer(offset+4+1+8*1, 8), "Sent: ", tostring(buffer(offset+4+1+8*1, 8):uint64())) + subtree:add(buffer(offset+4+1+8*5, 8), "CRC Errors:", tostring(buffer(offset+4+1+8*5, 8):uint64())) + +end + -function dissect_port_status (buffer, offset, subtree) + +local function dissect_port_status (buffer, offset, subtree) - subtree:add(f_attr_port, buffer(offset+4, 1)) - subtree:add(f_attr_port_status, buffer(offset+5, 1)):append_text(" ("..(status_codes[buffer(offset+5, 1):uint()] or "unk")..")") + local st=buffer(offset+5, 1):uint() + subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint())) + subtree:add(buffer(offset+5, 1), string.format("Status: %i (%s)", st, status_codes[st] or "unk")) end +local function dissect_bitrate (buffer, offset, subtree) + + local sp=buffer(offset+5, 4):uint() + subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint())) + subtree:add(buffer(offset+5, 4), string.format("Speed: %i (%s)", sp, bitrates_codes[sp] or "unk")) + +end + + +local function dissect_vlan_type (buffer, offset, subtree) + + local vt=buffer(offset+4, 1):uint() + subtree:add(buffer(offset+4, 1), string.format("VLAN Type: %i (%s)", vt, vlan_type_codes[vt] or "unk")) + +end + + +local function parse_ports (val) + + local ports="" + + for i=8,1,-1 do + if ( val%2==1 ) then + ports=ports..i.." " + end + val=math.floor(val/2) + end + + return ports + +end + + +local function dissect_vlan_8021q_conf (buffer, offset, subtree) + + subtree:add(buffer(offset+4, 2), string.format("VLAN: %u", buffer(offset+4, 2):uint())) + + if ( buffer(offset+2, 2):uint()>=4 ) then + subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint())) + subtree:add(buffer(offset+7, 1), "Tagged Ports:", parse_ports(buffer(offset+7, 1):uint())) + end + +end + + +local function dissect_vlan_pvid (buffer, offset, subtree) + + subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint())) + subtree:add(buffer(offset+5, 2), string.format("VLAN: %u", buffer(offset+5, 2):uint())) + +end + + + +local function dissect_mirror (buffer, offset, subtree) + + local op=buffer(offset+4, 1):uint() + + if ( op==0 ) then + subtree:add(buffer(offset+4, 1), "Disabled") + else + subtree:add(buffer(offset+4, 1), "Output Port:", op) + subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint())) + end + +end + local attributes={ - [0x0001]={name="Product", dissect=f_attr_product}, - [0x0003]={name="Name", dissect=f_attr_name}, - [0x0004]={name="MAC", dissect=f_attr_mac}, - [0x0006]={name="IP", dissect=f_attr_ip}, - [0x0007]={name="Mask", dissect=f_attr_mask}, - [0x0008]={name="Gateway", dissect=f_attr_gateway}, - [0x0009]={name="New Password", dissect=f_attr_newpassword}, - [0x000A]={name="Password", dissect=f_attr_password}, - [0x000B]={name="DHCP", dissect=f_attr_dhcp}, - [0x000D]={name="Firmware Version", dissect=f_attr_firmver}, + [0x0001]={name="Product", dissect="string"}, + [0x0003]={name="Name", dissect="string"}, + [0x0004]={name="MAC", dissect="ether"}, + [0x0006]={name="IP", dissect="ipv4"}, + [0x0007]={name="Mask", dissect="ipv4"}, + [0x0008]={name="Gateway", dissect="ipv4"}, + [0x0009]={name="New Password", dissect="string"}, + [0x000A]={name="Password", dissect="string"}, + [0x000B]={name="DHCP", dissect="uint"}, + [0x000D]={name="Firmware Version", dissect="string"}, + [0x0013]={name="Restart", dissect="uint"}, + [0x0400]={name="Defaults", dissect="uint"}, [0x0C00]={name="Port Status", dissect=dissect_port_status}, - [0x6000]={name="Ports Count", dissect=f_attr_portscount} + [0x1000]={name="Port Statistics", dissect=dissect_port_statistics}, + [0x1400]={name="Reset Ports Statistics", dissect="uint"}, + [0x1800]={name="Cabletest Do", dissect=nil}, + [0x1C00]={name="Cabletest Result", dissect=nil}, + [0x2000]={name="VLAN Type", dissect=dissect_vlan_type}, + [0x2400]={name="VLAN Port Conf", dissect=nil}, + [0x2800]={name="VLAN 802.1Q Conf", dissect=dissect_vlan_8021q_conf}, + [0x2C00]={name="Destroy VLAN", dissect="uint"}, + [0x3000]={name="VLAN PVID", dissect=dissect_vlan_pvid}, + [0x3400]={name="QoS Type", dissect=nil}, + [0x3800]={name="QoS Config", dissect=nil}, + [0x4C00]={name="Input Bitrate", dissect=dissect_bitrate}, + [0x5000]={name="Output Bitrate", dissect=dissect_bitrate}, + [0x5400]={name="Broadcast Filtering State", dissect="uint"}, + [0x5800]={name="Broadcast Filtering Bitrate", dissect=dissect_bitrate}, + [0x5C00]={name="Mirror", dissect=dissect_mirror}, + [0x6000]={name="Ports Count", dissect="uint"}, + [0x6800]={name="IGMP Enable & VLAN", dissect=nil}, + [0x6C00]={name="Block Unknown IGMP Addresses", dissect="uint"}, + [0x7000]={name="Validate IGMPv3 Headers", dissect="uint"}, + [0xFFFF]={name="End", dissect=nil} } -function dissect_header (buffer, subtree) + +local function dissect_header (buffer, subtree) subtree:add(f_version, buffer(0, 1)) @@ -100,7 +220,7 @@ function dissect_header (buffer, subtree) local errcode=buffer(2, 1):uint() subtree:add(f_error, buffer(2, 1)):append_text(" ("..(error_codes[errcode] or "unknown")..")") - -- print the erroneous attribute if an error occurred + -- add the erroneous attribute only if an error occurred if ( errcode~=0 ) then local atf=attributes[buffer(4, 2):uint()] subtree:add(f_errattr, buffer(4, 2)):append_text(" ("..(atf and atf.name or "unk")..")") @@ -117,34 +237,46 @@ end -function dissect_attributes (buffer, subtree) +local function dissect_attributes (buffer, subtree) local offset=32 while ( offsetbuffer:len() ) then + -- no room for an attribute header, it is an error + subtree:add(buffer(offset), "Junk"):set_expert_flags(PI_MALFORMED, PI_ERROR) + break + end + local code=buffer(offset, 2):uint() local len=buffer(offset+2, 2):uint() local atf=attributes[code] - local attr=subtree:add(f_attr, buffer(offset, 4+len), code) - attr:append_text(" ("..(atf and atf.name or "unk")..")") + local attr=subtree:add(buffer(offset, math.min(4+len, buffer:len()-offset)), string.format("Attribute: 0x%04X (%s)", code, atf and atf.name or "unk")) + attr:add(buffer(offset, 2), string.format("Code: 0x%04X", code)) + attr:add(buffer(offset+2, 2), string.format("Length: %u", len)) - attr:add(f_attr_code, buffer(offset, 2)) + if ( offset+4+len>buffer:len() ) then + -- attribute length is bigger than remaining packet size, it is an error + attr:append_text(" [malformed]") + attr:set_expert_flags(PI_MALFORMED, PI_ERROR) + break + end - attr:add(f_attr_length, buffer(offset+2, 2)) if ( len<=0 ) then -- no data, display nothing - elseif ( atf==nil ) then + elseif ( atf==nil or atf.dissect==nil ) then -- unknown attribute, display raw bytes - attr:add(f_attr_data, buffer(offset+4, len)) + attr:add(buffer(offset+4, len), "Data:", tostring(buffer(offset+4, len):bytes())) elseif ( type(atf.dissect)=="function" ) then -- custom sub-dissector for complex type atf.dissect(buffer, offset, attr) else - -- simple type, directly use field - attr:add(atf.dissect, buffer(offset+4, len)) + -- simple type, directly show it + local func=assert(loadstring("return function(buffer, offset, len) return tostring(buffer(offset+4, len):"..atf.dissect.."()) end"))() -- ugly, isn't it ? + attr:add(buffer(offset+4, len), atf.name..":", func(buffer, offset, len)) end offset=offset+4+len @@ -166,7 +298,7 @@ function p_nsdp.dissector (buffer, pinfo, tree) dissect_header(buffer, subtree) -- stop if it is just a header - if ( buffer:len()<=32 ) then return end + if ( buffer:len()==32 ) then return end local attr_list=subtree:add(buffer(32), "Attributes list") dissect_attributes(buffer, attr_list) -- 2.39.5