]> git.sur5r.net Git - ngadmin/commitdiff
CLI: added program options.
authordarkcoven <admin@darkcoven.tk>
Fri, 18 Nov 2011 11:00:00 +0000 (12:00 +0100)
committerdarkcoven <admin@darkcoven.tk>
Sat, 29 Dec 2012 20:53:01 +0000 (21:53 +0100)
CLI: improved autocompletion.
CLI: improved storm filtering command handling.
CLI: added command to list all the commands.
Added support for bitrate limitation.
Added the possibility to force the output interface.
Added the possibility to keep broadcasting.
Lib: improved network code.

cli/admin.c
cli/commands.c
cli/common.c
cli/common.h
lib/ngadmin.h
lib/src/lib.h
lib/src/network.c
lib/src/network.h
lib/src/ngadmin.c

index 2644d38233d261763e11b5a6d13849274414baa3..3318cbc55086779e91bfb009c5d54c20bc290f68 100644 (file)
@@ -1,6 +1,7 @@
 
 #include <stdio.h>
 
+#include <getopt.h>
 #include <readline/readline.h>
 #include <readline/history.h>
 
@@ -69,12 +70,12 @@ char* my_generator (const char* text, int state) {
   return NULL;
  } else if ( state==0 ) {
   tn=compcur->sub;
-  if ( tn==NULL ) { // terminal command
-   return NULL;
-  }
   len=strlen(text);
  }
  
