]> git.sur5r.net Git - ngadmin/commitdiff
Split lib code into several files
authordarkcoven <admin@darkcoven.tk>
Sun, 22 Sep 2013 11:25:45 +0000 (13:25 +0200)
committerdarkcoven <admin@darkcoven.tk>
Sun, 22 Sep 2013 11:25:45 +0000 (13:25 +0200)
lib/src/bitrate.c [new file with mode: 0644]
lib/src/firmware.c [new file with mode: 0644]
lib/src/libconf.c [new file with mode: 0644]
lib/src/mirror.c [new file with mode: 0644]
lib/src/misc.c [new file with mode: 0644]
lib/src/netconf.c [new file with mode: 0644]
lib/src/ngadmin.c [deleted file]
lib/src/ports.c [new file with mode: 0644]
lib/src/qos.c [new file with mode: 0644]
lib/src/session.c [new file with mode: 0644]
lib/src/vlan.c [new file with mode: 0644]

diff --git a/lib/src/bitrate.c b/lib/src/bitrate.c
new file mode 100644 (file)
index 0000000..f9fa11d
--- /dev/null
@@ -0,0 +1,215 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || s == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_STORM_ENABLE, ATTR_END);
+       
+       *s = 0;
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               *s = *(char*)at->data;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
+{
+       List *attr;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK, port;
+       struct attr_bitrate *sb;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_STORM_BITRATE, ATTR_END);
+       
+       for (port = 0; port < nga->current->ports; port++)
+               ports[port] = BITRATE_UNSPEC;
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               sb = at->data;
+               ports[sb->port - 1] = sb->bitrate;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
+{
+       List *attr;
+       int port;
+       struct attr_bitrate *sb;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       
+       for (port = 0; port < nga->current->ports; port++) {
+               if (ports[port] != BITRATE_UNSPEC) {
+                       sb = malloc(sizeof(struct attr_bitrate));
+                       if (sb == NULL)
+                               return ERR_MEM;
+                       sb->port = port + 1;
+                       sb->bitrate = ports[port];
+                       pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
+               }
+       }
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK, port;
+       struct attr_bitrate *pb;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
+       pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       
+       for (port = 0; port < nga->current->ports; port++) {
+               ports[2 * port + 0] = BITRATE_UNSPEC;
+               ports[2 * port + 1] = BITRATE_UNSPEC;
+       }
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               pb = at->data;
+               if (at->attr == ATTR_BITRATE_INPUT)
+                       ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
+               else if (at->attr == ATTR_BITRATE_OUTPUT)
+                       ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       return ret;
+}
+
+
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
+{
+       List *attr;
+       int port;
+       struct attr_bitrate *pb;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       
+       for (port = 0; port < nga->current->ports; port++) {
+               if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
+                       pb = malloc(sizeof(struct attr_bitrate));
+                       if (pb == NULL)
+                               return ERR_MEM;
+                       pb->port = port + 1;
+                       pb->bitrate = ports[2 * port + 0];
+                       pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
+               }
+               if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
+                       pb = malloc(sizeof(struct attr_bitrate));
+                       if (pb == NULL)
+                               return ERR_MEM;
+                       pb->port = port + 1;
+                       pb->bitrate = ports[2 * port + 1];
+                       pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
+               }
+       }
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
diff --git a/lib/src/firmware.c b/lib/src/firmware.c
new file mode 100644 (file)
index 0000000..351678b
--- /dev/null
@@ -0,0 +1,28 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
+{
+       if (nga == NULL || filename == NULL || *filename == 0)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       /*
+       Firmware upgrade is not yet implemented. 
+       This would require much more work and the use of a TFTP client. 
+       Overall, it could be quite dangerous, as the switch may not check the binary 
+       content sent to it. 
+       */
+       
+       return ERR_NOTIMPL;
+}
+
+
diff --git a/lib/src/libconf.c b/lib/src/libconf.c
new file mode 100644 (file)
index 0000000..e26a722
--- /dev/null
@@ -0,0 +1,112 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
+
+
+struct ngadmin* ngadmin_init (const char *iface)
+{
+       struct ngadmin *nga;
+       
+       
+       /* allocate main structure */
+       nga = malloc(sizeof(struct ngadmin));
+       memset(nga, 0, sizeof(struct ngadmin));
+       
+       strncpy(nga->iface, iface, IFNAMSIZ - 1);
+       
+       if (startNetwork(nga) < 0) {
+               free(nga);
+               return NULL;
+       }
+       
+       nga->timeout = default_timeout;
+       if (updateTimeout(nga) < 0) {
+               free(nga);
+               return NULL;
+       }
+       
+       
+       return nga;
+}
+
+
+int ngadmin_close (struct ngadmin *nga)
+{
+       if (nga == NULL)
+               return ERR_INVARG;
+               
+       stopNetwork(nga);
+       free(nga->swi_tab);
+       free(nga);
+       
+       return ERR_OK;
+}
+
+
+int ngadmin_forceInterface (struct ngadmin *nga)
+{
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       return forceInterface(nga) == 0 ? ERR_OK : ERR_NET;
+}
+
+
+int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value)
+{
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       nga->keepbroad = value;
+       
+       return ERR_OK;
+}
+
+
+int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value)
+{
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       nga->globalbroad = value;
+       
+       return ERR_OK;
+}
+
+
+int ngadmin_setPassword (struct ngadmin *nga, const char *pass)
+{
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       strncpy(nga->password, pass, PASSWORD_MAX);
+       
+       return ERR_OK;
+}
+
+
+int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv)
+{
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || tv == NULL)
+               return ERR_INVARG;
+       
+       nga->timeout = *tv;
+       if (updateTimeout(nga) < 0)
+               ret = ERR_NET;
+       
+       
+       return ret;
+}
+
+
diff --git a/lib/src/mirror.c b/lib/src/mirror.c
new file mode 100644 (file)
index 0000000..7fe51cb
--- /dev/null
@@ -0,0 +1,78 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getMirror (struct ngadmin *nga, char *ports)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
+       ret = readRequest(nga, attr);
+       if (ret < 0)
+               goto end;
+       
+       filterAttributes(attr, ATTR_MIRROR, ATTR_END);
+       
+       memset(ports, 0, 1 + nga->current->ports);
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               memcpy(ports, at->data, 1 + nga->current->ports);
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
+{
+       List *attr;
+       char *p;
+       struct swi_attr *sa;
+       
+       
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       p = malloc(1 + sa->ports);
+       if (p == NULL)
+               return ERR_MEM;
+       
+       if (ports == NULL)
+               memset(p, 0, 1 + sa->ports);
+       else
+               memcpy(p, ports, 1 + sa->ports);
+       
+       attr = createEmptyList();
+       pushBackList(attr, newAttr(ATTR_MIRROR, 1 + sa->ports, p));
+       
+       
+       return writeRequest(nga, attr);
+}
+
diff --git a/lib/src/misc.c b/lib/src/misc.c
new file mode 100644 (file)
index 0000000..4da6812
--- /dev/null
@@ -0,0 +1,115 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_setName (struct ngadmin *nga, const char *name)
+{
+       List *attr;
+       struct attr *at;
+       struct swi_attr *sa;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       if (name == NULL)
+               at = newEmptyAttr(ATTR_NAME);
+       else
+               at = newAttr(ATTR_NAME, strlen(name), strdup(name));
+       pushBackList(attr, at);
+       ret = writeRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+        
+       /* successful, also update local name */
+       if (name == NULL)
+               memset(sa->name, '\0', NAME_SIZE);
+       else
+               strncpy(sa->name, name, NAME_SIZE);
+       
+end:
+       return ret;
+}
+
+
+int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || pass == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       at = newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass));
+       if (nga->encrypt_pass)
+               passwordEndecode(at->data, at->size);
+       pushBackList(attr, at);
+       ret = writeRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       /* successful, also update local password */
+       strncpy(nga->password, pass, PASSWORD_MAX);
+       
+end:
+       
+       return ret;
+}
+
+
+int ngadmin_restart (struct ngadmin *nga)
+{
+       List *attr;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_defaults (struct ngadmin *nga)
+{
+       List *attr;
+       int ret = ERR_OK;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
+       ret = writeRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       
+       /* successful: delog and clean list */
+       free(nga->swi_tab);
+       nga->swi_tab = NULL;
+       nga->swi_count = 0;
+       nga->current = NULL;
+       
+end:
+       return ret;
+}
+
+
diff --git a/lib/src/netconf.c b/lib/src/netconf.c
new file mode 100644 (file)
index 0000000..0a804b7
--- /dev/null
@@ -0,0 +1,172 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct attr_igmp_vlan *aiv;
+       
+       
+       if (nga == NULL || ic == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       /*
+       ATTR_IGMP_ENABLE_VLAN
+       ATTR_IGMP_BLOCK_UNK
+       ATTR_IGMP_VALID_V3
+       
+       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. 
+       */
+       
+       
+       attr = createEmptyList();
+       memset(ic, 0, sizeof(struct igmp_conf));
+       
+       
+       pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
+       ret = readRequest(nga, attr);
+       if (ret < 0)
+               goto end;
+       
+       filterAttributes(attr, ATTR_IGMP_ENABLE_VLAN, ATTR_END);
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               aiv = at->data;
+               ic->enable = aiv->enable;
+               ic->vlan = aiv->vlan;
+       }
+       
+       clearList(attr, (void(*)(void*))freeAttr);
+       
+       
+       pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
+       ret = readRequest(nga, attr);
+       if (ret < 0)
+               goto end;
+       
+       filterAttributes(attr, ATTR_IGMP_BLOCK_UNK, ATTR_END);
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               ic->block = *(char*)at->data;
+       }
+       
+       clearList(attr, (void(*)(void*))freeAttr);
+       
+       
+       pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
+       ret = readRequest(nga, attr);
+       if (ret < 0)
+               goto end;
+       
+       filterAttributes(attr, ATTR_IGMP_VALID_V3, ATTR_END);
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               ic->validate = *(char*)at->data;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
+{
+       List *attr;
+       struct attr_igmp_vlan *aiv;
+       
+       
+       if (nga == NULL || ic == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       aiv = malloc(sizeof(struct attr_igmp_vlan));
+       if (aiv == NULL)
+               return ERR_MEM;
+       aiv->enable = ic->enable;
+       aiv->vlan = ic->vlan;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
+       pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
+       pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
+{
+       List *attr;
+       int ret = ERR_OK;
+       struct swi_attr *sa;
+       
+       
+       if (nga == NULL || nc == NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       
+       if (nc->dhcp) {
+               pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
+       } else {
+               pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
+               /* only add non-null values */
+               if (nc->ip.s_addr != 0)
+                       pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
+               if (nc->netmask.s_addr != 0)
+                       pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
+               if (nc->gw.s_addr != 0)
+                       pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
+       }
+       
+       ret = writeRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       
+       /* update local values */
+       sa->nc.dhcp = nc->dhcp;
+       if (!nc->dhcp) {
+               if (nc->ip.s_addr !=0)
+                       sa->nc.ip = nc->ip;
+               if (nc->netmask.s_addr != 0)
+                       sa->nc.netmask = nc->netmask;
+               if (nc->gw.s_addr != 0)
+                       sa->nc.gw = nc->gw;
+       }
+       
+       
+end:
+       
+       return ret;
+}
+
+
diff --git a/lib/src/ngadmin.c b/lib/src/ngadmin.c
deleted file mode 100644 (file)
index fa09829..0000000
+++ /dev/null
@@ -1,1530 +0,0 @@
-
-#include <errno.h>
-
-#include <ngadmin.h>
-
-#include <attr.h>
-#include <protocol.h>
-
-#include "lib.h"
-#include "network.h"
-
-
-static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
-
-
-
-struct ngadmin* ngadmin_init (const char *iface)
-{
-       struct ngadmin *nga;
-       
-       
-       /* allocate main structure */
-       nga = malloc(sizeof(struct ngadmin));
-       memset(nga, 0, sizeof(struct ngadmin));
-       
-       strncpy(nga->iface, iface, IFNAMSIZ - 1);
-       
-       if (startNetwork(nga) < 0) {
-               free(nga);
-               return NULL;
-       }
-       
-       nga->timeout = default_timeout;
-       if (updateTimeout(nga) < 0) {
-               free(nga);
-               return NULL;
-       }
-       
-       
-       return nga;
-}
-
-
-int ngadmin_close (struct ngadmin *nga)
-{
-       if (nga == NULL)
-               return ERR_INVARG;
-               
-       stopNetwork(nga);
-       free(nga->swi_tab);
-       free(nga);
-       
-       return ERR_OK;
-}
-
-
-int ngadmin_forceInterface (struct ngadmin *nga)
-{
-       if (nga == NULL)
-               return ERR_INVARG;
-       
-       return forceInterface(nga) == 0 ? ERR_OK : ERR_NET;
-}
-
-
-int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value)
-{
-       if (nga == NULL)
-               return ERR_INVARG;
-       
-       nga->keepbroad = value;
-       
-       return ERR_OK;
-}
-
-
-int ngadmin_useGlobalBroadcast (struct ngadmin *nga, bool value)
-{
-       if (nga == NULL)
-               return ERR_INVARG;
-       
-       nga->globalbroad = value;
-       
-       return ERR_OK;
-}
-
-
-int ngadmin_setPassword (struct ngadmin *nga, const char *pass)
-{
-       if (nga == NULL)
-               return ERR_INVARG;
-       
-       strncpy(nga->password, pass, PASSWORD_MAX);
-       
-       return ERR_OK;
-}
-
-
-int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv)
-{
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || tv == NULL)
-               return ERR_INVARG;
-       
-       nga->timeout = *tv;
-       if (updateTimeout(nga) < 0)
-               ret = ERR_NET;
-       
-       
-       return ret;
-}
-
-
-int ngadmin_scan (struct ngadmin *nga)
-{
-       int i;
-       List *attr, *swiList;
-       struct swi_attr *sa;
-       /*
-       sent by official win client:
-       ATTR_PRODUCT,
-       ATTR_UNK2,
-       ATTR_NAME,
-       ATTR_MAC,
-       ATTR_UNK5,
-       ATTR_IP,
-       ATTR_NETMASK,
-       ATTR_GATEWAY,
-       ATTR_DHCP,
-       ATTR_UNK12,
-       ATTR_FIRM_VER,
-       ATTR_UNK14,
-       ATTR_UNK15,
-       ATTR_END
-       */
-       static const unsigned short hello[] = {
-               ATTR_PRODUCT,
-               ATTR_NAME,
-               ATTR_MAC,
-               ATTR_IP,
-               ATTR_NETMASK,
-               ATTR_GATEWAY,
-               ATTR_DHCP,
-               ATTR_FIRM_VER,
-               ATTR_PORTS_COUNT,
-               ATTR_END
-       };
-       
-       
-       if (nga == NULL)
-               return ERR_INVARG;
-       
-       free(nga->swi_tab);
-       nga->swi_tab = NULL;
-       nga->swi_count = 0;
-       nga->current = NULL;
-       
-       
-       /* create attributes for an "hello" request */
-       attr = createEmptyList();
-       for (i = 0; ; i++) {
-               pushBackList(attr, newEmptyAttr(hello[i]));
-               if (hello[i] == ATTR_END)
-                       break;
-       }
-       
-       /* send request to all potential switches */
-       i = sendNgPacket(nga, CODE_READ_REQ, attr);
-       clearList(attr, (void(*)(void*))freeAttr);
-       if (i == -EINVAL)
-               return ERR_INVARG;
-       else if (i < 0)
-               return ERR_NET;
-       
-       /* try to receive any packets until timeout */
-       swiList = createEmptyList();
-       /* FIXME: end after timeout whatever received packet is good or not */
-       while (recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr) >= 0) {
-               sa = malloc(sizeof(struct swi_attr));
-               if (sa == NULL)
-                       return ERR_MEM;
-               extractSwitchAttributes(sa, attr);
-               clearList(attr, (void(*)(void*))freeAttr);
-               pushBackList(swiList, sa);
-       }
-       
-       nga->swi_count = swiList->count;
-       nga->swi_tab = convertToArray(swiList, sizeof(struct swi_attr));
-       destroyList(swiList, free);
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ERR_OK;
-}
-
-
-const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
-{
-       if (nga == NULL || nb == NULL)
-               return NULL;
-       
-       *nb = nga->swi_count;
-       
-       return nga->swi_tab;
-}
-
-
-const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
-{
-       if (nga == NULL)
-               return NULL;
-       
-       return nga->current;
-}
-
-
-int ngadmin_login (struct ngadmin *nga, int id)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct swi_attr *sa;
-       
-       
-       if (nga == NULL)
-               return ERR_INVARG;
-       else if (id < 0 || id >= nga->swi_count)
-               return ERR_BADID;
-       
-       sa = &nga->swi_tab[id];
-       nga->current = sa;
-       nga->encrypt_pass = false;
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
-       }
-       clearList(attr, (void(*)(void*))freeAttr);
-       
-       /* Strangely, passwords must never be encrypted inside a read request,
-        * or it will be rejected. Seems more to be a firmware bug. */
-       pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
-       ret = readRequest(nga, attr);
-       if (ret == 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;
-       }
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_upgradeFirmware (struct ngadmin *nga, const char *filename)
-{
-       if (nga == NULL || filename == NULL || *filename == 0)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       /*
-       Firmware upgrade is not yet implemented. 
-       This would require much more work and the use of a TFTP client. 
-       Overall, it could be quite dangerous, as the switch may not check the binary 
-       content sent to it. 
-       */
-       
-       return ERR_NOTIMPL;
-}
-
-
-int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct attr_port_status *ps;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_PORT_STATUS, ATTR_END);
-       
-       memset(ports, SPEED_UNK, nga->current->ports);
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               ps = at->data;
-               ports[ps->port - 1] = ps->status;
-       }
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setName (struct ngadmin *nga, const char *name)
-{
-       List *attr;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, name == NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
-       ret = writeRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-        
-       /* successful, also update local name */
-       if (name == NULL)
-               memset(nga->current->name, '\0', NAME_SIZE);
-       else
-               strncpy(nga->current->name, name, NAME_SIZE);
-       
-end:
-       return ret;
-}
-
-
-int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct attr_port_stat *aps;
-       
-       
-       if (nga == NULL || ps == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_PORT_STATISTICS, ATTR_END);
-       
-       memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               aps = at->data;
-               ps[aps->port -1].recv = aps->recv;
-               ps[aps->port -1].sent = aps->sent;
-               ps[aps->port -1].crc = aps->crc;
-       }
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_resetPortsStatistics (struct ngadmin *nga)
-{
-       List *attr;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || pass == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       at = newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass));
-       if (nga->encrypt_pass)
-               passwordEndecode(at->data, at->size);
-       pushBackList(attr, at);
-       ret = writeRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       
-       /* successful, also update local password */
-       strncpy(nga->password, pass, PASSWORD_MAX);
-       
-end:
-       
-       return ret;
-}
-
-
-int ngadmin_getStormFilterState (struct ngadmin *nga, int *s)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || s == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_STORM_ENABLE, ATTR_END);
-       
-       *s = 0;
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               *s = *(char*)at->data;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setStormFilterState (struct ngadmin *nga, int s)
-{
-       List *attr;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s != 0));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK, port;
-       struct attr_bitrate *sb;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_STORM_BITRATE, ATTR_END);
-       
-       for (port = 0; port < nga->current->ports; port++)
-               ports[port] = BITRATE_UNSPEC;
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               sb = at->data;
-               ports[sb->port - 1] = sb->bitrate;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports)
-{
-       List *attr;
-       int port;
-       struct attr_bitrate *sb;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       
-       for (port = 0; port < nga->current->ports; port++) {
-               if (ports[port] != BITRATE_UNSPEC) {
-                       sb = malloc(sizeof(struct attr_bitrate));
-                       if (sb == NULL)
-                               return ERR_MEM;
-                       sb->port = port + 1;
-                       sb->bitrate = ports[port];
-                       pushBackList(attr, newAttr(ATTR_STORM_BITRATE, sizeof(struct attr_bitrate), sb));
-               }
-       }
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK, port;
-       struct attr_bitrate *pb;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
-       pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       
-       for (port = 0; port < nga->current->ports; port++) {
-               ports[2 * port + 0] = BITRATE_UNSPEC;
-               ports[2 * port + 1] = BITRATE_UNSPEC;
-       }
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               pb = at->data;
-               if (at->attr == ATTR_BITRATE_INPUT)
-                       ports[(pb->port - 1) * 2 + 0] = pb->bitrate;
-               else if (at->attr == ATTR_BITRATE_OUTPUT)
-                       ports[(pb->port - 1) * 2 + 1] = pb->bitrate;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       return ret;
-}
-
-
-int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports)
-{
-       List *attr;
-       int port;
-       struct attr_bitrate *pb;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       
-       for (port = 0; port < nga->current->ports; port++) {
-               if (ports[2 * port + 0] >= BITRATE_NOLIMIT && ports[2 * port + 0] <= BITRATE_512M) {
-                       pb = malloc(sizeof(struct attr_bitrate));
-                       if (pb == NULL)
-                               return ERR_MEM;
-                       pb->port = port + 1;
-                       pb->bitrate = ports[2 * port + 0];
-                       pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, sizeof(struct attr_bitrate), pb));
-               }
-               if (ports[2 * port + 1] >= BITRATE_NOLIMIT && ports[2 * port + 1] <= BITRATE_512M) {
-                       pb = malloc(sizeof(struct attr_bitrate));
-                       if (pb == NULL)
-                               return ERR_MEM;
-                       pb->port = port + 1;
-                       pb->bitrate = ports[2 * port + 1];
-                       pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, sizeof(struct attr_bitrate), pb));
-               }
-       }
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || s == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_QOS_TYPE, ATTR_END);
-       
-       *s = 0;
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               *s = *(char*)at->data;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setQOSMode (struct ngadmin *nga, int s)
-{
-       List *attr;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK, port;
-       struct attr_qos *aq;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
-       ret = readRequest(nga, attr);
-       if (ret < 0)
-               goto end;
-       
-       filterAttributes(attr, ATTR_QOS_CONFIG, ATTR_END);
-       
-       for (port = 0; port < nga->current->ports; port++)
-               ports[port] = PRIO_UNSPEC;
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               aq = at->data;
-               ports[aq->port - 1] = aq->prio;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
-{
-       List *attr;
-       int port;
-       struct attr_qos *aq;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       
-       for (port = 0; port < nga->current->ports; port++) {
-               if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
-                       aq = malloc(sizeof(struct attr_qos));
-                       if (aq == NULL)
-                               return ERR_MEM;
-                       aq->port = port + 1;
-                       aq->prio = ports[port];
-                       pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
-               }
-       }
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_restart (struct ngadmin *nga)
-{
-       List *attr;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_defaults (struct ngadmin *nga)
-{
-       List *attr;
-       int ret = ERR_OK;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
-       ret = writeRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       
-       /* successful: delog and clean list */
-       free(nga->swi_tab);
-       nga->swi_tab = NULL;
-       nga->swi_count = 0;
-       nga->current = NULL;
-       
-end:
-       return ret;
-}
-
-
-int ngadmin_getMirror (struct ngadmin *nga, char *ports)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
-       ret = readRequest(nga, attr);
-       if (ret < 0)
-               goto end;
-       
-       filterAttributes(attr, ATTR_MIRROR, ATTR_END);
-       
-       memset(ports, 0, 1 + nga->current->ports);
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               memcpy(ports, at->data, 1 + nga->current->ports);
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setMirror (struct ngadmin *nga, const char *ports)
-{
-       List *attr;
-       char *p;
-       
-       
-       if (nga == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       p = malloc(1 + nga->current->ports);
-       if (p == NULL)
-               return ERR_MEM;
-       
-       if (ports == NULL)
-               memset(p, 0, 1 + nga->current->ports);
-       else
-               memcpy(p, ports, 1 + nga->current->ports);
-       
-       attr = createEmptyList();
-       pushBackList(attr, newAttr(ATTR_MIRROR, 1 + nga->current->ports, p));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct attr_igmp_vlan *aiv;
-       
-       
-       if (nga == NULL || ic == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       /*
-       ATTR_IGMP_ENABLE_VLAN
-       ATTR_IGMP_BLOCK_UNK
-       ATTR_IGMP_VALID_V3
-       
-       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. 
-       */
-       
-       
-       attr = createEmptyList();
-       memset(ic, 0, sizeof(struct igmp_conf));
-       
-       
-       pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
-       ret = readRequest(nga, attr);
-       if (ret < 0)
-               goto end;
-       
-       filterAttributes(attr, ATTR_IGMP_ENABLE_VLAN, ATTR_END);
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               aiv = at->data;
-               ic->enable = aiv->enable;
-               ic->vlan = aiv->vlan;
-       }
-       
-       clearList(attr, (void(*)(void*))freeAttr);
-       
-       
-       pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
-       ret = readRequest(nga, attr);
-       if (ret < 0)
-               goto end;
-       
-       filterAttributes(attr, ATTR_IGMP_BLOCK_UNK, ATTR_END);
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               ic->block = *(char*)at->data;
-       }
-       
-       clearList(attr, (void(*)(void*))freeAttr);
-       
-       
-       pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
-       ret = readRequest(nga, attr);
-       if (ret < 0)
-               goto end;
-       
-       filterAttributes(attr, ATTR_IGMP_VALID_V3, ATTR_END);
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               ic->validate = *(char*)at->data;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic)
-{
-       List *attr;
-       struct attr_igmp_vlan *aiv;
-       
-       
-       if (nga == NULL || ic == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       aiv = malloc(sizeof(struct attr_igmp_vlan));
-       if (aiv == NULL)
-               return ERR_MEM;
-       aiv->enable = ic->enable;
-       aiv->vlan = ic->vlan;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, sizeof(struct attr_igmp_vlan), aiv));
-       pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block != false));
-       pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate != false));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK, i;
-       struct attr_cabletest_do *acd;
-       struct attr_cabletest_result *acr;
-       
-       
-       if (nga == NULL || ct == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       
-       for (i = 0; i < nb; i++) {
-               
-               acd = malloc(sizeof(struct attr_cabletest_do));
-               if (acd == NULL)
-                       return ERR_MEM;
-               acd->port = ct[i].port;
-               acd->action = 1;
-               pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
-               
-               ret = writeRequest(nga, attr);
-               attr = NULL;
-               if (ret < 0)
-                       goto end;
-               
-               /* the list is destroyed by writeRequest, so we need to recreate it */
-               attr = createEmptyList();
-               pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
-               ret = readRequest(nga, attr);
-               if (ret < 0)
-                       goto end;
-               
-               filterAttributes(attr, ATTR_CABLETEST_RESULT, ATTR_END);
-               
-               for (ln = attr->first; ln != NULL; ln = ln->next) {
-                       at = ln->data;
-                       acr = at->data;
-                       if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
-                               ct[i].v1 = acr->v1;
-                               ct[i].v2 = acr->v2;
-                               break;
-                       }
-               }
-               
-               /* just empty the list, it will be used at next iteration */
-               clearList(attr, (void(*)(void*))freeAttr);
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc)
-{
-       List *attr;
-       int ret = ERR_OK;
-       struct swi_attr *sa;
-       
-       
-       if (nga == NULL || nc == NULL)
-               return ERR_INVARG;
-       
-       sa = nga->current;
-       if (sa == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       
-       if (nc->dhcp) {
-               pushBackList(attr, newShortAttr(ATTR_DHCP, 1));
-       } else {
-               pushBackList(attr, newShortAttr(ATTR_DHCP, 0));
-               /* only add non-null values */
-               if (nc->ip.s_addr != 0)
-                       pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
-               if (nc->netmask.s_addr != 0)
-                       pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
-               if (nc->gw.s_addr != 0)
-                       pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
-       }
-       
-       ret = writeRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       
-       /* update local values */
-       sa->nc.dhcp = nc->dhcp;
-       if (!nc->dhcp) {
-               if (nc->ip.s_addr !=0)
-                       sa->nc.ip = nc->ip;
-               if (nc->netmask.s_addr != 0)
-                       sa->nc.netmask = nc->netmask;
-               if (nc->gw.s_addr != 0)
-                       sa->nc.gw = nc->gw;
-       }
-       
-       
-end:
-       
-       return ret;
-}
-
-
-int ngadmin_getVLANType (struct ngadmin *nga, int *t)
-{
-       List *attr;
-       struct attr *at;
-       int ret = ERR_OK;
-       
-       
-       if (nga == NULL || t == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
-       ret=readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_VLAN_TYPE, ATTR_END);
-       
-       *t = VLAN_DISABLED;
-       
-       if (attr->first != NULL) {
-               at = attr->first->data;
-               *t =(int)*(char*)at->data;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setVLANType (struct ngadmin *nga, int t)
-{
-       List *attr;
-       
-       
-       if (nga == NULL || t < 1 || t > 4)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getVLANPortConf (struct ngadmin *nga, unsigned char *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct attr_vlan_conf *avc;
-       struct swi_attr *sa;
-       int port;
-       
-       
-       if (nga == NULL || ports== NULL)
-               return ERR_INVARG;
-       
-       sa = nga->current;
-       if (sa == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
-       
-       memset(ports, 0, sa->ports);
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               avc = at->data;
-
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
-                       return ERR_INVARG;
-               
-               for (port = 0; port < sa->ports; port++) {
-                       if (avc->ports[port] == VLAN_UNTAGGED)
-                               ports[port] = avc->vlan;
-               }
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
-{
-       List *attr = NULL;
-       ListNode *ln;
-       struct attr *at;
-       struct swi_attr *sa;
-       struct attr_vlan_conf *avc;
-       int ret = ERR_OK, port;
-       unsigned char vlan;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       
-       sa = nga->current;
-       if (sa == NULL)
-               return ERR_NOTLOG;
-       
-       /* if nothing is to be changed, do nothing */
-       for (port = 0; port < sa->ports && ports[port] == 0; port++);
-       if (port == sa->ports )
-               goto end;
-       
-       attr = createEmptyList();
-
-       if (memchr(ports, 0, sa->ports) != NULL) {
-               /* if at least one port is unchanged, we need to read old config */
-               pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
-               ret = readRequest(nga, attr);
-               if (ret != ERR_OK)
-                       goto end;
-               
-               filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
-               /* FIXME: check if the returned array effectively contains correct data */
-       } else {
-               /* create an empty VLAN config */
-               for (vlan = VLAN_MIN; vlan <= VLAN_PORT_MAX; vlan++) {
-                       avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
-                       avc->vlan = vlan;
-                       memset(avc->ports, 0, sa->ports);
-                       pushBackList(attr, newAttr(ATTR_VLAN_PORT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
-               }
-       }
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               avc = at->data;
-               for (port = 0; port < sa->ports; port++) {
-                       if (ports[port] == avc->vlan)
-                               avc->ports[port] = VLAN_UNTAGGED;
-                       else
-                               avc->ports[port] = VLAN_NO;
-               }
-       }
-       
-       ret = writeRequest(nga, attr);
-       attr = NULL;
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK, total;
-       struct attr_vlan_conf *avc;
-       struct swi_attr *sa;
-       
-       
-       if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
-               return ERR_INVARG;
-       
-       sa = nga->current;
-       if (sa == NULL)
-               return ERR_NOTLOG;
-       
-       
-       total = *nb;
-       *nb = 0;
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
-       
-       memset(vlans, 0, total * sizeof(unsigned short));
-       memset(ports, 0, total * sa->ports);
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               avc = at->data;
-               
-               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
-                       return ERR_INVARG;
-               
-               *vlans = avc->vlan;
-               memcpy(ports, avc->ports, sa->ports);
-               
-               vlans++;
-               ports += sa->ports;
-               (*nb)++;
-               
-               if (*nb > total)
-                       break; /* no more room */
-       }
-       
-       
-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;
-       int ret = ERR_OK;
-       struct attr_vlan_conf *avc;
-       
-       
-       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
-       
-       memset(ports, 0, nga->current->ports);
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               avc = at->data;
-               if (avc->vlan == vlan) {
-                       memcpy(ports, avc->ports, nga->current->ports);
-                       break;
-               }
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
-{
-       List *attr = NULL;
-       struct attr *at;
-       struct swi_attr *sa;
-       struct attr_vlan_conf *avc;
-       int ret = ERR_OK, port;
-       
-       
-       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
-               return ERR_INVARG;
-       
-       sa = nga->current;
-       if (sa == NULL)
-               return ERR_NOTLOG;
-       
-       
-       /* if nothing is to be changed, do nothing */
-       for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
-       if (port == sa->ports )
-               goto end;
-       
-       
-       attr = createEmptyList();
-       avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
-       if (avc == NULL)
-               return ERR_MEM;
-       
-       avc->vlan = vlan;
-       
-       /* if all is to be changed, we do not need to read old config */
-       if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
-               
-               pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
-               ret = readRequest(nga, attr);
-               if (ret != ERR_OK)
-                       goto end;
-               
-               filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
-               
-               if (attr->first != NULL) {
-                       at = attr->first->data;
-                       memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
-               }
-               
-               clearList(attr, (void(*)(void*))freeAttr);
-       }
-       
-       
-       /* apply changes */
-       for (port = 0; port < sa->ports; port++) {
-               if (ports[port] != VLAN_UNSPEC)
-                       avc->ports[port] = ports[port];
-       }
-       
-       
-       pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
-       ret = writeRequest(nga, attr);
-       attr = NULL;
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
-{
-       List *attr;
-       
-       
-       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
-{
-       List *attr;
-       ListNode *ln;
-       struct attr *at;
-       int ret = ERR_OK;
-       struct attr_pvid *ap;
-       
-       
-       if (nga == NULL || ports == NULL)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       
-       
-       attr = createEmptyList();
-       pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
-       ret = readRequest(nga, attr);
-       if (ret != ERR_OK)
-               goto end;
-       
-       filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
-       
-       memset(ports, 0, nga->current->ports * sizeof(unsigned short));
-       
-       for (ln = attr->first; ln != NULL; ln = ln->next) {
-               at = ln->data;
-               ap = at->data;
-               ports[ap->port - 1] = ap->vlan;
-       }
-       
-       
-end:
-       destroyList(attr, (void(*)(void*))freeAttr);
-       
-       
-       return ret;
-}
-
-
-int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
-{
-       List *attr;
-       struct attr_pvid *ap;
-       
-       
-       if (nga == NULL || port < 1 || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
-               return ERR_INVARG;
-       else if (nga->current == NULL)
-               return ERR_NOTLOG;
-       else if (port > nga->current->ports)
-               return ERR_INVARG;
-       
-       
-       attr = createEmptyList();
-       ap = malloc(sizeof(struct attr_pvid));
-       if (ap == NULL)
-               return ERR_MEM;
-       ap->port = port;
-       ap->vlan = vlan;
-       
-       pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
-       
-       
-       return writeRequest(nga, attr);
-}
-
-
-
diff --git a/lib/src/ports.c b/lib/src/ports.c
new file mode 100644 (file)
index 0000000..25ce18d
--- /dev/null
@@ -0,0 +1,168 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct attr_port_status *ps;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_PORT_STATUS, ATTR_END);
+       
+       memset(ports, SPEED_UNK, nga->current->ports);
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               ps = at->data;
+               ports[ps->port - 1] = ps->status;
+       }
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+
+int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct attr_port_stat *aps;
+       
+       
+       if (nga == NULL || ps == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_PORT_STATISTICS, ATTR_END);
+       
+       memset(ps, 0, nga->current->ports * sizeof(struct port_stats));
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               aps = at->data;
+               ps[aps->port -1].recv = aps->recv;
+               ps[aps->port -1].sent = aps->sent;
+               ps[aps->port -1].crc = aps->crc;
+       }
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_resetPortsStatistics (struct ngadmin *nga)
+{
+       List *attr;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+
+int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK, i;
+       struct attr_cabletest_do *acd;
+       struct attr_cabletest_result *acr;
+       
+       
+       if (nga == NULL || ct == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       
+       for (i = 0; i < nb; i++) {
+               
+               acd = malloc(sizeof(struct attr_cabletest_do));
+               if (acd == NULL)
+                       return ERR_MEM;
+               acd->port = ct[i].port;
+               acd->action = 1;
+               pushBackList(attr, newAttr(ATTR_CABLETEST_DO, sizeof(struct attr_cabletest_do), acd));
+               
+               ret = writeRequest(nga, attr);
+               attr = NULL;
+               if (ret < 0)
+                       goto end;
+               
+               /* the list is destroyed by writeRequest, so we need to recreate it */
+               attr = createEmptyList();
+               pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
+               ret = readRequest(nga, attr);
+               if (ret < 0)
+                       goto end;
+               
+               filterAttributes(attr, ATTR_CABLETEST_RESULT, ATTR_END);
+               
+               for (ln = attr->first; ln != NULL; ln = ln->next) {
+                       at = ln->data;
+                       acr = at->data;
+                       if (at->size == sizeof(struct attr_cabletest_result) && acr->port == ct[i].port) {
+                               ct[i].v1 = acr->v1;
+                               ct[i].v2 = acr->v2;
+                               break;
+                       }
+               }
+               
+               /* just empty the list, it will be used at next iteration */
+               clearList(attr, (void(*)(void*))freeAttr);
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
diff --git a/lib/src/qos.c b/lib/src/qos.c
new file mode 100644 (file)
index 0000000..cecfaf0
--- /dev/null
@@ -0,0 +1,132 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getQOSMode (struct ngadmin *nga, int *s)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || s == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_QOS_TYPE, ATTR_END);
+       
+       *s = 0;
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               *s = *(char*)at->data;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setQOSMode (struct ngadmin *nga, int s)
+{
+       List *attr;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_getQOSValues (struct ngadmin *nga, char *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK, port;
+       struct attr_qos *aq;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
+       ret = readRequest(nga, attr);
+       if (ret < 0)
+               goto end;
+       
+       filterAttributes(attr, ATTR_QOS_CONFIG, ATTR_END);
+       
+       for (port = 0; port < nga->current->ports; port++)
+               ports[port] = PRIO_UNSPEC;
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               aq = at->data;
+               ports[aq->port - 1] = aq->prio;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports)
+{
+       List *attr;
+       int port;
+       struct attr_qos *aq;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       
+       for (port = 0; port < nga->current->ports; port++) {
+               if (ports[port] >= PRIO_HIGH && ports[port] <= PRIO_LOW) {
+                       aq = malloc(sizeof(struct attr_qos));
+                       if (aq == NULL)
+                               return ERR_MEM;
+                       aq->port = port + 1;
+                       aq->prio = ports[port];
+                       pushBackList(attr, newAttr(ATTR_QOS_CONFIG, sizeof(struct attr_qos), aq));
+               }
+       }
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
diff --git a/lib/src/session.c b/lib/src/session.c
new file mode 100644 (file)
index 0000000..672bbe7
--- /dev/null
@@ -0,0 +1,167 @@
+
+#include <errno.h>
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_scan (struct ngadmin *nga)
+{
+       int i;
+       List *attr, *swiList;
+       struct swi_attr *sa;
+       /*
+       sent by official win client:
+       ATTR_PRODUCT,
+       ATTR_UNK2,
+       ATTR_NAME,
+       ATTR_MAC,
+       ATTR_UNK5,
+       ATTR_IP,
+       ATTR_NETMASK,
+       ATTR_GATEWAY,
+       ATTR_DHCP,
+       ATTR_UNK12,
+       ATTR_FIRM_VER,
+       ATTR_UNK14,
+       ATTR_UNK15,
+       ATTR_END
+       */
+       static const unsigned short hello[] = {
+               ATTR_PRODUCT,
+               ATTR_NAME,
+               ATTR_MAC,
+               ATTR_IP,
+               ATTR_NETMASK,
+               ATTR_GATEWAY,
+               ATTR_DHCP,
+               ATTR_FIRM_VER,
+               ATTR_PORTS_COUNT,
+               ATTR_END
+       };
+       
+       
+       if (nga == NULL)
+               return ERR_INVARG;
+       
+       free(nga->swi_tab);
+       nga->swi_tab = NULL;
+       nga->swi_count = 0;
+       nga->current = NULL;
+       
+       
+       /* create attributes for an "hello" request */
+       attr = createEmptyList();
+       for (i = 0; ; i++) {
+               pushBackList(attr, newEmptyAttr(hello[i]));
+               if (hello[i] == ATTR_END)
+                       break;
+       }
+       
+       /* send request to all potential switches */
+       i = sendNgPacket(nga, CODE_READ_REQ, attr);
+       clearList(attr, (void(*)(void*))freeAttr);
+       if (i == -EINVAL)
+               return ERR_INVARG;
+       else if (i < 0)
+               return ERR_NET;
+       
+       /* try to receive any packets until timeout */
+       swiList = createEmptyList();
+       /* FIXME: end after timeout whatever received packet is good or not */
+       while (recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr) >= 0) {
+               sa = malloc(sizeof(struct swi_attr));
+               if (sa == NULL)
+                       return ERR_MEM;
+               extractSwitchAttributes(sa, attr);
+               clearList(attr, (void(*)(void*))freeAttr);
+               pushBackList(swiList, sa);
+       }
+       
+       nga->swi_count = swiList->count;
+       nga->swi_tab = convertToArray(swiList, sizeof(struct swi_attr));
+       destroyList(swiList, free);
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ERR_OK;
+}
+
+
+const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb)
+{
+       if (nga == NULL || nb == NULL)
+               return NULL;
+       
+       *nb = nga->swi_count;
+       
+       return nga->swi_tab;
+}
+
+
+const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga)
+{
+       if (nga == NULL)
+               return NULL;
+       
+       return nga->current;
+}
+
+
+int ngadmin_login (struct ngadmin *nga, int id)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct swi_attr *sa;
+       
+       
+       if (nga == NULL)
+               return ERR_INVARG;
+       else if (id < 0 || id >= nga->swi_count)
+               return ERR_BADID;
+       
+       sa = &nga->swi_tab[id];
+       nga->current = sa;
+       nga->encrypt_pass = false;
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_ENCPASS));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_ENCPASS, ATTR_END);
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               nga->encrypt_pass = (at->size == 4 && ntohl(*(unsigned int*)at->data) == 1);
+       }
+       clearList(attr, (void(*)(void*))freeAttr);
+       
+       /* Strangely, passwords must never be encrypted inside a read request,
+        * or it will be rejected. Seems more to be a firmware bug. */
+       pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+       ret = readRequest(nga, attr);
+       if (ret == 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;
+       }
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
diff --git a/lib/src/vlan.c b/lib/src/vlan.c
new file mode 100644 (file)
index 0000000..9bd14c6
--- /dev/null
@@ -0,0 +1,442 @@
+
+#include <ngadmin.h>
+
+#include <attr.h>
+#include <protocol.h>
+
+#include "lib.h"
+#include "network.h"
+
+
+int ngadmin_getVLANType (struct ngadmin *nga, int *t)
+{
+       List *attr;
+       struct attr *at;
+       int ret = ERR_OK;
+       
+       
+       if (nga == NULL || t == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
+       ret=readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_VLAN_TYPE, ATTR_END);
+       
+       *t = VLAN_DISABLED;
+       
+       if (attr->first != NULL) {
+               at = attr->first->data;
+               *t =(int)*(char*)at->data;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setVLANType (struct ngadmin *nga, int t)
+{
+       List *attr;
+       
+       
+       if (nga == NULL || t < 1 || t > 4)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_getVLANPortConf (struct ngadmin *nga, unsigned char *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct attr_vlan_conf *avc;
+       struct swi_attr *sa;
+       int port;
+       
+       
+       if (nga == NULL || ports== NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
+       
+       memset(ports, 0, sa->ports);
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               avc = at->data;
+
+               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
+                       return ERR_INVARG;
+               
+               for (port = 0; port < sa->ports; port++) {
+                       if (avc->ports[port] == VLAN_UNTAGGED)
+                               ports[port] = avc->vlan;
+               }
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
+{
+       List *attr = NULL;
+       ListNode *ln;
+       struct attr *at;
+       struct swi_attr *sa;
+       struct attr_vlan_conf *avc;
+       int ret = ERR_OK, port;
+       unsigned char vlan;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       /* if nothing is to be changed, do nothing */
+       for (port = 0; port < sa->ports && ports[port] == 0; port++);
+       if (port == sa->ports )
+               goto end;
+       
+       attr = createEmptyList();
+
+       if (memchr(ports, 0, sa->ports) != NULL) {
+               /* if at least one port is unchanged, we need to read old config */
+               pushBackList(attr, newEmptyAttr(ATTR_VLAN_PORT_CONF));
+               ret = readRequest(nga, attr);
+               if (ret != ERR_OK)
+                       goto end;
+               
+               filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
+               /* FIXME: check if the returned array effectively contains correct data */
+       } else {
+               /* create an empty VLAN config */
+               for (vlan = VLAN_MIN; vlan <= VLAN_PORT_MAX; vlan++) {
+                       avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
+                       avc->vlan = vlan;
+                       memset(avc->ports, 0, sa->ports);
+                       pushBackList(attr, newAttr(ATTR_VLAN_PORT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
+               }
+       }
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               avc = at->data;
+               for (port = 0; port < sa->ports; port++) {
+                       if (ports[port] == avc->vlan)
+                               avc->ports[port] = VLAN_UNTAGGED;
+                       else
+                               avc->ports[port] = VLAN_NO;
+               }
+       }
+       
+       ret = writeRequest(nga, attr);
+       attr = NULL;
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK, total;
+       struct attr_vlan_conf *avc;
+       struct swi_attr *sa;
+       
+       
+       if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       total = *nb;
+       *nb = 0;
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
+       
+       memset(vlans, 0, total * sizeof(unsigned short));
+       memset(ports, 0, total * sa->ports);
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               avc = at->data;
+               
+               if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
+                       return ERR_INVARG;
+               
+               *vlans = avc->vlan;
+               memcpy(ports, avc->ports, sa->ports);
+               
+               vlans++;
+               ports += sa->ports;
+               (*nb)++;
+               
+               if (*nb > total)
+                       break; /* no more room */
+       }
+       
+       
+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;
+       int ret = ERR_OK;
+       struct attr_vlan_conf *avc;
+       
+       
+       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
+       
+       memset(ports, 0, nga->current->ports);
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               avc = at->data;
+               if (avc->vlan == vlan) {
+                       memcpy(ports, avc->ports, nga->current->ports);
+                       break;
+               }
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports)
+{
+       List *attr = NULL;
+       struct attr *at;
+       struct swi_attr *sa;
+       struct attr_vlan_conf *avc;
+       int ret = ERR_OK, port;
+       
+       
+       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
+               return ERR_INVARG;
+       
+       sa = nga->current;
+       if (sa == NULL)
+               return ERR_NOTLOG;
+       
+       
+       /* if nothing is to be changed, do nothing */
+       for (port = 0; port < sa->ports && ports[port] == VLAN_UNSPEC; port++);
+       if (port == sa->ports )
+               goto end;
+       
+       
+       attr = createEmptyList();
+       avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
+       if (avc == NULL)
+               return ERR_MEM;
+       
+       avc->vlan = vlan;
+       
+       /* if all is to be changed, we do not need to read old config */
+       if (memchr(ports, VLAN_UNSPEC, sa->ports) != NULL) {
+               
+               pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+               ret = readRequest(nga, attr);
+               if (ret != ERR_OK)
+                       goto end;
+               
+               filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
+               
+               if (attr->first != NULL) {
+                       at = attr->first->data;
+                       memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
+               }
+               
+               clearList(attr, (void(*)(void*))freeAttr);
+       }
+       
+       
+       /* apply changes */
+       for (port = 0; port < sa->ports; port++) {
+               if (ports[port] != VLAN_UNSPEC)
+                       avc->ports[port] = ports[port];
+       }
+       
+       
+       pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
+       ret = writeRequest(nga, attr);
+       attr = NULL;
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan)
+{
+       List *attr;
+       
+       
+       if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+
+int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports)
+{
+       List *attr;
+       ListNode *ln;
+       struct attr *at;
+       int ret = ERR_OK;
+       struct attr_pvid *ap;
+       
+       
+       if (nga == NULL || ports == NULL)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       
+       
+       attr = createEmptyList();
+       pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
+       ret = readRequest(nga, attr);
+       if (ret != ERR_OK)
+               goto end;
+       
+       filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
+       
+       memset(ports, 0, nga->current->ports * sizeof(unsigned short));
+       
+       for (ln = attr->first; ln != NULL; ln = ln->next) {
+               at = ln->data;
+               ap = at->data;
+               ports[ap->port - 1] = ap->vlan;
+       }
+       
+       
+end:
+       destroyList(attr, (void(*)(void*))freeAttr);
+       
+       
+       return ret;
+}
+
+
+int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan)
+{
+       List *attr;
+       struct attr_pvid *ap;
+       
+       
+       if (nga == NULL || port < 1 || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
+               return ERR_INVARG;
+       else if (nga->current == NULL)
+               return ERR_NOTLOG;
+       else if (port > nga->current->ports)
+               return ERR_INVARG;
+       
+       
+       attr = createEmptyList();
+       ap = malloc(sizeof(struct attr_pvid));
+       if (ap == NULL)
+               return ERR_MEM;
+       ap->port = port;
+       ap->vlan = vlan;
+       
+       pushBackList(attr, newAttr(ATTR_VLAN_PVID, sizeof(struct attr_pvid), ap));
+       
+       
+       return writeRequest(nga, attr);
+}
+
+