+// =============================================================================
+// cabletest
+
+
+static bool do_cabletest (int nb, const char **com, struct ngadmin *nga) {
+
+ bool ret=true;
+ const struct swi_attr *sa;
+ struct cabletest *ct=NULL;
+ int i, j=0, k=0;
+
+
+ if ( nb<1 ) {
+ printf("Usage: cabletest <port1> [<port2> ...]\n");
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ ct=malloc(sa->ports*sizeof(struct cabletest));
+ memset(ct, 0, sa->ports*sizeof(struct cabletest));
+
+ while ( k<nb ) {
+ ct[j].port=strtol(com[k++], NULL, 0);
+ if ( ct[j].port>=1 && ct[j].port<=sa->ports ) ++j;
+ }
+
+ i=ngadmin_cabletest(nga, ct, j);
+ if ( i<0 ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+
+ for (i=0; i<j; ++i) {
+ printf("port %i: %08X %08X\n", ct[i].port, ct[i].v1, ct[i].v2);
+ }
+
+
+ end:
+ free(ct);
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// defaults
-static bool do_defaults (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+static bool do_defaults (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
int i, ret=true;
const struct swi_attr *sa;
+// =============================================================================
+// igmp
+
+
+static bool do_igmp_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i;
+ struct igmp_conf ic;
+
+
+ if ( nb!=4 ) {
+ printf("Usage: igmp set <enable> <vlan> <validate> <block>\n");
+ return false;
+ }
+
+ if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+ ic.enable=strtol(com[0], NULL, 0);
+ ic.vlan=strtol(com[1], NULL, 0);
+ ic.validate=strtol(com[2], NULL, 0);
+ ic.block=strtol(com[3], NULL, 0);
+
+ i=ngadmin_setIGMPConf(nga, &ic);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_igmp_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+ const struct swi_attr *sa;
+ struct igmp_conf ic;
+ bool ret=true;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ i=ngadmin_getIGMPConf(nga, &ic);
+ if ( i!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+
+ printf("IGMP snooping enabled: %s\n", ic.enable ? "yes" : "no" );
+ printf("IGMP snooping vlan: %u\n", ic.vlan);
+ printf("Validate IGMPv3 headers: %s\n", ic.validate ? "yes" : "no" );
+ printf("Block unknown multicast addresses: %s\n", ic.block ? "yes" : "no" );
+
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// list
+// =============================================================================
+// mirror
+
+
+static bool do_mirror_disable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i;
+
+
+ if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+
+ i=ngadmin_setMirror(nga, NULL);
+ printErrCode(i);
+
+
+ return true;
+
+}
+
+
+
+static bool do_mirror_set (int nb, const char **com, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+ char *ports=NULL;
+ bool ret=true;
+ int i, k=0;
+
+
+ if ( nb<3 ) {
+ printf("Usage: mirror set <destination port> clone <port1> [<port2> ...]\n");
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc((sa->ports+1)*sizeof(char));
+ memset(ports, 0, sa->ports+1);
+
+ ports[0]=strtol(com[k++], NULL, 0);
+ if ( ports[0]<1 || ports[0]>sa->ports || strcasecmp(com[k++], "clone")!=0 ) {
+ printf("syntax error\n");
+ ret=false;
+ goto end;
+ }
+
+
+ while ( k<nb ) {
+ i=strtol(com[k++], NULL, 0);
+ if ( i<1 || i>sa->ports ) {
+ printf("port out of range\n");
+ ret=false;
+ goto end;
+ } else if ( i==ports[0] ) {
+ printf("destination port cannot be in port list\n");
+ ret=false;
+ goto end;
+ }
+ ports[i]=1;
+ }
+
+
+ i=ngadmin_setMirror(nga, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+ return true;
+
+}
+
+
+
+static bool do_mirror_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ const struct swi_attr *sa;
+ char *ports=NULL;
+ int i;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ return false;
+ }
+
+
+ ports=malloc((sa->ports+1)*sizeof(char));
+
+ i=ngadmin_getMirror(nga, ports);
+ if ( i!=ERR_OK ) {
+ printErrCode(i);
+ goto end;
+ }
+
+ if ( ports[0]==0 ) {
+ printf("port mirroring is disabled\n");
+ goto end;
+ }
+
+ printf("destination: %i\n", ports[0]);
+ printf("ports: ");
+ for (i=1; i<=sa->ports; ++i) {
+ if ( ports[i] ) {
+ printf("%i ", i);
+ }
+ }
+ printf("\n");
+
+
+
+ end:
+ free(ports);
+
+ return true;
+
+}
+
+
+
// =============================================================================
// name
COM_TERM(show, do_bitrate_show, false)
COM_END
- COM_TERM(cabletest, NULL, true)
+ COM_TERM(cabletest, do_cabletest, true)
COM_TERM(defaults, do_defaults, false)
COM_END
COM_START(igmp)
- COM_TERM(set, NULL, false)
- COM_TERM(show, NULL, false)
+ COM_TERM(set, do_igmp_set, true)
+ COM_TERM(show, do_igmp_show, false)
COM_END
COM_TERM(list, do_list, false)
COM_TERM(login, do_login, true)
COM_START(mirror)
- COM_TERM(enable, NULL, false)
- COM_TERM(disable, NULL, false)
- COM_TERM(set, NULL, true)
- COM_TERM(show, NULL, false)
+ COM_TERM(disable, do_mirror_disable, false)
+ COM_TERM(set, do_mirror_set, true)
+ COM_TERM(show, do_mirror_show, false)
COM_END
COM_START(name)
close(nga->sock);
return ret;
}
+ /*
+ Here we have a problem: when you have multiple interfaces, sending a packet to
+ 255.255.255.255 may not send it to the interface you want. If you bind() to
+ the address of the interface, you will not be able to receive broadcasts.
+ The only solution I have found yet is in this case to use
+ setsockopt(SO_BINDTODEVICE) but this requires root priviledges.
+ */
//local.sin_addr=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr; // FIXME
// get the interface MAC address
+ /*
+ As described bellow, when you have multiple interfaces, this forces the packet
+ to go to a particular interface.
+ */
ret=1;
if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface)+1))<0 ) {
perror("setsockopt(SO_BINDTODEVICE)");
return ret;
}
+ /*
+ If the switch's IP is not in your network range, for instance because you do
+ not have DHCP enabled or you started the switch after it, this allows to
+ bypass the routing tables and consider every address is directly reachable on
+ the interface.
+ */
ret=1;
if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret)))<0 ) {
perror("setsockopt(SO_DONTROUTE)");
-// -----------------------------------------------------------------------------------------
-List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error) {
+// ---------------------------------------------------------------------------------------------------
+int recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, List *attr) {
char buffer[1500];
struct ng_packet np;
struct sockaddr_in remote;
socklen_t slen=sizeof(struct sockaddr_in);
const struct swi_attr *sa=nga->current;
- List *l=NULL;
int len;
memset(&remote, 0, sizeof(struct sockaddr_in));
remote.sin_family=AF_INET;
- while ( (len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 ) {
+ while ( 1 ) {
+
+ len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen);
+
+ if ( len<0 ) {
+ break;
+ }
+
if ( ntohs(remote.sin_port)==SWITCH_PORT && len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ) {
initNgPacket(&np);
- l=extractPacketAttributes(&np, error, attr_error);
+ extractPacketAttributes(&np, error, attr_error, attr);
+ len=0;
break;
}
+
+ }
+
+
+ return len;
+
+}
+
+
+
+// ----------------------------------------------
+int readRequest (struct ngadmin *nga, List *attr) {
+
+ int i, ret=ERR_OK;
+ unsigned short attr_error;
+ char err;
+
+
+ if ( nga==NULL ) {
+ ret=ERR_INVARG;
+ goto end;
+ }
+
+ // add end attribute to end
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
+
+ // the list will be filled again by recvNgPacket
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ if ( i<0 || (i=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, attr))<0 ) {
+ ret=ERR_NET;
+ }
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+
+ return ret;
+
+}
+
+
+
+// -----------------------------------------------
+int writeRequest (struct ngadmin *nga, List *attr) {
+
+ int i, ret=ERR_OK;
+ unsigned short attr_error;
+ char err;
+
+
+ if ( nga==NULL ) {
+ ret=ERR_INVARG;
+ goto end;
+ } else if ( nga->current==NULL ) {
+ ret=ERR_NOTLOG;
+ goto end;
+ }
+
+
+ if ( attr==NULL ) {
+ attr=createEmptyList();
+ }
+
+ // add password attribute to start
+ pushFrontList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+
+ // add end attribute to end
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
+
+ // the list will be filled again by recvNgPacket
+ // but normally it will be still empty
+ clearList(attr, (void(*)(void*))freeAttr);
+
+ if ( i<0 || (i=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, attr))<0 ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
}
- return l;
+ end:
+ // the switch replies to write request by just a header (no attributes), so the list can be destroyed
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ return ret;
}
-static const struct timeval default_timeout={.tv_sec=3, .tv_usec=0};
+static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
// 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 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);
}
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 ) {
}
}
- 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;
- 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;
if ( nga==NULL || s==NULL ) {
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
- 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_QOS_TYPE && at->size>=1 ) {
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
return ret;
int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
- if ( nga==NULL || s<1 || s>2 ) {
+ if ( s<QOS_PORT || s>QOS_DOT ) {
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_QOS_TYPE, s));
- 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;
char *p;
attr=createEmptyList();
pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
- 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))<0 ) {
goto end;
}
}
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
return ret;
int ngadmin_setQOSValues (struct ngadmin *nga, const char *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]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
}
}
- 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);
+ return writeRequest(nga, attr);
+
+}
+
+
+
+// --------------------------------------
+int ngadmin_restart (struct ngadmin *nga) {
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
+ 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_restart (struct ngadmin *nga) {
+// -----------------------------------------------------
+int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
List *attr;
+ ListNode *ln;
+ struct attr *at;
+ struct swi_attr *sa;
int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ unsigned char *p;
- if ( nga==NULL ) {
+ if ( nga==NULL || ports==NULL ) {
return ERR_INVARG;
- } else if ( nga->current==NULL ) {
+ } else if ( (sa=nga->current)==NULL ) {
return ERR_NOTLOG;
}
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- pushBackList(attr, newByteAttr(ATTR_RESTART, 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;
+ pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
+ if ( (ret=readRequest(nga, attr))<0 ) {
goto end;
}
- destroyList(attr, (void(*)(void*))freeAttr);
-
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
- goto end;
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ p=at->data;
+ if ( at->attr==ATTR_MIRROR && at->size>=2+sa->ports/8 && p[0]<=nga->current->ports ) {
+ ports[0]=p[0];
+ for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
+ ports[i]=(p[2]>>(sa->ports-i))&1;
+ }
+ break;
+ }
}
end:
+ destroyList(attr, (void(*)(void*))freeAttr);
+
return ret;
-// ---------------------------------------
-int ngadmin_defaults (struct ngadmin *nga) {
+// -----------------------------------------------------------
+int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
List *attr;
- int ret=ERR_OK, i;
- char err;
- unsigned short attr_error;
+ int i;
+ char *p;
+ struct swi_attr *sa;
if ( nga==NULL ) {
return ERR_INVARG;
- } else if ( nga->current==NULL ) {
+ } 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)<<(sa->ports-i);
+ }
+ }
+ }
+
attr=createEmptyList();
- pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
- pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 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;
+ 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 theses 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;
}
- destroyList(attr, (void(*)(void*))freeAttr);
+ 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);
- if ( err==7 && attr_error==ATTR_PASSWORD ) {
- ret=ERR_BADPASS;
+
+ 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;
+ }
+ }
- // successful: delog and clean list
- free(nga->swi_tab);
- nga->swi_tab=NULL;
- nga->swi_count=0;
- nga->current=NULL;
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;
+
+}
+
+
+