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