Added support of QoS.
Added support for restarting the switch.
Lib: added an extra check of the remote port.
+// =============================================================================
+// defaults
+
+
+static bool do_defaults (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+
+ int i, ret=true;
+ const struct swi_attr *sa;
+ char line[16];
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ printf("The switch settings will be CLEARED. Continue ? [y/N]: ");
+ fflush(stdout);
+
+ if ( fgets(line, sizeof(line), stdin)!=NULL && strcasecmp(line, "y\n")==0 ) {
+ i=ngadmin_defaults(nga);
+ printErrCode(i);
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// firmware
+
+// =============================================================================
+// qos
+
+
+
+static bool do_qos_mode (int nb, const char **com, struct ngadmin *nga) {
+
+ int i, s, ret=true;
+ const struct swi_attr *sa;
+
+
+ if ( nb==0 ) {
+ printf("Usage: qos mode port|802.1p\n");
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ if ( strcasecmp(com[0], "port")==0 ) {
+ s=QOS_PORT;
+ } else if ( strcasecmp(com[0], "802.1p")==0 ) {
+ s=QOS_DOT;
+ } else {
+ printf("Unknown QOS mode\n");
+ ret=false;
+ goto end;
+ }
+
+
+ i=ngadmin_setQOSMode(nga, s);
+ printErrCode(i);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+static bool do_qos_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i, p;
+ const struct swi_attr *sa;
+ bool ret=true;
+ char d=PRIO_UNSPEC, *ports=NULL;
+
+
+ if ( nb<2 ) {
+ printf("Usage: qos set (all <prio0>)|(<port1> <prio1> [<port2> <prio2> ...])\n");
+ ret=false;
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc(sa->ports*sizeof(char));
+
+ if ( strcmp(com[0], "all")==0 ) {
+ d=parsePrio(com[1]);
+ com+=2;
+ nb-=2;
+ }
+
+ for (i=0; i<sa->ports; ++i) {
+ ports[i]=d;
+ }
+
+ for (i=0; i<nb; i+=2) {
+ if ( (p=strtol(com[i], NULL, 0))<1 || p>sa->ports ) continue;
+ ports[p-1]=parsePrio(com[i+1]);
+ }
+
+
+ i=ngadmin_setQOSValues(nga, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
+static bool do_qos_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i, s=0, ret=true;
+ const struct swi_attr *sa;
+ char *ports=NULL;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ if ( (i=ngadmin_getQOSMode(nga, &s))!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+
+ printf("QOS mode: ");
+
+ if ( s==QOS_DOT ) {
+ printf("802.1p\n");
+ goto end;
+ } else if ( s!=QOS_PORT ) {
+ printf("unknown (%i)\n", s);
+ goto end;
+ }
+
+ printf("port based\n");
+
+ ports=malloc(sa->ports*sizeof(char));
+
+ if ( (i=ngadmin_getQOSValues(nga, ports))!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+ for (i=0; i<sa->ports; ++i) {
+ printf("port %i: %s\n", i+1, prio[(int)ports[i]]);
+ }
+
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// quit
+// =============================================================================
+// restart
+
+
+static bool do_restart (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+
+ int i, ret=true;
+ const struct swi_attr *sa;
+ char line[16];
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ printf("The switch will be restarted. Continue ? [y/N]: ");
+ fflush(stdout);
+
+ if ( fgets(line, sizeof(line), stdin)!=NULL && strcasecmp(line, "y\n")==0 ) {
+ i=ngadmin_restart(nga);
+ printErrCode(i);
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// scan
COM_TERM(cabletest, NULL, true)
- COM_TERM(defaults, NULL, false)
+ COM_TERM(defaults, do_defaults, false)
COM_START(firmware)
COM_TERM(show, do_firmware_show, false)
COM_TERM(upgrade, do_firmware_upgrade, true)
COM_END
+ COM_START(igmp)
+ COM_TERM(set, NULL, false)
+ COM_TERM(show, NULL, false)
+ COM_END
+
COM_TERM(list, do_list, false)
COM_TERM(login, do_login, true)
COM_END
COM_START(qos)
- COM_TERM(mode, NULL, true)
- COM_TERM(set, NULL, true)
- COM_TERM(show, NULL, false)
+ COM_TERM(mode, do_qos_mode, true)
+ COM_TERM(set, do_qos_set, true)
+ COM_TERM(show, do_qos_show, false)
COM_END
COM_TERM(quit, do_quit, false)
- COM_TERM(restart, NULL, false)
+ COM_TERM(restart, do_restart, false)
COM_TERM(scan, do_scan, false)
#define COM_ROOT_START(v) const struct TreeNode v={.name="<root>", .comfunc=NULL, .hasArgs=false, .sub=(const struct TreeNode[]){
#define COM_ROOT_END {.name=NULL, .comfunc=NULL, .hasArgs=false, .sub=NULL}}};
#define COM_START(nam) {.name=#nam, .comfunc=NULL, .hasArgs=false, .sub=(const struct TreeNode[]){
-#define COM_TERM(nam, func, args) {.name=#nam, .comfunc=func, .hasArgs=args, .sub=NULL},
#define COM_END {.name=NULL, .comfunc=NULL, .hasArgs=false, .sub=NULL}}},
+#define COM_TERM(nam, func, args) {.name=#nam, .comfunc=func, .hasArgs=args, .sub=NULL},
extern const struct TreeNode coms;
};
+const char* prio[]={
+ NULL,
+ "high",
+ "medium",
+ "normal",
+ "low",
+ NULL
+};
+
int parseBitrate (const char *s) {
+char parsePrio (const char *s) {
+
+ int i;
+
+
+ for (i=1; prio[i]!=NULL && strcasecmp(prio[i], s)!=0; ++i);
+
+
+ return (char)i;
+
+}
+
+
+
void displaySwitchTab (const struct swi_attr *sa, int nb) {
int i=0;
extern int cont;
-extern const char* bitrates[];
+extern const char *bitrates[], *prio[];
void displaySwitchTab (const struct swi_attr *sa, int nb);
void printErrCode (int err);
int parseBitrate (const char *s);
+char parsePrio (const char *s);
+
//
int trim (char *txt, int start);
int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) EXPORT;
+//
+int ngadmin_getQOSMode (struct ngadmin *nga, int *s) EXPORT;
+
+
+//
+int ngadmin_setQOSMode (struct ngadmin *nga, int s) EXPORT;
+
+
+//
+int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) EXPORT;
+
+
+//
+int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) EXPORT;
+
+
+//
+int ngadmin_restart (struct ngadmin *nga) EXPORT;
+
+
+//
+int ngadmin_defaults (struct ngadmin *nga) EXPORT;
+
+
+
#endif
memset(&remote, 0, sizeof(struct sockaddr_in));
remote.sin_family=AF_INET;
- remote.sin_port=htons(SWITCH_PORT);
while ( (len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 ) {
- if ( len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ) {
+ 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);
break;
}
free(nga->swi_tab);
+ nga->swi_tab=NULL;
nga->swi_count=0;
nga->current=NULL;
}
+
+// -------------------------------------------------
+int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || s==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ 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;
+ 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;
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ 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 ) {
+ 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;
+
+}
+
+
+
+// -------------------------------------------------------
+int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+ 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));
+ 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;
+ 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];
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// --------------------------------------------------------------
+int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
+
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ char *p;
+
+
+ if ( nga==NULL || ports==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)));
+
+ 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));
+ }
+ }
+
+ 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;
+
+}
+
+
+
+// --------------------------------------
+int ngadmin_restart (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_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;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// ---------------------------------------
+int ngadmin_defaults (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_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;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ 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;
+
+}
+
+