#include <ngadmin.h>
+#include <attr.h>
+#include <protocol.h>
+
#include "lib.h"
#include "network.h"
-#include "attr.h"
-#include "protocol.h"
-
static const struct timeval default_timeout = {.tv_sec = 4, .tv_usec = 0};
/* 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, ATTR_END) >= 0) {
+ while (recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr) >= 0) {
sa = malloc(sizeof(struct swi_attr));
if (sa == NULL)
return ERR_MEM;
int ngadmin_login (struct ngadmin *nga, int id)
{
List *attr;
+ struct attr *at;
int ret = ERR_OK;
struct swi_attr *sa;
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, ATTR_END);
+ ret = readRequest(nga, attr);
if (ret == ERR_OK ) {
/* login succeeded */
/* TODO: if keep broadcasting is disabled, connect() the UDP
nga->current = NULL;
}
+end:
destroyList(attr, (void(*)(void*))freeAttr);
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
- ret = readRequest(nga, attr, 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) {
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
- ret = readRequest(nga, attr, 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) {
int ngadmin_changePassword (struct ngadmin *nga, const char* pass)
{
List *attr;
+ struct attr *at;
int ret = ERR_OK;
attr = createEmptyList();
- pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
+ 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;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
- ret = readRequest(nga, attr, 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) {
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
- ret = readRequest(nga, attr, 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;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
- ret = readRequest(nga, attr, ATTR_END);
+ ret = readRequest(nga, attr);
if (ret != ERR_OK)
goto end;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
- ret = readRequest(nga, attr, 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) {
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
- ret = readRequest(nga, attr, 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;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
- ret = readRequest(nga, attr, 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) {
pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
- ret = readRequest(nga, attr, 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;
pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
- ret = readRequest(nga, attr, 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;
pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
- ret = readRequest(nga, attr, 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;
/* 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, ATTR_CABLETEST_RESULT);
+ 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;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
- ret=readRequest(nga, attr, 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) {
}
+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_dot *avd;
+ struct attr_vlan_conf *avc;
+ struct swi_attr *sa;
if (nga == NULL || vlans == NULL || ports== NULL || nb == NULL || *nb <= 0)
return ERR_INVARG;
- else if (nga->current == NULL)
+
+ sa = nga->current;
+ if (sa == NULL)
return ERR_NOTLOG;
attr = createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
- ret = readRequest(nga, attr, 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 * nga->current->ports);
+ memset(ports, 0, total * sa->ports);
for (ln = attr->first; ln != NULL; ln = ln->next) {
at = ln->data;
- avd = at->data;
+ avc = at->data;
+
+ if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
+ return ERR_INVARG;
- *vlans = avd->vlan;
- memcpy(ports, avd->ports, nga->current->ports);
+ *vlans = avc->vlan;
+ memcpy(ports, avc->ports, sa->ports);
vlans++;
- ports += nga->current->ports;
+ ports += sa->ports;
(*nb)++;
if (*nb > total)
ListNode *ln;
struct attr *at;
int ret = ERR_OK;
- struct attr_vlan_dot *avd;
+ struct attr_vlan_conf *avc;
- if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
+ 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, ATTR_END);
+ 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;
- avd = at->data;
- if (avd->vlan == vlan) {
- memcpy(ports, avd->ports, nga->current->ports);
+ avc = at->data;
+ if (avc->vlan == vlan) {
+ memcpy(ports, avc->ports, nga->current->ports);
break;
}
}
List *attr = NULL;
struct attr *at;
struct swi_attr *sa;
- struct attr_vlan_dot *avd;
+ struct attr_vlan_conf *avc;
int ret = ERR_OK, port;
- if (nga == NULL || vlan < 1 || vlan > VLAN_MAX || ports == NULL)
+ if (nga == NULL || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX || ports == NULL)
return ERR_INVARG;
sa = nga->current;
attr = createEmptyList();
- avd = malloc(sizeof(struct attr_vlan_dot) + sa->ports);
- if (avd == NULL)
+ avc = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
+ if (avc == NULL)
return ERR_MEM;
- avd->vlan = vlan;
+ 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, ATTR_VLAN_DOT_CONF);
+ 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(avd, at->data, sizeof(struct attr_vlan_dot) + sa->ports);
+ 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)
- avd->ports[port] = ports[port];
+ avc->ports[port] = ports[port];
}
- pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_dot) + sa->ports, avd));
+ pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc));
ret = writeRequest(nga, attr);
attr = NULL;
List *attr;
- if (nga == NULL || vlan < 1 || vlan > VLAN_MAX)
+ 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, newEmptyAttr(ATTR_VLAN_PVID));
- ret = readRequest(nga, attr, 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) {
struct attr_pvid *ap;
- if (nga == NULL || port < 1 || vlan < 1 || vlan > VLAN_MAX)
+ if (nga == NULL || port < 1 || vlan < VLAN_MIN || vlan > VLAN_DOT_MAX)
return ERR_INVARG;
else if (nga->current == NULL)
return ERR_NOTLOG;