]> git.sur5r.net Git - ngadmin/commitdiff
Code reorganized.
authordarkcoven <admin@darkcoven.tk>
Tue, 15 Nov 2011 11:00:00 +0000 (12:00 +0100)
committerdarkcoven <admin@darkcoven.tk>
Sat, 29 Dec 2012 20:37:08 +0000 (21:37 +0100)
Separated low level protocol handling in a library and CLI.
Removed switch emulator.
CLI: command input using libreadline.

38 files changed:
.gitignore
admin.c [deleted file]
cli/Makefile [new file with mode: 0644]
cli/admin.c [new file with mode: 0644]
cli/com_firmware.c [new file with mode: 0644]
cli/com_list.c [new file with mode: 0644]
cli/com_login.c [new file with mode: 0644]
cli/com_name.c [new file with mode: 0644]
cli/com_password.c [new file with mode: 0644]
cli/com_ports.c [new file with mode: 0644]
cli/com_quit.c [new file with mode: 0644]
cli/com_scan.c [new file with mode: 0644]
cli/command.c [new file with mode: 0644]
cli/command.h [new file with mode: 0644]
cli/common.h [new file with mode: 0644]
command.c [deleted file]
command.h [deleted file]
commandes [deleted file]
controller.c [deleted file]
controller.h [deleted file]
emu.c [deleted file]
lib/ngadmin.h [new file with mode: 0644]
lib/src/Makefile [new file with mode: 0644]
lib/src/lib.h [new file with mode: 0644]
lib/src/list.c [new file with mode: 0644]
lib/src/list.h [new file with mode: 0644]
lib/src/network.c [new file with mode: 0644]
lib/src/network.h [new file with mode: 0644]
lib/src/ngadmin.c [new file with mode: 0644]
lib/src/protocol.c [new file with mode: 0644]
lib/src/protocol.h [new file with mode: 0644]
list.c [deleted file]
list.h [deleted file]
makefile [deleted file]
network.c [deleted file]
network.h [deleted file]
protocol.c [deleted file]
protocol.h [deleted file]

index 2c0253151299ecd508f8286c9156681e176184af..5240222e1d69baa21e12b3341ac4189816574019 100644 (file)
@@ -1,4 +1,5 @@
 *.o
 *~
+*.so
 admin
 emu
