#include <ngadmin.h>
-#include <attr.h>
-#include <protocol.h>
+#include <nsdp/attr.h>
+#include <nsdp/protocol.h>
#include "lib.h"
#include "network.h"
*t = VLAN_DISABLED;
- if (attr->first != NULL) {
- at = attr->first->data;
- *t =(int)*(char*)at->data;
+ if (attr->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto end;
}
-
+ at = attr->first->data;
+ *t =(int)*(char*)at->data;
end:
destroyList(attr, (void(*)(void*))freeAttr);
List *attr;
- if (nga == NULL || t < 1 || t > 4)
+ if (nga == NULL || t < VLAN_DISABLED || t > VLAN_DOT_ADV)
return ERR_INVARG;
else if (nga->current == NULL)
return ERR_NOTLOG;
filterAttributes(attr, ATTR_VLAN_PORT_CONF, ATTR_END);
+ if (attr->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto 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;
+ if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
+ ret = ERR_BADREPLY;
+ goto end;
+ }
for (port = 0; port < sa->ports; port++) {
if (avc->ports[port] == VLAN_UNTAGGED)
int ngadmin_setVLANPortConf (struct ngadmin *nga, const unsigned char *ports)
{
- List *attr = NULL;
+ List *conf_old = NULL, *conf_new = NULL;
ListNode *ln;
struct attr *at;
struct swi_attr *sa;
- struct attr_vlan_conf *avc;
+ struct attr_vlan_conf *avc_old, *avc_new;
int ret = ERR_OK, port;
- unsigned char vlan;
if (nga == NULL || ports == NULL)
/* if nothing is to be changed, do nothing */
for (port = 0; port < sa->ports && ports[port] == 0; port++);
- if (port == sa->ports )
+ 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));
- }
+ /* read old config */
+ conf_old = createEmptyList();
+ pushBackList(conf_old, newEmptyAttr(ATTR_VLAN_PORT_CONF));
+ ret = readRequest(nga, conf_old);
+ if (ret != ERR_OK)
+ goto end;
+
+ filterAttributes(conf_old, ATTR_VLAN_PORT_CONF, ATTR_END);
+
+ if (conf_old->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto end;
}
- for (ln = attr->first; ln != NULL; ln = ln->next) {
+ /* merge old config with requested config */
+ conf_new = createEmptyList();
+ avc_new = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
+
+ for (ln = conf_old->first; ln != NULL; ln = ln->next) {
at = ln->data;
- avc = at->data;
+ avc_old = at->data;
+
+ if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
+ ret = ERR_BADREPLY;
+ free(avc_new);
+ goto end;
+ }
+
+ /* compute new VLAN configuration */
+ avc_new->vlan = avc_old->vlan;
+
for (port = 0; port < sa->ports; port++) {
- if (ports[port] == avc->vlan)
- avc->ports[port] = VLAN_UNTAGGED;
+ if (ports[port] == 0)
+ avc_new->ports[port] = avc_old->ports[port];
+ else if (ports[port] == avc_new->vlan)
+ avc_new->ports[port] = VLAN_UNTAGGED;
else
- avc->ports[port] = VLAN_NO;
+ avc_new->ports[port] = VLAN_NO;
+ }
+
+ /* only add it if it is different from old config */
+ if (memcmp(avc_old->ports, avc_new->ports, sa->ports) != 0) {
+ pushBackList(conf_new, newAttr(ATTR_VLAN_PORT_CONF, sizeof(struct attr_vlan_conf) + sa->ports, avc_new));
+ avc_new = malloc(sizeof(struct attr_vlan_conf) + sa->ports);
}
}
- ret = writeRequest(nga, attr);
- attr = NULL;
+ free(avc_new);
+
+ /* if no VLAN is changed, no need to send anything to the switch */
+ if (conf_new->first == NULL)
+ goto end;
+ /* send new configuration to the switch */
+ ret = writeRequest(nga, conf_new);
+ conf_new = NULL;
end:
- destroyList(attr, (void(*)(void*))freeAttr);
+ destroyList(conf_old, (void(*)(void*))freeAttr);
+ destroyList(conf_new, (void(*)(void*))freeAttr);
return ret;
filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
+ if (attr->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto end;
+ }
+
memset(vlans, 0, total * sizeof(unsigned short));
memset(ports, 0, total * sa->ports);
at = ln->data;
avc = at->data;
- if (at->size != sizeof(struct attr_vlan_conf) + sa->ports)
- return ERR_INVARG;
+ if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
+ ret = ERR_BADREPLY;
+ goto end;
+ }
*vlans = avc->vlan;
memcpy(ports, avc->ports, sa->ports);
ListNode *ln;
struct attr *at;
int ret = ERR_OK;
+ struct swi_attr *sa;
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;
+ sa = nga->current;
+ if (sa == NULL)
+ return ERR_NOTLOG;
attr = createEmptyList();
pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
- memset(ports, 0, nga->current->ports);
+ if (attr->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto 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) {
+ ret = ERR_BADREPLY;
+ goto end;
+ }
+
if (avc->vlan == vlan) {
- memcpy(ports, avc->ports, nga->current->ports);
+ memcpy(ports, avc->ports, sa->ports);
break;
}
}
filterAttributes(attr, ATTR_VLAN_DOT_CONF, ATTR_END);
- if (attr->first != NULL) {
+ /* check if the switch is in 802.1Q mode */
+ if (attr->first == NULL) {
+ ret = ERR_BADREPLY;
+ goto end;
+ } else {
at = attr->first->data;
- memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
+ if (at->size < sizeof(struct attr_vlan_conf) + sa->ports) {
+ ret = ERR_BADREPLY;
+ goto end;
+ }
}
+ memcpy(avc, at->data, sizeof(struct attr_vlan_conf) + sa->ports);
clearList(attr, (void(*)(void*))freeAttr);
}
struct attr *at;
int ret = ERR_OK;
struct attr_pvid *ap;
+ struct swi_attr *sa;
if (nga == NULL || ports == NULL)
return ERR_INVARG;
- else if (nga->current == NULL)
+
+ sa = nga->current;
+ if (sa == NULL)
return ERR_NOTLOG;
filterAttributes(attr, ATTR_VLAN_PVID, ATTR_END);
- memset(ports, 0, nga->current->ports * sizeof(unsigned short));
+ memset(ports, 0, sa->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;
+ if (ap->port <= sa->ports)
+ ports[ap->port - 1] = ap->vlan;
}