]> git.sur5r.net Git - ngadmin/blob - lib/src/ngadmin.c
Added chained makefiles.
[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 succeeded
273   // TODO: if keep broadcasting is disabled, connect() the UDP socket so icmp errors messages (port unreachable, TTL exceeded in transit, ...)can be received
274  } else {
275   // login failed
276   nga->current=NULL;
277  }
278  
279  destroyList(attr, (void(*)(void*))freeAttr);
280  
281  
282  return ret;
283  
284 }
285
286
287
288 // -------------------------------------------------------------------
289 int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
290  
291  List *attr;
292  ListNode *ln;
293  struct attr *at;
294  int ret=ERR_OK, i;
295  char *p;
296  
297  
298  if ( nga==NULL || ports==NULL ) {
299   return ERR_INVARG;
300  } else if ( nga->current==NULL ) {
301   return ERR_NOTLOG;
302  }
303  
304  
305  attr=createEmptyList();
306  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
307  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
308   goto end;
309  }
310  
311  for (ln=attr->first; ln!=NULL; ln=ln->next) {
312   at=ln->data;
313   p=at->data;
314   if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
315    ports[i]=p[1];
316   }
317  }
318  
319  
320  end:
321  destroyList(attr, (void(*)(void*))freeAttr);
322  
323  return ret;
324  
325 }
326
327
328
329 // --------------------------------------------------------
330 int ngadmin_setName (struct ngadmin *nga, const char *name) {
331  
332  List *attr;
333  int ret=ERR_OK;
334  
335  
336  if ( nga==NULL ) {
337   return ERR_INVARG;
338  } else if ( nga->current==NULL ) {
339   return ERR_NOTLOG;
340  }
341  
342  
343  attr=createEmptyList();
344  pushBackList(attr, name==NULL ? newEmptyAttr(ATTR_NAME) : newAttr(ATTR_NAME, strlen(name), strdup(name)) );
345  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
346   goto end;
347  }
348  
349  
350  // successful, also update local name
351  if ( name==NULL ) {
352   nga->current->name[0]=0;
353  } else {
354   strncpy(nga->current->name, name, NAME_SIZE);
355  }
356  
357  
358  end:
359  
360  return ret;
361  
362 }
363
364
365
366 // ------------------------------------------------------------------------
367 int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
368  
369  List *attr;
370  ListNode *ln;
371  struct attr *at;
372  int ret=ERR_OK;
373  int port;
374  
375  
376  if ( nga==NULL || ps==NULL ) {
377   return ERR_INVARG;
378  } else if ( nga->current==NULL ) {
379   return ERR_NOTLOG;
380  }
381  
382  
383  attr=createEmptyList();
384  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
385  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
386   goto end;
387  }
388  
389  
390  for (ln=attr->first; ln!=NULL; ln=ln->next) {
391   at=ln->data;
392   if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
393    ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
394    ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
395    ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
396    // all offsets between 2 and 4 inclusive are unknown values
397   }
398  }
399  
400  
401  end:
402  destroyList(attr, (void(*)(void*))freeAttr);
403  
404  return ret;
405  
406 }
407
408
409
410 // ---------------------------------------------------
411 int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
412  
413  List *attr;
414  
415  
416  attr=createEmptyList();
417  pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
418  
419  
420  return writeRequest(nga, attr);
421  
422 }
423
424
425
426 // ---------------------------------------------------------------
427 int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
428  
429  List *attr;
430  int ret=ERR_OK;
431  
432  
433  if ( nga==NULL || pass==NULL ) {
434   return ERR_INVARG;
435  } else if ( nga->current==NULL ) {
436   return ERR_NOTLOG;
437  }
438  
439  
440  attr=createEmptyList();
441  pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
442  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
443   goto end;
444  }
445  
446  
447  // successful, also update local password
448  strncpy(nga->password, pass, PASSWORD_MAX);
449  
450  
451  end:
452  
453  return ret;
454  
455 }
456
457
458
459 // ----------------------------------------------------------
460 int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
461  
462  List *attr;
463  ListNode *ln;
464  struct attr *at;
465  int ret=ERR_OK;
466  
467  
468  if ( nga==NULL || s==NULL ) {
469   return ERR_INVARG;
470  } else if ( nga->current==NULL ) {
471   return ERR_NOTLOG;
472  }
473  
474  
475  attr=createEmptyList();
476  pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
477  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
478   goto end;
479  }
480  
481  
482  for (ln=attr->first; ln!=NULL; ln=ln->next) {
483   at=ln->data;
484   if ( at->attr==ATTR_STORM_ENABLE && at->size>=1 ) {
485    *s= *(char*)at->data!=0 ;
486    break;
487   }
488  }
489  
490  
491  end:
492  destroyList(attr, (void(*)(void*))freeAttr);
493  
494  return ret;
495  
496 }
497
498
499
500 // ---------------------------------------------------------
501 int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
502  
503  List *attr;
504  
505  
506  attr=createEmptyList();
507  pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
508  
509  
510  return writeRequest(nga, attr);
511  
512 }
513
514
515
516 // ---------------------------------------------------------------
517 int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
518  
519  List *attr;
520  ListNode *ln;
521  struct attr *at;
522  int ret=ERR_OK, i;
523  
524  
525  if ( nga==NULL || ports==NULL ) {
526   return ERR_INVARG;
527  } else if ( nga->current==NULL ) {
528   return ERR_NOTLOG;
529  }
530  
531  
532  attr=createEmptyList();
533  pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
534  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
535   goto end;
536  }
537  
538  
539  for (ln=attr->first; ln!=NULL; ln=ln->next) {
540   at=ln->data;
541   if ( at->attr==ATTR_STORM_BITRATE && at->size>=5 && (i=(int)*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
542    ports[i]=ntohl(*(int*)(1+(char*)at->data));
543   }
544  }
545  
546  
547  end:
548  destroyList(attr, (void(*)(void*))freeAttr);
549  
550  return ret;
551  
552 }
553
554
555
556 // ---------------------------------------------------------------------
557 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
558  
559  List *attr;
560  int i;
561  char *p;
562  
563  
564  if ( nga==NULL || ports==NULL ) {
565   return ERR_INVARG;
566  } else if ( nga->current==NULL ) {
567   return ERR_NOTLOG;
568  }
569  
570  
571  attr=createEmptyList();
572  
573  for (i=0; i<nga->current->ports; ++i) {
574   if ( ports[i]>=0 && ports[i]<=11 ) {
575    p=malloc(5);
576    *p=i+1;
577    *(int*)(p+1)=htonl(ports[i]);
578    pushBackList(attr, newAttr(ATTR_STORM_BITRATE, 5, p));
579   }
580  }
581  
582  
583  return writeRequest(nga, attr);
584  
585 }
586
587
588
589 // -----------------------------------------------------------
590 int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
591  
592  List *attr;
593  ListNode *ln;
594  struct attr *at;
595  int ret=ERR_OK;
596  struct {
597   char port;
598   int bitrate;
599  } __attribute__((packed)) *p;
600  
601  
602  if ( nga==NULL || ports==NULL ) {
603   return ERR_INVARG;
604  } else if ( nga->current==NULL ) {
605   return ERR_NOTLOG;
606  }
607  
608  
609  attr=createEmptyList();
610  pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
611  pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
612  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
613   goto end;
614  }
615  
616  
617  for (ln=attr->first; ln!=NULL; ln=ln->next) {
618   at=ln->data;
619   p=at->data;
620   if ( at->size<sizeof(*p) || p->port<1 || p->port>nga->current->ports ) continue;
621   if ( at->attr==ATTR_BITRATE_INPUT ) {
622    ports[(p->port-1)*2+0]=ntohl(p->bitrate);
623   } else if ( at->attr==ATTR_BITRATE_OUTPUT ) {
624    ports[(p->port-1)*2+1]=ntohl(p->bitrate);
625   }
626  }
627  
628  
629  end:
630  destroyList(attr, (void(*)(void*))freeAttr);
631  
632  return ret;
633  
634 }
635
636
637
638 // -----------------------------------------------------------------
639 int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
640  
641  List *attr;
642  int i;
643  char *p;
644  
645  
646  if ( nga==NULL || ports==NULL ) {
647   return ERR_INVARG;
648  } else if ( nga->current==NULL ) {
649   return ERR_NOTLOG;
650  }
651  
652  
653  attr=createEmptyList();
654  
655  for (i=0; i<nga->current->ports; ++i) {
656   if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
657    p=malloc(5);
658    *p=i+1;
659    *(int*)(p+1)=htonl(ports[2*i+0]);
660    pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
661   }
662   if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
663    p=malloc(5);
664    *p=i+1;
665    *(int*)(p+1)=htonl(ports[2*i+1]);
666    pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
667   }
668  }
669  
670  
671  return writeRequest(nga, attr);
672  
673 }
674
675
676
677 // -------------------------------------------------
678 int ngadmin_getQOSMode (struct ngadmin *nga, int *s) {
679  
680  List *attr;
681  ListNode *ln;
682  struct attr *at;
683  int ret=ERR_OK;
684  
685  
686  if ( nga==NULL || s==NULL ) {
687   return ERR_INVARG;
688  } else if ( nga->current==NULL ) {
689   return ERR_NOTLOG;
690  }
691  
692  
693  attr=createEmptyList();
694  pushBackList(attr, newEmptyAttr(ATTR_QOS_TYPE));
695  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
696   goto end;
697  }
698  
699  
700  for (ln=attr->first; ln!=NULL; ln=ln->next) {
701   at=ln->data;
702   if ( at->attr==ATTR_QOS_TYPE && at->size>=1 ) {
703    *s= *(char*)at->data ;
704    break;
705   }
706  }
707  
708  
709  end:
710  destroyList(attr, (void(*)(void*))freeAttr);
711  
712  return ret;
713  
714 }
715
716
717 // ------------------------------------------------
718 int ngadmin_setQOSMode (struct ngadmin *nga, int s) {
719  
720  List *attr;
721  
722  
723  if ( s<QOS_PORT || s>QOS_DOT ) {
724   return ERR_INVARG;
725  }
726  
727  attr=createEmptyList();
728  pushBackList(attr, newByteAttr(ATTR_QOS_TYPE, s));
729  
730  
731  return writeRequest(nga, attr);
732  
733 }
734
735
736
737 // -------------------------------------------------------
738 int ngadmin_getQOSValues (struct ngadmin *nga, char *ports) {
739  
740  List *attr;
741  ListNode *ln;
742  struct attr *at;
743  int ret=ERR_OK;
744  char *p;
745  
746  
747  if ( nga==NULL || ports==NULL ) {
748   return ERR_INVARG;
749  } else if ( nga->current==NULL ) {
750   return ERR_NOTLOG;
751  }
752  
753  
754  attr=createEmptyList();
755  pushBackList(attr, newEmptyAttr(ATTR_QOS_CONFIG));
756  if ( (ret=readRequest(nga, attr))<0 ) {
757   goto end;
758  }
759  
760  for (ln=attr->first; ln!=NULL; ln=ln->next) {
761   at=ln->data;
762   p=at->data;
763   if ( at->attr==ATTR_QOS_CONFIG && at->size>=2 && --p[0]>=0 && p[0]<nga->current->ports ) {
764    ports[(int)p[0]]=p[1];
765   }
766  }
767  
768  
769  end:
770  destroyList(attr, (void(*)(void*))freeAttr);
771  
772  
773  return ret;
774  
775 }
776
777
778
779 // --------------------------------------------------------------
780 int ngadmin_setQOSValues (struct ngadmin *nga, const char *ports) {
781  
782  List *attr;
783  int i;
784  char *p;
785  
786  
787  if ( nga==NULL || ports==NULL ) {
788   return ERR_INVARG;
789  } else if ( nga->current==NULL ) {
790   return ERR_NOTLOG;
791  }
792  
793  
794  attr=createEmptyList();
795  
796  for (i=0; i<nga->current->ports; ++i) {
797   if ( ports[i]>=PRIO_HIGH && ports[i]<=PRIO_LOW ) {
798    p=malloc(2);
799    p[0]=i+1;
800    p[1]=ports[i];
801    pushBackList(attr, newAttr(ATTR_QOS_CONFIG, 2, p));
802   }
803  }
804  
805  
806  return writeRequest(nga, attr);
807  
808 }
809
810
811
812 // --------------------------------------
813 int ngadmin_restart (struct ngadmin *nga) {
814  
815  List *attr;
816  
817  
818  attr=createEmptyList();
819  pushBackList(attr, newByteAttr(ATTR_RESTART, 1));
820  
821  
822  return writeRequest(nga, attr);
823  
824 }
825
826
827
828 // ---------------------------------------
829 int ngadmin_defaults (struct ngadmin *nga) {
830  
831  List *attr;
832  int ret=ERR_OK;
833  
834  
835  attr=createEmptyList();
836  pushBackList(attr, newByteAttr(ATTR_DEFAULTS, 1));
837  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
838   goto end;
839  }
840  
841  
842  // successful: delog and clean list
843  free(nga->swi_tab);
844  nga->swi_tab=NULL;
845  nga->swi_count=0;
846  nga->current=NULL;
847  
848  
849  end:
850  
851  return ret;
852  
853 }
854
855
856
857 // -----------------------------------------------------
858 int ngadmin_getMirror (struct ngadmin *nga, char *ports) {
859  
860  List *attr;
861  ListNode *ln;
862  struct attr *at;
863  struct swi_attr *sa;
864  int ret=ERR_OK, i;
865  unsigned char *p;
866  
867  
868  if ( nga==NULL || ports==NULL ) {
869   return ERR_INVARG;
870  } else if ( (sa=nga->current)==NULL ) {
871   return ERR_NOTLOG;
872  }
873  
874  
875  attr=createEmptyList();
876  pushBackList(attr, newEmptyAttr(ATTR_MIRROR));
877  if ( (ret=readRequest(nga, attr))<0 ) {
878   goto end;
879  }
880  
881  for (ln=attr->first; ln!=NULL; ln=ln->next) {
882   at=ln->data;
883   p=at->data;
884   if ( at->attr==ATTR_MIRROR && at->size>=3 && p[0]<=nga->current->ports ) {
885    ports[0]=p[0];
886    for (i=1; i<=sa->ports; ++i) { // FIXME: if ports>8
887     ports[i]=(p[2]>>(8-i))&1;
888    }
889    break;
890   }
891  }
892  
893  
894  end:
895  destroyList(attr, (void(*)(void*))freeAttr);
896  
897  
898  return ret;
899  
900 }
901
902
903
904 // -----------------------------------------------------------
905 int ngadmin_setMirror (struct ngadmin *nga, const char *ports) {
906  
907  List *attr;
908  int i;
909  char *p;
910  struct swi_attr *sa;
911  
912  
913  if ( nga==NULL ) {
914   return ERR_INVARG;
915  } else if ( (sa=nga->current)==NULL ) {
916   return ERR_NOTLOG;
917  }
918  
919  
920  p=malloc(3); // FIXME: if ports>8
921  memset(p, 0, 3);
922  
923  if ( ports!=NULL && ports[0]>0 && ports[0]<=sa->ports ) {
924   p[0]=ports[0];
925   for (i=1; i<=sa->ports; ++i) {
926    if ( i!=p[0] ) {
927     p[2]|=(ports[i]&1)<<(8-i);
928    }
929   }
930  }
931  
932  attr=createEmptyList();
933  pushBackList(attr, newAttr(ATTR_MIRROR, 3, p));
934  
935  
936  return writeRequest(nga, attr);
937  
938 }
939
940
941
942 // ----------------------------------------------------------------
943 int ngadmin_getIGMPConf (struct ngadmin *nga, struct igmp_conf *ic) {
944  
945  List *attr;
946  ListNode *ln;
947  struct attr *at;
948  struct swi_attr *sa;
949  int ret=ERR_OK;
950  unsigned char *p;
951  unsigned short *s;
952  
953  
954  if ( nga==NULL || ic==NULL ) {
955   return ERR_INVARG;
956  } else if ( (sa=nga->current)==NULL ) {
957   return ERR_NOTLOG;
958  }
959  
960  /*
961  ATTR_IGMP_ENABLE_VLAN
962  ATTR_IGMP_BLOCK_UNK
963  ATTR_IGMP_VALID_V3
964  
965  Apparently, read-querying these attributes at the same time causes the switch to reply garbage. 
966  Here we are forced to do like the official win app and send a separate request for each attribute. 
967  */
968  
969  
970  attr=createEmptyList();
971  memset(ic, 0, sizeof(struct igmp_conf));
972  
973  
974  pushBackList(attr, newEmptyAttr(ATTR_IGMP_ENABLE_VLAN));
975  if ( (ret=readRequest(nga, attr))<0 ) {
976   goto end;
977  }
978  
979  for (ln=attr->first; ln!=NULL; ln=ln->next) {
980   at=ln->data;
981   s=at->data;
982   if ( at->attr==ATTR_IGMP_ENABLE_VLAN && at->size>=4 ) {
983    ic->enable= ntohs(s[0])!=0 ;
984    ic->vlan=htons(s[1]);
985    break;
986   }
987  }
988  
989  clearList(attr, (void(*)(void*))freeAttr);
990  
991  
992  pushBackList(attr, newEmptyAttr(ATTR_IGMP_BLOCK_UNK));
993  if ( (ret=readRequest(nga, attr))<0 ) {
994   goto end;
995  }
996  
997  for (ln=attr->first; ln!=NULL; ln=ln->next) {
998   at=ln->data;
999   p=at->data;
1000   if ( at->attr==ATTR_IGMP_BLOCK_UNK && at->size>=1 ) {
1001    ic->block= p[0]!=0 ;
1002    break;
1003   }
1004  }
1005  
1006  clearList(attr, (void(*)(void*))freeAttr);
1007  
1008  
1009  pushBackList(attr, newEmptyAttr(ATTR_IGMP_VALID_V3));
1010  if ( (ret=readRequest(nga, attr))<0 ) {
1011   goto end;
1012  }
1013  
1014  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1015   at=ln->data;
1016   p=at->data;
1017   if ( at->attr==ATTR_IGMP_VALID_V3 && at->size>=1 ) {
1018    ic->validate= p[0]!=0 ;
1019    break;
1020   }
1021  }
1022  
1023  
1024  
1025  end:
1026  destroyList(attr, (void(*)(void*))freeAttr);
1027  
1028  
1029  return ret;
1030  
1031 }
1032
1033
1034
1035 // ----------------------------------------------------------------------
1036 int ngadmin_setIGMPConf (struct ngadmin *nga, const struct igmp_conf *ic) {
1037  
1038  List *attr;
1039  short *s;
1040  struct swi_attr *sa;
1041  
1042  
1043  if ( nga==NULL || ic==NULL ) {
1044   return ERR_INVARG;
1045  } else if ( (sa=nga->current)==NULL ) {
1046   return ERR_NOTLOG;
1047  }
1048  
1049  
1050  s=malloc(2*sizeof(short));
1051  s[0]=htons(ic->enable!=false);
1052  s[1]=htons(ic->vlan&0x0FFF);
1053  
1054  attr=createEmptyList();
1055  pushBackList(attr, newAttr(ATTR_IGMP_ENABLE_VLAN, 2*sizeof(short), s));
1056  pushBackList(attr, newByteAttr(ATTR_IGMP_BLOCK_UNK, ic->block!=false ));
1057  pushBackList(attr, newByteAttr(ATTR_IGMP_VALID_V3, ic->validate!=false ));
1058  
1059  
1060  return writeRequest(nga, attr);
1061  
1062 }
1063
1064
1065
1066 // ----------------------------------------------------------------------
1067 int ngadmin_cabletest (struct ngadmin *nga, struct cabletest *ct, int nb) {
1068  
1069  List *attr;
1070  ListNode *ln;
1071  struct attr *at;
1072  int i, ret=ERR_OK;
1073  struct swi_attr *sa;
1074  char *p;
1075  
1076  
1077  if ( nga==NULL || ct==NULL ) {
1078   return ERR_INVARG;
1079  } else if ( (sa=nga->current)==NULL ) {
1080   return ERR_NOTLOG;
1081  }
1082  
1083  
1084  attr=createEmptyList();
1085  
1086  for (i=0; i<nb; ++i) {
1087   if ( ct[i].port>=1 && ct[i].port<=sa->ports ) {
1088    
1089    p=malloc(2);
1090    p[0]=ct[i].port;
1091    p[1]=1;
1092    pushBackList(attr, newAttr(ATTR_CABLETEST_DO, 2, p));
1093    
1094    ret=writeRequest(nga, attr);
1095    attr=NULL;
1096    if ( ret<0 ) goto end;
1097    
1098    // the list is destroyed by writeRequest, so we need to recreate it
1099    attr=createEmptyList();
1100    pushBackList(attr, newByteAttr(ATTR_CABLETEST_RESULT, ct[i].port));
1101    
1102    if ( (ret=readRequest(nga, attr))<0 ) goto end;
1103    
1104    for (ln=attr->first; ln!=NULL; ln=ln->next) {
1105     at=ln->data;
1106     p=at->data;
1107     if ( at->attr==ATTR_CABLETEST_RESULT && at->size>=9 && p[0]==ct[i].port ) {
1108      ct[i].v1=ntohl(*(int*)&p[1]);
1109      ct[i].v2=ntohl(*(int*)&p[5]);
1110      break;
1111     }
1112    }
1113    
1114    // just empty the list, it will be used at next iteration
1115    clearList(attr, (void(*)(void*))freeAttr);
1116    
1117   }
1118  }
1119  
1120  
1121  end:
1122  destroyList(attr, (void(*)(void*))freeAttr);
1123  
1124  return ret;
1125  
1126 }
1127
1128
1129
1130 // --------------------------------------------------------------------
1131 int ngadmin_setNetConf (struct ngadmin *nga, const struct net_conf *nc) {
1132  
1133  List *attr;
1134  struct swi_attr *sa;
1135  int ret=ERR_OK;
1136  
1137  
1138  if ( nga==NULL || nc==NULL ) {
1139   return ERR_INVARG;
1140  } else if ( (sa=nga->current)==NULL ) {
1141   return ERR_NOTLOG;
1142  }
1143  
1144  
1145  attr=createEmptyList();
1146  
1147  if ( nc->dhcp ) {
1148   pushBackList(attr, newByteAttr(ATTR_DHCP, 1));
1149  } else {
1150   pushBackList(attr, newByteAttr(ATTR_DHCP, 0));
1151   // only add non-null values
1152   if ( nc->ip.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_IP, nc->ip));
1153   if ( nc->netmask.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_NETMASK, nc->netmask));
1154   if ( nc->gw.s_addr!=0 ) pushBackList(attr, newAddrAttr(ATTR_GATEWAY, nc->gw));
1155  }
1156  
1157  if ( (ret=writeRequest(nga, attr))!=ERR_OK ) {
1158   goto end;
1159  }
1160  
1161  
1162  // update local values
1163  sa->nc.dhcp=nc->dhcp;
1164  if ( !nc->dhcp ) {
1165   if ( nc->ip.s_addr!=0 ) sa->nc.ip=nc->ip;
1166   if ( nc->netmask.s_addr!=0 ) sa->nc.netmask=nc->netmask;
1167   if ( nc->gw.s_addr!=0 ) sa->nc.gw=nc->gw;
1168  }
1169  
1170  
1171  end:
1172  
1173  return ret;
1174  
1175 }
1176
1177
1178
1179 // --------------------------------------------------
1180 int ngadmin_getVLANType (struct ngadmin *nga, int *t) {
1181  
1182  List *attr;
1183  ListNode *ln;
1184  struct attr *at;
1185  int ret=ERR_OK;
1186  
1187  
1188  if ( nga==NULL || t==NULL ) {
1189   return ERR_INVARG;
1190  } else if ( nga->current==NULL ) {
1191   return ERR_NOTLOG;
1192  }
1193  
1194  
1195  attr=createEmptyList();
1196  pushBackList(attr, newEmptyAttr(ATTR_VLAN_TYPE));
1197  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1198   goto end;
1199  }
1200  
1201  
1202  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1203   at=ln->data;
1204   if ( at->attr==ATTR_VLAN_TYPE && at->size>=1 ) {
1205    *t= (int)*(char*)at->data ;
1206    break;
1207   }
1208  }
1209  
1210  
1211  end:
1212  destroyList(attr, (void(*)(void*))freeAttr);
1213  
1214  return ret;
1215  
1216 }
1217
1218
1219
1220 // -------------------------------------------------
1221 int ngadmin_setVLANType (struct ngadmin *nga, int t) {
1222  
1223  List *attr;
1224  struct swi_attr *sa;
1225  
1226  
1227  if ( nga==NULL || t<1 || t>4 ) {
1228   return ERR_INVARG;
1229  } else if ( (sa=nga->current)==NULL ) {
1230   return ERR_NOTLOG;
1231  }
1232  
1233  
1234  attr=createEmptyList();
1235  pushBackList(attr, newByteAttr(ATTR_VLAN_TYPE, t));
1236  
1237  
1238  return writeRequest(nga, attr);
1239  
1240 }
1241
1242
1243
1244 // ------------------------------------------------------------------------------------------------------
1245 int ngadmin_getVLANDotAllConf (struct ngadmin *nga, unsigned short *vlans, unsigned char *ports, int *nb) {
1246  
1247  List *attr;
1248  ListNode *ln;
1249  struct attr *at;
1250  struct swi_attr *sa;
1251  int ret=ERR_OK, total, i;
1252  char *p=NULL;
1253  
1254  
1255  if ( nga==NULL || vlans==NULL || ports==NULL || nb==NULL || *nb<=0 ) {
1256   return ERR_INVARG;
1257  } else if ( (sa=nga->current)==NULL ) {
1258   return ERR_NOTLOG;
1259  }
1260  
1261  
1262  total=*nb;
1263  *nb=0;
1264  
1265  attr=createEmptyList();
1266  pushBackList(attr, newEmptyAttr(ATTR_VLAN_DOT_CONF));
1267  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1268   goto end;
1269  }
1270  
1271  
1272  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1273   at=ln->data;
1274   p=at->data;
1275   if ( *nb>=total ) break; // no more room
1276   if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1277    for (i=0; i<sa->ports; ++i) {
1278     if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1279     else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1280     else ports[i]=VLAN_NO;
1281    }
1282    *vlans++=ntohs(*(unsigned short*)p);
1283    ports+=sa->ports;
1284    ++*nb;
1285   }
1286  }
1287  
1288  
1289  end:
1290  destroyList(attr, (void(*)(void*))freeAttr);
1291  
1292  return ret;
1293  
1294 }
1295
1296
1297
1298 // ----------------------------------------------------------------------------------------
1299 int ngadmin_getVLANDotConf (struct ngadmin *nga, unsigned short vlan, unsigned char *ports) {
1300  
1301  List *attr;
1302  ListNode *ln;
1303  struct attr *at;
1304  struct swi_attr *sa;
1305  int ret=ERR_OK, i;
1306  char *p=NULL;
1307  
1308  
1309  if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1310   return ERR_INVARG;
1311  } else if ( (sa=nga->current)==NULL ) {
1312   return ERR_NOTLOG;
1313  }
1314  
1315  
1316  attr=createEmptyList();
1317  pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1318  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1319   goto end;
1320  }
1321  
1322  
1323  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1324   at=ln->data;
1325   p=at->data;
1326   if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1327    for (i=0; i<sa->ports; ++i) {
1328     if ( (p[3]>>(7-i))&1 ) ports[i]=VLAN_TAGGED; // tagged
1329     else if ( (p[2]>>(7-i))&1 ) ports[i]=VLAN_UNTAGGED; // untagged
1330     else ports[i]=VLAN_NO;
1331    }
1332    break;
1333   }
1334  }
1335  
1336  
1337  end:
1338  destroyList(attr, (void(*)(void*))freeAttr);
1339  
1340  return ret;
1341  
1342 }
1343
1344
1345
1346 // ----------------------------------------------------------------------------------------------
1347 int ngadmin_setVLANDotConf (struct ngadmin *nga, unsigned short vlan, const unsigned char *ports) {
1348  
1349  List *attr=NULL;
1350  ListNode *ln;
1351  struct attr *at;
1352  struct swi_attr *sa;
1353  char *p, fl;
1354  int ret=ERR_OK, i;
1355  
1356  
1357  if ( nga==NULL || vlan<1 || vlan>VLAN_MAX || ports==NULL ) {
1358   return ERR_INVARG;
1359  } else if ( (sa=nga->current)==NULL ) {
1360   return ERR_NOTLOG;
1361  }
1362  
1363  
1364  // if nothing is to be changed, do nothing
1365  for (i=0; i<sa->ports && ports[i]==VLAN_UNSPEC; ++i);
1366  if ( i==sa->ports ) goto end;
1367  
1368  
1369  attr=createEmptyList();
1370  
1371  p=malloc(4);
1372  *(unsigned short*)p=htons(vlan);
1373  *(unsigned short*)&p[2]=0;
1374  
1375  // if all is to be changed, we do not need to read old config
1376  if ( memchr(ports, VLAN_UNSPEC, sa->ports)!=NULL ) {
1377   
1378   attr=createEmptyList();
1379   pushBackList(attr, newShortAttr(ATTR_VLAN_DOT_CONF, vlan));
1380   if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1381    goto end;
1382   }
1383   
1384   for (ln=attr->first; ln!=NULL; ln=ln->next) {
1385    at=ln->data;
1386    if ( at->attr==ATTR_VLAN_DOT_CONF && at->size>=4 ) {
1387     *(unsigned short*)&p[2]=*(unsigned short*)(at->data+2);
1388     break;
1389    }
1390   }
1391   
1392   clearList(attr, (void(*)(void*))freeAttr);
1393   
1394  }
1395  
1396  
1397  // apply changes
1398  for (i=0; i<sa->ports; ++i) {
1399   fl=(1<<(7-i));
1400   switch ( ports[i] ) {
1401    case VLAN_NO:
1402     p[2]&=~fl;
1403     p[3]&=~fl;
1404    break;
1405    case VLAN_UNTAGGED:
1406     p[2]|=fl;
1407     p[3]&=~fl;
1408    break;
1409    case VLAN_TAGGED:
1410     p[2]|=fl;
1411     p[3]|=fl;
1412   }
1413  }
1414  
1415  
1416  
1417  pushBackList(attr, newAttr(ATTR_VLAN_DOT_CONF, 4, p));
1418  ret=writeRequest(nga, attr);
1419  attr=NULL;
1420  
1421  
1422  end:
1423  destroyList(attr, (void(*)(void*))freeAttr);
1424  
1425  return ret;
1426  
1427  
1428 }
1429
1430
1431
1432 // ---------------------------------------------------------------
1433 int ngadmin_VLANDestroy (struct ngadmin *nga, unsigned short vlan) {
1434  
1435  List *attr;
1436  struct swi_attr *sa;
1437  
1438  
1439  if ( nga==NULL || vlan<1 || vlan>VLAN_MAX ) {
1440   return ERR_INVARG;
1441  } else if ( (sa=nga->current)==NULL ) {
1442   return ERR_NOTLOG;
1443  }
1444  
1445  
1446  attr=createEmptyList();
1447  pushBackList(attr, newShortAttr(ATTR_VLAN_DESTROY, vlan));
1448  
1449  
1450  return writeRequest(nga, attr);
1451  
1452 }
1453
1454
1455
1456 // ----------------------------------------------------------------
1457 int ngadmin_getAllPVID (struct ngadmin *nga, unsigned short *ports) {
1458  
1459  List *attr;
1460  ListNode *ln;
1461  struct attr *at;
1462  struct swi_attr *sa;
1463  int ret=ERR_OK;
1464  char *p;
1465  
1466  
1467  if ( nga==NULL || ports==NULL ) {
1468   return ERR_INVARG;
1469  } else if ( (sa=nga->current)==NULL ) {
1470   return ERR_NOTLOG;
1471  }
1472  
1473  
1474  attr=createEmptyList();
1475  pushBackList(attr, newEmptyAttr(ATTR_VLAN_PVID));
1476  if ( (ret=readRequest(nga, attr))!=ERR_OK ) {
1477   goto end;
1478  }
1479  
1480  
1481  for (ln=attr->first; ln!=NULL; ln=ln->next) {
1482   at=ln->data;
1483   p=at->data;
1484   if ( at->attr==ATTR_VLAN_PVID && at->size>=3 && p[0]>=1 && p[0]<=sa->ports ) {
1485    ports[p[0]-1]=htons(*(unsigned short*)&p[1]);
1486   }
1487  }
1488  
1489  
1490  end:
1491  destroyList(attr, (void(*)(void*))freeAttr);
1492  
1493  return ret;
1494  
1495 }
1496
1497
1498
1499 // -------------------------------------------------------------------------------
1500 int ngadmin_setPVID (struct ngadmin *nga, unsigned char port, unsigned short vlan) {
1501  
1502  List *attr;
1503  struct swi_attr *sa;
1504  char *p;
1505  
1506  
1507  if ( nga==NULL || port<1 || vlan<1 || vlan>VLAN_MAX ) {
1508   return ERR_INVARG;
1509  } else if ( (sa=nga->current)==NULL ) {
1510   return ERR_NOTLOG;
1511  } else if ( port>sa->ports ) {
1512   return ERR_INVARG;
1513  }
1514  
1515  
1516  attr=createEmptyList();
1517  p=malloc(3);
1518  p[0]=port;
1519  *(unsigned short*)&p[1]=htons(vlan);
1520  
1521  pushBackList(attr, newAttr(ATTR_VLAN_PVID, 3, p));
1522  
1523  
1524  return writeRequest(nga, attr);;
1525  
1526 }
1527
1528
1529