diff --git a/admin.c b/admin.c
deleted file mode 100644 (file)
index 01e7765..0000000
--- a/admin.c
+++ /dev/null
@@ -1,404 +0,0 @@
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <termios.h>
-
-
-
-#include "protocol.h"
-#include "command.h"
-#include "controller.h"
-
-
-
-#define MAXCOM 8
-#define MAXSW  16
-
-
-/*
-getVlanStatus ()
-setVlanMode (char mode)
-
-makeCableTest (int n, const unsigned char* ports)
-
-char speedIndex (const char* txt);
-getBitrateStatus ()
-setBiratePorts (int n, const unsigned char* ports, char index)
-
-getBroadfiltStatus ()
-disableBroadfilt ()
-setBroadfiltPorts (int n, cons unsigned char* ports, char index)
-*/
-
-
-/*
-sendPacket ()
-receivePacket()
-*/
-
-
-
-void printErrCode (int err) {
- switch ( err ) {
-  case ERR_OK: /*printf("ok\n");*/ break;
-  case ERR_NOTLOG: printf("not switch selected\n"); break;
-  case ERR_BADPASS: printf("wrong password\n"); break;
-  default: printf("unknown status code (%i)\n", err);
- }
-}
-
-
-void displaySwitchList (const List *l) {
- ListNode *ln;
- struct swi_attr *sa;
- int i=0;
- if ( l->count==0 ) {
-  printf("no switch found\n");
-  return;
- }
- printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\n");
- for (ln=l->first; ln!=NULL; ln=ln->next) {
-  sa=ln->data;
-  printf("%i\t%s\t%s\t\t%s\t%s/", i, ether_ntoa(&sa->mac), sa->product, sa->name, inet_ntoa(sa->nc.ip));
-  printf("%s\n", inet_ntoa(sa->nc.netmask));
-  i++;
- }
- printf("\nfound %i switch(es)\n", l->count);
-}
-
-
-
-
-int main (int argc, char **argv) {
- char buffer[512], *com[MAXCOM], cont=1;
- int n, i;
- //struct termios tr;
- const List *swi;
- if ( argc<2 ) {
-  printf("Usage: %s <interface>\n", argv[0]);
-  return 1;
- }
- memset(com, 0, sizeof(com));
- if ( startNetwork(argv[1])<0 ) {
-  printf("networking error\n");
-  goto end;
- } 
- startController();
- swi=getSwitchList();
- //printf("client: ip %s, mac %s\n", inet_ntoa(local.sin_addr), ether_ntoa(&localmac));
- while ( cont ) {
-  
-  printf("> ");
-  fflush(stdout);
-  
-  if ( fgets(buffer, sizeof(buffer), stdin)==NULL ) {
-   if ( !feof(stdin) ) {
-    perror("fgets");
-   }
-   goto end;
-  }
-  
-  trim(buffer, strlen(buffer));
-  n=explode(buffer, com, MAXCOM);
-  
-  /*
-  } else if ( strcmp(com[0], "password")==0 ) {
-   // password: specify password to use to login
-   
-   printf("enter password: ");
-   fflush(stdout);
-   
-   tcgetattr(STDIN_FILENO, &tr);
-   tr.c_lflag &= ~ECHO ;
-   tcsetattr(STDIN_FILENO, TCSANOW, &tr);
-   
-   if ( fgets(password, sizeof(password), stdin)==NULL ) {
-    perror("fgets");
-   }
-   
-   tr.c_lflag |= ECHO ;
-   tcsetattr(STDIN_FILENO, TCSANOW, &tr);
-   
-   putchar('\n');
-   
-   trim(password, strlen(password));
-   
-   
-  } else if ( strcmp(com[0], "ports")==0 ) {
-   // ports: show ports status
-   
-   if ( current==NULL ) {
-    printf("no switch selected for configuration\n");
-    goto nxt;
-   }
-   
-   initNgPacket(&np);
-   initNgHeader(np.nh, CODE_READ_REQ, &localmac, &current->mac, ++seq);
-   
-   addPacketEmptyAttr(&np, ATTR_PORT_STATUS);
-   addPacketEmptyAttr(&np, ATTR_END);
-   
-   len=getPacketTotalSize(&np);
-   remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
-   remote.sin_port=htons(SWITCH_PORT);
-   if ( sendto(sock, buffer, len, 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in))<0 ) {
-    perror("sendto");
-    goto nxt;
-   }
-   
-   while ( (len=recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 && !validateNgHeader(np.nh, &localmac, &current->mac, seq) );
-   
-   if ( len<0 ) {
-    printf("time out\n");
-    goto nxt;
-   }
-   
-   initNgPacket(&np);
-   l=extractPacketAttributes(&np);
-   
-   for (ln=l->first; ln!=NULL; ln=ln->next) {
-    at=ln->data;
-    char *p=at->data;
-    if ( at->attr==ATTR_PORT_STATUS ) {
-     printf("port %i: ", p[0]);
-     switch ( p[1] ) {
-      case 0: printf("down"); break;
-      case SPEED_10: printf("up, 10M"); break;
-      case SPEED_100: printf("up, 100M"); break;
-      case SPEED_1000: printf("up, 1000M"); break;
-      default: printf("unknown (%i)", p[2]);
-     }
-     putchar('\n');
-    }
-   }
-   
-   destroyList(l, (void(*)(void*))freeAttr);
-   
-  } else if ( strcmp(com[0], "mirror")==0 ) {
-   // 
-   
-   if ( current==NULL ) {
-    printf("no switch selected for configuration\n");
-    goto nxt;
-   }
-   
-   if ( n==1 ) {
-    
-    initNgPacket(&np);
-    initNgHeader(np.nh, CODE_READ_REQ, &localmac, &current->mac, ++seq);
-    
-    addPacketEmptyAttr(&np, ATTR_MIRROR);
-    addPacketEmptyAttr(&np, ATTR_END);
-    
-    len=getPacketTotalSize(&np);
-    remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
-    remote.sin_port=htons(SWITCH_PORT);
-    if ( sendto(sock, buffer, len, 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in))<0 ) {
-     perror("sendto");
-     goto nxt;
-    }
-    
-    
-    while ( (len=recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 && !validateNgHeader(np.nh, &localmac, &current->mac, seq) );
-    
-    if ( len<0 ) {
-     printf("time out\n");
-     goto nxt;
-    }
-    
-    initNgPacket(&np);
-    l=extractPacketAttributes(&np);
-    
-    for (ln=l->first; ln!=NULL; ln=ln->next) {
-     at=ln->data;
-     char *p=at->data;
-     if ( at->attr==ATTR_MIRROR ) {
-      if ( p[0]==0 ) {
-       printf("mirorring disabled\n");
-      } else {
-       printf("ports ");
-       // FIXME
-       printf("redirected to port %i\n", p[0]);
-      }
-     }
-    }
-    
-    destroyList(l, (void(*)(void*))freeAttr);
-    
-    
-   } else {
-    
-    initNgPacket(&np);
-    
-    strcpy(np.ah->data, password);
-    addPacketAttr(&np, ATTR_PASSWORD, strlen(password), NULL);
-    
-    if ( strcmp(com[1], "disable")==0 ) {
-     
-    }
-    
-    addPacketEmptyAttr(&np, ATTR_END);
-    
-    initNgHeader(np.nh, CODE_WRITE_REQ, &localmac, &current->mac, ++seq);
-    
-    len=getPacketTotalSize(&np);
-    remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
-    remote.sin_port=htons(SWITCH_PORT);
-    if ( sendto(sock, buffer, len, 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in))<0 ) {
-     perror("sendto");
-     goto nxt;
-    }
-    
-    
-   }
-   
-   
-  } else if ( strcmp(com[0], "clear")==0 ) {
-   // 
-   
-   printf("\e[H\e[J");
-   
-  } else {
-   // unknown command
-   
-   printf("unknown command\n");
-   
-  }
-  */
-  
-  
-  if ( n==0 ) {
-   // nothing: do nothing
-   
-  } else if ( strcmp(com[0], "quit")==0 ) {
-   // quit: exits
-   
-   cont=0;
-   
-  } else if ( strcmp(com[0], "scan")==0 ) {
-   // scan: scan for switches
-   
-   if ( (i=discoverSwitches())<0 ) {
-    printErrCode(i);
-    goto nxt;
-   }
-   
-   displaySwitchList(swi);
-   
-  } else if ( strcmp(com[0], "list")==0 ) {
-   // list: display last detected switches
-   
-   displaySwitchList(swi);
-   
-  } else if ( strcmp(com[0], "login")==0 ) {
-   // login: selects a switch from the list
-   
-   printErrCode(i=login(strtol(com[1], NULL, 0)));
-   
-  } else if ( strcmp(com[0], "ports")==0 ) {
-   // 
-   
-   if ( n==1 ) {
-    
-    printf("ports\n");
-    printf("\tstate\n");
-    printf("\tstats\n");
-    printf("\t\tshow\n");
-    printf("\t\treset\n");
-    
-   } else if ( strcmp(com[1], "state")==0 ) {
-    
-    unsigned char ports[16];
-    if ( (i=getPortsStatus(ports, 16))<0 ) {
-     printErrCode(i);
-     goto nxt;
-    }
-    
-    for (i=0; i<8; i++) { // FIXME
-     printf("port %i: ", i+1);
-     switch ( ports[i] ) {
-      case 0: printf("down"); break;
-      case SPEED_10: printf("up, 10M"); break;
-      case SPEED_100: printf("up, 100M"); break;
-      case SPEED_1000: printf("up, 1000M"); break;
-      default: printf("unknown (%i)", ports[i]);
-     }
-     putchar('\n');
-    }
-    
-   }
-   
-  } else if ( strcmp(com[0], "password")==0 ) {
-   // 
-   
-   if ( n==1 ) {
-    printf("usage: password set|change\n");
-   } else if ( strcmp(com[1], "set")==0 ) {
-    printf("password set\n");
-   } else if ( strcmp(com[1], "change")==0 ) {
-    printf("password change\n");
-   } else {
-    printf("unknown password subcommand\n");
-   }
-   
-  } else if ( strcmp(com[0], "timeout")==0 ) {
-   // 
-   
-   
-   
-  } else {
-   // unknown command
-   
-   printf("unknown command\n");
-   
-  }
-  
-  
-  nxt:
-  for (i=0; i<MAXCOM; i++) {
-   if ( com[i]!=NULL ) {
-    free(com[i]);
-    com[i]=NULL;
-   }
-  }
-  
- }
- end:
- stopController();
- stopNetwork();
- return 0;
-}
-
diff --git a/cli/Makefile b/cli/Makefile
new file mode 100644 (file)
index 0000000..a477b71
--- /dev/null
@@ -0,0 +1,26 @@
+
+CC=gcc
+CFLAGS=-I../lib -W -Wall -Wextra -Os -fomit-frame-pointer
+LDFLAGS=-L../lib -lngadmin -lreadline -s
+EXEC=admin
+
+SRC=$(wildcard *.c)
+OBJ=$(SRC:.c=.o)
+
+
+
+$(EXEC): $(OBJ)
+       $(CC) $^ -o $@ $(LDFLAGS)
+
+%.o: %.c
+       $(CC) -c $^ -o $@ $(CFLAGS)
+
+
+clean:
+       @rm -f *.o
+
+mrproper: clean
+       @rm -f $(EXEC)
+
+
+
diff --git a/cli/admin.c b/cli/admin.c
new file mode 100644 (file)
index 0000000..523a96c
--- /dev/null
@@ -0,0 +1,186 @@
+
+#include <stdio.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "command.h"
+#include "common.h"
+
+
+
+
+#define MAXCOM 8
+
+
+
+
+
+int cont=1;
+
+
+static const struct TreeNode rootNode={.sub={
+ &com_quit,
+ &com_login, 
+ &com_scan, 
+ &com_ports, 
+ &com_password, 
+ &com_list, 
+ &com_firmware, 
+ &com_name, 
+ NULL
+}};
+
+
+
+void printErrCode (int err) {
+ switch ( err ) {
+  case ERR_OK: /*printf("ok\n");*/ break;
+  case ERR_NET: printf("network error\n"); break;
+  case ERR_NOTLOG: printf("no switch selected\n"); break;
+  case ERR_BADPASS: printf("wrong password\n"); break;
+  case ERR_BADID: printf("bad switch id\n"); break;
+  case ERR_INVARG: printf("invalid argument\n"); break;
+  case ERR_TIMEOUT: printf("timeout\n"); break;
+  default: printf("unknown status code (%i)\n", err);
+ }
+}
+
+
+
+void displaySwitchTab (const struct swi_attr *sa, int nb) {
+ int i=0;
+ if ( nb==0 ) {
+  printf("no switch found\n");
+  return;
+ }
+ printf("Num\tMac\t\t\tProduct\t\tName\t\t\tIP/mask\t\t\t\tDHCP\tPorts\tFirmware\n");
+ for (i=0; i<nb; ++i) {
+  printf("%i\t%s\t%s\t\t%s\t%s/", i, ether_ntoa(&sa[i].mac), sa[i].product, sa[i].name, inet_ntoa(sa[i].nc.ip));
+  printf("%s\t%s\t%i\t%s\n", inet_ntoa(sa[i].nc.netmask), ( sa[i].nc.dhcp ? "Yes" : "No" ), sa[i].ports, sa[i].firmware);
+ }
+ printf("\nfound %i switch(es)\n", nb);
+}
+
+
+
+
+int main (int argc, char **argv) {
+ char *line, *com[MAXCOM];
+ struct ngadmin *nga=NULL;
+ struct timeval tv;
+ const struct TreeNode *cur, *next, **tab;
+ int i, n;
+ if ( argc<2 ) {
+  printf("Usage: %s <interface>\n", argv[0]);
+  return 1;
+ }
+ memset(com, 0, MAXCOM*sizeof(char*));
+ if ( (nga=ngadmin_init(argv[1]))==NULL ) {
+  fprintf(stderr, "Initialization error\n");
+  goto end;
+ }
+ // set timeout
+ tv.tv_sec=3;
+ tv.tv_usec=0;
+ ngadmin_setTimeout(nga, &tv);
+ rl_bind_key('\t', rl_abort); // disable auto completion
+ while ( cont ) {
+  
+  if ( (line=readline("> "))==NULL ) goto end;
+  trim(line, strlen(line));
+  if ( *line!=0 ) add_history(line);
+  n=explode(line, com, MAXCOM);
+  free(line);
+  
+  
+  i=0;
+  for (next=&rootNode; i<n; ++i) {
+   cur=next;
+   for (tab=cur->sub; (next=*tab)!=NULL && strcmp(next->name, com[i])!=0; ++tab);
+   if ( next==NULL ) break;
+  }
+  
+  
+  if ( i<n ) { // commands left uncompared
+   
+   if ( cur->hasArgs ) { // left "commands" are in fact parameters
+    cur->comfunc(cur, n-i, (const char**)&com[i], nga);
+   } else {
+    if ( i==0 ) {
+     printf("unknown command\n");
+    } else {
+     printf("unknown %s subcommand\n", com[i-1]);
+    }
+   }
+   
+  } else {
+   
+   cur=next;
+   if ( cur->comfunc==NULL ) {
+    // print available subcommands
+    for (tab=cur->sub; (next=*tab)!=NULL; ++tab) {
+     printf("%s ", next->name);
+    }
+    printf("\n");
+    
+   } else { // terminal command
+   
+    cur->comfunc(cur, 0, NULL, nga);
+    
+   }
+  }
+  
+  /*
+  if ( n==0 ) {
+   // nothing: do nothing
+   
+  } else if ( strcmp(com[0], "timeout")==0 ) {
+   // 
+   
+  }
+  */
+  
+  for (i=0; i<MAXCOM; i++) {
+   if ( com[i]!=NULL ) {
+    free(com[i]);
+    com[i]=NULL;
+   }
+  }
+  
+ }
+ end:
+ ngadmin_close(nga);
+ return 0;
+}
+
+
diff --git a/cli/com_firmware.c b/cli/com_firmware.c
new file mode 100644 (file)
index 0000000..f697af6
--- /dev/null
@@ -0,0 +1,64 @@
+
+#include "common.h"
+
+
+
+
+static bool do_firmware_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ const struct swi_attr *sa;
+ bool ret=true;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+ puts(sa->firmware);
+ end:
+ return ret;
+}
+
+
+
+static bool do_firmware_upgrade (const struct TreeNode *tn UNUSED, int nb, const char **com UNUSED, struct ngadmin *nga) {
+ const struct swi_attr *sa;
+ bool ret=true;
+ if ( nb!=1 ) {
+  printf("Usage: firmware upgrade <file>\n");
+  ret=false;
+ }
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+ printf("not implemented yet\n");
+ end:
+ return ret;
+}
+
+
+
+static const struct TreeNode com_firmware_show=COM("show", do_firmware_show, false, NULL);
+static const struct TreeNode com_firmware_upgrade=COM("upgrade", do_firmware_upgrade, true, NULL);
+
+const struct TreeNode com_firmware=COM("firmware", NULL, false, &com_firmware_show, &com_firmware_upgrade, NULL);
+
+
+
diff --git a/cli/com_list.c b/cli/com_list.c
new file mode 100644 (file)
index 0000000..3c8eb8c
--- /dev/null
@@ -0,0 +1,26 @@
+
+#include "common.h"
+
+
+
+
+static bool do_list (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int n;
+ const struct swi_attr *sa;
+ sa=ngadmin_getSwitchTab(nga, &n);
+ displaySwitchTab(sa, n);
+ return true;
+}
+
+
+
+const struct TreeNode com_list=COM("list", do_list, false, NULL);
+
+
+
diff --git a/cli/com_login.c b/cli/com_login.c
new file mode 100644 (file)
index 0000000..e50e096
--- /dev/null
@@ -0,0 +1,32 @@
+
+#include "common.h"
+
+
+
+
+static bool do_login (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
+ int i;
+ if ( nb!=1 ) {
+  printf("Usage: login <num>\n");
+  return false;
+ }
+ i=strtol(com[0], NULL, 0);
+ i=ngadmin_login(nga, i);
+ printErrCode(i);
+ return true;
+}
+
+
+
+const struct TreeNode com_login=COM("login", do_login, true, NULL);
+
+
+
diff --git a/cli/com_name.c b/cli/com_name.c
new file mode 100644 (file)
index 0000000..54b152e
--- /dev/null
@@ -0,0 +1,80 @@
+
+#include "common.h"
+
+
+
+
+static bool do_name_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ const struct swi_attr *sa;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  return false;
+ }
+ puts(sa->name);
+ return true;
+}
+
+
+
+static bool do_name_set (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ if ( nb!=1 ) {
+  printf("Usage: name set <value>\n");
+  return false;
+ }
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  return false;
+ }
+ i=ngadmin_setName(nga, com[0]);
+ printErrCode(i);
+ return true;
+}
+
+
+
+static bool do_name_clear (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  return false;
+ }
+ i=ngadmin_setName(nga, NULL);
+ printErrCode(i);
+ return true;
+}
+
+
+
+static struct TreeNode com_name_show=COM("show", do_name_show, false, NULL);
+static struct TreeNode com_name_set=COM("set", do_name_set, true, NULL);
+static struct TreeNode com_name_clear=COM("clear", do_name_clear, false, NULL);
+
+const struct TreeNode com_name=COM("name", NULL, false, &com_name_show, &com_name_set, &com_name_clear, NULL);
+
+
+
diff --git a/cli/com_password.c b/cli/com_password.c
new file mode 100644 (file)
index 0000000..4b1f184
--- /dev/null
@@ -0,0 +1,60 @@
+
+#include "common.h"
+
+
+
+
+static bool do_password_change (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ if ( nb!=1 ) {
+  printf("Usage: password set <value>\n");
+  return false;
+ }
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  return false;
+ }
+ i=ngadmin_changePassword(nga, com[0]);
+ printErrCode(i);
+ return true;
+}
+
+
+
+static bool do_password_set (const struct TreeNode *tn UNUSED, int nb, const char **com, struct ngadmin *nga) {
+ int i;
+ if ( nb!=1 ) {
+  printf("Usage: password set <value>\n");
+  return false;
+ }
+ i=ngadmin_setPassword(nga, com[0]);
+ printErrCode(i);
+ return true;
+}
+
+
+
+
+static const struct TreeNode com_password_change=COM("change", do_password_change, true, NULL);
+static const struct TreeNode com_password_set=COM("set", do_password_set, true, NULL);
+
+const struct TreeNode com_password=COM("password", NULL, false, &com_password_change, &com_password_set, NULL);
+
+
+
diff --git a/cli/com_ports.c b/cli/com_ports.c
new file mode 100644 (file)
index 0000000..b520218
--- /dev/null
@@ -0,0 +1,116 @@
+
+#include "common.h"
+
+
+
+
+static bool do_ports_state (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ unsigned char *ports=NULL;
+ bool ret=true;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+ ports=malloc(sa->ports*sizeof(unsigned char));
+ if ( (i=ngadmin_getPortsStatus(nga, ports))<0 ) {
+  printErrCode(i);
+  ret=false;
+  goto end;
+ }
+ for (i=0; i<sa->ports; i++) {
+  printf("port %i: ", i+1);
+  switch ( ports[i] ) {
+   case 0: printf("down"); break;
+   case SPEED_10: printf("up, 10M"); break;
+   case SPEED_100: printf("up, 100M"); break;
+   case SPEED_1000: printf("up, 1000M"); break;
+   default: printf("unknown (%i)", ports[i]);
+  }
+  putchar('\n');
+ }
+ end:
+ free(ports);
+ return ret;
+}
+
+
+
+static bool do_ports_stats_show (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ bool ret=true;
+ struct port_stats *ps=NULL;
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+  printf("must be logged\n");
+  ret=false;
+  goto end;
+ }
+  
+ ps=calloc(sa->ports, sizeof(struct port_stats));
+ if ( (i=ngadmin_getPortsStatistics(nga, ps))<0 ) {
+  printErrCode(i);
+  ret=false;
+  goto end;
+ }
+ printf("Port\tReceived\tSent\t\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);
+ }
+ end:
+ free(ps);
+ return ret;
+}
+
+
+
+static bool do_ports_stats_reset (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i;
+ if ( ngadmin_getCurrentSwitch(nga)==NULL ) {
+  printf("must be logged\n");
+  return false;
+ }
+ i=ngadmin_resetPortsStatistics(nga);
+ printErrCode(i);
+ return true;
+}
+
+
+
+static const struct TreeNode com_ports_state=COM("state", do_ports_state, false, NULL);
+
+static const struct TreeNode com_ports_stats_show=COM("show", do_ports_stats_show, false, NULL);
+static const struct TreeNode com_ports_stats_reset=COM("reset", do_ports_stats_reset, false, NULL);
+static const struct TreeNode com_ports_stats=COM("stats", NULL, false, &com_ports_stats_reset, &com_ports_stats_show, NULL);
+
+const struct TreeNode com_ports=COM("ports", NULL, false, &com_ports_state, &com_ports_stats, NULL);
+
+
+
diff --git a/cli/com_quit.c b/cli/com_quit.c
new file mode 100644 (file)
index 0000000..61dc5ce
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "common.h"
+
+
+
+
+static bool do_quit (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+ cont=0;
+ return true;
+}
+
+
+
+const struct TreeNode com_quit=COM("quit", do_quit, false, NULL);
+
+
+
diff --git a/cli/com_scan.c b/cli/com_scan.c
new file mode 100644 (file)
index 0000000..51b24b8
--- /dev/null
@@ -0,0 +1,31 @@
+
+#include "common.h"
+
+
+
+
+static bool do_scan (const struct TreeNode *tn UNUSED, int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+ int i;
+ const struct swi_attr *sa;
+ if ( (i=ngadmin_scan(nga))<0 ) {
+  printErrCode(i);
+  return false;
+ }
+ sa=ngadmin_getSwitchTab(nga, &nb);
+ displaySwitchTab(sa, nb);
+ return true;
+}
+
+
+
+const struct TreeNode com_scan=COM("scan", do_scan, false, NULL);
+
+
+
diff --git a/cli/command.c b/cli/command.c
new file mode 100644 (file)
index 0000000..943d148
--- /dev/null
@@ -0,0 +1,56 @@
+
+#include "command.h"
+
+
+
+
+// ----------------------------
+int trim (char *txt, int start) {
+ char *p, c;
+ if ( txt==NULL ) {
+  return 0;
+ }
+ //for (p=txt; *p!=0; p++);
+ p=txt+start;
+ for (p--; p>=txt && ( (c=*p)==' ' || c=='\n' ); *p--=0);
+ return p-txt+1;
+}
+
+
+
+// --------------------------------------------------------
+int explode (const char *commande, char** tab, int maximum) {
+ const char *start, *end;
+ char c;
+ int n=0, len;
+ for (end=commande; ; n++) {
+  
+  for (start=end; (c=*start)==' ' && c!=0; start++);
+  for (end=start; ( (c=*end)!=' ' || n>=maximum-1 ) && c!=0; end++);
+  
+  if ( (len=end-start)==0 ) {
+   break;
+  }
+  
+  tab[n]=malloc(sizeof(char)*(len+1));
+  memcpy(tab[n], start, len);
+  tab[n][len]=0;
+  
+ }
+ return n;
+}
+
+
diff --git a/cli/command.h b/cli/command.h
new file mode 100644 (file)
index 0000000..0689b22
--- /dev/null
@@ -0,0 +1,20 @@
+
+#ifndef DEF_COMMAND
+#define DEF_COMMAND
+
+
+#include <stdlib.h>
+#include <string.h>
+
+
+
+// 
+int trim (char *txt, int start);
+
+// 
+int explode (const char *commande, char** tab, int maximum);
+
+
+
+#endif
+
diff --git a/cli/common.h b/cli/common.h
new file mode 100644 (file)
index 0000000..ee845af
--- /dev/null
@@ -0,0 +1,48 @@
+
+#ifndef DEF_COMMON
+#define DEF_COMMON
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ngadmin.h>
+
+
+#define UNUSED                         __attribute__((unused))
+#define COM(nam, func, args, ...)      {.name=nam, .comfunc=func, .hasArgs=args, .sub={__VA_ARGS__}}
+
+
+
+struct TreeNode {
+ const char *name;
+ bool (* const comfunc)(const struct TreeNode*, int, const char**, struct ngadmin*);
+ bool hasArgs;
+ const struct TreeNode *sub[];
+};
+
+
+
+extern int cont;
+
+
+
+extern const struct TreeNode com_quit;
+extern const struct TreeNode com_login;
+extern const struct TreeNode com_scan;
+extern const struct TreeNode com_ports;
+extern const struct TreeNode com_password;
+extern const struct TreeNode com_list;
+extern const struct TreeNode com_list;
+extern const struct TreeNode com_firmware;
+extern const struct TreeNode com_name;
+
+
+
+void displaySwitchTab (const struct swi_attr *sa, int nb);
+void printErrCode (int err);
+
+
+
+#endif
+
diff --git a/command.c b/command.c
deleted file mode 100644 (file)
index 943d148..0000000
--- a/command.c
+++ /dev/null
@@ -1,56 +0,0 @@
-
-#include "command.h"
-
-
-
-
-// ----------------------------
-int trim (char *txt, int start) {
- char *p, c;
- if ( txt==NULL ) {
-  return 0;
- }
- //for (p=txt; *p!=0; p++);
- p=txt+start;
- for (p--; p>=txt && ( (c=*p)==' ' || c=='\n' ); *p--=0);
- return p-txt+1;
-}
-
-
-
-// --------------------------------------------------------
-int explode (const char *commande, char** tab, int maximum) {
- const char *start, *end;
- char c;
- int n=0, len;
- for (end=commande; ; n++) {
-  
-  for (start=end; (c=*start)==' ' && c!=0; start++);
-  for (end=start; ( (c=*end)!=' ' || n>=maximum-1 ) && c!=0; end++);
-  
-  if ( (len=end-start)==0 ) {
-   break;
-  }
-  
-  tab[n]=malloc(sizeof(char)*(len+1));
-  memcpy(tab[n], start, len);
-  tab[n][len]=0;
-  
- }
- return n;
-}
-
-
diff --git a/command.h b/command.h
deleted file mode 100644 (file)
index 0689b22..0000000
--- a/command.h
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#ifndef DEF_COMMAND
-#define DEF_COMMAND
-
-
-#include <stdlib.h>
-#include <string.h>
-
-
-
-// 
-int trim (char *txt, int start);
-
-// 
-int explode (const char *commande, char** tab, int maximum);
-
-
-
-#endif
-
diff --git a/commandes b/commandes
deleted file mode 100644 (file)
index 7ecd1e4..0000000
--- a/commandes
+++ /dev/null
@@ -1,52 +0,0 @@
-
-scan
-
-login 5
-
-password set
-password change
-
-timeout show
-timeout set 10
-
-restart
-
-defaults
-
-firmware show
-firmware update new_firmware.bin
-
-mirror show
-mirror disable
-mirror set 1 4 6 3 2 to 8
-
-ports state
-ports stats show
-ports stats reset
-
-vlan show
-vlan disable
-vlan set mode port|dot basic|adv
-
-cabletest 1 5 8 7
-
-qos show
-qos set mode dot|port
-qos set 5 high|mid|norm|low
-
-bitrate show
-bitrate set 4 in nl|512K|1M|2M|4M|8M|16M|32M|64M|128M|256M|512M out nl|512K|1M|2M|4M|8M|16M|32M|64M|128M|256M|512M
-
-broadfilt show
-broadfilt disable
-broadfilt set 8 nl|512K|1M|2M|4M|8M|16M|32M|64M|128M|256M|512M
-
-ip show
-ip set dhcp enable|disable
-ip set ip 192.168.0.1 mask 255.255.255.0|24 gw 192.168.0.254
-
-name show
-name set bordel_de_merde
-
-quit
-
diff --git a/controller.c b/controller.c
deleted file mode 100644 (file)
index 14b596f..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-
-#include "controller.h"
-
-
-
-
-static char password[128];
-static List *swiList=NULL;
-static struct swi_attr *current=NULL;
-static unsigned int seq=0;
-
-
-
-
-// =============================================================================
-
-
-// ------------------------
-void startController (void) {
- password[0]=0;
- swiList=createEmptyList();
-}
-
-
-// -----------------------
-void stopController (void) {
- destroyList(swiList, free);
- current=NULL;
-}
-
-
-
-// =============================================================================
-
-
-static void getSwitchAttributes (struct swi_attr *sa, const List *l) {
- const ListNode *ln;
- const struct attr *at;
- int len;
- memset(sa, 0, sizeof(struct swi_attr));
- sa->ports=0;
- for (ln=l->first; ln!=NULL; ln=ln->next) {
-  at=ln->data;
-  
-  switch ( at->attr ) {
-   
-   case ATTR_PRODUCT:
-    len=min(at->size, PRODUCT_SIZE);
-    memcpy(sa->product, at->data, len);
-    trim(sa->product, len);
-   break;
-   
-   case ATTR_NAME:
-    len=min(at->size, NAME_SIZE);
-    memcpy(sa->name, at->data, len);
-    trim(sa->name, len);
-   break;
-   
-   case ATTR_MAC:
-    memcpy(&sa->mac, at->data, ETH_ALEN);
-   break;
-   
-   case ATTR_IP:
-    sa->nc.ip=*(struct in_addr*)at->data;
-   break;
-   
-   case ATTR_NETMASK:
-    sa->nc.netmask=*(struct in_addr*)at->data;
-   break;
-   
-   case ATTR_GATEWAY:
-    sa->nc.gw=*(struct in_addr*)at->data;
-   break;
-   
-   case ATTR_END:
-    return;
-   
-  }
-  
- }
-}
-
-
-
-// ------------------------
-int discoverSwitches (void) {
- int i;
- List *attr;
- struct swi_attr *sa;
- clearList(swiList, free);
- current=NULL;
- attr=createEmptyList();
- i=0;
- do {
-  pushBackList(attr, newEmptyAttr(helloRequest[i]));
- } while ( helloRequest[i++]!=ATTR_END );
- i=sendNgPacket(CODE_READ_REQ, NULL, ++seq, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 ) {
-  return ERR_NET;
- }
- while ( (attr=recvNgPacket (CODE_READ_REP, NULL, seq))!=NULL ) {
-  sa=malloc(sizeof(struct swi_attr));
-  getSwitchAttributes(sa, attr);
-  pushBackList(swiList, sa);
- }
- destroyList(attr, (void(*)(void*))freeAttr);
- return ERR_OK;
-}
-
-
-// -----------------------------
-const List* getSwitchList (void) {
- return swiList;
-}
-
-
-// ------------------------------------
-const struct swi_attr* getCurrentSwitch (void) {
- return current;
-}
-
-
-// --------------
-int login (int i) {
- List *attr;
- ListNode *ln;
- if ( i<0 || i>(int)swiList->count ) {
-  return ERR_BADID;
- }
- for (ln=swiList->first; i-->0; ln=ln->next);
- current=ln->data;
- //attr=createEmptyList();
- return ERR_OK;
-}
-
-
-//int logout (void);
-
-
-// --------------------------------
-void setPassword (const char *pass) {
- strncpy(password, pass, sizeof(password));
-}
-
-
-//int changePassword (const char *pass);
-
-
-
-// =============================================================================
-
-
-//int getPortsNumber (void);
-
-// ------------------------------------------------
-int getPortsStatus (unsigned char *ports, int size) {
- List *attr;
- ListNode *ln;
- struct attr *at;
- char *p;
- int i;
- if ( ports==NULL || size<=0 ) {
-  return ERR_INVARG;
- } else if ( current==NULL ) {
-  return ERR_NOTLOG;
- }
- attr=createEmptyList();
- pushBackList(attr, newEmptyAttr(ATTR_PORT_STATUS));
- pushBackList(attr, newEmptyAttr(ATTR_END));
- i=sendNgPacket(CODE_READ_REQ, NULL, ++seq, attr);
- destroyList(attr, (void(*)(void*))freeAttr);
- if ( i<0 ) {
-  return ERR_NET;
- }
- if ( (attr=recvNgPacket (CODE_READ_REP, NULL, seq))==NULL ) {
-  return ERR_TIMEOUT;
- }
- for (ln=attr->first; ln!=NULL; ln=ln->next) {
-  at=ln->data;
-  p=at->data;
-  if ( at->attr==ATTR_PORT_STATUS && p[0]-1<size ) {
-   i=p[0]-1;
-   ports[i]=p[1];
-  }
- }
- destroyList(attr, (void(*)(void*))freeAttr);
- return ERR_OK;
-}
-
-
-//int getPortsStatistics (unsigned long long stats[][6], int size);
-
-//int resetPortsStatistics (void);
-
-
-
diff --git a/controller.h b/controller.h
deleted file mode 100644 (file)
index 877901c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-
-#ifndef DEF_CONTROLLER
-#define DEF_CONTROLLER
-
-
-#include <stdbool.h>
-#include <arpa/inet.h>
-#include <netinet/ether.h>
-
-#include "list.h"
-#include "protocol.h"
-#include "network.h"
-
-
-
-#define ERR_OK         0
-#define ERR_NET                -1
-#define ERR_NOTLOG     -2
-#define ERR_BADPASS    -3
-#define ERR_BADID      -4
-#define ERR_INVARG     -5
-#define ERR_TIMEOUT    -6
-
-#define PRODUCT_SIZE   64
-#define NAME_SIZE      64
-#define FIRMWARE_SIZE  64
-
-
-
-struct net_conf {
- struct in_addr ip, netmask, gw;
- bool dhcp;
-};
-
-
-struct swi_attr {
- char product[PRODUCT_SIZE];
- char name[NAME_SIZE];
- char firmware[FIRMWARE_SIZE];
- unsigned char ports;
- struct ether_addr mac;
- struct net_conf nc;
-};
-
-
-
-
-
-void startController (void);
-
-void stopController (void);
-
-
-
-int discoverSwitches (void);
-
-const List* getSwitchList (void);
-
-const struct swi_attr* getCurrentSwitch (void);
-
-int login (int i);
-
-int logout (void);
-
-
-
-void setPassword (const char *pass);
-
-int changePassword (const char *pass);
-
-
-
-int getFirmwareVersion (char *buf, int size);
-
-int getMirrorPorts (unsigned char *ports, int size);
-
-int setMirrorPorts (const unsigned char *ports, int size);
-
-
-
-int getPortsNumber (void);
-
-int getPortsStatus (unsigned char *ports, int size);
-
-int getPortsStatistics (unsigned long long stats[][6], int size);
-
-int resetPortsStatistics (void);
-
-
-
-int getQosStatus (void);
-
-int setQosMode (char mode);
-
-int setQosPorts (const unsigned char* ports, int size, char level);
-
-
-
-int getNetConf (struct net_conf *nc);
-
-int setNetConf (const struct net_conf *nc);
-
-
-
-int getName (char *name, int size);
-
-int setName (const char *name);
-
-
-
-#endif
-
diff --git a/emu.c b/emu.c
deleted file mode 100644 (file)
index d968ded..0000000
--- a/emu.c
+++ /dev/null
@@ -1,299 +0,0 @@
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <signal.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <sys/ioctl.h>
-
-#include "protocol.h"
-
-
-
-
-int sock;
-
-
-
-__attribute__((noreturn)) void handler (int sig) {
- if ( sig==SIGINT ) {
-  printf("\033[1G");
- }
- close(sock);
- exit(0);
-}
-
-
-
-int main (int argc, char **argv) {
- char buffer[1024];
- socklen_t slen=sizeof(struct sockaddr_in);
- struct sockaddr_in local, client;
- struct ether_addr localmac;
- struct in_addr localip;
- struct ifreq ifr;
- int len, i;
- unsigned char ports=8;
- struct ng_packet np;
- struct attr *at;
- List *l;
- ListNode *ln;
- if ( argc<2 ) {
-  printf("Usage: %s <interface>\n", argv[0]);
-  return 1;
- }
- memset(&local, 0, sizeof(struct sockaddr_in));
- local.sin_family=AF_INET;
- client=local;
- local.sin_addr.s_addr=htonl(INADDR_ANY);
- local.sin_port=htons(SWITCH_PORT);
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, argv[1], IFNAMSIZ-1);
- np.buffer=buffer;
- np.maxlen=sizeof(buffer);
- if ( (sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))<0 ) {
-  perror("socket");
- } else if ( bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_in))<0 ) {
-  perror("bind");
- }
- i=1;
- if ( setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i))<0 ) {
-  perror("setsockopt(SO_BROADCAST)");
- }
- /*
- i=0;
- if ( setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &i, sizeof(i)) ) {
-  perror("setsockopt(IP_MULTICAST_LOOP)");
- }
- */
- if ( ioctl(sock, SIOCGIFHWADDR, &ifr)<0 ) {
-  perror("ioctl(SIOCGIFHWADDR)");
- }
- memcpy(&localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
- if ( ioctl(sock, SIOCGIFADDR, &ifr)<0 ) {
-  perror("ioctl(SIOCGIFADDR)");
- }
- localip=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr;
- printf("server: ip %s, mac %s\n", inet_ntoa(localip), ether_ntoa(&localmac));
- signal(SIGINT, handler);
- signal(SIGTERM, handler);
- while ( 1 ) {
-  
-  if ( (len=recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&client, &slen))<0 ) {
-   perror("recvfrom");
-   break;
-  }
-  
-  if ( len<(int)sizeof(struct ng_header) || ( memcmp(&np.nh->switch_mac, &nullMac, 6)!=0 && memcmp(&np.nh->switch_mac, &localmac, 6)!=0 ) ) {
-   continue;
-  }
-  
-  printf("received %d bytes from %s: \n", len, inet_ntoa(client.sin_addr));
-  
-  printf("code: %i\n", np.nh->code);
-  printf("client mac: %s\n", ether_ntoa((struct ether_addr*)np.nh->client_mac));
-  printf("seq num: %d\n", ntohl(np.nh->seqnum));
-  printf("\n");
-  
-  memcpy(np.nh->switch_mac, &localmac, ETH_ALEN);
-  
-  initNgPacket(&np);
-  l=extractPacketAttributes(&np);
-  
-  initNgPacket(&np);
-  
-  
-  switch ( np.nh->code ) {
-   
-   case CODE_READ_REQ:
-    
-    for (ln=l->first; ln!=NULL; ln=ln->next) {
-     at=ln->data;
-     
-     switch ( at->attr ) {
-      
-      case ATTR_PRODUCT:
-       strcpy(np.ah->data, "NgEmu");
-       addPacketAttr(&np, ATTR_PRODUCT, strlen(np.ah->data), NULL);
-      break;
-      
-      case ATTR_UNK2:
-       addPacketShortAttr(&np, ATTR_UNK2, 0);
-      break;
-      
-      case ATTR_NAME:
-       strcpy(np.ah->data, "netgear switch emulator");
-       addPacketAttr(&np, ATTR_NAME, strlen(np.ah->data), NULL);
-      break;
-      
-      case ATTR_MAC:
-       memcpy(np.ah->data, &localmac, ETH_ALEN);
-       addPacketAttr(&np, ATTR_MAC, ETH_ALEN, NULL);
-      break;
-      
-      case ATTR_UNK5:
-       memset(np.ah->data, 0, 64);
-       addPacketAttr(&np, ATTR_UNK5, 64, NULL);
-      break;
-      
-      case ATTR_IP:
-       *(struct in_addr*)np.ah->data=localip;
-       addPacketAttr(&np, ATTR_IP, 4, NULL);
-      break;
-      
-      case ATTR_NETMASK:
-       *(in_addr_t*)np.ah->data=inet_addr("255.255.255.0");
-       addPacketAttr(&np, ATTR_NETMASK, 4, NULL);
-      break;
-      
-      case ATTR_GATEWAY:
-       *(in_addr_t*)np.ah->data=inet_addr("192.168.0.16");
-       addPacketAttr(&np, ATTR_GATEWAY, 4, NULL);
-      break;
-      
-      case ATTR_DHCP:
-       addPacketShortAttr(&np, ATTR_DHCP, 1);
-      break;
-      
-      case ATTR_UNK12:
-       addPacketByteAttr(&np, ATTR_UNK12, 1);
-      break;
-      
-      case ATTR_FIRM_VER:
-       strcpy(np.ah->data, "NgAdmin 0.0.1");
-       addPacketAttr(&np, ATTR_FIRM_VER, strlen(np.ah->data), NULL);
-      break;
-      
-      case ATTR_UNK15:
-       addPacketByteAttr(&np, ATTR_UNK15, 1);
-      break;
-      
-      case ATTR_PORTS_NUMBER:
-       addPacketByteAttr(&np, ATTR_PORTS_NUMBER, ports);
-      break;
-      
-      case ATTR_PORT_STATUS:
-       for (i=1; i<=ports; i++) {
-        np.ah->data[0]=i;
-        switch ( i&3 ) {
-         case 0: np.ah->data[2]=0; np.ah->data[1]=0; break;
-         case 1: np.ah->data[2]=1; np.ah->data[1]=SPEED_10; break;
-         case 2: np.ah->data[2]=1; np.ah->data[1]=SPEED_100; break;
-         case 3: np.ah->data[2]=1; np.ah->data[1]=SPEED_1000; 
-        }
-        addPacketAttr(&np, ATTR_PORT_STATUS, 3, NULL);
-       }
-      break;
-      
-      case ATTR_QOS_TYPE:
-       addPacketByteAttr(&np, ATTR_QOS_TYPE, QOS_PORT);
-      break;
-      
-      case ATTR_QOS_CONFIG:
-       for (i=1; i<=(int)ports; i++) {
-        np.ah->data[0]=i;
-        np.ah->data[1]=(i&3)+1;
-        addPacketAttr(&np, ATTR_QOS_CONFIG, 2, NULL);
-       }
-      break;
-      
-      case 0x5400:
-       addPacketByteAttr(&np, 0x5400, 0);
-      break;
-      
-      /*
-      case 0x1000: // System -> Monitoring -> Port Statistics
-       len=1+3*8;
-       for (i=1; i<=(int)ports; i++) {
-        memset(np.ah->data, 0, len);
-        addPacketAttr(&np, 0x1000, len, NULL);
-       }
-      break;
-      */
-      
-      case ATTR_MIRROR:
-       np.ah->data[0]=ports;
-       np.ah->data[1]=0;
-       len=(ports>>3)+((ports&7)!=0);
-       *(unsigned int*)&np.ah->data[2]=0;
-       for (i=0; i<ports-1; i+=2) {
-        np.ah->data[2+(i>>3)] |= 1<<(7-(i&7)) ;
-       }
-       addPacketAttr(&np, ATTR_MIRROR, 2+len, NULL);
-      break;
-      
-      case ATTR_VLAN_TYPE:
-       addPacketByteAttr(&np, ATTR_VLAN_TYPE, VLAN_DOT_ADV);
-      break;
-      
-      /*
-      case 0x7400:
-      break
-      */
-      
-      default:
-       addPacketEmptyAttr(&np, at->attr);
-      
-     }
-     
-    }
-    
-    np.nh->code=CODE_READ_REP;
-    len=getPacketTotalSize(&np);
-    
-   break;
-   
-   case CODE_WRITE_REQ:
-    np.nh->code=CODE_WRITE_REP;
-   break;
-   
-   default:
-    printf("unkown code\n");
-   
-  }
-  
-  
-  destroyList(l, (void(*)(void*))freeAttr);
-  
-  client.sin_addr.s_addr=htonl(INADDR_BROADCAST);
-  client.sin_port=htons(CLIENT_PORT);
-  if ( sendto(sock, buffer, len, 0, (struct sockaddr*)&client, sizeof(struct sockaddr))<0 ) {
-   perror("sendto");
-  }
-  
-  
- }
- handler(0);
-}
-
diff --git a/lib/ngadmin.h b/lib/ngadmin.h
new file mode 100644 (file)
index 0000000..824b0dd
--- /dev/null
@@ -0,0 +1,151 @@
+
+#ifndef DEF_NGADMIN
+#define DEF_NGADMIN
+
+
+#include <stdbool.h>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+
+
+#ifdef BUILD_LIB
+#define EXPORT __attribute__((visibility("default")))
+#else
+#define EXPORT 
+#endif
+
+
+#define ERR_OK         0       // no error
+#define ERR_NET                -1      // network
+#define ERR_NOTLOG     -2      // not logged on a switch
+#define ERR_BADPASS    -3      // bad password
+#define ERR_BADID      -4      // bad switch id
+#define ERR_INVARG     -5      // invalid argument
+#define ERR_TIMEOUT    -6      // timeout
+
+#define PRODUCT_SIZE   64
+#define NAME_SIZE      64
+#define FIRMWARE_SIZE  64
+
+
+
+
+#define SPEED_DOWN             0
+#define SPEED_10               1
+#define SPEED_100              4
+#define SPEED_1000             5
+
+#define VLAN_PORT_BASIC                1
+#define VLAN_PORT_ADV          2
+#define VLAN_DOT_BASIC         3
+#define VLAN_DOT_ADV           4
+
+#define QOS_PORT               1
+#define QOS_DOT                        2
+
+#define PRIO_HIGH              1
+#define PRIO_MED               2
+#define PRIO_NORM              3
+#define PRIO_LOW               4
+
+#define BITRATE_NOLIMIT                0
+#define BITRATE_512K           1
+#define BITRATE_1M             2
+#define BITRATE_2M             3
+#define BITRATE_4M             4
+#define BITRATE_8M             5
+#define BITRATE_16M            6
+#define BITRATE_32M            7
+#define BITRATE_64M            8
+#define BITRATE_128M           9
+#define BITRATE_256M           10
+#define BITRATE_512M           11
+
+
+
+
+// opaque type to clients
+struct ngadmin;
+
+
+struct net_conf {
+ struct in_addr ip;            // IP
+ struct in_addr netmask;       // netmask
+ struct in_addr gw;            // gateway IP
+ bool dhcp;                    // DHCP enabled
+};
+
+
+struct swi_attr {
+ char product[PRODUCT_SIZE];   // product name (eg. GS108E)
+ char name[NAME_SIZE];         // custom name
+ char firmware[FIRMWARE_SIZE]; // firmware version string
+ unsigned char ports;          // number of ports
+ struct ether_addr mac;                // MAC address
+ struct net_conf nc;           // network configuration
+};
+
+
+struct port_stats {
+ unsigned long long recv;
+ unsigned long long sent;
+ unsigned long long crc;
+};
+
+
+
+
+// initialize NgAdmin lib
+struct ngadmin* ngadmin_init (const char *iface) EXPORT;
+
+// 
+int ngadmin_close (struct ngadmin *nga) EXPORT;
+
+
+// specify password to use for authenticating on switches
+int ngadmin_setPassword (struct ngadmin *nga, const char *pass) EXPORT;
+
+
+// 
+int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) EXPORT;
+
+
+// 
+int ngadmin_scan (struct ngadmin *nga) EXPORT;
+
+
+// 
+const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) EXPORT;
+
+
+// 
+const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) EXPORT;
+
+
+// 
+int ngadmin_login (struct ngadmin *nga, int id) EXPORT;
+
+
+// 
+int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) EXPORT;
+
+
+// 
+int ngadmin_setName (struct ngadmin *nga, const char *name) EXPORT;
+
+
+// 
+int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) EXPORT;
+
+
+// 
+int ngadmin_resetPortsStatistics (struct ngadmin *nga) EXPORT;
+
+
+// 
+int ngadmin_changePassword (struct ngadmin *nga, const char* pass) EXPORT;
+
+
+
+#endif
+
diff --git a/lib/src/Makefile b/lib/src/Makefile
new file mode 100644 (file)
index 0000000..9013cd8
--- /dev/null
@@ -0,0 +1,25 @@
+
+CC=gcc
+CFLAGS=-DBUILD_LIB -D_REENTRANT -I.. -W -Wall -Wextra -Os -fomit-frame-pointer -fno-strict-aliasing -fvisibility=hidden -fPIC
+LDFLAGS=-lpthread -s
+EXEC=../libngadmin.so
+
+SRC=$(wildcard *.c)
+OBJ=$(SRC:.c=.o)
+
+
+
+$(EXEC): $(OBJ)
+       $(CC) $^ -shared -o $@ $(LDFLAGS)
+
+%.o: %.c
+       $(CC) -c $^ -o $@ $(CFLAGS)
+
+
+clean:
+       @rm -f *.o
+
+mrproper: clean
+       @rm -f $(EXEC)
+
+
diff --git a/lib/src/lib.h b/lib/src/lib.h
new file mode 100644 (file)
index 0000000..f89d02f
--- /dev/null
@@ -0,0 +1,77 @@
+
+#ifndef DEF_LIB
+#define DEF_LIB
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <net/if.h>
+
+#include <ngadmin.h>
+
+
+#define PASSWORD_MAX   32
+
+
+#define CLIENT_PORT            63321
+#define SWITCH_PORT            63322
+
+#define CODE_READ_REQ          1
+#define CODE_READ_REP          2
+#define CODE_WRITE_REQ         3
+#define CODE_WRITE_REP         4
+
+#define ATTR_PRODUCT           0x0001
+#define ATTR_UNK2              0x0002
+#define ATTR_NAME              0x0003
+#define ATTR_MAC               0x0004
+#define ATTR_UNK5              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_FIRM_VER          0x000D
+#define ATTR_UNK14             0x000E
+#define ATTR_UNK15             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_QOS_TYPE          0x3400
+#define ATTR_QOS_CONFIG                0x3800
+#define ATTR_BITRATE_INPUT     0x4C00
+#define ATTR_BITRATE_OUTPUT    0x5000
+#define ATTR_STORM_ENABLE      0x5400
+#define ATTR_STORM_BITRATE     0x5800
+#define ATTR_MIRROR            0x5C00
+#define ATTR_PORTS_COUNT       0x6000
+#define ATTR_END               0xFFFF
+
+
+
+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
+ // 
+ char password[PASSWORD_MAX];  // password to use to login on switches
+ struct swi_attr *swi_tab;     // array of detected switches
+ int swi_count;                        // number of detected switches
+ struct swi_attr *current;     // administred switch
+ int seq;                      // sequence number for packets
+};
+
+
+
+#endif
+
diff --git a/lib/src/list.c b/lib/src/list.c
new file mode 100644 (file)
index 0000000..bc48e1e
--- /dev/null
@@ -0,0 +1,366 @@
+
+#include "list.h"
+
+
+
+
+// -------------------------
+List* createEmptyList (void) {
+ List *l;
+ l=malloc(sizeof(List));
+ l->first=NULL;
+ l->last=NULL;
+ l->count=0;
+ pthread_cond_init(&l->cond, NULL);
+ pthread_mutex_init(&l->mutex, NULL);
+ return l;
+}
+
+
+
+// ------------------------------------------------
+void destroyList (List *l, void (*freefunc)(void*)) {
+ ListNode *pr, *ln;
+ if ( l==NULL ) {
+  return;
+ }
+ pthread_mutex_destroy(&l->mutex);
+ pthread_cond_destroy(&l->cond);
+ for (ln=l->first; ln!=NULL; ) {
+  
+  pr=ln;
+  
+  if ( freefunc!=NULL ) {
+   freefunc(pr->data);
+  }
+  
+  ln=pr->next;
+  free(pr);
+  
+ }
+ free(l);
+}
+
+
+
+// -------------------------------------
+void pushFrontList (List *l, void* data) {
+ ListNode *ln;
+ if ( l==NULL ) {
+  return;
+ }
+ pthread_mutex_lock(&l->mutex);
+ ln=malloc(sizeof(ListNode));
+ ln->data=data;
+ ln->prev=NULL;
+ ln->next=l->first;
+ if ( l->first==NULL ) {
+  l->last=ln;
+ } else {
+  l->first->prev=ln;
+ }
+ l->first=ln;
+ l->count++;
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+}
+
+
+
+// ------------------------------------
+void pushBackList (List *l, void* data) {
+ ListNode *ln;
+ if ( l==NULL ) {
+  return;
+ }
+ pthread_mutex_lock(&l->mutex);
+ ln=malloc(sizeof(ListNode));
+ ln->data=data;
+ ln->prev=l->last;
+ ln->next=NULL;
+ if ( l->last==NULL ) {
+  l->first=ln;
+ } else {
+  l->last->next=ln;
+ }
+ l->last=ln;
+ l->count++;
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+}
+
+
+
+// -------------------------
+void* popFrontList (List *l) {
+ ListNode *ln;
+ void* data;
+ if ( l==NULL ) {
+  return NULL;
+ }
+ pthread_mutex_lock(&l->mutex);
+ if ( (ln=l->first)==NULL ) {
+  pthread_mutex_unlock(&l->mutex);
+  return NULL;
+ }
+ data=ln->data;
+ l->first=ln->next;
+ if ( ln->next==NULL ) {
+  l->last=NULL;
+ } else {
+  ln->next->prev=NULL;
+ }
+ l->count--;
+ free(ln);
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ return data;
+}
+
+
+
+// ------------------------
+void* popBackList (List *l) {
+ ListNode *ln;
+ void* data;
+ if ( l==NULL ) {
+  return NULL;
+ }
+ pthread_mutex_lock(&l->mutex);
+ if ( (ln=l->last)==NULL ) {
+  pthread_mutex_unlock(&l->mutex);
+  return NULL;
+ }
+ data=ln->data;
+ l->last=ln->prev;
+ if ( ln->prev==NULL ) {
+  l->first=NULL;
+ } else {
+  ln->prev->next=NULL;
+ }
+ l->count--;
+ free(ln);
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+ return data;
+}
+
+
+
+// ----------------------------------------------
+void clearList (List *l, void (*freefunc)(void*)) {
+ ListNode *ln, *pr;
+ if ( l==NULL ) {
+  return;
+ }
+ pthread_mutex_lock(&l->mutex);
+ for (ln=l->first; ln!=NULL; ) {
+  
+  pr=ln;
+  
+  if ( freefunc!=NULL ) {
+   freefunc(pr->data);
+  }
+  
+  ln=pr->next;
+  free(pr);
+  
+ }
+ l->first=NULL;
+ l->last=NULL;
+ l->count=0;
+ pthread_mutex_unlock(&l->mutex);
+ pthread_cond_broadcast(&l->cond);
+}
+
+
+
+// ---------------------------------------------------------------
+bool findAndDestroy (List *l, void* data, void (*freefunc)(void*)) {
+ ListNode *ln;
+ if ( l==NULL ) {
+  return false;
+ }
+ pthread_mutex_lock(&l->mutex);
+ for (ln=l->first; ln!=NULL && ln->data!=data; ln=ln->next);
+ if ( ln==NULL ) {
+  
+  pthread_mutex_unlock(&l->mutex);
+  
+ } else {
+  
+  if ( ln->prev==NULL ) {
+   l->first=ln->next;
+  } else {
+   ln->prev->next=ln->next;
+  }
+  
+  if ( ln->next==NULL ) {
+   l->last=ln->prev;
+  } else {
+   ln->next->prev=ln->prev;
+  }
+  
+  
+  if ( freefunc!=NULL ) {
+   freefunc(data);
+  }
+  
+  l->count--;
+  
+  pthread_mutex_unlock(&l->mutex);
+  pthread_cond_broadcast(&l->cond);
+  
+ }
+ return true;
+}
+
+
+
+// -------------------------------------------------
+void browseList (List *l, void (*browsefunc)(void*)) {
+ ListNode *ln;
+ if ( l==NULL || browsefunc==NULL ) {
+  return;
+ }
+ pthread_mutex_lock(&l->mutex);
+ for (ln=l->first; ln!=NULL; ln=ln->next) {
+  browsefunc(ln->data);
+ }
+ pthread_mutex_unlock(&l->mutex);
+}
+
+
+// --------------------------------------
+void* convertToArray (List *l, size_t sz) {
+ ListNode *ln;
+ void *tab=NULL, *p;
+ if ( l==NULL || sz==0 ) {
+  return NULL;
+ }
+ pthread_mutex_lock(&l->mutex);
+ if ( l->count>0 ) {
+  
+  tab=malloc(l->count*sz);
+  p=tab;
+  
+  for (ln=l->first; ln!=NULL; ln=ln->next) {
+   memcpy(p, ln->data, sz);
+   p+=sz;
+  }
+  
+ }
+ pthread_mutex_unlock(&l->mutex);
+ return tab;
+}
+
+
+
+
diff --git a/lib/src/list.h b/lib/src/list.h
new file mode 100644 (file)
index 0000000..39a1751
--- /dev/null
@@ -0,0 +1,67 @@
+
+#ifndef DEF_LIST
+#define DEF_LIST
+
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <pthread.h>
+
+
+
+
+typedef struct ListNode ListNode;
+
+struct ListNode {
+ void* data;
+ ListNode *prev, *next;
+};
+
+
+typedef struct {
+ ListNode *first, *last;
+ unsigned int count;
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+} List;
+
+
+
+
+// Creates an empty list
+List* createEmptyList (void);
+
+// Destroys a list, and eventually frees the elements
+// NOT MT SAFE
+void destroyList (List *l, void (*freefunc)(void*));
+
+// Adds an element at front of the list
+void pushFrontList (List *l, void* data);
+
+// Adds an element at back of the list
+void pushBackList (List *l, void* data);
+
+// Pops an element from the front of the list and returns its value
+void* popFrontList (List *l);
+
+// Pops an element from the back of the list and returns its value
+void* popBackList (List *l);
+
+// Clears all the items of the list, and eventually frees them
+void clearList (List *l, void (*freefunc)(void*));
+
+// Find and destroy a particular element of the list, and eventually frees it
+bool findAndDestroy (List *l, void* data, void (*freefunc)(void*));
+
+// Browse all the items of the list through the callback function
+void browseList (List *l, void (*browsefunc)(void*));
+
+// 
+void* convertToArray (List *l, size_t sz);
+
+
+
+
+#endif
+
diff --git a/lib/src/network.c b/lib/src/network.c
new file mode 100644 (file)
index 0000000..e8fa713
--- /dev/null
@@ -0,0 +1,154 @@
+
+#include "network.h"
+
+
+
+
+// -----------------------------------
+int startNetwork (struct ngadmin *nga) {
+ struct ifreq ifr;
+ int ret;
+ nga->local.sin_family=AF_INET;
+ nga->remote=nga->local;
+ nga->local.sin_port=htons(CLIENT_PORT);
+ memset(&ifr, 0, sizeof(struct ifreq));
+ strncpy(ifr.ifr_name, nga->iface, IFNAMSIZ-1);
+ if ( (nga->sock=socket(AF_INET, SOCK_DGRAM, 0))<0 ) {
+  perror("socket");
+  return nga->sock;
+ }
+ // get the interface IP address
+ if ( (ret=ioctl(nga->sock, SIOCGIFADDR, &ifr))<0 ) {
+  perror("ioctl(SIOCGIFADDR)");
+  close(nga->sock);
+  return ret;
+ }
+ //local.sin_addr=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr; // FIXME
+ // get the interface MAC address
+ if ( (ret=ioctl(nga->sock, SIOCGIFHWADDR, &ifr))<0 ) {
+  perror("ioctl(SIOCGIFHWADDR)");
+  close(nga->sock);
+  return ret;
+ }
+ memcpy(&nga->localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ // bind
+ if ( (ret=bind(nga->sock, (struct sockaddr*)&nga->local, sizeof(struct sockaddr_in)))<0 ) {
+  perror("bind");
+  close(nga->sock);
+  return ret;
+ }
+ // allow broadcasting
+ ret=1;
+ if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret)))<0 ) {
+  perror("setsockopt(SO_BROADCAST)");
+  return ret;
+ }
+ return 0;
+}
+
+
+
+// ----------------------------------
+int stopNetwork (struct ngadmin *nga) {
+ return close(nga->sock);
+}
+
+
+
+// ------------------------------------
+int updateTimeout (struct ngadmin *nga) {
+ int ret;
+ // specify receive timeout
+ if ( (ret=setsockopt(nga->sock, SOL_SOCKET, SO_RCVTIMEO, &nga->timeout, sizeof(struct timeval)))<0 ) {
+  perror("setsockopt(SO_RCVTIMEO)");
+  return ret;
+ }
+ return 0;
+}
+
+
+
+// --------------------------------------------------------------------------------------------------------------------------
+int sendNgPacket (struct ngadmin *nga, char code, const struct ether_addr *switch_mac, unsigned int seqnum, const List *attr) {
+ char buffer[1500];
+ struct ng_packet np;
+ ListNode *ln;
+ struct attr *at;
+ int ret;
+ np.buffer=buffer;
+ np.maxlen=sizeof(buffer);
+ initNgPacket(&np);
+ initNgHeader(np.nh, code, &nga->localmac, switch_mac, seqnum);
+ if ( attr!=NULL ) {
+  for (ln=attr->first; ln!=NULL; ln=ln->next) {
+   at=ln->data;
+   addPacketAttr(&np, at->attr, at->size, at->data);
+  }
+ }
+ 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 ) {
+  perror("sendto");
+ }
+ return ret;
+}
+
+
+
+// ---------------------------------------------------------------------------------------------------------------------------------------------------
+List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, const struct ether_addr *switch_mac, unsigned int seqnum) {
+ char buffer[1500];
+ struct ng_packet np;
+ socklen_t slen=sizeof(struct sockaddr_in);
+ List *l=NULL;
+ int len;
+ 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) ) {
+   initNgPacket(&np);
+   l=extractPacketAttributes(&np, error, attr_error);
+   break;
+  }
+ }
+ return l;
+}
+
+
diff --git a/lib/src/network.h b/lib/src/network.h
new file mode 100644 (file)
index 0000000..0b895b8
--- /dev/null
@@ -0,0 +1,37 @@
+
+#ifndef DEF_NETWORK
+#define DEF_NETWORK
+
+
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <netinet/ether.h>
+#include <sys/ioctl.h>
+
+#include "list.h"
+#include "lib.h"
+#include "protocol.h"
+
+
+
+// 
+int startNetwork (struct ngadmin *nga);
+
+// 
+int stopNetwork (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);
+
+// 
+List* recvNgPacket (struct ngadmin *nga, char code, char *error, unsigned short *attr_error, const struct ether_addr *switch_mac, unsigned int seqnum);
+
+
+
+#endif
+
diff --git a/lib/src/ngadmin.c b/lib/src/ngadmin.c
new file mode 100644 (file)
index 0000000..bdcc9b5
--- /dev/null
@@ -0,0 +1,501 @@
+
+#include "lib.h"
+#include "network.h"
+
+
+
+static const struct timeval default_timeout={.tv_sec=3, .tv_usec=0};
+
+
+
+// ---------------------------------------------
+struct ngadmin* ngadmin_init (const char *iface) {
+ struct ngadmin *nga;
+ // allocate main structure
+ nga=malloc(sizeof(struct ngadmin));
+ memset(nga, 0, sizeof(struct ngadmin));
+ strncpy(nga->iface, iface, IFNAMSIZ-1);
+ if ( startNetwork(nga)<0 ) {
+  free(nga);
+  return NULL;
+ }
+ nga->timeout=default_timeout;
+ if ( updateTimeout(nga)<0 ) {
+  free(nga);
+  return NULL;
+ }
+ return nga;
+}
+
+
+
+// ------------------------------------
+int ngadmin_close (struct ngadmin *nga) {
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ }
+ stopNetwork(nga);
+ free(nga->swi_tab);
+ free(nga);
+ return ERR_OK;
+}
+
+
+
+// ------------------------------------------------------------
+int ngadmin_setPassword (struct ngadmin *nga, const char *pass) {
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ }
+ strncpy(nga->password, pass, PASSWORD_MAX);
+ return ERR_OK;
+}
+
+
+
+// -------------------------------------------------------------------
+int ngadmin_setTimeout (struct ngadmin *nga, const struct timeval *tv) {
+ int ret=ERR_OK;
+ if ( nga==NULL || tv==NULL ) {
+  return ERR_INVARG;
+ }
+ nga->timeout=*tv;
+ if ( updateTimeout(nga)<0 ) {
+  ret=ERR_NET;
+ }
+ return ret;
+}
+
+
+
+// -----------------------------------
+int ngadmin_scan (struct ngadmin *nga) {
+ int i;
+ List *attr, *swiList;
+ struct swi_attr *sa;
+ /*
+ sent by official win client:
+  ATTR_PRODUCT, 
+  ATTR_UNK2, 
+  ATTR_NAME, 
+  ATTR_MAC, 
+  ATTR_UNK5, 
+  ATTR_IP, 
+  ATTR_NETMASK, 
+  ATTR_GATEWAY, 
+  ATTR_DHCP, 
+  ATTR_UNK12, 
+  ATTR_FIRM_VER, 
+  ATTR_UNK14, 
+  ATTR_UNK15, 
+  ATTR_END
+ */
+ static const unsigned short hello[]={
+  ATTR_PRODUCT, 
+  ATTR_NAME, 
+  ATTR_MAC, 
+  ATTR_IP, 
+  ATTR_NETMASK, 
+  ATTR_GATEWAY, 
+  ATTR_DHCP, 
+  ATTR_FIRM_VER, 
+  ATTR_PORTS_COUNT, 
+  ATTR_END
+ };
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ }
+ free(nga->swi_tab);
+ nga->swi_count=0;
+ nga->current=NULL;
+ // create attributes for an "hello" request
+ attr=createEmptyList();
+ for (i=0; ; ++i) {
+  pushBackList(attr, newEmptyAttr(hello[i]));
+  if ( hello[i]==ATTR_END ) break;
+ }
+ // send request to all potential switches
+ i=sendNgPacket(nga, CODE_READ_REQ, NULL, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 ) {
+  return ERR_NET;
+ }
+ // try to receive any packets until timeout
+ swiList=createEmptyList();
+ while ( (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, NULL, nga->seq))!=NULL ) {
+  sa=malloc(sizeof(struct swi_attr));
+  extractSwitchAttributes(sa, attr);
+  destroyList(attr, (void(*)(void*))freeAttr);
+  pushBackList(swiList, sa);
+ }
+ nga->swi_count=swiList->count;
+ nga->swi_tab=convertToArray(swiList, sizeof(struct swi_attr));
+ return ERR_OK;
+}
+
+
+
+// -----------------------------------------------------------------------
+const struct swi_attr* ngadmin_getSwitchTab (struct ngadmin *nga, int *nb) {
+ if ( nga==NULL || nb==NULL ) {
+  return NULL;
+ }
+ *nb=nga->swi_count;
+ return nga->swi_tab;
+}
+
+
+
+// ------------------------------------------------------------------
+const struct swi_attr* ngadmin_getCurrentSwitch (struct ngadmin *nga) {
+ if ( nga==NULL ) {
+  return NULL;
+ }
+ return nga->current;
+}
+
+
+
+// --------------------------------------------
+int ngadmin_login (struct ngadmin *nga, int id) {
+ List *attr;
+ int ret=ERR_OK, i;
+ struct swi_attr *sa;
+ char err;
+ unsigned short attr_error;
+ if ( nga==NULL ) {
+  return ERR_INVARG;
+ } else if ( id<0 || id>=nga->swi_count ) {
+  return ERR_BADID;
+ }
+ nga->current=NULL;
+ sa=&nga->swi_tab[id];
+ 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);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, &err, &attr_error, &sa->mac, nga->seq))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+  ret=ERR_BADPASS;
+  goto end;
+ }
+ // login successful
+ nga->current=sa;
+ end:
+ return ret;
+}
+
+
+
+// -------------------------------------------------------------------
+int ngadmin_getPortsStatus (struct ngadmin *nga, unsigned char *ports) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+ char *p;
+ if ( nga==NULL || ports==NULL ) {
+  return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+  return ERR_NOTLOG;
+ }
+ 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);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  p=at->data;
+  if ( at->attr==ATTR_PORT_STATUS && at->size>=2 && (i=p[0]-1)>=0 && i<nga->current->ports ) {
+   ports[i]=p[1];
+  }
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ end:
+ return ret;
+}
+
+
+
+// --------------------------------------------------------
+int ngadmin_setName (struct ngadmin *nga, const char *name) {
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ if ( nga==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)));
+ if ( name==NULL ) {
+  pushBackList(attr, newEmptyAttr(ATTR_NAME));
+ } else {
+  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);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+  ret=ERR_BADPASS;
+  goto end;
+ }
+ // successful, also update local name
+ if ( name==NULL ) {
+  nga->current->name[0]=0;
+ } else {
+  strncpy(nga->current->name, name, NAME_SIZE);
+ }
+ end:
+ return ret;
+}
+
+
+
+// ------------------------------------------------------------------------
+int ngadmin_getPortsStatistics (struct ngadmin *nga, struct port_stats *ps) {
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+ int port;
+ if ( nga==NULL || ps==NULL ) {
+  return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+  return ERR_NOTLOG;
+ }
+ 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);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL, &nga->current->mac, nga->seq))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  if ( at->attr==ATTR_PORT_STATISTICS && at->size>=49 && (port=(int)(*(char*)at->data)-1)>=0 && port<nga->current->ports ) {
+   ps[port].recv=be64toh(*(unsigned long long*)(at->data+1+8*0));
+   ps[port].sent=be64toh(*(unsigned long long*)(at->data+1+8*1));
+   ps[port].crc=be64toh(*(unsigned long long*)(at->data+1+8*5));
+   // all offsets between 2 and 4 inclusive are unknown values
+  }
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ end:
+ return ret;
+}
+
+
+
+// ---------------------------------------------------
+int ngadmin_resetPortsStatistics (struct ngadmin *nga) {
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ if ( nga==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)));
+ pushBackList(attr, newByteAttr(ATTR_STATS_RESET, 1));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, &nga->current->mac, ++nga->seq, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==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;
+}
+
+
+
+// ---------------------------------------------------------------
+int ngadmin_changePassword (struct ngadmin *nga, const char* pass) {
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ if ( nga==NULL || pass==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)));
+ 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);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error, &nga->current->mac, nga->seq))==NULL ) {
+  ret=ERR_NET;
+  goto end;
+ }
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+  ret=ERR_BADPASS;
+  goto end;
+ }
+ // successful, also update local password
+ strncpy(nga->password, pass, PASSWORD_MAX);
+ end:
+ return ret;
+}
+
+
diff --git a/lib/src/protocol.c b/lib/src/protocol.c
new file mode 100644 (file)
index 0000000..51e0611
--- /dev/null
@@ -0,0 +1,321 @@
+
+#include "protocol.h"
+
+
+
+
+
+const struct ether_addr nullMac={.ether_addr_octet={0, 0, 0, 0, 0, 0}};
+
+
+
+// -------------------
+int min (int a, int b) {
+ return a<b ? a : b ;
+}
+
+
+
+// -----------------------------------------------------------------------------------------------------------------------------------------------
+void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum) {
+ memset(nh, 0, sizeof(struct ng_header));
+ nh->unk1=1;
+ nh->code=code;
+ memcpy(nh->client_mac, client_mac, ETH_ALEN);
+ if ( switch_mac!=NULL ) {
+  memcpy(nh->switch_mac, switch_mac, ETH_ALEN);
+ }
+ nh->seqnum=htonl(seqnum);
+ strcpy(nh->proto_id, "NSDP");
+}
+
+
+
+// ---------------------------------------------------------------------------------------------------------------------------------------------------------
+bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum) {
+ if ( nh->unk1!=1 ) {
+  return false;
+ }
+ if ( code>0 && nh->code!=code ) {
+  return false;
+ }
+ if ( nh->unk2!=0 ) {
+  return false;
+ }
+ if ( *(unsigned short*)nh->unk3!=0 ) {
+  return false;
+ }
+ if ( client_mac!=NULL && memcmp(nh->client_mac, client_mac, ETH_ALEN)!=0 ) {
+  return false;
+ }
+ if ( switch_mac!=NULL && memcmp(nh->switch_mac, switch_mac, ETH_ALEN)!=0 ) {
+  return false;
+ }
+ if ( seqnum>0 && ntohl(nh->seqnum)!=seqnum ) {
+  return false;
+ }
+ if ( *(unsigned int*)nh->unk4!=0 ) {
+  return false;
+ }
+ return true;
+}
+
+
+
+// -------------------------------------
+void initNgPacket (struct ng_packet *np) {
+ np->ah=(struct attr_header*)np->nh->data;
+}
+
+
+
+// --------------------------------------------------------------------------------------------
+void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data) {
+ struct attr_header *ah=np->ah;
+ if ( (int)(getPacketTotalSize(np)+sizeof(struct attr_header)+size)>(np->maxlen) ) {
+  return;
+ }
+ ah->attr=htons(attr);
+ ah->size=htons(size);
+ if ( size>0 && data!=NULL ) {
+  memcpy(ah->data, data, size);
+ }
+ np->ah=(struct attr_header*)(ah->data+size);
+}
+
+
+
+// ----------------------------------------------------------------
+void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr) {
+ addPacketAttr(np, attr, 0, NULL);
+}
+
+
+
+// -------------------------------------------------------------------------
+void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val) {
+ addPacketAttr(np, attr, 1, &val);
+}
+
+
+
+// ---------------------------------------------------------------------------
+void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val) {
+ short s=htons(val);
+ addPacketAttr(np, attr, 2, &s);
+}
+
+
+
+// ------------------------------------------------
+int getPacketTotalSize (const struct ng_packet *np) {
+ return ((char*)np->ah)-np->buffer;
+}
+
+
+
+// --------------------------------------------
+struct attr* newEmptyAttr (unsigned short attr) {
+ return newAttr(attr, 0, NULL);
+}
+
+
+
+// ------------------------------------------------------------------------
+struct attr* newAttr (unsigned short attr, unsigned short size, void *data) {
+ struct attr *at;
+ at=malloc(sizeof(struct attr));
+ at->attr=attr;
+ at->size=size;
+ at->data=data;
+ return at;
+}
+
+
+
+// ----------------------------------------------------------------
+struct attr* newByteAttr (unsigned short attr, unsigned char value) {
+ char *v=malloc(sizeof(char));
+ *v=value;
+ return newAttr(attr, 1, v);
+}
+
+
+
+// ----------------------------
+void freeAttr (struct attr *at) {
+ if ( at!=NULL ) {
+  free(at->data);
+  free(at);
+ }
+}
+
+
+
+// ------------------------------------------------------------------------------------------
+List* extractPacketAttributes (struct ng_packet *np, char *error, unsigned short *attr_error) {
+ List *l;
+ struct attr *at;
+ if ( error!=NULL ) {
+  *error=np->nh->error;
+ }
+ if ( attr_error!=NULL ) {
+  *attr_error=ntohs(np->nh->attr);
+ }
+ l=createEmptyList();
+ while ( getPacketTotalSize(np)<np->maxlen ) {
+  
+  at=malloc(sizeof(struct attr));
+  at->attr=ntohs(np->ah->attr);
+  at->size=ntohs(np->ah->size);
+  
+  if ( getPacketTotalSize(np)+at->size>np->maxlen ) {
+   free(at);
+   break;
+  }
+  
+  if ( at->size==0 ) {
+   at->data=NULL;
+  } else {
+   at->data=malloc(at->size*sizeof(char));
+   memcpy(at->data, np->ah->data, at->size);
+  }
+  
+  pushBackList(l, at);
+  
+  if ( at->attr==ATTR_END ) {
+   break;
+  }
+  
+  np->ah=(struct attr_header*)(np->ah->data+at->size);
+  
+ }
+ return l;
+}
+
+
+
+// --------------------------------------------------------------
+void extractSwitchAttributes (struct swi_attr *sa, const List *l) {
+ const ListNode *ln;
+ const struct attr *at;
+ int len;
+ memset(sa, 0, sizeof(struct swi_attr));
+ // FIXME: mutex lock ?
+ for (ln=l->first; ln!=NULL; ln=ln->next) {
+  at=ln->data;
+  
+  switch ( at->attr ) {
+   
+   case ATTR_PRODUCT:
+    len=min(at->size, PRODUCT_SIZE);
+    memcpy(sa->product, at->data, len);
+    //trim(sa->product, len); // FIXME
+   break;
+   
+   case ATTR_NAME:
+    len=min(at->size, NAME_SIZE);
+    memcpy(sa->name, at->data, len);
+    //trim(sa->name, len); // FIXME
+   break;
+   
+   case ATTR_MAC:
+    memcpy(&sa->mac, at->data, ETH_ALEN);
+   break;
+   
+   case ATTR_IP:
+    sa->nc.ip=*(struct in_addr*)at->data;
+   break;
+   
+   case ATTR_NETMASK:
+    sa->nc.netmask=*(struct in_addr*)at->data;
+   break;
+   
+   case ATTR_GATEWAY:
+    sa->nc.gw=*(struct in_addr*)at->data;
+   break;
+   
+   case ATTR_DHCP:
+    sa->nc.dhcp=( ntohs(*(unsigned short*)at->data)==1 );
+   break;
+   
+   case ATTR_FIRM_VER:
+    len=min(at->size, FIRMWARE_SIZE-1);
+    memcpy(sa->firmware, at->data, len);
+    sa->firmware[len]=0;
+   break;
+   
+   case ATTR_PORTS_COUNT:
+    sa->ports=*(unsigned char*)at->data;
+   break;
+   
+   case ATTR_END:
+    return;
+   
+  }
+  
+ }
+}
+
+
+
diff --git a/lib/src/protocol.h b/lib/src/protocol.h
new file mode 100644 (file)
index 0000000..abc7707
--- /dev/null
@@ -0,0 +1,115 @@
+
+#ifndef DEF_PROTOCOL
+#define DEF_PROTOCOL
+
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+
+#include <ngadmin.h>
+#include "list.h"
+#include "lib.h"
+
+
+
+
+
+struct ng_header {
+ char unk1; // always 1
+ char code;
+ char error;
+ char unk2; // always 0
+ unsigned short attr; // attribute code which caused error
+ char unk3[2]; // always 0
+ char client_mac[6];
+ char switch_mac[6];
+ unsigned int seqnum;
+ char proto_id[4]; // always "NSDP"
+ char unk4[4]; // always 0
+ char data[0];
+} __attribute__((packed)) ;
+
+struct attr_header {
+ unsigned short attr;
+ unsigned short size;
+ char data[0];
+} __attribute__((packed)) ;
+
+
+struct ng_packet {
+ union {
+  char *buffer;
+  struct ng_header *nh;
+ };
+ int maxlen;
+ struct attr_header *ah;
+};
+
+
+struct attr {
+ unsigned short attr;
+ unsigned short size;
+ void *data;
+};
+
+
+
+extern const unsigned short helloRequest[];
+
+extern const struct ether_addr nullMac;
+
+
+
+// 
+int min (int a, int b);
+
+// 
+void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
+
+// 
+bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
+
+// 
+void initNgPacket (struct ng_packet *np);
+
+// 
+void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data);
+
+// 
+void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr);
+
+// 
+void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val);
+
+// 
+void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val);
+
+// 
+int getPacketTotalSize (const struct ng_packet *np);
+
+// 
+struct attr* newEmptyAttr (unsigned short attr);
+
+// 
+struct attr* newAttr (unsigned short attr, unsigned short size, void *data);
+
+// 
+struct attr* newByteAttr (unsigned short attr, unsigned char value);
+
+// 
+void freeAttr (struct attr *at);
+
+// 
+List* extractPacketAttributes (struct ng_packet *np, char *error, unsigned short *attr_error);
+
+// 
+void extractSwitchAttributes (struct swi_attr *sa, const List *l);
+
+
+
+
+#endif
+
diff --git a/list.c b/list.c
deleted file mode 100644 (file)
index 491889e..0000000
--- a/list.c
+++ /dev/null
@@ -1,332 +0,0 @@
-
-#include "list.h"
-
-
-
-
-// -------------------------
-List* createEmptyList (void) {
- List *l;
- l=malloc(sizeof(List));
- l->first=NULL;
- l->last=NULL;
- l->count=0;
- pthread_cond_init(&l->cond, NULL);
- pthread_mutex_init(&l->mutex, NULL);
- return l;
-}
-
-
-
-// ------------------------------------------------
-void destroyList (List *l, void (*freefunc)(void*)) {
- ListNode *pr, *ln;
- if ( l==NULL ) {
-  return;
- }
- pthread_mutex_destroy(&l->mutex);
- pthread_cond_destroy(&l->cond);
- for (ln=l->first; ln!=NULL; ) {
-  
-  pr=ln;
-  
-  if ( freefunc!=NULL ) {
-   freefunc(pr->data);
-  }
-  
-  ln=pr->next;
-  free(pr);
-  
- }
- free(l);
-}
-
-
-
-// -------------------------------------
-void pushFrontList (List *l, void* data) {
- ListNode *ln;
- if ( l==NULL ) {
-  return;
- }
- pthread_mutex_lock(&l->mutex);
- ln=malloc(sizeof(ListNode));
- ln->data=data;
- ln->prev=NULL;
- ln->next=l->first;
- if ( l->first==NULL ) {
-  l->last=ln;
- } else {
-  l->first->prev=ln;
- }
- l->first=ln;
- l->count++;
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
-}
-
-
-
-// ------------------------------------
-void pushBackList (List *l, void* data) {
- ListNode *ln;
- if ( l==NULL ) {
-  return;
- }
- pthread_mutex_lock(&l->mutex);
- ln=malloc(sizeof(ListNode));
- ln->data=data;
- ln->prev=l->last;
- ln->next=NULL;
- if ( l->last==NULL ) {
-  l->first=ln;
- } else {
-  l->last->next=ln;
- }
- l->last=ln;
- l->count++;
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
-}
-
-
-
-// -------------------------
-void* popFrontList (List *l) {
- ListNode *ln;
- void* data;
- if ( l==NULL ) {
-  return NULL;
- }
- pthread_mutex_lock(&l->mutex);
- if ( (ln=l->first)==NULL ) {
-  pthread_mutex_unlock(&l->mutex);
-  return NULL;
- }
- data=ln->data;
- l->first=ln->next;
- if ( ln->next==NULL ) {
-  l->last=NULL;
- } else {
-  ln->next->prev=NULL;
- }
- l->count--;
- free(ln);
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- return data;
-}
-
-
-
-// ------------------------
-void* popBackList (List *l) {
- ListNode *ln;
- void* data;
- if ( l==NULL ) {
-  return NULL;
- }
- pthread_mutex_lock(&l->mutex);
- if ( (ln=l->last)==NULL ) {
-  pthread_mutex_unlock(&l->mutex);
-  return NULL;
- }
- data=ln->data;
- l->last=ln->prev;
- if ( ln->prev==NULL ) {
-  l->first=NULL;
- } else {
-  ln->prev->next=NULL;
- }
- l->count--;
- free(ln);
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
- return data;
-}
-
-
-
-// ----------------------------------------------
-void clearList (List *l, void (*freefunc)(void*)) {
- ListNode *ln, *pr;
- if ( l==NULL ) {
-  return;
- }
- pthread_mutex_lock(&l->mutex);
- for (ln=l->first; ln!=NULL; ) {
-  
-  pr=ln;
-  
-  if ( freefunc!=NULL ) {
-   freefunc(pr->data);
-  }
-  
-  ln=pr->next;
-  free(pr);
-  
- }
- l->first=NULL;
- l->last=NULL;
- l->count=0;
- pthread_mutex_unlock(&l->mutex);
- pthread_cond_broadcast(&l->cond);
-}
-
-
-
-// ---------------------------------------------------------------
-bool findAndDestroy (List *l, void* data, void (*freefunc)(void*)) {
- ListNode *ln;
- if ( l==NULL ) {
-  return false;
- }
- pthread_mutex_lock(&l->mutex);
- for (ln=l->first; ln!=NULL && ln->data!=data; ln=ln->next);
- if ( ln==NULL ) {
-  
-  pthread_mutex_unlock(&l->mutex);
-  
- } else {
-  
-  if ( ln->prev==NULL ) {
-   l->first=ln->next;
-  } else {
-   ln->prev->next=ln->next;
-  }
-  
-  if ( ln->next==NULL ) {
-   l->last=ln->prev;
-  } else {
-   ln->next->prev=ln->prev;
-  }
-  
-  
-  if ( freefunc!=NULL ) {
-   freefunc(data);
-  }
-  
-  l->count--;
-  
-  pthread_mutex_unlock(&l->mutex);
-  pthread_cond_broadcast(&l->cond);
-  
- }
- return true;
-}
-
-
-
-// -------------------------------------------------
-void browseList (List *l, void (*browsefunc)(void*)) {
- ListNode *ln;
- if ( l==NULL || browsefunc==NULL ) {
-  return;
- }
- pthread_mutex_lock(&l->mutex);
- for (ln=l->first; ln!=NULL; ln=ln->next) {
-  browsefunc(ln->data);
- }
- pthread_mutex_unlock(&l->mutex);
-}
-
-
-
-
-
diff --git a/list.h b/list.h
deleted file mode 100644 (file)
index 1088584..0000000
--- a/list.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-#ifndef DEF_LIST
-#define DEF_LIST
-
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <pthread.h>
-
-
-
-
-typedef struct ListNode ListNode;
-
-struct ListNode {
- void* data;
- ListNode *prev, *next;
-};
-
-
-typedef struct {
- ListNode *first, *last;
- unsigned int count;
- pthread_cond_t cond;
- pthread_mutex_t mutex;
-} List;
-
-
-
-
-// Creates an empty list
-List* createEmptyList (void);
-
-// Destroys a list, and eventually frees the elements
-// NOT MT SAFE
-void destroyList (List *l, void (*freefunc)(void*));
-
-// Adds an element at front of the list
-void pushFrontList (List *l, void* data);
-
-// Adds an element at back of the list
-void pushBackList (List *l, void* data);
-
-// Pops an element from the front of the list and returns its value
-void* popFrontList (List *l);
-
-// Pops an element from the back of the list and returns its value
-void* popBackList (List *l);
-
-// Clears all the items of the list, and eventually frees them
-void clearList (List *l, void (*freefunc)(void*));
-
-// Find and destroy a particular element of the list, and eventually frees it
-bool findAndDestroy (List *l, void* data, void (*freefunc)(void*));
-
-// Browse all the items of the list through the callback function
-void browseList (List *l, void (*browsefunc)(void*));
-
-
-
-
-#endif
-
diff --git a/makefile b/makefile
deleted file mode 100644 (file)
index 54740e1..0000000
--- a/makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-
-CFLAGS=-W -Wall -Wextra -Os -fomit-frame-pointer -fno-strict-aliasing -pthread
-LDFLAGS=-s -pthread
-CC=gcc
-
-
-
-all: admin emu
-       
-
-
-admin: admin.o protocol.o list.o command.o network.o controller.o
-       $(CC) $^ -o $@ $(LDFLAGS)
-
-
-emu: emu.o protocol.o list.o command.o
-       $(CC) $^ -o $@ $(LDFLAGS)
-
-
-%.o: %.c %.h
-       $(CC) -c $< -o $@ $(CFLAGS)
-
-
-%.o: %.c
-       $(CC) -c $^ -o $@ $(CFLAGS)
-
-
-.PHONY: clean mrproper
-       
-
-
-clean: 
-       @rm -f *.o
-
-
-mrproper: clean
-       @rm -f admin emu
-
-
-
diff --git a/network.c b/network.c
deleted file mode 100644 (file)
index 431bfb1..0000000
--- a/network.c
+++ /dev/null
@@ -1,175 +0,0 @@
-
-#include "network.h"
-
-
-
-
-static struct timeval tv;
-static struct ether_addr localmac;
-
-static char buffer[1024];
-static int sock;
-static struct sockaddr_in local, remote;
-static socklen_t slen=sizeof(struct sockaddr_in);
-
-
-
-
-int startNetwork (const char *iface) {
- struct ifreq ifr;
- int ret;
- memset(&local, 0, sizeof(struct sockaddr_in));
- local.sin_family=AF_INET;
- remote=local;
- local.sin_port=htons(CLIENT_PORT);
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, iface, IFNAMSIZ-1);
- if ( (sock=socket(AF_INET, SOCK_DGRAM, 0))<0 ) {
-  perror("socket");
-  return sock;
- } else if ( (ret=ioctl(sock, SIOCGIFADDR, &ifr))<0 ) {
-  perror("ioctl(SIOCGIFADDR)");
-  close(sock);
-  return ret;
- }
- //local.sin_addr=(*(struct sockaddr_in*)&ifr.ifr_addr).sin_addr; // FIXME
- if ( (ret=ioctl(sock, SIOCGIFHWADDR, &ifr))<0 ) {
-  perror("ioctl(SIOCGIFHWADDR)");
-  close(sock);
-  return ret;
- }
- memcpy(&localmac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
- if ( (ret=bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_in)))<0 ) {
-  perror("bind");
-  close(sock);
-  return ret;
- }
- ret=1;
- if ( (ret=setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &ret, sizeof(ret)))<0 ) {
-  perror("setsockopt(SO_BROADCAST)");
-  return ret;
- }
- /*
- i=0;
- if ( setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &i, sizeof(i)) ) {
-  perror("setsockopt(IP_MULTICAST_LOOP)");
-  goto end;
- }
- */
- return setTimeout(1.);
-}
-
-
-int stopNetwork (void) {
- return close(sock);
-}
-
-
-
-
-int setTimeout (double sec) {
- int ret;
- tv.tv_sec=(int)sec;
- tv.tv_usec=(int)((sec-(double)tv.tv_sec)*1e6);
- if ( (ret=setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))<0 ) {
-  perror("setsockopt(SO_RCVTIMEO)");
-  return ret;
- }
- return 0;
-}
-
-
-int getTimeout (double *sec) {
- *sec=((double)tv.tv_sec)+1e-6*((double)tv.tv_usec);
- return 0;
-}
-
-
-
-
-int sendNgPacket (char code, const struct ether_addr *switch_mac, unsigned int seqnum, const List *attr) {
- struct ng_packet np;
- ListNode *ln;
- struct attr *at;
- int ret;
- np.buffer=buffer;
- np.maxlen=sizeof(buffer);
- initNgPacket(&np);
- initNgHeader(np.nh, code, &localmac, switch_mac, seqnum);
- if ( attr!=NULL ) {
-  for (ln=attr->first; ln!=NULL; ln=ln->next) {
-   at=ln->data;
-   addPacketAttr(&np, at->attr, at->size, at->data);
-  }
- }
- remote.sin_addr.s_addr=htonl(INADDR_BROADCAST);
- remote.sin_port=htons(SWITCH_PORT);
- if ( (ret=sendto(sock, buffer, getPacketTotalSize(&np), 0, (struct sockaddr*)&remote, sizeof(struct sockaddr_in)))<0 ) {
-  perror("sendto");
- }
- return ret;
-}
-
-
-List* recvNgPacket (char code, const struct ether_addr *switch_mac, unsigned int seqnum) {
- struct ng_packet np;
- List *l=NULL;
- int len;
- np.buffer=buffer;
- np.maxlen=sizeof(buffer);
- while ( (len=recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen))>=0 ) {
-  if ( len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &localmac, switch_mac, seqnum) ) {
-   initNgPacket(&np);
-   l=extractPacketAttributes(&np);
-   break;
-  }
- }
- return l;
-}
-
-
diff --git a/network.h b/network.h
deleted file mode 100644 (file)
index 9ba9f07..0000000
--- a/network.h
+++ /dev/null
@@ -1,37 +0,0 @@
-
-#ifndef DEF_NETWORK
-#define DEF_NETWORK
-
-
-#include <string.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netinet/ether.h>
-#include <sys/ioctl.h>
-
-#include "list.h"
-#include "protocol.h"
-
-
-
-int startNetwork (const char *iface);
-
-int stopNetwork (void);
-
-
-
-int setTimeout (double sec);
-
-int getTimeout (double *sec);
-
-
-
-int sendNgPacket (char code, const struct ether_addr *switch_mac, unsigned int seqnum, const List *attr);
-
-List* recvNgPacket (char code, const struct ether_addr *switch_mac, unsigned int seqnum);
-
-
-
-#endif
-
diff --git a/protocol.c b/protocol.c
deleted file mode 100644 (file)
index 3afe35d..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-
-#include "protocol.h"
-
-
-
-const unsigned short helloRequest[]={
- ATTR_PRODUCT, 
- ATTR_UNK2, 
- ATTR_NAME, 
- ATTR_MAC, 
- ATTR_UNK5, 
- ATTR_IP, 
- ATTR_NETMASK, 
- ATTR_GATEWAY, 
- ATTR_DHCP, 
- ATTR_UNK12, 
- ATTR_FIRM_VER, 
- ATTR_UNK14, 
- ATTR_UNK15, 
- ATTR_END
-};
-
-
-const struct ether_addr nullMac={.ether_addr_octet={0, 0, 0, 0, 0, 0}};
-
-
-
-// -------------------
-int min (int a, int b) {
- return a<b ? a : b ;
-}
-
-
-
-// -----------------------------------------------------------------------------------------------------------------------------------------------
-void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum) {
- memset(nh, 0, sizeof(struct ng_header));
- nh->unk1=1;
- nh->code=code;
- memcpy(nh->client_mac, client_mac, ETH_ALEN);
- if ( switch_mac!=NULL ) {
-  memcpy(nh->switch_mac, switch_mac, ETH_ALEN);
- }
- nh->seqnum=htonl(seqnum);
- strcpy(nh->proto_id, "NSDP");
-}
-
-
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------
-bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum) {
- int i;
- if ( nh->unk1!=1 ) {
-  //printf("unk1 not 1\n");
-  return false;
- }
- if ( code>0 && nh->code!=code ) {
-  return false;
- }
- for (i=0; i<6; i++) {
-  if ( nh->unk2[i]!=0 ) {
-   //printf("unk2[%i] not 0\n", i);
-   return false;
-  }
- }
- if ( client_mac!=NULL && memcmp(nh->client_mac, client_mac, ETH_ALEN)!=0 ) {
-  //printf("client_mac err\n");
-  return false;
- }
- if ( switch_mac!=NULL && memcmp(nh->switch_mac, switch_mac, ETH_ALEN)!=0 ) {
-  //printf("switch_mac err\n");
-  return false;
- }
- if ( seqnum>0 && ntohl(nh->seqnum)!=seqnum ) {
-  //printf("incorrect seqnum\n");
-  return false;
- }
- if ( *(unsigned int*)nh->unk3!=0 ) {
-  //printf("unk3 not 0\n");
-  return false;
- }
- return true;
-}
-
-
-
-// -------------------------------------
-void initNgPacket (struct ng_packet *np) {
- np->ah=(struct attr_header*)np->nh->data;
-}
-
-
-
-// --------------------------------------------------------------------------------------------
-void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data) {
- struct attr_header *ah=np->ah;
- if ( (int)(getPacketTotalSize(np)+sizeof(struct attr_header)+size)>(np->maxlen) ) {
-  return;
- }
- ah->attr=htons(attr);
- ah->size=htons(size);
- if ( size>0 && data!=NULL ) {
-  memcpy(ah->data, data, size);
- }
- np->ah=(struct attr_header*)(ah->data+size);
-}
-
-
-
-// ----------------------------------------------------------------
-void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr) {
- addPacketAttr(np, attr, 0, NULL);
-}
-
-
-
-// -------------------------------------------------------------------------
-void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val) {
- addPacketAttr(np, attr, 1, &val);
-}
-
-
-
-// ---------------------------------------------------------------------------
-void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val) {
- short s=htons(val);
- addPacketAttr(np, attr, 2, &s);
-}
-
-
-
-// ------------------------------------------------
-int getPacketTotalSize (const struct ng_packet *np) {
- return ((char*)np->ah)-np->buffer;
-}
-
-
-// --------------------------------------------
-struct attr* newEmptyAttr (unsigned short attr) {
- struct attr *at;
- at=malloc(sizeof(struct attr));
- at->attr=attr;
- at->size=0;
- at->data=NULL;
- return at;
-}
-
-
-// ----------------------------
-void freeAttr (struct attr *at) {
- if ( at!=NULL ) {
-  free(at->data);
-  free(at);
- }
-}
-
-
-
-// -------------------------------------------------
-List* extractPacketAttributes (struct ng_packet *np) {
- List *l;
- struct attr *at;
- l=createEmptyList();
- while ( getPacketTotalSize(np)<np->maxlen ) {
-  
-  at=malloc(sizeof(struct attr));
-  at->attr=ntohs(np->ah->attr);
-  at->size=ntohs(np->ah->size);
-  
-  if ( getPacketTotalSize(np)+at->size>np->maxlen ) {
-   free(at);
-   break;
-  }
-  
-  if ( at->size==0 ) {
-   at->data=NULL;
-  } else {
-   at->data=malloc(at->size*sizeof(char));
-   memcpy(at->data, np->ah->data, at->size);
-  }
-  
-  pushBackList(l, at);
-  
-  if ( at->attr==ATTR_END ) {
-   break;
-  }
-  
-  np->ah=(struct attr_header*)(np->ah->data+at->size);
-  
- }
- return l;
-}
-
-
diff --git a/protocol.h b/protocol.h
deleted file mode 100644 (file)
index 2ffeec3..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-
-#ifndef DEF_PROTOCOL
-#define DEF_PROTOCOL
-
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <arpa/inet.h>
-#include <netinet/ether.h>
-
-#include "list.h"
-#include "command.h"
-
-
-
-
-#define CLIENT_PORT            63321
-#define SWITCH_PORT            63322
-
-#define CODE_READ_REQ          1
-#define CODE_READ_REP          2
-#define CODE_WRITE_REQ         3
-#define CODE_WRITE_REP         4
-
-#define ATTR_PRODUCT           0x0001
-#define ATTR_UNK2              0x0002
-#define ATTR_NAME              0x0003
-#define ATTR_MAC               0x0004
-#define ATTR_UNK5              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_FIRM_VER          0x000D
-#define ATTR_UNK14             0x000E
-#define ATTR_UNK15             0x000F
-#define ATTR_RESTART           0x0013
-#define ATTR_DEFAULTS          0x0400
-#define ATTR_PORT_STATUS       0x0C00
-#define ATTR_VLAN_TYPE         0x2000
-#define ATTR_VLAN_CONFIG       0x2400
-#define ATTR_QOS_TYPE          0x3400
-#define ATTR_QOS_CONFIG                0x3800
-#define ATTR_MIRROR            0x5C00
-#define ATTR_PORTS_NUMBER      0x6000
-#define ATTR_END               0xFFFF
-
-#define SPEED_DOWN             0
-#define SPEED_10               1
-#define SPEED_100              4
-#define SPEED_1000             5
-
-#define VLAN_PORT_BASIC                1
-#define VLAN_PORT_ADV          2
-#define VLAN_DOT_BASIC         3
-#define VLAN_DOT_ADV           4
-
-#define QOS_PORT               1
-#define QOS_DOT                        2
-
-#define PRIO_HIGH              1
-#define PRIO_MED               2
-#define PRIO_NORM              3
-#define PRIO_LOW               4
-
-
-
-struct ng_header {
- char unk1; // always 1
- char code;
- char unk2[6]; // always 0
- char client_mac[6];
- char switch_mac[6];
- unsigned int seqnum;
- char proto_id[4]; // always "NSDP"
- char unk3[4]; // always 0
- char data[0];
-} __attribute__((packed)) ;
-
-struct attr_header {
- unsigned short attr;
- unsigned short size;
- char data[0];
-} __attribute__((packed)) ;
-
-
-struct ng_packet {
- union {
-  char *buffer;
-  struct ng_header *nh;
- };
- int maxlen;
- struct attr_header *ah;
-};
-
-
-struct attr {
- unsigned short attr;
- unsigned short size;
- void *data;
-};
-
-
-
-extern const unsigned short helloRequest[];
-
-extern const struct ether_addr nullMac;
-
-
-
-// 
-int min (int a, int b);
-
-// 
-void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
-
-// 
-bool validateNgHeader (const struct ng_header *nh, char code, const struct ether_addr *client_mac, const struct ether_addr *switch_mac, unsigned int seqnum);
-
-// 
-void initNgPacket (struct ng_packet *np);
-
-// 
-void addPacketAttr (struct ng_packet *np, unsigned short attr, unsigned short size, void* data);
-
-// 
-void addPacketEmptyAttr (struct ng_packet *np, unsigned short attr);
-
-// 
-void addPacketByteAttr (struct ng_packet *np, unsigned short attr, char val);
-
-// 
-void addPacketShortAttr (struct ng_packet *np, unsigned short attr, short val);
-
-// 
-int getPacketTotalSize (const struct ng_packet *np);
-
-// 
-struct attr* newEmptyAttr (unsigned short attr);
-
-// 
-void freeAttr (struct attr *at);
-
-// 
-List* extractPacketAttributes (struct ng_packet *np);
-
-
-
-
-
-#endif
-