+// --------------------------------------------------------------------
+int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
+
+ List *attr;
+ struct swi_attr *sa;
+ int ret=ERR_OK;
+
+
+ if ( nga==NULL || nc==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+
+ if ( nc->dhcp ) {
+ pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
+ } else {
+ pushBackList(attr, newByteAttr(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));
+ }
+
+ if ( (ret=writeRequest(nga, attr))!=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;
+ ListNode *ln;
+ 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));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
+ *t= (int)*(char*)at->data ;
+ break;
+ }
+ }
+
+
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ return ret;
+
+}
+
+
+
+// -------------------------------------------------
+int ngadmin_setVLANType (struct ngadmin *nga, int t) {
+
+ List *attr;
+ struct swi_attr *sa;
+
+
+ if ( nga==NULL || t<1 || t>4 ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
+
+
+ return writeRequest(nga, attr);
+
+}
+
+
+
+// ------------------------------------------------------------------------------------------------------
+int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK, total, i;
+ char *p=NULL;
+
+
+ if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ total=*nb;
+ *nb=0;
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( *nb>=total ) break; // no more room
+ if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+ for (i=0; i<sa->ports; ++i) {
+ if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+ else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+ else ports[i]=VLAN_NO;
+ }
+ *vlans++=ntohs(*(unsigned short*)p);
+ ports+=sa->ports;
+ ++*nb;
+ }
+ }
+
+
+ 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;
+ struct swi_attr *sa;
+ int ret=ERR_OK, i;
+ char *p=NULL;
+
+
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+ for (i=0; i<sa->ports; ++i) {
+ if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
+ else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
+ else ports[i]=VLAN_NO;
+ }
+ break;
+ }
+ }
+
+
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ return ret;
+
+}
+
+
+
+// ----------------------------------------------------------------------------------------------
+int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
+
+ List *attr=NULL;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ char *p, fl;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ // if nothing is to be changed, do nothing
+ for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
+ if ( i==sa->ports ) goto end;
+
+
+ attr=createEmptyList();
+
+ p=malloc(4);
+ *(unsigned short*)p=htons(vlan);
+ *(unsigned short*)&p[2]=0;
+
+ // if all is to be changed, we do not need to read old config
+ if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
+
+ attr=createEmptyList();
+ pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
+ *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
+ break;
+ }
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ }
+
+
+ // apply changes
+ for (i=0; i<sa->ports; ++i) {
+ fl=(1<<(7-i));
+ switch ( ports[i] ) {
+ case VLAN_NO:
+ p[2]&=~fl;
+ p[3]&=~fl;
+ break;
+ case VLAN_UNTAGGED:
+ p[2]|=fl;
+ p[3]&=~fl;
+ break;
+ case VLAN_TAGGED:
+ p[2]|=fl;
+ p[3]|=fl;
+ }
+ }
+
+
+
+ pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
+ 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;
+ struct swi_attr *sa;
+
+
+ if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
+ return ERR_INVARG;
+ } else if ( (sa=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;
+ struct swi_attr *sa;
+ int ret=ERR_OK;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
+ goto end;
+ }
+
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
+ ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
+ }
+ }
+
+
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ return ret;
+
+}
+
+
+
+// -------------------------------------------------------------------------------
+int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
+
+ List *attr;
+ struct swi_attr *sa;
+ char *p;
+
+
+ if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ } else if ( port>sa->ports ) {
+ return ERR_INVARG;
+ }
+
+
+ attr=createEmptyList();
+ p=malloc(3);
+ p[0]=port;
+ *(unsigned short*)&p[1]=htons(vlan);
+
+ pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
+
+
+ return writeRequest(nga, attr);;
+
+}
+
+
+