]> git.sur5r.net Git - ngadmin/blob - lib/src/ngadmin.c
Added the possibility to specify the command timeout.
[ngadmin] / lib / src / ngadmin.c
1
2 #include "lib.h"
3 #include "network.h"
4
5
6
7 static const struct timeval default_timeout={.tv_sec=4, .tv_usec=0};
8
9
10
11 // ---------------------------------------------
12 struct ngadmin* ngadmin_init (const char *iface) {
13  
14  struct ngadmin *nga;
15  
16  
17  // allocate main structure
18  nga=malloc(sizeof(struct ngadmin));
19  memset(nga, 0, sizeof(struct ngadmin));
20  
21  strncpy(nga->iface, iface, IFNAMSIZ-1);
22  
23  if ( startNetwork(nga)<0 ) {
24   free(nga);
25   return NULL;
26  }
27  
28  nga->timeout=default_timeout;
29  if ( updateTimeout(nga)<0 ) {
30   free(nga);
31   return NULL;
32  }
33  
34  
35  return nga;
36  
37 }
38
39
40
41 // ------------------------------------
42 int ngadmin_close (struct ngadmin *nga) {
43  
44  if ( nga==NULL ) {
45   return ERR_INVARG;
46  }
47  
48  
49  stopNetwork(nga);
50  free(nga->swi_tab);
51  free(nga);
52  
53  
54  return ERR_OK;
55  
56 }
57
58
59
60 // ---------------------------------------------
61 int ngadmin_forceInterface (struct ngadmin *nga) {
62  
63  
64  if ( nga==NULL ) {
65   return ERR_INVARG;
66  }
67  
68  
69  if ( forceInterface(nga)!=0 ) {
70   return ERR_NET;
71  } else {
72   return ERR_OK;
73  }
74  
75 }
76
77
78
79 // --------------------------------------------------------------
80 int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) {
81  
82  
83  if ( nga==NULL ) {
84   return ERR_INVARG;
85  }
86  
87  
88  nga->keepbroad=value;
89  
90  
91  return ERR_OK;
92  
93 }
94
95
96
97 // ------------------------------------------------------------
98 int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
99  
100  if ( nga==NULL ) {
101   return ERR_INVARG;
102  }
103  
104  
105  strncpy(nga->password, pass, PASSWORD_MAX);
106  
107  
108  return ERR_OK;
109  
110 }
111
112
113
114 // -------------------------------------------------------------------
115 int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) {
116  
117  int ret=ERR_OK;
118  
119  
120  if ( nga==NULL || tv==NULL ) {
121   return ERR_INVARG;
122  }
123  
124  
125  nga->timeout=*tv;
126  if ( updateTimeout(nga)<0 ) {
127   ret=ERR_NET;
128  }
129  
130  
131  return ret;
132  
133 }
134
135
136
137 // -----------------------------------
138 int ngadmin_scan (struct ngadmin *nga) {
139  
140  int i;
141  List *attr, *swiList;
142  struct swi_attr *sa;
143  /*
144  sent by official win client:
145   ATTR_PRODUCT, 
146   ATTR_UNK2, 
147   ATTR_NAME, 
148   ATTR_MAC, 
149   ATTR_UNK5, 
150   ATTR_IP, 
151   ATTR_NETMASK, 
152   ATTR_GATEWAY, 
153   ATTR_DHCP, 
154   ATTR_UNK12, 
155   ATTR_FIRM_VER, 
156   ATTR_UNK14, 
157   ATTR_UNK15, 
158   ATTR_END
159  */
160  static const unsigned short hello[]={
161   ATTR_PRODUCT, 
162   ATTR_NAME, 
163   ATTR_MAC, 
164   ATTR_IP, 
165   ATTR_NETMASK, 
166   ATTR_GATEWAY, 
167   ATTR_DHCP, 
168   ATTR_FIRM_VER, 
169   ATTR_PORTS_COUNT, 
170   ATTR_END
171  };
172  
173  
174  if ( nga==NULL ) {
175   return ERR_INVARG;
176  }
177  
178  free(nga->swi_tab);
179  nga->swi_tab=NULL;
180  nga->swi_count=0;
181  nga->current=NULL;
182  
183  
184  // create attributes for an "hello" request
185  attr=createEmptyList();
186  for (i=0; ; ++i) {
187   pushBackList(attr, newEmptyAttr(hello[i]));
188   if ( hello[i]==ATTR_END ) break;
189  }
190  
191  // send request to all potential switches
192  i=sendNgPacket(nga, CODE_READ_REQ, attr);
193  clearList(attr, (void(*)(void*))freeAttr);
194  if ( i<0 ) {
195   return ERR_NET;
196  }
197  
198  
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);
206  }
207  
208  nga->swi_count=swiList->count;
209  nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
210  
211  
212  return ERR_OK;
213  
214 }
215
216
217
218 // -----------------------------------------------------------------------
219 const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
220  
221  
222  if ( nga==NULL || nb==NULL ) {
223   return NULL;
224  }
225  
226  
227  *nb=nga->swi_count;
228  
229  
230  return nga->swi_tab;
231  
232 }
233
234
235
236 // ------------------------------------------------------------------
237 const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
238  
239  
240  if ( nga==NULL ) {
241   return NULL;
242  }
243  
244  
245  return nga->current;
246  
247 }
248
249
250
251 // --------------------------------------------
252 int ngadmin_login (struct ngadmin *nga, int id) {
253  
254  List *attr;
255  int ret=ERR_OK;
256  struct swi_attr *sa;
257  
258  
259  if ( nga==NULL ) {
260   return ERR_INVARG;
261  } else if ( id<0 || id>=nga->swi_count ) {
262   return ERR_BADID;
263  }
264  
265  
266  sa=&nga->swi_tab[id];
267  nga->current=sa;
268  
269  attr=createEmptyList();
270  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
271  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
272   // login failed
273   nga->current=NULL;
274  }
275  
276  destroyList(attr, (void(*)(void*))freeAttr);
277  
278  
279  return ret;
280  
281 }
282
283
284
285 // -------------------------------------------------------------------
286 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
287  
288  List *attr;
289  ListNode *ln;
290  struct attr *at;
291  int ret=ERR_OK, i;
292  char *p;
293  
294  
295  if ( nga==NULL || ports==NULL ) {
296   return ERR_INVARG;
297  } else if ( nga->current==NULL ) {
298   return ERR_NOTLOG;
299  }
300  
301  
302  attr=createEmptyList();
303  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
304  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
305   goto end;
306  }
307  
308  for (ln=attr->first; ln!=NULL; ln=ln->next) {
309   at=ln->data;
310   p=at->data;
311   if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
312    ports[i]=p[1];
313   }
314  }
315  
316  
317  end:
318  destroyList(attr, (void(*)(void*))freeAttr);
319  
320  return ret;
321  
322 }
323
324
325
326 // --------------------------------------------------------
327 int ngadmin_setName (struct ngadmin *nga, const char *name) {
328  
329  List *attr;
330  int ret=ERR_OK;
331  
332  
333  if ( nga==NULL ) {
334   return ERR_INVARG;
335  } else if ( nga->current==NULL ) {
336   return ERR_NOTLOG;
337  }
338  
339  
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 ) {
343   goto end;
344  }
345  
346  
347  // successful, also update local name
348  if ( name==NULL ) {
349   nga->current->name[0]=0;
350  } else {
351   strncpy(nga->current->name, name, NAME_SIZE);
352  }
353  
354  
355  end:
356  
357  return ret;
358  
359 }
360
361
362
363 // ------------------------------------------------------------------------
364 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
365  
366  List *attr;
367  ListNode *ln;
368  struct attr *at;
369  int ret=ERR_OK;
370  int port;
371  
372  
373  if ( nga==NULL || ps==NULL ) {
374   return ERR_INVARG;
375  } else if ( nga->current==NULL ) {
376   return ERR_NOTLOG;
377  }
378  
379  
380  attr=createEmptyList();
381  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
382  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
383   goto end;
384  }
385  
386  
387  for (ln=attr->first; ln!=NULL; ln=ln->next) {
388   at=ln->data;
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
394   }
395  }
396  
397  
398  end:
399  destroyList(attr, (void(*)(void*))freeAttr);
400  
401  return ret;
402  
403 }
404
405
406
407 // ---------------------------------------------------
408 int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
409  
410  List *attr;
411  
412  
413  attr=createEmptyList();
414  pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
415  
416  
417  return writeRequest(nga, attr);
418  
419 }
420
421
422
423 // ---------------------------------------------------------------
424 int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
425  
426  List *attr;
427  int ret=ERR_OK;
428  
429  
430  if ( nga==NULL || pass==NULL ) {
431   return ERR_INVARG;
432  } else if ( nga->current==NULL ) {
433   return ERR_NOTLOG;
434  }
435  
436  
437  attr=createEmptyList();
438  pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
439  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
440   goto end;
441  }
442  
443  
444  // successful, also update local password
445  strncpy(nga->password, pass, PASSWORD_MAX);
446  
447  
448  end:
449  
450  return ret;
451  
452 }
453
454
455
456 // ----------------------------------------------------------
457 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
458  
459  List *attr;
460  ListNode *ln;
461  struct attr *at;
462  int ret=ERR_OK;
463  
464  
465  if ( nga==NULL || s==NULL ) {
466   return ERR_INVARG;
467  } else if ( nga->current==NULL ) {
468   return ERR_NOTLOG;
469  }
470  
471  
472  attr=createEmptyList();
473  pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
474  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
475   goto end;
476  }
477  
478  
479  for (ln=attr->first; ln!=NULL; ln=ln->next) {
480   at=ln->data;
481   if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
482    *s= *(char*)at->data!=0 ;
483    break;
484   }
485  }
486  
487  
488  end:
489  destroyList(attr, (void(*)(void*))freeAttr);
490  
491  return ret;
492  
493 }
494
495
496
497 // ---------------------------------------------------------
498 int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
499  
500  List *attr;
501  
502  
503  attr=createEmptyList();
504  pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
505  
506  
507  return writeRequest(nga, attr);
508  
509 }
510
511
512
513 // ---------------------------------------------------------------
514 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
515  
516  List *attr;
517  ListNode *ln;
518  struct attr *at;
519  int ret=ERR_OK, i;
520  
521  
522  if ( nga==NULL || ports==NULL ) {
523   return ERR_INVARG;
524  } else if ( nga->current==NULL ) {
525   return ERR_NOTLOG;
526  }
527  
528  
529  attr=createEmptyList();
530  pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
531  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
532   goto end;
533  }
534  
535  
536  for (ln=attr->first; ln!=NULL; ln=ln->next) {
537   at=ln->data;
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));
540   }
541  }
542  
543  
544  end:
545  destroyList(attr, (void(*)(void*))freeAttr);
546  
547  return ret;
548  
549 }
550
551
552
553 // ---------------------------------------------------------------------
554 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
555  
556  List *attr;
557  int i;
558  char *p;
559  
560  
561  if ( nga==NULL || ports==NULL ) {
562   return ERR_INVARG;
563  } else if ( nga->current==NULL ) {
564   return ERR_NOTLOG;
565  }
566  
567  
568  attr=createEmptyList();
569  
570  for (i=0; i<nga->current->ports; ++i) {
571   if ( ports[i]>=0 && ports[i]<=11 ) {
572    p=malloc(5);
573    *p=i+1;
574    *(int*)(p+1)=htonl(ports[i]);
575    pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
576   }
577  }
578  
579  
580  return writeRequest(nga, attr);
581  
582 }
583
584
585
586 // -----------------------------------------------------------
587 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
588  
589  List *attr;
590  ListNode *ln;
591  struct attr *at;
592  int ret=ERR_OK, i;
593  
594  
595  if ( nga==NULL || ports==NULL ) {
596   return ERR_INVARG;
597  } else if ( nga->current==NULL ) {
598   return ERR_NOTLOG;
599  }
600  
601  
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 ) {
606   goto end;
607  }
608  
609  
610  for (ln=attr->first; ln!=NULL; ln=ln->next) {
611   at=ln->data;
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));
616   }
617  }
618  
619  
620  end:
621  destroyList(attr, (void(*)(void*))freeAttr);
622  
623  return ret;
624  
625 }
626
627
628
629 // -----------------------------------------------------------------
630 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
631  
632  List *attr;
633  int i;
634  char *p;
635  
636  
637  if ( nga==NULL || ports==NULL ) {
638   return ERR_INVARG;
639  } else if ( nga->current==NULL ) {
640   return ERR_NOTLOG;
641  }
642  
643  
644  attr=createEmptyList();
645  
646  for (i=0; i<nga->current->ports; ++i) {
647   if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
648    p=malloc(5);
649    *p=i+1;
650    *(int*)(p+1)=htonl(ports[2*i+0]);
651    pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
652   }
653   if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
654    p=malloc(5);
655    *p=i+1;
656    *(int*)(p+1)=htonl(ports[2*i+1]);
657    pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
658   }
659  }
660  
661  
662  return writeRequest(nga, attr);
663  
664 }
665
666
667
668 // -------------------------------------------------
669 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
670  
671  List *attr;
672  ListNode *ln;
673  struct attr *at;
674  int ret=ERR_OK;
675  
676  
677  if ( nga==NULL || s==NULL ) {
678   return ERR_INVARG;
679  } else if ( nga->current==NULL ) {
680   return ERR_NOTLOG;
681  }
682  
683  
684  attr=createEmptyList();
685  pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
686  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
687   goto end;
688  }
689  
690  
691  for (ln=attr->first; ln!=NULL; ln=ln->next) {
692   at=ln->data;
693   if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
694    *s= *(char*)at->data ;
695    break;
696   }
697  }
698  
699  
700  end:
701  destroyList(attr, (void(*)(void*))freeAttr);
702  
703  return ret;
704  
705 }
706
707
708 // ------------------------------------------------
709 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
710  
711  List *attr;
712  
713  
714  if ( s<QOS_PORT || s>QOS_DOT ) {
715   return ERR_INVARG;
716  }
717  
718  attr=createEmptyList();
719  pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
720  
721  
722  return writeRequest(nga, attr);
723  
724 }
725
726
727
728 // -------------------------------------------------------
729 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
730  
731  List *attr;
732  ListNode *ln;
733  struct attr *at;
734  int ret=ERR_OK;
735  char *p;
736  
737  
738  if ( nga==NULL || ports==NULL ) {
739   return ERR_INVARG;
740  } else if ( nga->current==NULL ) {
741   return ERR_NOTLOG;
742  }
743  
744  
745  attr=createEmptyList();
746  pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
747  if ( (ret=readRequest(nga, attr))<0 ) {
748   goto end;
749  }
750  
751  for (ln=attr->first; ln!=NULL; ln=ln->next) {
752   at=ln->data;
753   p=at->data;
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];
756   }
757  }
758  
759  
760  end:
761  destroyList(attr, (void(*)(void*))freeAttr);
762  
763  
764  return ret;
765  
766 }
767
768
769
770 // --------------------------------------------------------------
771 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
772  
773  List *attr;
774  int i;
775  char *p;
776  
777  
778  if ( nga==NULL || ports==NULL ) {
779   return ERR_INVARG;
780  } else if ( nga->current==NULL ) {
781   return ERR_NOTLOG;
782  }
783  
784  
785  attr=createEmptyList();
786  
787  for (i=0; i<nga->current->ports; ++i) {
788   if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
789    p=malloc(2);
790    p[0]=i+1;
791    p[1]=ports[i];
792    pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
793   }
794  }
795  
796  
797  return writeRequest(nga, attr);
798  
799 }
800
801
802
803 // --------------------------------------
804 int ngadmin_restart (struct ngadmin *nga) {
805  
806  List *attr;
807  
808  
809  attr=createEmptyList();
810  pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
811  
812  
813  return writeRequest(nga, attr);
814  
815 }
816
817
818
819 // ---------------------------------------
820 int ngadmin_defaults (struct ngadmin *nga) {
821  
822  List *attr;
823  int ret=ERR_OK;
824  
825  
826  attr=createEmptyList();
827  pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
828  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
829   goto end;
830  }
831  
832  
833  // successful: delog and clean list
834  free(nga->swi_tab);
835  nga->swi_tab=NULL;
836  nga->swi_count=0;
837  nga->current=NULL;
838  
839  
840  end:
841  
842  return ret;
843  
844 }
845
846
847
848 // -----------------------------------------------------
849 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
850  
851  List *attr;
852  ListNode *ln;
853  struct attr *at;
854  struct swi_attr *sa;
855  int ret=ERR_OK, i;
856  unsigned char *p;
857  
858  
859  if ( nga==NULL || ports==NULL ) {
860   return ERR_INVARG;
861  } else if ( (sa=nga->current)==NULL ) {
862   return ERR_NOTLOG;
863  }
864  
865  
866  attr=createEmptyList();
867  pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
868  if ( (ret=readRequest(nga, attr))<0 ) {
869   goto end;
870  }
871  
872  for (ln=attr->first; ln!=NULL; ln=ln->next) {
873   at=ln->data;
874   p=at->data;
875   if ( at->attr==ATTR_MIRROR && at->size>=2+sa->ports/8 && p[0]<=nga->current->ports ) {
876    ports[0]=p[0];
877    for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
878     ports[i]=(p[2]>>(sa->ports-i))&1;
879    }
880    break;
881   }
882  }
883  
884  
885  end:
886  destroyList(attr, (void(*)(void*))freeAttr);
887  
888  
889  return ret;
890  
891 }
892
893
894
895 // -----------------------------------------------------------
896 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
897  
898  List *attr;
899  int i;
900  char *p;
901  struct swi_attr *sa;
902  
903  
904  if ( nga==NULL ) {
905   return ERR_INVARG;
906  } else if ( (sa=nga->current)==NULL ) {
907   return ERR_NOTLOG;
908  }
909  
910  
911  p=malloc(3); // FIXME: if ports>8
912  memset(p, 0, 3);
913  
914  if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
915   p[0]=ports[0];
916   for (i=1; i<=sa->ports; ++i) {
917    if ( i!=p[0] ) {
918     p[2]|=(ports[i]&1)<<(sa->ports-i);
919    }
920   }
921  }
922  
923  attr=createEmptyList();
924  pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
925  
926  
927  return writeRequest(nga, attr);
928  
929 }
930
931
932
933 // ----------------------------------------------------------------
934 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
935  
936  List *attr;
937  ListNode *ln;
938  struct attr *at;
939  struct swi_attr *sa;
940  int ret=ERR_OK;
941  unsigned char *p;
942  unsigned short *s;
943  
944  
945  if ( nga==NULL || ic==NULL ) {
946   return ERR_INVARG;
947  } else if ( (sa=nga->current)==NULL ) {
948   return ERR_NOTLOG;
949  }
950  
951  /*
952  ATTR_IGMP_ENABLE_VLAN
953  ATTR_IGMP_BLOCK_UNK
954  ATTR_IGMP_VALID_V3
955  
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. 
958  */
959  
960  
961  attr=createEmptyList();
962  memset(ic, 0, sizeof(struct igmp_conf));
963  
964  
965  pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
966  if ( (ret=readRequest(nga, attr))<0 ) {
967   goto end;
968  }
969  
970  for (ln=attr->first; ln!=NULL; ln=ln->next) {
971   at=ln->data;
972   s=at->data;
973   if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
974    ic->enable= ntohs(s[0])!=0 ;
975    ic->vlan=htons(s[1]);
976    break;
977   }
978  }
979  
980  clearList(attr, (void(*)(void*))freeAttr);
981  
982  
983  pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
984  if ( (ret=readRequest(nga, attr))<0 ) {
985   goto end;
986  }
987  
988  for (ln=attr->first; ln!=NULL; ln=ln->next) {
989   at=ln->data;
990   p=at->data;
991   if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
992    ic->block= p[0]!=0 ;
993    break;
994   }
995  }
996  
997  clearList(attr, (void(*)(void*))freeAttr);
998  
999  
1000  pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1001  if ( (ret=readRequest(nga, attr))<0 ) {
1002   goto end;
1003  }
1004  
1005  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1006   at=ln->data;
1007   p=at->data;
1008   if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1009    ic->validate= p[0]!=0 ;
1010    break;
1011   }
1012  }
1013  
1014  
1015  
1016  end:
1017  destroyList(attr, (void(*)(void*))freeAttr);
1018  
1019  
1020  return ret;
1021  
1022 }
1023
1024
1025
1026 // ----------------------------------------------------------------------
1027 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1028  
1029  List *attr;
1030  short *s;
1031  struct swi_attr *sa;
1032  
1033  
1034  if ( nga==NULL || ic==NULL ) {
1035   return ERR_INVARG;
1036  } else if ( (sa=nga->current)==NULL ) {
1037   return ERR_NOTLOG;
1038  }
1039  
1040  
1041  s=malloc(2*sizeof(short));
1042  s[0]=htons(ic->enable!=false);
1043  s[1]=htons(ic->vlan&0x0FFF);
1044  
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 ));
1049  
1050  
1051  return writeRequest(nga, attr);
1052  
1053 }
1054
1055
1056
1057 // ----------------------------------------------------------------------
1058 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1059  
1060  List *attr;
1061  ListNode *ln;
1062  struct attr *at;
1063  int i, ret=ERR_OK;
1064  struct swi_attr *sa;
1065  char *p;
1066  
1067  
1068  if ( nga==NULL || ct==NULL ) {
1069   return ERR_INVARG;
1070  } else if ( (sa=nga->current)==NULL ) {
1071   return ERR_NOTLOG;
1072  }
1073  
1074  
1075  attr=createEmptyList();
1076  
1077  for (i=0; i<nb; ++i) {
1078   if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1079    
1080    p=malloc(2);
1081    p[0]=ct[i].port;
1082    p[1]=1;
1083    pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1084    
1085    ret=writeRequest(nga, attr);
1086    attr=NULL;
1087    if ( ret<0 ) goto end;
1088    
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));
1092    
1093    if ( (ret=readRequest(nga, attr))<0 ) goto end;
1094    
1095    for (ln=attr->first; ln!=NULL; ln=ln->next) {
1096     at=ln->data;
1097     p=at->data;
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]);
1101      break;
1102     }
1103    }
1104    
1105    // just empty the list, it will be used at next iteration
1106    clearList(attr, (void(*)(void*))freeAttr);
1107    
1108   }
1109  }
1110  
1111  
1112  end:
1113  destroyList(attr, (void(*)(void*))freeAttr);
1114  
1115  return ret;
1116  
1117 }
1118
1119
1120