]> git.sur5r.net Git - ngadmin/commitdiff
Added support for creating and deleting a 802.1q VLAN.
authordarkcoven <admin@darkcoven.tk>
Sat, 3 Dec 2011 11:00:00 +0000 (12:00 +0100)
committerdarkcoven <admin@darkcoven.tk>
Sat, 29 Dec 2012 21:55:57 +0000 (22:55 +0100)
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
cli/commands.c
lib/ngadmin.h
lib/src/lib.h
lib/src/ngadmin.c
nsdp.lua

index 813bc18f93b80d92c5d1865bc8b5fcaf7f13b99f..9f9331be06792ecda945bfc22bee48522429e612 100644 (file)
@@ -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 <vlan>\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 <vlan> [all unspec|no|untagged|tagged] [<port1> 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 ( k<nb-1 && strcasecmp(com[k], "all")==0 ) {
+  ++k;
+  if ( strcasecmp(com[k], "tagged")==0 ) def=VLAN_TAGGED;
+  else if ( strcasecmp(com[k], "untagged")==0 ) def=VLAN_UNTAGGED;
+  else if ( strcasecmp(com[k], "no")==0 ) def=VLAN_NO;
+  else if ( strcasecmp(com[k], "unspec")==0 ) def=VLAN_UNSPEC;
+  else {
+   printf("incorrect type\n");
+   ret=false;
+   goto end;
+  }
+  ++k;
+ }
+ ports=malloc(sa->ports*sizeof(unsigned char));
+ // apply defaults
+ memset(ports, def, sa->ports);
+ // apply port specifics
+ while ( k<nb-1 ) {
+  p=strtoul(com[k++], NULL, 0)-1;
+  if ( p>=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 <vlan>\n");
-  return false;
+ if ( nb==0 ) {
+  printf("Usage: vlan mode set <mode>\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);
  
  
index 552d18e03b4e9fd8430f9fd30148828e5239c50e..2d5e9cc643e8f58e3fb579d79503ede3be796ccf 100644 (file)
@@ -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)
index 9edcfe5761b83f203517f1c79b8c00efa0e88ada..0ee138ddc1d6513f51dfa3b6bbf190fec424cd46 100644 (file)
@@ -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
 
index 3d47a8942b1ee42456fd16b2881e5e2c026116ce..3d499b3f3e5850830086e3308ec0c0742ac11758 100644 (file)
@@ -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
index 8248345b67612cc2b7e775f77e8795667439be89..72e2bd376fea88f9ba0bea667c463be4bb0a21aa 100644 (file)
@@ -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; i<sa->ports; ++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; i<sa->ports; ++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; i<sa->ports && 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; i<sa->ports; ++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;
  
 }
 
index bbd3933c7252f46b9e74d1389cc25374d2c02208..30b28d2783b23dc9e832c82cd36f656e94fd362d 100644 (file)
--- 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}