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