+ if ( tn==NULL ) { // terminal command
+  return NULL;
+ }
  
  
  while ( (name=tn->name)!=NULL ) {
@@ -123,7 +124,16 @@ char** my_completion (const char *text, int start, int end UNUSED) {
 
 int main (int argc, char **argv) {
  
+ static const struct option opts[]={
+  {"keep-broadcasting", no_argument, NULL, 'b'}, 
+  {"force-interface", no_argument, NULL, 'f'}, 
+  {"interface", required_argument, NULL, 'i'}, 
+  {"help", no_argument, NULL, 'h'}, 
+  {0, 0, 0, 0}
+ };
  char *line, *com[MAXCOM];
+ const char *iface="eth0";
+ bool kb=false, force=false;
  struct ngadmin *nga=NULL;
  struct timeval tv;
  const struct TreeNode *cur, *next;
@@ -131,14 +141,47 @@ int main (int argc, char **argv) {
  
  
  
- if ( argc<2 ) {
-  printf("Usage: %s <interface>\n", argv[0]);
-  return 1;
+ opterr=0;
+ while ( (n=getopt_long(argc, argv, "bfi:h", opts, NULL))!=-1 ) {
+  switch ( n ) {
+   
+   case 'b':
+    kb=true;
+   break;
+   
+   case 'f':
+    force=true;
+   break;
+   
+   case 'i':
+    iface=optarg;
+   break;
+   
+   case 'h':
+    printf("Usage: %s [-b] [-f] [-i <interface>]\n", argv[0]);
+    goto end;
+   
+   case '?':
+    printf("Unknown option: \"%s\"\n", argv[optind-1]);
+    goto end;
+   
+  }
  }
  
+ argc-=optind;
+ argv+=optind;
+ if ( argc!=0 ) {
+  printf("Unknown trailing options\n");
+  goto end;
+ }
  memset(com, 0, MAXCOM*sizeof(char*));
  
- if ( (nga=ngadmin_init(argv[1]))==NULL ) {
+ if ( (nga=ngadmin_init(iface))==NULL ) {
   fprintf(stderr, "Initialization error\n");
   goto end;
  }
@@ -149,48 +192,54 @@ int main (int argc, char **argv) {
  ngadmin_setTimeout(nga, &tv);
  
  
+ if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
+ if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
  //rl_bind_key('\t', rl_abort); // disable auto completion
+ //rl_bind_key('\t', rl_complete); // enable auto-complete
  rl_attempted_completion_function=my_completion;
+ rl_completion_entry_function=my_generator;
  
  
  while ( cont ) {
   
-  //rl_bind_key('\t', rl_complete); // enable auto-complete
-  
   if ( (line=readline("> "))==NULL ) goto end;
-  trim(line, strlen(line));
   if ( *line!=0 ) add_history(line);
+  trim(line, strlen(line));
   n=explode(line, com, MAXCOM);
   free(line);
   
-  if ( n==0 ) {
-   continue;
-  }
+  if ( n==0 ) continue;
   
   cur=getSubCom(com, n, &i);
   
   if ( i<n ) { // commands left unchecked
    
-   if ( cur->hasArgs ) { // left "commands" are in fact parameters
-    cur->comfunc(n-i, (const char**)&com[i], nga);
-   } else if ( i==0 ) { // root command
+   if ( i==0 ) { // root command
     printf("unknown command\n");
-   } else if ( cur->sub==NULL ) { // terminal command without arguments
-    printf("%s as no subcommand and takes no parameter\n", com[i-1]);
-   } else { // intermediate command
+   } else if ( cur->sub!=NULL ) { // intermediate command
     printf("unknown %s subcommand\n", com[i-1]);
+   } else if ( !cur->hasArgs ) { // terminal command without arguments
+    printf("%s as no subcommand and takes no parameter\n", com[i-1]);
+   } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+    printf("terminal command without function\n");
+   } else { // terminal command with arguments, left "commands" are in fact parameters
+    cur->comfunc(n-i, (const char**)&com[i], nga);
    }
    
-  } else {
+  } else { // no command left
    
-   if ( cur->comfunc==NULL ) { // intermediate command
+   if ( cur->sub!=NULL ) { // intermediate command
     // print available subcommands
-    for (next=cur->sub; next!=NULL && next->name!=NULL; ++next) {
+    for (next=cur->sub; next->name!=NULL; ++next) {
      printf("%s ", next->name);
     }
     printf("\n");
-    
-   } else { // terminal command
+   } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+    printf("terminal command without function\n");
+   } else { // terminal command without arguments
     cur->comfunc(0, NULL, nga); 
    }
    
index 7ed9020243e0d5784d1f82cee3c46e7125119fcf..e17891cb9e9da33cc688f5fbc211439cdec15774 100644 (file)
@@ -4,6 +4,125 @@
 
 
 
+// =============================================================================
+// bitrate
+
+
+// helper function to analyse bitrate speed specifications
+static int bitrate_analyse (int nb, const char **com, int *ports) {
+ int i=0, s;
+ while ( i<nb-1 ) {
+  s=parseBitrate(com[i+1]);
+  if ( strcmp(com[i], "inout")==0 ) {
+   ports[0]=s;
+   ports[1]=s;
+  } else if ( strcmp(com[i], "in")==0 ) {
+   ports[0]=s;
+  } else if ( strcmp(com[i], "out")==0 ) {
+   ports[1]=s;
+  } else {
+   break;
+  }
+  i+=2;
+ }
+ return i;
+}
+
+
+static bool do_bitrate_set (int nb, const char **com, struct ngadmin *nga) {
+ int i, k=0, defs[]={12, 12}, p, *ports=NULL;
+ const struct swi_attr *sa;
+ bool ret=true;
+ if ( nb<2 ) {
+  printf("Usage: bitrate set [all SPEEDSPEC] <port1> SPEEDSPEC [<port2> SPEEDSPEC ...]\n");
+  printf("SPEEDSPEC: [inout <speed>] [in <ispeed>] [out <ospeed>]\n");
+  ret=false;
+  goto end;
+ }
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+ ports=malloc(2*sa->ports*sizeof(int));
+ // get defaults if present
+ if ( strcmp(com[k], "all")==0 ) {
+  ++k;
+  k+=bitrate_analyse(nb-k, &com[k], defs);
+ }
+ // apply defaults
+ for (i=0; i<sa->ports; ++i) {
+  memcpy(&ports[2*i], defs, sizeof(defs));
+ }
+ // get ports specifics
+ while ( k<nb ) {
+  p=strtol(com[k++], NULL, 0)-1;
+  if ( p>=0 && p<sa->ports ) {
+   k+=bitrate_analyse(nb-k, &com[k], &ports[2*p]);
+  }
+ }
+ // send it to the switch
+ i=ngadmin_setBitrateLimits(nga, ports);
+ printErrCode(i);
+ end:
+ free(ports);
+ return ret;
+}
+
+
+
+static bool do_bitrate_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i, ret=true, *ports=NULL;
+ const struct swi_attr *sa;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+ ports=malloc(2*sa->ports*sizeof(int));
+ if ( (i=ngadmin_getBitrateLimits(nga, ports))!=ERR_OK ) {
+  printErrCode(i);
+  ret=false;
+  goto end;
+ }
+ for (i=0; i<sa->ports; ++i) {
+  printf("port %i: in %s, out %s\n", i+1, bitrates[ports[2*i+0]], bitrates[ports[2*i+1]]);
+ }
+ end:
+ free(ports);
+ return ret;
+}
+
+
+
 // =============================================================================
 // firmware
 
@@ -273,7 +392,7 @@ static bool do_ports_state (int nb UNUSED, const char **com UNUSED, struct ngadm
 
 
 
-static bool do_ports_stats_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_ports_statistics_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
  
  int i;
  
@@ -293,7 +412,7 @@ static bool do_ports_stats_reset (int nb UNUSED, const char **com UNUSED, struct
 
 
 
-static bool do_ports_stats_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_ports_statistics_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
  
  int i;
  const struct swi_attr *sa;
@@ -306,7 +425,7 @@ static bool do_ports_stats_show (int nb UNUSED, const char **com UNUSED, struct
   ret=false;
   goto end;
  }
-  
  ps=calloc(sa->ports, sizeof(struct port_stats));
  if ( (i=ngadmin_getPortsStatistics(nga, ps))<0 ) {
   printErrCode(i);
@@ -314,9 +433,9 @@ static bool do_ports_stats_show (int nb UNUSED, const char **com UNUSED, struct
   goto end;
  }
  
- printf("Port\tReceived\tSent\t\tCRC errors\n");
+ printf("Port\tReceived\tSent\tCRC errors\n");
  for (i=0; i<sa->ports; ++i) {
-  printf("%i\t%8llu\t%8llu\t%8llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
+  printf("% 4i%12llu%12llu%14llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
  }
  
  end:
@@ -369,10 +488,10 @@ static bool do_scan (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga
 
 
 // =============================================================================
-// stormfilt
+// stormfilter
 
 
-static bool do_stormfilt_enable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_enable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
  
  int i;
  const struct swi_attr *sa;
@@ -393,7 +512,7 @@ static bool do_stormfilt_enable (int nb UNUSED, const char **com UNUSED, struct
 
 
 
-static bool do_stormfilt_disable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_disable (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
  
  int i;
  const struct swi_attr *sa;
@@ -414,52 +533,19 @@ static bool do_stormfilt_disable (int nb UNUSED, const char **com UNUSED, struct
 
 
 
-static bool do_stormfilt_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_set (int nb, const char **com, struct ngadmin *nga) {
  
- int i, *ports=NULL;
+ int i, d=BITRATE_UNSPEC, p, *ports=NULL;
  const struct swi_attr *sa;
  bool ret=true;
  
  
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
-  printf("must be logged\n");
+ if ( nb<2 ) {
+  printf("Usage: stormfilt set (all <speed0>)|(<port1> <speed1> [<port2> <speed2> ...])\n");
   ret=false;
   goto end;
  }
  
- ports=malloc(sa->ports*sizeof(int));
- for (i=0; i<sa->ports; ++i) {
-  ports[i]=BITRATE_NOLIMIT;
- }
- i=ngadmin_setStormFilterValues(nga, ports);
- printErrCode(i);
- end:
- free(ports);
- return ret;
-}
-
-
-
-static bool do_stormfilt_set (int nb, const char **com, struct ngadmin *nga) {
- int i, p, *ports=NULL;
- const struct swi_attr *sa;
- bool ret=true;
- if ( nb==0 ) {
-  printf("Usage: stormfilt set <port1> <speed1> [<port2> <speed2> ...]\n");
-  ret=false;
-  goto end;
- }
  if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
   printf("must be logged\n");
   ret=false;
@@ -468,8 +554,15 @@ static bool do_stormfilt_set (int nb, const char **com, struct ngadmin *nga) {
  
  
  ports=malloc(sa->ports*sizeof(int));
+ if ( strcmp(com[0], "all")==0 ) {
+  d=parseBitrate(com[1]);
+  com+=2;
+  nb-=2;
+ }
  for (i=0; i<sa->ports; ++i) {
-  ports[i]=BITRATE_UNSPEC;
+  ports[i]=d;
  }
  
  for (i=0; i<nb; i+=2) {
@@ -491,7 +584,7 @@ static bool do_stormfilt_set (int nb, const char **com, struct ngadmin *nga) {
 
 
 
-static bool do_stormfilt_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
  
  int i, s, ret=true, *ports=NULL;
  const struct swi_attr *sa;
@@ -525,8 +618,7 @@ static bool do_stormfilt_show (int nb UNUSED, const char **com UNUSED, struct ng
  }
  
  for (i=0; i<sa->ports; ++i) {
-  printf("port %i: ", i+1);
-  printBitrate(ports[i]);
+  printf("port %i: %s\n", i+1, bitrates[ports[i]]);
  }
  
  end:
@@ -538,11 +630,58 @@ static bool do_stormfilt_show (int nb UNUSED, const char **com UNUSED, struct ng
 
 
 
+// =============================================================================
+// tree
+
+
+static void display_node (const struct TreeNode *tn, int depth) {
+ int i;
+ const struct TreeNode *s;
+ for (i=0; i<depth; ++i) {
+  putchar('\t');
+ }
+ puts(tn->name);
+ if ( tn->sub==NULL ) return;
+ for (s=tn->sub; s->name!=NULL; ++s) {
+  display_node(s, depth+1);
+ }
+}
+
+
+static bool do_tree (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+ display_node(&coms, 0);
+ return true;
+}
+
+
+
 // =============================================================================
 
 
 COM_ROOT_START(coms)
  
+ COM_START(bitrate)
+  COM_TERM(set, do_bitrate_set, true)
+  COM_TERM(show, do_bitrate_show, false)
+ COM_END
+ COM_TERM(cabletest, NULL, true)
+ COM_TERM(defaults, NULL, false)
  COM_START(firmware)
   COM_TERM(show, do_firmware_show, false)
   COM_TERM(upgrade, do_firmware_upgrade, true)
@@ -552,12 +691,24 @@ COM_ROOT_START(coms)
  
  COM_TERM(login, do_login, true)
  
+ COM_START(mirror)
+  COM_TERM(enable, NULL, false)
+  COM_TERM(disable, NULL, false)
+  COM_TERM(set, NULL, true)
+  COM_TERM(show, NULL, false)
+ COM_END
  COM_START(name)
   COM_TERM(show, do_name_show, false)
   COM_TERM(set, do_name_set, true)
   COM_TERM(clear, do_name_clear, false)
  COM_END
  
+ COM_START(netconf)
+  COM_TERM(show, NULL, false)
+  COM_TERM(set, NULL, true)
+ COM_END
  COM_START(password)
   COM_TERM(change, do_password_change, true)
   COM_TERM(set, do_password_set, true)
@@ -565,22 +716,36 @@ COM_ROOT_START(coms)
  
  COM_START(ports)
   COM_TERM(state, do_ports_state, false)
-  COM_START(stats)
-   COM_TERM(reset, do_ports_stats_reset, false)
-   COM_TERM(show, do_ports_stats_show, false)
+  COM_START(statistics)
+   COM_TERM(reset, do_ports_statistics_reset, false)
+   COM_TERM(show, do_ports_statistics_show, false)
   COM_END
  COM_END
  
+ COM_START(qos)
+  COM_TERM(mode, NULL, true)
+  COM_TERM(set, NULL, true)
+  COM_TERM(show, NULL, false)
+ COM_END
  COM_TERM(quit, do_quit, false)
  
+ COM_TERM(restart, NULL, false)
  COM_TERM(scan, do_scan, false)
  
- COM_START(stormfilt)
-  COM_TERM(enable, do_stormfilt_enable, false)
-  COM_TERM(disable, do_stormfilt_disable, false)
-  COM_TERM(reset, do_stormfilt_reset, false)
-  COM_TERM(set, do_stormfilt_set, true)
-  COM_TERM(show, do_stormfilt_show, false)
+ COM_START(stormfilter)
+  COM_TERM(enable, do_stormfilter_enable, false)
+  COM_TERM(disable, do_stormfilter_disable, false)
+  COM_TERM(set, do_stormfilter_set, true)
+  COM_TERM(show, do_stormfilter_show, false)
+ COM_END
+ COM_TERM(tree, do_tree, false)
+ COM_START(vlan)
+  COM_TERM(show, NULL, false)
+  COM_TERM(mode, NULL, true)
  COM_END
  
 COM_ROOT_END
index 224344b58f5e0996975c4c8be76de68ea9097f44..f621d0bb8bf91a92883ae90a2298938fbc821018 100644 (file)
@@ -26,61 +26,34 @@ void printErrCode (int err) {
 
 
 
-void printBitrate (int br) {
- switch ( br ) {
-  case BITRATE_UNSPEC: printf("unspecified\n"); break;
-  case BITRATE_NOLIMIT: printf("unlimited\n"); break;
-  case BITRATE_512K: printf("512K\n"); break;
-  case BITRATE_1M: printf("1M\n"); break;
-  case BITRATE_2M: printf("2M\n"); break;
-  case BITRATE_4M: printf("4M\n"); break;
-  case BITRATE_8M: printf("8M\n"); break;
-  case BITRATE_16M: printf("16M\n"); break;
-  case BITRATE_32M: printf("32M\n"); break;
-  case BITRATE_64M: printf("64M\n"); break;
-  case BITRATE_128M: printf("128M\n"); break;
-  case BITRATE_256M: printf("256M\n"); break;
-  case BITRATE_512M: printf("512M\n"); break;
-  default: printf("unknown (%i)\n", br);
- }
-}
-
 
-struct BrStr {
- const char *str;
- int br;
+const char* bitrates[]={
+ "nl", 
+ "512K", 
+ "1M", 
+ "2M",  
+ "4M", 
+ "8M", 
+ "16M", 
+ "32M", 
+ "64M", 
+ "128M", 
+ "256M", 
+ "512M", 
+ NULL
 };
 
-static const struct BrStr bitrates[]={
- {"nl", BITRATE_NOLIMIT}, 
- {"512K", BITRATE_512K}, 
- {"1M", BITRATE_1M}, 
- {"2M", BITRATE_2M}, 
- {"4M", BITRATE_4M}, 
- {"8M", BITRATE_8M}, 
- {"16M", BITRATE_16M}, 
- {"32M", BITRATE_32M}, 
- {"64M", BITRATE_64M}, 
- {"128M", BITRATE_128M}, 
- {"256M", BITRATE_256M}, 
- {"512M", BITRATE_512M}, 
- {NULL, BITRATE_UNSPEC}
-};
 
 
 int parseBitrate (const char *s) {
  
const struct BrStr *b;
int i;
  
  
- for (b=bitrates; b->str!=NULL && strcasecmp(b->str, s)!=0; ++b);
+ for (i=0; bitrates[i]!=NULL && strcasecmp(bitrates[i], s)!=0; ++i);
  
  
- return b->br;
+ return i;
  
 }
 
index ea24327ee03ff6434f4e72069f96af7debd0f8f4..3d4b5e047622c537994b69074563c751ca2e1476 100644 (file)
 extern int cont;
 
 
+extern const char* bitrates[];
+
 
 void displaySwitchTab (const struct swi_attr *sa, int nb);
 void printErrCode (int err);
-void printBitrate (int br);
 int parseBitrate (const char *s);
 
 // 
index 69286c79af916ec26cb1b4e99f8c7768b3ac9035..0326d32992fb6265aeea4f2b41772805561d92e0 100644 (file)
@@ -43,6 +43,7 @@
 #define QOS_PORT               1
 #define QOS_DOT                        2
 
+#define PRIO_UNSPEC            -1
 #define PRIO_HIGH              1
 #define PRIO_MED               2
 #define PRIO_NORM              3
@@ -103,6 +104,14 @@ struct ngadmin* ngadmin_init (const char *iface) EXPORT;
 int ngadmin_close (struct ngadmin *nga) EXPORT;
 
 
+// 
+int ngadmin_forceInterface (struct ngadmin *nga) EXPORT;
+
+
+// 
+int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) EXPORT;
+
+
 // specify password to use for authenticating on switches
 int ngadmin_setPassword (struct ngadmin *nga, const char *pass) EXPORT;
 
@@ -163,6 +172,14 @@ int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) EXPORT;
 int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) EXPORT;
 
 
+// 
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) EXPORT;
+
+
+// 
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) EXPORT;
+
+
 
 #endif
 
index f89d02f91cd5594ee960699a49d81e584d3ee1be..f71fb2b30f0f406f41eb567e66b584f06ea8f12b 100644 (file)
 #define CODE_WRITE_REP         4
 
 #define ATTR_PRODUCT           0x0001
-#define ATTR_UNK2              0x0002
+#define ATTR_UNK_0002          0x0002
 #define ATTR_NAME              0x0003
 #define ATTR_MAC               0x0004
-#define ATTR_UNK5              0x0005
+#define ATTR_UNK_0005          0x0005
 #define ATTR_IP                        0x0006
 #define ATTR_NETMASK           0x0007
 #define ATTR_GATEWAY           0x0008
 #define ATTR_NEW_PASSWORD      0x0009
 #define ATTR_PASSWORD          0x000A
 #define ATTR_DHCP              0x000B
-#define ATTR_UNK12             0x000C
+#define ATTR_UNK_000C          0x000C
 #define ATTR_FIRM_VER          0x000D
-#define ATTR_UNK14             0x000E
-#define ATTR_UNK15             0x000F
+#define ATTR_UNK_000E          0x000E
+#define ATTR_UNK_000F          0x000F
 #define ATTR_RESTART           0x0013
 #define ATTR_DEFAULTS          0x0400
 #define ATTR_PORT_STATUS       0x0C00
 #define ATTR_PORT_STATISTICS   0x1000
 #define ATTR_STATS_RESET       0x1400
 #define ATTR_VLAN_TYPE         0x2000
-#define ATTR_VLAN_CONFIG       0x2400
+#define ATTR_VLAN_PORT_CONF    0x2400
+#define ATTR_VLAN_DOT_CONF     0x2800
 #define ATTR_QOS_TYPE          0x3400
 #define ATTR_QOS_CONFIG                0x3800
 #define ATTR_BITRATE_INPUT     0x4C00
 #define ATTR_STORM_BITRATE     0x5800
 #define ATTR_MIRROR            0x5C00
 #define ATTR_PORTS_COUNT       0x6000
+#define ATTR_UNK_6800          0x6800
+#define ATTR_UNK_6C00          0x6C00
+#define ATTR_UNK_7000          0x7000
+#define ATTR_UNK_7400          0x7400
 #define ATTR_END               0xFFFF
 
 
@@ -59,10 +64,10 @@ struct ngadmin {
  // network
  int sock;                     // socket
  struct sockaddr_in local;
- struct sockaddr_in remote;
  char iface[IFNAMSIZ];         // interface
  struct timeval timeout;       // timeout
  struct ether_addr localmac;   // local MAC address
+ bool keepbroad;               // keep broadcasting
  // 
  char password[PASSWORD_MAX];  // password to use to login on switches
  struct swi_attr *swi_tab;     // array of detected switches
index e8fa7134d4d310e338d717c757876a91439cdd5c..793dc0085473af7a9ab9fb6c3de45cac52346f24 100644 (file)
@@ -11,8 +11,8 @@ int startNetwork (struct ngadmin *nga) {
  int ret;
  
  
+ memset(&nga->local, 0, sizeof(struct sockaddr_in));
  nga->local.sin_family=AF_INET;
- nga->remote=nga->local;
  nga->local.sin_port=htons(CLIENT_PORT);
  
  memset(&ifr, 0, sizeof(struct ifreq));
@@ -69,6 +69,32 @@ int stopNetwork (struct ngadmin *nga) {
 
 
 
+// -------------------------------------
+int forceInterface (struct ngadmin *nga) {
+ int ret;
+ ret=1;
+ if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_BINDTODEVICE, nga->iface, strlen(nga->iface)+1))<0 ) {
+  perror("setsockopt(SO_BINDTODEVICE)");
+  return ret;
+ }
+ ret=1;
+ if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_DONTROUTE, &ret, sizeof(ret)))<0 ) {
+  perror("setsockopt(SO_DONTROUTE)");
+  return ret;
+ }
+ return 0;
+}
+
+
+
 // ------------------------------------
 int updateTimeout (struct ngadmin *nga) {
  
@@ -88,13 +114,15 @@ int updateTimeout (struct ngadmin *nga) {
 
 
 
-// --------------------------------------------------------------------------------------------------------------------------
-int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switch_mac, unsigned int seqnum, const List *attr) {
+// ----------------------------------------------------------------
+int sendNgPacket (struct ngadmin *nga, char code, const List *attr) {
  
  char buffer[1500];
  struct ng_packet np;
  ListNode *ln;
  struct attr *at;
+ struct sockaddr_in remote;
+ const struct swi_attr *sa=nga->current;
  int ret;
  
  
@@ -102,7 +130,7 @@ int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switc
  np.buffer=buffer;
  np.maxlen=sizeof(buffer);
  initNgPacket(&np);
- initNgHeader(np.nh, code, &nga->localmac, switch_mac, seqnum);
+ initNgHeader(np.nh, code, &nga->localmac, sa==NULL ? &nullMac : &sa->mac , ++nga->seq);
  
  if ( attr!=NULL ) {
   for (ln=attr->first; ln!=NULL; ln=ln->next) {
@@ -111,10 +139,12 @@ int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switc
   }
  }
  
+ memset(&remote, 0, sizeof(struct sockaddr_in));
+ remote.sin_family=AF_INET;
+ remote.sin_addr.s_addr= sa==NULL || nga->keepbroad ? htonl(INADDR_BROADCAST) : sa->nc.ip.s_addr ;
+ remote.sin_port=htons(SWITCH_PORT);
  
- nga->remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
- nga->remote.sin_port=htons(SWITCH_PORT);
- if ( (ret=sendto(nga->sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&nga->remote, sizeof(struct sockaddr_in)))<0 ) {
+ if ( (ret=sendto(nga->sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in)))<0 ) {
   perror("sendto");
  }
  
@@ -125,12 +155,14 @@ int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switc
 
 
 
-// ---------------------------------------------------------------------------------------------------------------------------------------------------
-List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, const struct ether_addr *switch_mac, unsigned int seqnum) {
+// -----------------------------------------------------------------------------------------
+List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error) {
  
  char buffer[1500];
  struct ng_packet np;
+ struct sockaddr_in remote;
  socklen_t slen=sizeof(struct sockaddr_in);
+ const struct swi_attr *sa=nga->current;
  List *l=NULL;
  int len;
  
@@ -138,8 +170,12 @@ List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short
  np.buffer=buffer;
  np.maxlen=sizeof(buffer);
  
- while ( (len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&nga->remote, &slen))>=0 ) {
-  if ( len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &nga->localmac, switch_mac, seqnum) ) {
+ memset(&remote, 0, sizeof(struct sockaddr_in));
+ remote.sin_family=AF_INET;
+ remote.sin_port=htons(SWITCH_PORT);
+ while ( (len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 ) {
+  if ( len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ) {
    initNgPacket(&np);
    l=extractPacketAttributes(&np, error, attr_error);
    break;
index 0b895b8c08b053de92da1bcc35a7476a9d1d32ee..1d6fc1fafd58d9d956e2200508f579d90463c004 100644 (file)
@@ -22,14 +22,17 @@ int startNetwork (struct ngadmin *nga);
 // 
 int stopNetwork (struct ngadmin *nga);
 
+// 
+int forceInterface (struct ngadmin *nga);
+
 // 
 int updateTimeout (struct ngadmin *nga);
 
 // 
-int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switch_mac, unsigned int seqnum, const List *attr);
+int sendNgPacket (struct ngadmin *nga, char code, const List *attr);
 
 // 
-List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, const struct ether_addr *switch_mac, unsigned int seqnum);
+List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error);
 
 
 
index 312ab584ea3a5c6b3de784c2d32c9c6917641f6d..179302e20bcaef753482dce827323677369948f8 100644 (file)
@@ -57,6 +57,43 @@ int ngadmin_close (struct ngadmin *nga) {
 
 
 
+// ---------------------------------------------
+int ngadmin_forceInterface (struct ngadmin *nga) {
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ }
+ if ( forceInterface(nga)!=0 ) {
+  return ERR_NET;
+ } else {
+  return ERR_OK;
+ }
+}
+
+
+
+// --------------------------------------------------------------
+int ngadmin_setKeepBroadcasting (struct ngadmin *nga, bool value) {
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ }
+ nga->keepbroad=value;
+ return ERR_OK;
+}
+
+
+
 // ------------------------------------------------------------
 int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
  
@@ -151,7 +188,7 @@ int ngadmin_scan (struct ngadmin *nga) {
  }
  
  // send request to all potential switches
- i=sendNgPacket(nga, CODE_READ_REQ, NULL, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
  if ( i<0 ) {
   return ERR_NET;
@@ -160,7 +197,7 @@ int ngadmin_scan (struct ngadmin *nga) {
  
  // try to receive any packets until timeout
  swiList=createEmptyList();
- while ( (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, NULL, nga->seq))!=NULL ) {
+ while ( (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))!=NULL ) {
   sa=malloc(sizeof(struct swi_attr));
   extractSwitchAttributes(sa, attr);
   destroyList(attr, (void(*)(void*))freeAttr);
@@ -227,16 +264,17 @@ int ngadmin_login (struct ngadmin *nga, int id) {
  }
  
  
- nga->current=NULL;
  sa=&nga->swi_tab[id];
+ nga->current=sa;
  
  attr=createEmptyList();
  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, &sa->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, &sa->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
+  nga->current=NULL;
   goto end;
  }
  
@@ -244,16 +282,14 @@ int ngadmin_login (struct ngadmin *nga, int id) {
  destroyList(attr, (void(*)(void*))freeAttr);
  if ( err==7 && attr_error==ATTR_PASSWORD ) {
   ret=ERR_BADPASS;
+  nga->current=NULL;
   goto end;
  }
  
  
- // login successful
- nga->current=sa;
  
  end:
  
  return ret;
  
 }
@@ -280,9 +316,9 @@ int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
  attr=createEmptyList();
  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -330,9 +366,9 @@ int ngadmin_setName (struct ngadmin *nga, const char *name) {
   pushBackList(attr, newAttr(ATTR_NAME, strlen(name), strdup(name)));
  }
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -380,9 +416,9 @@ int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
  attr=createEmptyList();
  pushBackList(attr, newEmptyAttr(ATTR_PORT_STATISTICS));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -428,9 +464,9 @@ int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
  pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -472,9 +508,9 @@ int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
  pushBackList(attr, newAttr(ATTR_NEW_PASSWORD, strlen(pass), strdup(pass)));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -518,9 +554,9 @@ int ngadmin_getStormFilterState (struct ngadmin *nga, int *s) {
  attr=createEmptyList();
  pushBackList(attr, newEmptyAttr(ATTR_STORM_ENABLE));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -564,9 +600,9 @@ int ngadmin_setStormFilterState (struct ngadmin *nga, int s) {
  pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
  pushBackList(attr, newByteAttr(ATTR_STORM_ENABLE, s!=0));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -606,9 +642,9 @@ int ngadmin_getStormFilterValues (struct ngadmin *nga, int *ports) {
  attr=createEmptyList();
  pushBackList(attr, newEmptyAttr(ATTR_STORM_BITRATE));
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_READ_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -661,9 +697,9 @@ int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
  }
  
  pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
  destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
   ret=ERR_NET;
   goto end;
  }
@@ -684,3 +720,108 @@ int ngadmin_setStormFilterValues (struct ngadmin *nga, const int *ports) {
 
 
 
+// -----------------------------------------------------------
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+ if ( nga==NULL || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+   ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
+  } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+   ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
+  }
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ end:
+ return ret;
+}
+
+
+
+// -----------------------------------------------------------------
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ char *p;
+ if ( nga==NULL || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+  return ERR_NOTLOG;
+ }
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+ for (i=0; i<nga->current->ports; ++i) {
+  if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
+   p=malloc(5);
+   *p=i+1;
+   *(int*)(p+1)=htonl(ports[2*i+0]);
+   pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
+  }
+  if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
+   p=malloc(5);
+   *p=i+1;
+   *(int*)(p+1)=htonl(ports[2*i+1]);
+   pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
+  }
+ }
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+  ret=ERR_BADPASS;
+  goto end;
+ }
+ end:
+ return ret;
+}
+
+