]> git.sur5r.net Git - ngadmin/blob - lib/src/ngadmin.c
Added support for changing the network configuration.
[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;
593  struct {
594   char port;
595   int bitrate;
596  } __attribute__((packed)) *p;
597  
598  
599  if ( nga==NULL || ports==NULL ) {
600   return ERR_INVARG;
601  } else if ( nga->current==NULL ) {
602   return ERR_NOTLOG;
603  }
604  
605  
606  attr=createEmptyList();
607  pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
608  pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
609  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
610   goto end;
611  }
612  
613  
614  for (ln=attr->first; ln!=NULL; ln=ln->next) {
615   at=ln->data;
616   p=at->data;
617   if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
618   if ( at->attr==ATTR_BITRATE_INPUT ) {
619    ports[(p->port-1)*2+0]=ntohl(p->bitrate);
620   } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
621    ports[(p->port-1)*2+1]=ntohl(p->bitrate);
622   }
623  }
624  
625  
626  end:
627  destroyList(attr, (void(*)(void*))freeAttr);
628  
629  return ret;
630  
631 }
632
633
634
635 // -----------------------------------------------------------------
636 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
637  
638  List *attr;
639  int i;
640  char *p;
641  
642  
643  if ( nga==NULL || ports==NULL ) {
644   return ERR_INVARG;
645  } else if ( nga->current==NULL ) {
646   return ERR_NOTLOG;
647  }
648  
649  
650  attr=createEmptyList();
651  
652  for (i=0; i<nga->current->ports; ++i) {
653   if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
654    p=malloc(5);
655    *p=i+1;
656    *(int*)(p+1)=htonl(ports[2*i+0]);
657    pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
658   }
659   if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
660    p=malloc(5);
661    *p=i+1;
662    *(int*)(p+1)=htonl(ports[2*i+1]);
663    pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
664   }
665  }
666  
667  
668  return writeRequest(nga, attr);
669  
670 }
671
672
673
674 // -------------------------------------------------
675 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
676  
677  List *attr;
678  ListNode *ln;
679  struct attr *at;
680  int ret=ERR_OK;
681  
682  
683  if ( nga==NULL || s==NULL ) {
684   return ERR_INVARG;
685  } else if ( nga->current==NULL ) {
686   return ERR_NOTLOG;
687  }
688  
689  
690  attr=createEmptyList();
691  pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
692  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
693   goto end;
694  }
695  
696  
697  for (ln=attr->first; ln!=NULL; ln=ln->next) {
698   at=ln->data;
699   if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
700    *s= *(char*)at->data ;
701    break;
702   }
703  }
704  
705  
706  end:
707  destroyList(attr, (void(*)(void*))freeAttr);
708  
709  return ret;
710  
711 }
712
713
714 // ------------------------------------------------
715 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
716  
717  List *attr;
718  
719  
720  if ( s<QOS_PORT || s>QOS_DOT ) {
721   return ERR_INVARG;
722  }
723  
724  attr=createEmptyList();
725  pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
726  
727  
728  return writeRequest(nga, attr);
729  
730 }
731
732
733
734 // -------------------------------------------------------
735 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
736  
737  List *attr;
738  ListNode *ln;
739  struct attr *at;
740  int ret=ERR_OK;
741  char *p;
742  
743  
744  if ( nga==NULL || ports==NULL ) {
745   return ERR_INVARG;
746  } else if ( nga->current==NULL ) {
747   return ERR_NOTLOG;
748  }
749  
750  
751  attr=createEmptyList();
752  pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
753  if ( (ret=readRequest(nga, attr))<0 ) {
754   goto end;
755  }
756  
757  for (ln=attr->first; ln!=NULL; ln=ln->next) {
758   at=ln->data;
759   p=at->data;
760   if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
761    ports[(int)p[0]]=p[1];
762   }
763  }
764  
765  
766  end:
767  destroyList(attr, (void(*)(void*))freeAttr);
768  
769  
770  return ret;
771  
772 }
773
774
775
776 // --------------------------------------------------------------
777 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
778  
779  List *attr;
780  int i;
781  char *p;
782  
783  
784  if ( nga==NULL || ports==NULL ) {
785   return ERR_INVARG;
786  } else if ( nga->current==NULL ) {
787   return ERR_NOTLOG;
788  }
789  
790  
791  attr=createEmptyList();
792  
793  for (i=0; i<nga->current->ports; ++i) {
794   if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
795    p=malloc(2);
796    p[0]=i+1;
797    p[1]=ports[i];
798    pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
799   }
800  }
801  
802  
803  return writeRequest(nga, attr);
804  
805 }
806
807
808
809 // --------------------------------------
810 int ngadmin_restart (struct ngadmin *nga) {
811  
812  List *attr;
813  
814  
815  attr=createEmptyList();
816  pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
817  
818  
819  return writeRequest(nga, attr);
820  
821 }
822
823
824
825 // ---------------------------------------
826 int ngadmin_defaults (struct ngadmin *nga) {
827  
828  List *attr;
829  int ret=ERR_OK;
830  
831  
832  attr=createEmptyList();
833  pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
834  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
835   goto end;
836  }
837  
838  
839  // successful: delog and clean list
840  free(nga->swi_tab);
841  nga->swi_tab=NULL;
842  nga->swi_count=0;
843  nga->current=NULL;
844  
845  
846  end:
847  
848  return ret;
849  
850 }
851
852
853
854 // -----------------------------------------------------
855 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
856  
857  List *attr;
858  ListNode *ln;
859  struct attr *at;
860  struct swi_attr *sa;
861  int ret=ERR_OK, i;
862  unsigned char *p;
863  
864  
865  if ( nga==NULL || ports==NULL ) {
866   return ERR_INVARG;
867  } else if ( (sa=nga->current)==NULL ) {
868   return ERR_NOTLOG;
869  }
870  
871  
872  attr=createEmptyList();
873  pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
874  if ( (ret=readRequest(nga, attr))<0 ) {
875   goto end;
876  }
877  
878  for (ln=attr->first; ln!=NULL; ln=ln->next) {
879   at=ln->data;
880   p=at->data;
881   if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
882    ports[0]=p[0];
883    for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
884     ports[i]=(p[2]>>(sa->ports-i))&1;
885    }
886    break;
887   }
888  }
889  
890  
891  end:
892  destroyList(attr, (void(*)(void*))freeAttr);
893  
894  
895  return ret;
896  
897 }
898
899
900
901 // -----------------------------------------------------------
902 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
903  
904  List *attr;
905  int i;
906  char *p;
907  struct swi_attr *sa;
908  
909  
910  if ( nga==NULL ) {
911   return ERR_INVARG;
912  } else if ( (sa=nga->current)==NULL ) {
913   return ERR_NOTLOG;
914  }
915  
916  
917  p=malloc(3); // FIXME: if ports>8
918  memset(p, 0, 3);
919  
920  if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
921   p[0]=ports[0];
922   for (i=1; i<=sa->ports; ++i) {
923    if ( i!=p[0] ) {
924     p[2]|=(ports[i]&1)<<(sa->ports-i);
925    }
926   }
927  }
928  
929  attr=createEmptyList();
930  pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
931  
932  
933  return writeRequest(nga, attr);
934  
935 }
936
937
938
939 // ----------------------------------------------------------------
940 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
941  
942  List *attr;
943  ListNode *ln;
944  struct attr *at;
945  struct swi_attr *sa;
946  int ret=ERR_OK;
947  unsigned char *p;
948  unsigned short *s;
949  
950  
951  if ( nga==NULL || ic==NULL ) {
952   return ERR_INVARG;
953  } else if ( (sa=nga->current)==NULL ) {
954   return ERR_NOTLOG;
955  }
956  
957  /*
958  ATTR_IGMP_ENABLE_VLAN
959  ATTR_IGMP_BLOCK_UNK
960  ATTR_IGMP_VALID_V3
961  
962  Apparently, read-querying theses attributes at the same time causes the switch to reply garbage. 
963  Here we are forced to do like the official win app and send a separate request for each attribute. 
964  */
965  
966  
967  attr=createEmptyList();
968  memset(ic, 0, sizeof(struct igmp_conf));
969  
970  
971  pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
972  if ( (ret=readRequest(nga, attr))<0 ) {
973   goto end;
974  }
975  
976  for (ln=attr->first; ln!=NULL; ln=ln->next) {
977   at=ln->data;
978   s=at->data;
979   if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
980    ic->enable= ntohs(s[0])!=0 ;
981    ic->vlan=htons(s[1]);
982    break;
983   }
984  }
985  
986  clearList(attr, (void(*)(void*))freeAttr);
987  
988  
989  pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
990  if ( (ret=readRequest(nga, attr))<0 ) {
991   goto end;
992  }
993  
994  for (ln=attr->first; ln!=NULL; ln=ln->next) {
995   at=ln->data;
996   p=at->data;
997   if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
998    ic->block= p[0]!=0 ;
999    break;
1000   }
1001  }
1002  
1003  clearList(attr, (void(*)(void*))freeAttr);
1004  
1005  
1006  pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1007  if ( (ret=readRequest(nga, attr))<0 ) {
1008   goto end;
1009  }
1010  
1011  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1012   at=ln->data;
1013   p=at->data;
1014   if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1015    ic->validate= p[0]!=0 ;
1016    break;
1017   }
1018  }
1019  
1020  
1021  
1022  end:
1023  destroyList(attr, (void(*)(void*))freeAttr);
1024  
1025  
1026  return ret;
1027  
1028 }
1029
1030
1031
1032 // ----------------------------------------------------------------------
1033 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1034  
1035  List *attr;
1036  short *s;
1037  struct swi_attr *sa;
1038  
1039  
1040  if ( nga==NULL || ic==NULL ) {
1041   return ERR_INVARG;
1042  } else if ( (sa=nga->current)==NULL ) {
1043   return ERR_NOTLOG;
1044  }
1045  
1046  
1047  s=malloc(2*sizeof(short));
1048  s[0]=htons(ic->enable!=false);
1049  s[1]=htons(ic->vlan&0x0FFF);
1050  
1051  attr=createEmptyList();
1052  pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
1053  pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
1054  pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
1055  
1056  
1057  return writeRequest(nga, attr);
1058  
1059 }
1060
1061
1062
1063 // ----------------------------------------------------------------------
1064 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1065  
1066  List *attr;
1067  ListNode *ln;
1068  struct attr *at;
1069  int i, ret=ERR_OK;
1070  struct swi_attr *sa;
1071  char *p;
1072  
1073  
1074  if ( nga==NULL || ct==NULL ) {
1075   return ERR_INVARG;
1076  } else if ( (sa=nga->current)==NULL ) {
1077   return ERR_NOTLOG;
1078  }
1079  
1080  
1081  attr=createEmptyList();
1082  
1083  for (i=0; i<nb; ++i) {
1084   if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1085    
1086    p=malloc(2);
1087    p[0]=ct[i].port;
1088    p[1]=1;
1089    pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1090    
1091    ret=writeRequest(nga, attr);
1092    attr=NULL;
1093    if ( ret<0 ) goto end;
1094    
1095    // the list is destroyed by writeRequest, so we need to recreate it
1096    attr=createEmptyList();
1097    pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1098    
1099    if ( (ret=readRequest(nga, attr))<0 ) goto end;
1100    
1101    for (ln=attr->first; ln!=NULL; ln=ln->next) {
1102     at=ln->data;
1103     p=at->data;
1104     if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
1105      ct[i].v1=ntohl(*(int*)&p[1]);
1106      ct[i].v2=ntohl(*(int*)&p[5]);
1107      break;
1108     }
1109    }
1110    
1111    // just empty the list, it will be used at next iteration
1112    clearList(attr, (void(*)(void*))freeAttr);
1113    
1114   }
1115  }
1116  
1117  
1118  end:
1119  destroyList(attr, (void(*)(void*))freeAttr);
1120  
1121  return ret;
1122  
1123 }
1124
1125
1126
1127 // --------------------------------------------------------------------
1128 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
1129  
1130  List *attr;
1131  struct swi_attr *sa;
1132  int ret=ERR_OK;
1133  
1134  
1135  if ( nga==NULL || nc==NULL ) {
1136   return ERR_INVARG;
1137  } else if ( (sa=nga->current)==NULL ) {
1138   return ERR_NOTLOG;
1139  }
1140  
1141  
1142  attr=createEmptyList();
1143  
1144  if ( nc->dhcp ) {
1145   pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
1146  } else {
1147   pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
1148   if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1149   if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1150   if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1151  }
1152  
1153  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
1154   goto end;
1155  }
1156  
1157  
1158  if ( nc->dhcp ) {
1159   sa->nc.dhcp=true;
1160  } else {
1161   memcpy(&sa->nc, nc, sizeof(struct net_conf));
1162  }
1163  
1164  
1165  end:
1166  
1167  return ret;
1168  
1169 }
1170
1171
1172
1173 // --------------------------------------------------
1174 int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
1175  
1176  List *attr;
1177  ListNode *ln;
1178  struct attr *at;
1179  int ret=ERR_OK;
1180  
1181  
1182  if ( nga==NULL || t==NULL ) {
1183   return ERR_INVARG;
1184  } else if ( nga->current==NULL ) {
1185   return ERR_NOTLOG;
1186  }
1187  
1188  
1189  attr=createEmptyList();
1190  pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1191  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1192   goto end;
1193  }
1194  
1195  
1196  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1197   at=ln->data;
1198   if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
1199    *t= (int)*(char*)at->data ;
1200    break;
1201   }
1202  }
1203  
1204  
1205  end:
1206  destroyList(attr, (void(*)(void*))freeAttr);
1207  
1208  return ret;
1209  
1210 }
1211
1212
1213
1214 // ------------------------------------------------------------------
1215 int ngadmin_getVLANDotConf (struct ngadmin *nga, char *buf, int *len) {
1216  
1217  List *attr;
1218  ListNode *ln;
1219  struct attr *at;
1220  struct swi_attr *sa;
1221  int ret=ERR_OK, i;
1222  char *b=buf, *p=NULL;
1223  
1224  
1225  if ( nga==NULL || buf==NULL || len==NULL || *len<=0 ) {
1226   return ERR_INVARG;
1227  } else if ( (sa=nga->current)==NULL ) {
1228   return ERR_NOTLOG;
1229  }
1230  
1231  
1232  attr=createEmptyList();
1233  pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1234  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1235   goto end;
1236  }
1237  
1238  
1239  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1240   at=ln->data;
1241   p=at->data;
1242   if ( (b-buf)+2+sa->ports>*len ) break; // no more room
1243   if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1244    *(unsigned short*)b=ntohs(*(unsigned short*)p);b+=2;
1245    for (i=1; i<=sa->ports; ++i) {
1246     if ( (p[3]>>(sa->ports-i))&1 ) *b++=VLAN_TAGGED; // tagged
1247     else if ( (p[2]>>(sa->ports-i))&1 ) *b++=VLAN_UNTAGGED; // untagged
1248     else *b++=VLAN_NO;
1249    }
1250   }
1251  }
1252  
1253  *len=b-buf;
1254  
1255  
1256  end:
1257  destroyList(attr, (void(*)(void*))freeAttr);
1258  
1259  return ret;
1260  
1261 }
1262
1263
1264
1265
1266