7 static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
11 // ---------------------------------------------
12 struct ngadmin* ngadmin_init (const char *iface) {
17 // allocate main structure
18 nga=malloc(sizeof(struct ngadmin));
19 memset(nga, 0, sizeof(struct ngadmin));
21 strncpy(nga->iface, iface, IFNAMSIZ-1);
23 if ( startNetwork(nga)<0 ) {
28 nga->timeout=default_timeout;
29 if ( updateTimeout(nga)<0 ) {
41 // ------------------------------------
42 int ngadmin_close (struct ngadmin *nga) {
60 // ---------------------------------------------
61 int ngadmin_forceInterface (struct ngadmin *nga) {
69 if ( forceInterface(nga)!=0 ) {
79 // --------------------------------------------------------------
80 int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) {
97 // ------------------------------------------------------------
98 int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
105 strncpy(nga->password, pass, PASSWORD_MAX);
114 // -------------------------------------------------------------------
115 int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) {
120 if ( nga==NULL || tv==NULL ) {
126 if ( updateTimeout(nga)<0 ) {
137 // -----------------------------------
138 int ngadmin_scan (struct ngadmin *nga) {
141 List *attr, *swiList;
144 sent by official win client:
160 static const unsigned short hello[]={
184 // create attributes for an "hello" request
185 attr=createEmptyList();
187 pushBackList(attr, newEmptyAttr(hello[i]));
188 if ( hello[i]==ATTR_END ) break;
191 // send request to all potential switches
192 i=sendNgPacket(nga, CODE_READ_REQ, attr);
193 clearList(attr, (void(*)(void*))freeAttr);
199 // try to receive any packets until timeout
200 swiList=createEmptyList();
201 while ( recvNgPacket(nga, CODE_READ_REP, NULL, NULL, attr)>=0 ) {
202 sa=malloc(sizeof(struct swi_attr));
203 extractSwitchAttributes(sa, attr);
204 clearList(attr, (void(*)(void*))freeAttr);
205 pushBackList(swiList, sa);
208 nga->swi_count=swiList->count;
209 nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
218 // -----------------------------------------------------------------------
219 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
222 if ( nga==NULL || nb==NULL ) {
236 // ------------------------------------------------------------------
237 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
251 // --------------------------------------------
252 int ngadmin_login (struct ngadmin *nga, int id) {
261 } else if ( id<0 || id>=nga->swi_count ) {
266 sa=&nga->swi_tab[id];
269 attr=createEmptyList();
270 pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
271 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
276 destroyList(attr, (void(*)(void*))freeAttr);
285 // -------------------------------------------------------------------
286 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
295 if ( nga==NULL || ports==NULL ) {
297 } else if ( nga->current==NULL ) {
302 attr=createEmptyList();
303 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
304 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
308 for (ln=attr->first; ln!=NULL; ln=ln->next) {
311 if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
318 destroyList(attr, (void(*)(void*))freeAttr);
326 // --------------------------------------------------------
327 int ngadmin_setName (struct ngadmin *nga, const char *name) {
335 } else if ( nga->current==NULL ) {
340 attr=createEmptyList();
341 pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
342 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
347 // successful, also update local name
349 nga->current->name[0]=0;
351 strncpy(nga->current->name, name, NAME_SIZE);
363 // ------------------------------------------------------------------------
364 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
373 if ( nga==NULL || ps==NULL ) {
375 } else if ( nga->current==NULL ) {
380 attr=createEmptyList();
381 pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
382 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
387 for (ln=attr->first; ln!=NULL; ln=ln->next) {
389 if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
390 ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
391 ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
392 ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
393 // all offsets between 2 and 4 inclusive are unknown values
399 destroyList(attr, (void(*)(void*))freeAttr);
407 // ---------------------------------------------------
408 int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
413 attr=createEmptyList();
414 pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
417 return writeRequest(nga, attr);
423 // ---------------------------------------------------------------
424 int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
430 if ( nga==NULL || pass==NULL ) {
432 } else if ( nga->current==NULL ) {
437 attr=createEmptyList();
438 pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
439 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
444 // successful, also update local password
445 strncpy(nga->password, pass, PASSWORD_MAX);
456 // ----------------------------------------------------------
457 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
465 if ( nga==NULL || s==NULL ) {
467 } else if ( nga->current==NULL ) {
472 attr=createEmptyList();
473 pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
474 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
479 for (ln=attr->first; ln!=NULL; ln=ln->next) {
481 if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
482 *s= *(char*)at->data!=0 ;
489 destroyList(attr, (void(*)(void*))freeAttr);
497 // ---------------------------------------------------------
498 int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
503 attr=createEmptyList();
504 pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
507 return writeRequest(nga, attr);
513 // ---------------------------------------------------------------
514 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
522 if ( nga==NULL || ports==NULL ) {
524 } else if ( nga->current==NULL ) {
529 attr=createEmptyList();
530 pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
531 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
536 for (ln=attr->first; ln!=NULL; ln=ln->next) {
538 if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
539 ports[i]=ntohl(*(int*)(1+(char*)at->data));
545 destroyList(attr, (void(*)(void*))freeAttr);
553 // ---------------------------------------------------------------------
554 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
561 if ( nga==NULL || ports==NULL ) {
563 } else if ( nga->current==NULL ) {
568 attr=createEmptyList();
570 for (i=0; i<nga->current->ports; ++i) {
571 if ( ports[i]>=0 && ports[i]<=11 ) {
574 *(int*)(p+1)=htonl(ports[i]);
575 pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
580 return writeRequest(nga, attr);
586 // -----------------------------------------------------------
587 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
595 if ( nga==NULL || ports==NULL ) {
597 } else if ( nga->current==NULL ) {
602 attr=createEmptyList();
603 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
604 pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
605 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
610 for (ln=attr->first; ln!=NULL; ln=ln->next) {
612 if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
613 ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
614 } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
615 ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
621 destroyList(attr, (void(*)(void*))freeAttr);
629 // -----------------------------------------------------------------
630 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
637 if ( nga==NULL || ports==NULL ) {
639 } else if ( nga->current==NULL ) {
644 attr=createEmptyList();
646 for (i=0; i<nga->current->ports; ++i) {
647 if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
650 *(int*)(p+1)=htonl(ports[2*i+0]);
651 pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
653 if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
656 *(int*)(p+1)=htonl(ports[2*i+1]);
657 pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
662 return writeRequest(nga, attr);
668 // -------------------------------------------------
669 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
677 if ( nga==NULL || s==NULL ) {
679 } else if ( nga->current==NULL ) {
684 attr=createEmptyList();
685 pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
686 if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
691 for (ln=attr->first; ln!=NULL; ln=ln->next) {
693 if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
694 *s= *(char*)at->data ;
701 destroyList(attr, (void(*)(void*))freeAttr);
708 // ------------------------------------------------
709 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
714 if ( s<QOS_PORT || s>QOS_DOT ) {
718 attr=createEmptyList();
719 pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
722 return writeRequest(nga, attr);
728 // -------------------------------------------------------
729 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
738 if ( nga==NULL || ports==NULL ) {
740 } else if ( nga->current==NULL ) {
745 attr=createEmptyList();
746 pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
747 if ( (ret=readRequest(nga, attr))<0 ) {
751 for (ln=attr->first; ln!=NULL; ln=ln->next) {
754 if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
755 ports[(int)p[0]]=p[1];
761 destroyList(attr, (void(*)(void*))freeAttr);
770 // --------------------------------------------------------------
771 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
778 if ( nga==NULL || ports==NULL ) {
780 } else if ( nga->current==NULL ) {
785 attr=createEmptyList();
787 for (i=0; i<nga->current->ports; ++i) {
788 if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
792 pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
797 return writeRequest(nga, attr);
803 // --------------------------------------
804 int ngadmin_restart (struct ngadmin *nga) {
809 attr=createEmptyList();
810 pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
813 return writeRequest(nga, attr);
819 // ---------------------------------------
820 int ngadmin_defaults (struct ngadmin *nga) {
826 attr=createEmptyList();
827 pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
828 if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
833 // successful: delog and clean list
848 // -----------------------------------------------------
849 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
859 if ( nga==NULL || ports==NULL ) {
861 } else if ( (sa=nga->current)==NULL ) {
866 attr=createEmptyList();
867 pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
868 if ( (ret=readRequest(nga, attr))<0 ) {
872 for (ln=attr->first; ln!=NULL; ln=ln->next) {
875 if ( at->attr==ATTR_MIRROR && at->size>=2+sa->ports/8 && p[0]<=nga->current->ports ) {
877 for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
878 ports[i]=(p[2]>>(sa->ports-i))&1;
886 destroyList(attr, (void(*)(void*))freeAttr);
895 // -----------------------------------------------------------
896 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
906 } else if ( (sa=nga->current)==NULL ) {
911 p=malloc(3); // FIXME: if ports>8
914 if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
916 for (i=1; i<=sa->ports; ++i) {
918 p[2]|=(ports[i]&1)<<(sa->ports-i);
923 attr=createEmptyList();
924 pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
927 return writeRequest(nga, attr);
933 // ----------------------------------------------------------------
934 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
945 if ( nga==NULL || ic==NULL ) {
947 } else if ( (sa=nga->current)==NULL ) {
952 ATTR_IGMP_ENABLE_VLAN
956 Apparently, read-querying theses attributes at the same time causes the switch to reply garbage.
957 Here we are forced to do like the official win app and send a separate request for each attribute.
961 attr=createEmptyList();
962 memset(ic, 0, sizeof(struct igmp_conf));
965 pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
966 if ( (ret=readRequest(nga, attr))<0 ) {
970 for (ln=attr->first; ln!=NULL; ln=ln->next) {
973 if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
974 ic->enable= ntohs(s[0])!=0 ;
975 ic->vlan=htons(s[1]);
980 clearList(attr, (void(*)(void*))freeAttr);
983 pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
984 if ( (ret=readRequest(nga, attr))<0 ) {
988 for (ln=attr->first; ln!=NULL; ln=ln->next) {
991 if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
997 clearList(attr, (void(*)(void*))freeAttr);
1000 pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1001 if ( (ret=readRequest(nga, attr))<0 ) {
1005 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1008 if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1009 ic->validate= p[0]!=0 ;
1017 destroyList(attr, (void(*)(void*))freeAttr);
1026 // ----------------------------------------------------------------------
1027 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1031 struct swi_attr *sa;
1034 if ( nga==NULL || ic==NULL ) {
1036 } else if ( (sa=nga->current)==NULL ) {
1041 s=malloc(2*sizeof(short));
1042 s[0]=htons(ic->enable!=false);
1043 s[1]=htons(ic->vlan&0x0FFF);
1045 attr=createEmptyList();
1046 pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
1047 pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
1048 pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
1051 return writeRequest(nga, attr);
1057 // ----------------------------------------------------------------------
1058 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1064 struct swi_attr *sa;
1068 if ( nga==NULL || ct==NULL ) {
1070 } else if ( (sa=nga->current)==NULL ) {
1075 attr=createEmptyList();
1077 for (i=0; i<nb; ++i) {
1078 if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1083 pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1085 ret=writeRequest(nga, attr);
1087 if ( ret<0 ) goto end;
1089 // the list is destroyed by writeRequest, so we need to recreate it
1090 attr=createEmptyList();
1091 pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1093 if ( (ret=readRequest(nga, attr))<0 ) goto end;
1095 for (ln=attr->first; ln!=NULL; ln=ln->next) {
1098 if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
1099 ct[i].v1=ntohl(*(int*)&p[1]);
1100 ct[i].v2=ntohl(*(int*)&p[5]);
1105 // just empty the list, it will be used at next iteration
1106 clearList(attr, (void(*)(void*))freeAttr);
1113 destroyList(attr, (void(*)(void*))freeAttr);