-static const struct timeval default_timeout={.tv_sec=3, .tv_usec=0};
+static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
}
free(nga->swi_tab);
+ nga->swi_tab=NULL;
nga->swi_count=0;
nga->current=NULL;
// send request to all potential switches
i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
+ clearList(attr, (void(*)(void*))freeAttr);
if ( i<0 ) {
return ERR_NET;
}
// try to receive any packets until timeout
swiList=createEmptyList();
- while ( (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))!=NULL ) {
+ while ( recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr)>=0 ) {
sa=malloc(sizeof(struct swi_attr));
extractSwitchAttributes(sa, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
+ clearList(attr, (void(*)(void*))freeAttr);
pushBackList(swiList, sa);
}
int ngadmin_login (struct ngadmin *nga, int id) {
List *attr;
- int ret=ERR_OK, i;
+ int ret=ERR_OK;
struct swi_attr *sa;
- char err;
- unsigned short attr_error;
if ( nga==NULL ) {
attr=createEmptyList();
pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
+ if ( (ret=readRequest(nga, attr))==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;
- goto end;
}
-
destroyList(attr, (void(*)(void*))freeAttr);
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
- nga->current=NULL;
- goto end;
- }
-
- end:
-
return ret;
}
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
- ret=ERR_NET;
+ if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
goto end;
}
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_setName (struct ngadmin *nga, const char *name) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ int ret=ERR_OK;
if ( nga==NULL ) {
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- if ( name==NULL ) {
- pushBackList(attr, newEmptyAttr(ATTR_NAME));
- } else {
- pushBackList(attr, newAttr(ATTR_NAME, strlen(name), strdup(name)));
- }
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
- goto end;
- }
-
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
+ pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
+ if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
goto end;
}
List *attr;
ListNode *ln;
struct attr *at;
- int ret=ERR_OK, i;
+ int ret=ERR_OK;
int port;
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
- ret=ERR_NET;
+ 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_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
- goto end;
- }
-
- destroyList(attr, (void(*)(void*))freeAttr);
-
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
- goto end;
- }
-
- end:
-
- return ret;
+ return writeRequest(nga, attr);
}
int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ int ret=ERR_OK;
if ( nga==NULL || pass==NULL ) {
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
- goto end;
- }
-
- destroyList(attr, (void(*)(void*))freeAttr);
-
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
+ if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
goto end;
}
List *attr;
ListNode *ln;
struct attr *at;
- int ret=ERR_OK, i;
+ int ret=ERR_OK;
if ( nga==NULL || s==NULL ) {
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
- ret=ERR_NET;
+ 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_STORM_ENABLE && at->size>=1 ) {
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
-
-
- if ( nga==NULL ) {
- return ERR_INVARG;
- } else if ( nga->current==NULL ) {
- return ERR_NOTLOG;
- }
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
- goto end;
- }
- destroyList(attr, (void(*)(void*))freeAttr);
-
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
- goto end;
- }
-
- end:
-
- return ret;
+ return writeRequest(nga, attr);
}
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
- ret=ERR_NET;
+ 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_STORM_BITRATE && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
ports[i]=ntohl(*(int*)(1+(char*)at->data));
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ int i;
char *p;
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
for (i=0; i<nga->current->ports; ++i) {
if ( ports[i]>=0 && ports[i]<=11 ) {
}
}
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
- goto end;
- }
-
- destroyList(attr, (void(*)(void*))freeAttr);
-
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
- goto end;
- }
-
- end:
-
- return ret;
+ return writeRequest(nga, attr);
}
List *attr;
ListNode *ln;
struct attr *at;
- int ret=ERR_OK, i;
+ int ret=ERR_OK;
+ struct {
+ char port;
+ int bitrate;
+ } __attribute__((packed)) *p;
if ( nga==NULL || ports==NULL ) {
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
- ret=ERR_NET;
+ 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_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
- ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
- } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
- ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
+ p=at->data;
+ if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
+ if ( at->attr==ATTR_BITRATE_INPUT ) {
+ ports[(p->port-1)*2+0]=ntohl(p->bitrate);
+ } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
+ ports[(p->port-1)*2+1]=ntohl(p->bitrate);
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ int i;
char *p;
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
for (i=0; i<nga->current->ports; ++i) {
if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
}
}
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
- ret=ERR_NET;
+
+ return writeRequest(nga, attr);
+
+}
+
+
+
+// -------------------------------------------------
+int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
+
+ List *attr;
+ ListNode *ln;
+ 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));
+ 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_QOS_TYPE && at->size>=1 ) {
+ *s= *(char*)at->data ;
+ break;
+ }
+ }
+
+
+ end:
destroyList(attr, (void(*)(void*))freeAttr);
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
+ return ret;
+
+}
+
+
+// ------------------------------------------------
+int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
+
+ List *attr;
+
+
+ if ( s<QOS_PORT || s>QOS_DOT ) {
+ return ERR_INVARG;
+ }
+
+ 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;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
+ if ( (ret=readRequest(nga, attr))<0 ) {
goto end;
}
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
+ ports[(int)p[0]]=p[1];
+ }
+ }
+
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
return ret;
}
+
+// --------------------------------------------------------------
+int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
+
+ List *attr;
+ int i;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+
+ for (i=0; i<nga->current->ports; ++i) {
+ if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
+ p=malloc(2);
+ p[0]=i+1;
+ p[1]=ports[i];
+ pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
+ }
+ }
+
+
+ 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));
+ if ( (ret=writeRequest(nga, attr))!=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;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK, i;
+ unsigned 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_MIRROR));
+ if ( (ret=readRequest(nga, attr))<0 ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
+ ports[0]=p[0];
+ for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
+ ports[i]=(p[2]>>(8-i))&1;
+ }
+ break;
+ }
+ }
+
+
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
+
+}
+
+
+
+// -----------------------------------------------------------
+int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
+
+ List *attr;
+ int i;
+ char *p;
+ struct swi_attr *sa;
+
+
+ if ( nga==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ p=malloc(3); // FIXME: if ports>8
+ memset(p, 0, 3);
+
+ if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
+ p[0]=ports[0];
+ for (i=1; i<=sa->ports; ++i) {
+ if ( i!=p[0] ) {
+ p[2]|=(ports[i]&1)<<(8-i);
+ }
+ }
+ }
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
+
+
+ return writeRequest(nga, attr);
+
+}
+
+
+
+// ----------------------------------------------------------------
+int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
+ int ret=ERR_OK;
+ unsigned char *p;
+ unsigned short *s;
+
+
+ if ( nga==NULL || ic==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=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));
+ if ( (ret=readRequest(nga, attr))<0 ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ s=at->data;
+ if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
+ ic->enable= ntohs(s[0])!=0 ;
+ ic->vlan=htons(s[1]);
+ break;
+ }
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+
+ pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
+ if ( (ret=readRequest(nga, attr))<0 ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
+ ic->block= p[0]!=0 ;
+ break;
+ }
+ }
+
+ clearList(attr, (void(*)(void*))freeAttr);
+
+
+ pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
+ if ( (ret=readRequest(nga, attr))<0 ) {
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
+ ic->validate= p[0]!=0 ;
+ break;
+ }
+ }
+
+
+
+ end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
+
+}
+
+
+
+// ----------------------------------------------------------------------
+int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
+
+ List *attr;
+ short *s;
+ struct swi_attr *sa;
+
+
+ if ( nga==NULL || ic==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ s=malloc(2*sizeof(short));
+ s[0]=htons(ic->enable!=false);
+ s[1]=htons(ic->vlan&0x0FFF);
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
+ 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 i, ret=ERR_OK;
+ struct swi_attr *sa;
+ char *p;
+
+
+ if ( nga==NULL || ct==NULL ) {
+ return ERR_INVARG;
+ } else if ( (sa=nga->current)==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+
+ for (i=0; i<nb; ++i) {
+ if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
+
+ p=malloc(2);
+ p[0]=ct[i].port;
+ p[1]=1;
+ pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
+
+ 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));
+
+ if ( (ret=readRequest(nga, attr))<0 ) goto end;
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
+ ct[i].v1=ntohl(*(int*)&p[1]);
+ ct[i].v2=ntohl(*(int*)&p[5]);
+ 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;
+ 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>=sa->ports ) 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;
+ int i;
+ char *p;
+ int ret=ERR_OK;
+
+
+ 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) {
+ if ( ports[i]==VLAN_NO ) {
+ p[2]&=~(1<<(7-i));
+ p[3]&=~(1<<(7-i));
+ } else if ( ports[i]==VLAN_UNTAGGED ) {
+ p[2]|=(1<<(7-i));
+ p[3]&=~(1<<(7-i));
+ } else if ( ports[i]==VLAN_TAGGED ) {
+ p[2]|=(1<<(7-i));
+ p[3]|=(1<<(7-i));
+ }
+ }
+
+
+
+ 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);;
+
+}
+
+
+