From 192ea617675b35fe37460a0fbb0c1511c0074fe8 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Tue, 15 Nov 2011 12:00:00 +0100 Subject: [PATCH] Code reorganized. Separated low level protocol handling in a library and CLI. Removed switch emulator. CLI: command input using libreadline. --- .gitignore | 1 + admin.c | 404 ------------------------- cli/Makefile | 26 ++ cli/admin.c | 186 ++++++++++++ cli/com_firmware.c | 64 ++++ cli/com_list.c | 26 ++ cli/com_login.c | 32 ++ cli/com_name.c | 80 +++++ cli/com_password.c | 60 ++++ cli/com_ports.c | 116 +++++++ cli/com_quit.c | 20 ++ cli/com_scan.c | 31 ++ command.c => cli/command.c | 0 command.h => cli/command.h | 0 cli/common.h | 48 +++ commandes | 52 ---- controller.c | 246 --------------- controller.h | 112 ------- emu.c | 299 ------------------ lib/ngadmin.h | 151 ++++++++++ lib/src/Makefile | 25 ++ lib/src/lib.h | 77 +++++ list.c => lib/src/list.c | 34 +++ list.h => lib/src/list.h | 4 + lib/src/network.c | 154 ++++++++++ lib/src/network.h | 37 +++ lib/src/ngadmin.c | 501 +++++++++++++++++++++++++++++++ protocol.c => lib/src/protocol.c | 148 ++++++--- protocol.h => lib/src/protocol.h | 77 ++--- makefile | 40 --- network.c | 175 ----------- network.h | 37 --- 32 files changed, 1805 insertions(+), 1458 deletions(-) delete mode 100644 admin.c create mode 100644 cli/Makefile create mode 100644 cli/admin.c create mode 100644 cli/com_firmware.c create mode 100644 cli/com_list.c create mode 100644 cli/com_login.c create mode 100644 cli/com_name.c create mode 100644 cli/com_password.c create mode 100644 cli/com_ports.c create mode 100644 cli/com_quit.c create mode 100644 cli/com_scan.c rename command.c => cli/command.c (100%) rename command.h => cli/command.h (100%) create mode 100644 cli/common.h delete mode 100644 commandes delete mode 100644 controller.c delete mode 100644 controller.h delete mode 100644 emu.c create mode 100644 lib/ngadmin.h create mode 100644 lib/src/Makefile create mode 100644 lib/src/lib.h rename list.c => lib/src/list.c (90%) rename list.h => lib/src/list.h (94%) create mode 100644 lib/src/network.c create mode 100644 lib/src/network.h create mode 100644 lib/src/ngadmin.c rename protocol.c => lib/src/protocol.c (62%) rename protocol.h => lib/src/protocol.h (55%) delete mode 100644 makefile delete mode 100644 network.c delete mode 100644 network.h diff --git a/.gitignore b/.gitignore index 2c02531..5240222 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o *~ +*.so admin emu diff --git a/admin.c b/admin.c deleted file mode 100644 index 01e7765..0000000 --- a/admin.c +++ /dev/null @@ -1,404 +0,0 @@ - -#include -#include -#include -#include -#include - - - -#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 \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, ¤t->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, ¤t->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, ¤t->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, ¤t->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, ¤t->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 + +#include +#include + +#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\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; isub; (next=*tab)!=NULL && strcmp(next->name, com[i])!=0; ++tab); + if ( next==NULL ) break; + } + + + if ( ihasArgs ) { // 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; ifirmware); + + + 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 \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 index 0000000..3c8eb8c --- /dev/null +++ b/cli/com_list.c @@ -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 index 0000000..e50e096 --- /dev/null +++ b/cli/com_login.c @@ -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 \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 index 0000000..54b152e --- /dev/null +++ b/cli/com_name.c @@ -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 \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 index 0000000..4b1f184 --- /dev/null +++ b/cli/com_password.c @@ -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 \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 \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 index 0000000..b520218 --- /dev/null +++ b/cli/com_ports.c @@ -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; iports; 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; iports; ++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 index 0000000..61dc5ce --- /dev/null +++ b/cli/com_quit.c @@ -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 index 0000000..51b24b8 --- /dev/null +++ b/cli/com_scan.c @@ -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/command.c b/cli/command.c similarity index 100% rename from command.c rename to cli/command.c diff --git a/command.h b/cli/command.h similarity index 100% rename from command.h rename to cli/command.h diff --git a/cli/common.h b/cli/common.h new file mode 100644 index 0000000..ee845af --- /dev/null +++ b/cli/common.h @@ -0,0 +1,48 @@ + +#ifndef DEF_COMMON +#define DEF_COMMON + + +#include +#include + +#include + + +#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/commandes b/commandes deleted file mode 100644 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 index 14b596f..0000000 --- a/controller.c +++ /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 -#include -#include - -#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 index d968ded..0000000 --- a/emu.c +++ /dev/null @@ -1,299 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 \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; idata[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 index 0000000..824b0dd --- /dev/null +++ b/lib/ngadmin.h @@ -0,0 +1,151 @@ + +#ifndef DEF_NGADMIN +#define DEF_NGADMIN + + +#include +#include +#include + + +#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 index 0000000..9013cd8 --- /dev/null +++ b/lib/src/Makefile @@ -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 index 0000000..f89d02f --- /dev/null +++ b/lib/src/lib.h @@ -0,0 +1,77 @@ + +#ifndef DEF_LIB +#define DEF_LIB + + +#include +#include +#include + +#include + + +#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/list.c b/lib/src/list.c similarity index 90% rename from list.c rename to lib/src/list.c index 491889e..bc48e1e 100644 --- a/list.c +++ b/lib/src/list.c @@ -327,6 +327,40 @@ void browseList (List *l, void (*browsefunc)(void*)) { } +// -------------------------------------- +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/list.h b/lib/src/list.h similarity index 94% rename from list.h rename to lib/src/list.h index 1088584..39a1751 100644 --- a/list.h +++ b/lib/src/list.h @@ -5,6 +5,7 @@ #include #include +#include #include @@ -56,6 +57,9 @@ 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); + diff --git a/lib/src/network.c b/lib/src/network.c new file mode 100644 index 0000000..e8fa713 --- /dev/null +++ b/lib/src/network.c @@ -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 index 0000000..0b895b8 --- /dev/null +++ b/lib/src/network.h @@ -0,0 +1,37 @@ + +#ifndef DEF_NETWORK +#define DEF_NETWORK + + +#include +#include +#include +#include +#include +#include + +#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 index 0000000..bdcc9b5 --- /dev/null +++ b/lib/src/ngadmin.c @@ -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 && icurrent->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 && portcurrent->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/protocol.c b/lib/src/protocol.c similarity index 62% rename from protocol.c rename to lib/src/protocol.c index 3afe35d..51e0611 100644 --- a/protocol.c +++ b/lib/src/protocol.c @@ -3,22 +3,6 @@ -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}}; @@ -54,14 +38,11 @@ void initNgHeader (struct ng_header *nh, char code, const struct ether_addr *cli -// ---------------------------------------------------------------------------------------------------------------------------------------------- +// --------------------------------------------------------------------------------------------------------------------------------------------------------- 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; } @@ -69,30 +50,27 @@ bool validateNgHeader (const struct ng_header *nh, char code, const struct ether return false; } - for (i=0; i<6; i++) { - if ( nh->unk2[i]!=0 ) { - //printf("unk2[%i] not 0\n", i); - 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 ) { - //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"); + if ( *(unsigned int*)nh->unk4!=0 ) { return false; } @@ -167,16 +145,24 @@ int getPacketTotalSize (const struct ng_packet *np) { } + // -------------------------------------------- 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=0; - at->data=NULL; + at->size=size; + at->data=data; return at; @@ -184,6 +170,20 @@ struct attr* newEmptyAttr (unsigned short attr) { } + +// ---------------------------------------------------------------- +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) { @@ -196,13 +196,21 @@ void freeAttr (struct attr *at) { -// ------------------------------------------------- -List* extractPacketAttributes (struct ng_packet *np) { +// ------------------------------------------------------------------------------------------ +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)maxlen ) { @@ -239,3 +247,75 @@ List* extractPacketAttributes (struct ng_packet *np) { } + +// -------------------------------------------------------------- +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/protocol.h b/lib/src/protocol.h similarity index 55% rename from protocol.h rename to lib/src/protocol.h index 2ffeec3..abc7707 100644 --- a/protocol.h +++ b/lib/src/protocol.h @@ -9,75 +9,26 @@ #include #include +#include #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 +#include "lib.h" + + struct ng_header { char unk1; // always 1 char code; - char unk2[6]; // always 0 + 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 unk3[4]; // always 0 + char unk4[4]; // always 0 char data[0]; } __attribute__((packed)) ; @@ -142,12 +93,20 @@ 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); +List* extractPacketAttributes (struct ng_packet *np, char *error, unsigned short *attr_error); +// +void extractSwitchAttributes (struct swi_attr *sa, const List *l); diff --git a/makefile b/makefile deleted file mode 100644 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 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 index 9ba9f07..0000000 --- a/network.h +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef DEF_NETWORK -#define DEF_NETWORK - - -#include -#include -#include -#include -#include -#include - -#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 - -- 2.39.5