From ec60646f6fd599919745940f85d25b1c9e156ed7 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Sat, 3 Dec 2011 12:00:00 +0100 Subject: [PATCH] Added support for creating and deleting a 802.1q VLAN. CLI: vlan category commands changed. Lib: added checks to include the header in C++ code. Lib: fixed an issue with switches with 5 ports. Lib: added checks of requested VLAN values. Lib: added possibility to specify only changing VLANs. Dissector: added support for few request types. --- cli/com_vlan.c | 149 ++++++++++++++++++++++++++++++++++++++++++---- cli/commands.c | 19 +++--- lib/ngadmin.h | 13 ++++ lib/src/lib.h | 1 + lib/src/ngadmin.c | 84 +++++++++++++++++++------- nsdp.lua | 54 +++++++++++++++-- 6 files changed, 271 insertions(+), 49 deletions(-) diff --git a/cli/com_vlan.c b/cli/com_vlan.c index 813bc18..9f9331b 100644 --- a/cli/com_vlan.c +++ b/cli/com_vlan.c @@ -17,6 +17,128 @@ static char vlan_char (int t) { +bool do_vlan_8021q_del (int nb, const char **com, struct ngadmin *nga) { + + const struct swi_attr *sa; + unsigned short vlan; + int i; + + + if ( nb!=1 ) { + printf("Usage: vlan 8021q del \n"); + return false; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + return false; + } + + vlan=strtoul(com[0], NULL, 0); + + if ( vlan<1 || vlan>VLAN_MAX ) { + printf("vlan out of range\n"); + return false; + } + + + i=ngadmin_VLANDestroy(nga, vlan); + printErrCode(i); + + + return true; + +} + + + +bool do_vlan_8021q_set (int nb, const char **com, struct ngadmin *nga) { + + unsigned char *ports=NULL, p, def=VLAN_UNSPEC; + const struct swi_attr *sa; + bool ret=true; + unsigned short vlan; + int i, k=0; + + + if ( nb==0 ) { + printf("Usage: vlan 802.1q set [all unspec|no|untagged|tagged] [ unspec|no|untagged|tagged ...]\n"); + ret=false; + goto end; + } + + if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + printf("must be logged\n"); + ret=false; + goto end; + } + + // read vlan + vlan=strtoul(com[k++], NULL, 0); + + if ( vlan<1 || vlan>VLAN_MAX ) { + printf("vlan out of range\n"); + ret=false; + goto end; + } + + + // read defaults + if ( kports*sizeof(unsigned char)); + + // apply defaults + memset(ports, def, sa->ports); + + // apply port specifics + while ( k=sa->ports ) { + printf("port out of range\n"); + ret=false; + goto end; + } + if ( strcasecmp(com[k], "tagged")==0 ) ports[p]=VLAN_TAGGED; + else if ( strcasecmp(com[k], "untagged")==0 ) ports[p]=VLAN_UNTAGGED; + else if ( strcasecmp(com[k], "no")==0 ) ports[p]=VLAN_NO; + else if ( strcasecmp(com[k], "unspec")==0 ) ports[p]=VLAN_UNSPEC; + else { + printf("incorrect type\n"); + ret=false; + goto end; + } + ++k; + } + + + // set conf + i=ngadmin_setVLANDotConf(nga, vlan, ports); + printErrCode(i); + + + end: + free(ports); + + + return ret; + +} + + + bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga) { unsigned short vl=0, *vlans=NULL; @@ -94,32 +216,35 @@ bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga) { -bool do_vlan_8021q_vlan_del (int nb, const char **com, struct ngadmin *nga) { +bool do_vlan_mode_set (int nb, const char **com, struct ngadmin *nga) { - const struct swi_attr *sa; - unsigned short vlan; - int i; + int mode, i; - if ( nb!=1 ) { - printf("Usage: vlan 8021q vlan del \n"); - return false; + if ( nb==0 ) { + printf("Usage: vlan mode set \n"); + printf("1 - basic port based\n"); + printf("2 - advanced port based\n"); + printf("3 - basic 802.1Q\n"); + printf("4 - advanced 802.1Q\n"); + return true; } - if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) { + if ( ngadmin_getCurrentSwitch(nga)==NULL ) { printf("must be logged\n"); return false; } - vlan=strtoul(com[0], NULL, 0); - if ( vlan<1 || vlan>VLAN_MAX ) { - printf("vlan out of range\n"); + mode=strtoul(com[0], NULL, 0); + + if ( mode<1 || mode>4 ) { + printf("mode out of range\n"); return false; } - i=ngadmin_VLANDestroy(nga, vlan); + i=ngadmin_setVLANType(nga, mode); printErrCode(i); diff --git a/cli/commands.c b/cli/commands.c index 552d18e..2d5e9cc 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -92,8 +92,10 @@ bool do_tree (int nb, const char **com, struct ngadmin *nga); // vlan +bool do_vlan_8021q_del (int nb, const char **com, struct ngadmin *nga); +bool do_vlan_8021q_set (int nb, const char **com, struct ngadmin *nga); bool do_vlan_8021q_show (int nb, const char **com, struct ngadmin *nga); -bool do_vlan_8021q_vlan_del (int nb, const char **com, struct ngadmin *nga); +bool do_vlan_mode_set (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_set (int nb, const char **com, struct ngadmin *nga); bool do_vlan_pvid_show (int nb, const char **com, struct ngadmin *nga); @@ -178,22 +180,17 @@ COM_ROOT_START(coms) COM_START(vlan) COM_START(802.1q) - COM_START(port) - COM_TERM(add, NULL, true) - COM_TERM(del, NULL, true) - COM_END + COM_TERM(del, do_vlan_8021q_del, true) + COM_TERM(set, do_vlan_8021q_set, true) COM_TERM(show, do_vlan_8021q_show, true) - COM_START(vlan) - COM_TERM(add, NULL, true) - COM_TERM(del, do_vlan_8021q_vlan_del, true) - COM_TERM(flush, NULL, true) - COM_END COM_END COM_START(mode) - COM_TERM(set, NULL, true) + COM_TERM(set, do_vlan_mode_set, true) COM_TERM(show, do_vlan_mode_show, false) COM_END COM_START(port) + COM_TERM(set, NULL, true) + COM_TERM(show, NULL, false) COM_END COM_START(pvid) COM_TERM(set, do_vlan_pvid_set, true) diff --git a/lib/ngadmin.h b/lib/ngadmin.h index 9edcfe5..0ee138d 100644 --- a/lib/ngadmin.h +++ b/lib/ngadmin.h @@ -41,6 +41,7 @@ #define VLAN_DOT_BASIC 3 #define VLAN_DOT_ADV 4 +#define VLAN_UNSPEC 0xFF #define VLAN_NO 0 #define VLAN_UNTAGGED 1 #define VLAN_TAGGED 2 @@ -118,9 +119,15 @@ struct cabletest { +#ifdef __cplusplus +extern "C" { +#endif + + // initialize NgAdmin lib struct ngadmin* ngadmin_init (const char *iface) EXPORT; + // int ngadmin_close (struct ngadmin *nga) EXPORT; @@ -282,5 +289,11 @@ int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vla +#ifdef __cplusplus +} +#endif + + + #endif diff --git a/lib/src/lib.h b/lib/src/lib.h index 3d47a89..3d499b3 100644 --- a/lib/src/lib.h +++ b/lib/src/lib.h @@ -41,6 +41,7 @@ #define ATTR_FIRM_VER 0x000D #define ATTR_UNK_000E 0x000E #define ATTR_UNK_000F 0x000F +#define ATTR_FIRM_UPGRADE 0x0010 #define ATTR_RESTART 0x0013 #define ATTR_DEFAULTS 0x0400 #define ATTR_PORT_STATUS 0x0C00 diff --git a/lib/src/ngadmin.c b/lib/src/ngadmin.c index 8248345..72e2bd3 100644 --- a/lib/src/ngadmin.c +++ b/lib/src/ngadmin.c @@ -884,7 +884,7 @@ int ngadmin_getMirror (struct ngadmin *nga, char *ports) { if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) { ports[0]=p[0]; for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8 - ports[i]=(p[2]>>(sa->ports-i))&1; + ports[i]=(p[2]>>(8-i))&1; } break; } @@ -924,7 +924,7 @@ int ngadmin_setMirror (struct ngadmin *nga, const char *ports) { p[0]=ports[0]; for (i=1; i<=sa->ports; ++i) { if ( i!=p[0] ) { - p[2]|=(ports[i]&1)<<(sa->ports-i); + p[2]|=(ports[i]&1)<<(8-i); } } } @@ -1274,10 +1274,10 @@ int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsig p=at->data; if ( *nb>=sa->ports ) break; // no more room 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; + for (i=0; iports; ++i) { + if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged + else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged + else ports[i]=VLAN_NO; } *vlans++=ntohs(*(unsigned short*)p); ports+=sa->ports; @@ -1306,14 +1306,13 @@ int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned c char *p=NULL; - if ( nga==NULL || ports==NULL ) { + if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || 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 ) { @@ -1325,10 +1324,10 @@ int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned c 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; + for (i=0; iports; ++i) { + if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged + else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged + else ports[i]=VLAN_NO; } break; } @@ -1347,40 +1346,81 @@ int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned c // ---------------------------------------------------------------------------------------------- int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) { - List *attr; + List *attr=NULL; + ListNode *ln; + struct attr *at; struct swi_attr *sa; int i; char *p; + int ret=ERR_OK; - if ( nga==NULL || ports==NULL || vlan<1 || vlan>VLAN_MAX ) { + if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) { return ERR_INVARG; } else if ( (sa=nga->current)==NULL ) { return ERR_NOTLOG; } + // if nothing is to be changed, do nothing + for (i=0; iports && ports[i]==VLAN_UNSPEC; ++i); + if ( i==sa->ports ) goto end; + attr=createEmptyList(); + p=malloc(4); *(unsigned short*)p=htons(vlan); + *(unsigned short*)&p[2]=0; + + // if all is to be changed, we do not need to read old config + if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) { + + 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; + if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) { + *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2); + break; + } + } + + clearList(attr, (void(*)(void*))freeAttr); + + } - for (i=1; i<=sa->ports; ++i) { - if ( ports[i-1]==VLAN_TAGGED ) { // tagged - p[3]|=(1<<(sa->ports-i)); - } else if ( ports[i-1]==VLAN_UNTAGGED ) { // untagged - p[2]|=(1<<(sa->ports-i)); + + // apply changes + for (i=0; iports; ++i) { + if ( ports[i]==VLAN_NO ) { + p[2]&=~(1<<(7-i)); + p[3]&=~(1<<(7-i)); + } else if ( ports[i]==VLAN_UNTAGGED ) { + p[2]|=(1<<(7-i)); + p[3]&=~(1<<(7-i)); + } else if ( ports[i]==VLAN_TAGGED ) { + p[2]|=(1<<(7-i)); + p[3]|=(1<<(7-i)); } } - // tagged ports must be also present in untagged ports - p[2]|=ports[3]; pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p)); + ret=writeRequest(nga, attr); + attr=NULL; - return writeRequest(nga, attr); + end: + destroyList(attr, (void(*)(void*))freeAttr); + + return ret; + } diff --git a/nsdp.lua b/nsdp.lua index bbd3933..30b28d2 100644 --- a/nsdp.lua +++ b/nsdp.lua @@ -100,6 +100,25 @@ end +local function dissect_qos_type (buffer, offset, subtree) + + local t=buffer(offset+4, 1):uint() + subtree:add(buffer(offset+4, 1), string.format("QoS Type: %i (%s)", t, qos_type_codes[t] or "unk")) + +end + + + +local function dissect_qos_config (buffer, offset, subtree) + + local p=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("Priority: %i (%s)", p, prio_codes[p] or "unk")) + +end + + + local function dissect_bitrate (buffer, offset, subtree) local sp=buffer(offset+5, 4):uint() @@ -109,6 +128,7 @@ local function dissect_bitrate (buffer, offset, subtree) end + local function dissect_vlan_type (buffer, offset, subtree) local vt=buffer(offset+4, 1):uint() @@ -117,6 +137,7 @@ local function dissect_vlan_type (buffer, offset, subtree) end + local function parse_ports (val) local ports="" @@ -133,6 +154,19 @@ local function parse_ports (val) end + +local function dissect_vlan_port_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()>=3 ) then + subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint())) + end + +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())) @@ -145,6 +179,7 @@ local function dissect_vlan_8021q_conf (buffer, offset, subtree) end + local function dissect_vlan_pvid (buffer, offset, subtree) subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint())) @@ -169,6 +204,16 @@ end +local function dissect_igmp_enablevlan (buffer, offset, subtree) + + subtree:add(buffer(offset+4, 2), string.format("Enable: %u", buffer(offset+4, 2):uint())) + subtree:add(buffer(offset+6, 2), string.format("VLAN: %u", buffer(offset+6, 2):uint())) + +end + + + + local attributes={ [0x0001]={name="Product", dissect="string"}, [0x0003]={name="Name", dissect="string"}, @@ -180,6 +225,7 @@ local attributes={ [0x000A]={name="Password", dissect="string"}, [0x000B]={name="DHCP", dissect="uint"}, [0x000D]={name="Firmware Version", dissect="string"}, + [0x0010]={name="Firmware Upgrade", dissect="uint"}, [0x0013]={name="Restart", dissect="uint"}, [0x0400]={name="Defaults", dissect="uint"}, [0x0C00]={name="Port Status", dissect=dissect_port_status}, @@ -188,19 +234,19 @@ local attributes={ [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}, + [0x2400]={name="VLAN Port Conf", dissect=dissect_vlan_port_conf}, [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}, + [0x3400]={name="QoS Type", dissect=dissect_qos_type}, + [0x3800]={name="QoS Config", dissect=dissect_qos_config}, [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}, + [0x6800]={name="IGMP Enable & VLAN", dissect=dissect_igmp_enablevlan}, [0x6C00]={name="Block Unknown IGMP Addresses", dissect="uint"}, [0x7000]={name="Validate IGMPv3 Headers", dissect="uint"}, [0xFFFF]={name="End", dissect=nil} -- 2.39.2