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.
#include <stdio.h>
+#include <getopt.h>
#include <readline/readline.h>
#include <readline/history.h>
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 ) {
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;
- if ( argc<2 ) {
- printf("Usage: %s <interface>\n", argv[0]);
- return 1;
+ opterr=0;
+
+ while ( (n=getopt_long(argc, argv, "bfi:h", opts, NULL))!=-1 ) {
+ switch ( n ) {
+
+ case 'b':
+ kb=true;
+ break;
+
+ case 'f':
+ force=true;
+ break;
+
+ case 'i':
+ iface=optarg;
+ break;
+
+ case 'h':
+ printf("Usage: %s [-b] [-f] [-i <interface>]\n", argv[0]);
+ goto end;
+
+ case '?':
+ printf("Unknown option: \"%s\"\n", argv[optind-1]);
+ goto end;
+
+ }
}
+ argc-=optind;
+ argv+=optind;
+
+
+ if ( argc!=0 ) {
+ printf("Unknown trailing options\n");
+ goto end;
+ }
+
+
memset(com, 0, MAXCOM*sizeof(char*));
- if ( (nga=ngadmin_init(argv[1]))==NULL ) {
+ if ( (nga=ngadmin_init(iface))==NULL ) {
fprintf(stderr, "Initialization error\n");
goto end;
}
ngadmin_setTimeout(nga, &tv);
+ if ( kb && ngadmin_setKeepBroadcasting(nga, true)!=ERR_OK ) goto end;
+
+ if ( force && ngadmin_forceInterface(nga)!=ERR_OK ) goto end;
+
+
//rl_bind_key('\t', rl_abort); // disable auto completion
+ //rl_bind_key('\t', rl_complete); // enable auto-complete
rl_attempted_completion_function=my_completion;
+ rl_completion_entry_function=my_generator;
while ( cont ) {
- //rl_bind_key('\t', rl_complete); // enable auto-complete
-
if ( (line=readline("> "))==NULL ) goto end;
- trim(line, strlen(line));
if ( *line!=0 ) add_history(line);
+ trim(line, strlen(line));
n=explode(line, com, MAXCOM);
free(line);
- if ( n==0 ) {
- continue;
- }
+ if ( n==0 ) continue;
cur=getSubCom(com, n, &i);
if ( i<n ) { // commands left unchecked
- if ( cur->hasArgs ) { // left "commands" are in fact parameters
- cur->comfunc(n-i, (const char**)&com[i], nga);
- } else if ( i==0 ) { // root command
+ if ( i==0 ) { // root command
printf("unknown command\n");
- } else if ( cur->sub==NULL ) { // terminal command without arguments
- printf("%s as no subcommand and takes no parameter\n", com[i-1]);
- } else { // intermediate command
+ } else if ( cur->sub!=NULL ) { // intermediate command
printf("unknown %s subcommand\n", com[i-1]);
+ } else if ( !cur->hasArgs ) { // terminal command without arguments
+ printf("%s as no subcommand and takes no parameter\n", com[i-1]);
+ } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+ printf("terminal command without function\n");
+ } else { // terminal command with arguments, left "commands" are in fact parameters
+ cur->comfunc(n-i, (const char**)&com[i], nga);
}
- } else {
+ } else { // no command left
- if ( cur->comfunc==NULL ) { // intermediate command
+ if ( cur->sub!=NULL ) { // intermediate command
// print available subcommands
- for (next=cur->sub; next!=NULL && next->name!=NULL; ++next) {
+ for (next=cur->sub; next->name!=NULL; ++next) {
printf("%s ", next->name);
}
printf("\n");
-
- } else { // terminal command
+ } else if ( cur->comfunc==NULL ) { // erroneous terminal command without function
+ printf("terminal command without function\n");
+ } else { // terminal command without arguments
cur->comfunc(0, NULL, nga);
}
+// =============================================================================
+// bitrate
+
+
+// helper function to analyse bitrate speed specifications
+static int bitrate_analyse (int nb, const char **com, int *ports) {
+
+ int i=0, s;
+
+
+ while ( i<nb-1 ) {
+ s=parseBitrate(com[i+1]);
+ if ( strcmp(com[i], "inout")==0 ) {
+ ports[0]=s;
+ ports[1]=s;
+ } else if ( strcmp(com[i], "in")==0 ) {
+ ports[0]=s;
+ } else if ( strcmp(com[i], "out")==0 ) {
+ ports[1]=s;
+ } else {
+ break;
+ }
+ i+=2;
+ }
+
+
+ return i;
+
+}
+
+
+static bool do_bitrate_set (int nb, const char **com, struct ngadmin *nga) {
+
+ int i, k=0, defs[]={12, 12}, p, *ports=NULL;
+ const struct swi_attr *sa;
+ bool ret=true;
+
+
+ if ( nb<2 ) {
+ printf("Usage: bitrate set [all SPEEDSPEC] <port1> SPEEDSPEC [<port2> SPEEDSPEC ...]\n");
+ printf("SPEEDSPEC: [inout <speed>] [in <ispeed>] [out <ospeed>]\n");
+ ret=false;
+ goto end;
+ }
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+ ports=malloc(2*sa->ports*sizeof(int));
+
+ // get defaults if present
+ if ( strcmp(com[k], "all")==0 ) {
+ ++k;
+ k+=bitrate_analyse(nb-k, &com[k], defs);
+ }
+
+ // apply defaults
+ for (i=0; i<sa->ports; ++i) {
+ memcpy(&ports[2*i], defs, sizeof(defs));
+ }
+
+ // get ports specifics
+ while ( k<nb ) {
+ p=strtol(com[k++], NULL, 0)-1;
+ if ( p>=0 && p<sa->ports ) {
+ k+=bitrate_analyse(nb-k, &com[k], &ports[2*p]);
+ }
+ }
+
+ // send it to the switch
+ i=ngadmin_setBitrateLimits(nga, ports);
+ printErrCode(i);
+
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
+static bool do_bitrate_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+
+ int i, ret=true, *ports=NULL;
+ const struct swi_attr *sa;
+
+
+ if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
+ printf("must be logged\n");
+ ret=false;
+ goto end;
+ }
+
+
+ ports=malloc(2*sa->ports*sizeof(int));
+ if ( (i=ngadmin_getBitrateLimits(nga, ports))!=ERR_OK ) {
+ printErrCode(i);
+ ret=false;
+ goto end;
+ }
+
+ for (i=0; i<sa->ports; ++i) {
+ printf("port %i: in %s, out %s\n", i+1, bitrates[ports[2*i+0]], bitrates[ports[2*i+1]]);
+ }
+
+ end:
+ free(ports);
+
+ return ret;
+
+}
+
+
+
// =============================================================================
// firmware
-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;
-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;
ret=false;
goto end;
}
-
+
ps=calloc(sa->ports, sizeof(struct port_stats));
if ( (i=ngadmin_getPortsStatistics(nga, ps))<0 ) {
printErrCode(i);
goto end;
}
- printf("Port\tReceived\tSent\t\tCRC errors\n");
+ printf("Port\tReceived\tSent\tCRC errors\n");
for (i=0; i<sa->ports; ++i) {
- printf("%i\t%8llu\t%8llu\t%8llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
+ printf("% 4i%12llu%12llu%14llu\n", i+1, ps[i].recv, ps[i].sent, ps[i].crc);
}
end:
// =============================================================================
-// 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;
-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;
-static bool do_stormfilt_reset (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_set (int nb, const char **com, struct ngadmin *nga) {
- int i, *ports=NULL;
+ int i, d=BITRATE_UNSPEC, p, *ports=NULL;
const struct swi_attr *sa;
bool ret=true;
- if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
- printf("must be logged\n");
+ if ( nb<2 ) {
+ printf("Usage: stormfilt set (all <speed0>)|(<port1> <speed1> [<port2> <speed2> ...])\n");
ret=false;
goto end;
}
-
- ports=malloc(sa->ports*sizeof(int));
- for (i=0; i<sa->ports; ++i) {
- ports[i]=BITRATE_NOLIMIT;
- }
-
- i=ngadmin_setStormFilterValues(nga, ports);
- printErrCode(i);
-
-
- end:
- free(ports);
-
- return ret;
-
-}
-
-
-
-static bool do_stormfilt_set (int nb, const char **com, struct ngadmin *nga) {
-
- int i, p, *ports=NULL;
- const struct swi_attr *sa;
- bool ret=true;
-
-
- if ( nb==0 ) {
- printf("Usage: stormfilt set <port1> <speed1> [<port2> <speed2> ...]\n");
- ret=false;
- goto end;
- }
-
-
if ( (sa=ngadmin_getCurrentSwitch(nga))==NULL ) {
printf("must be logged\n");
ret=false;
ports=malloc(sa->ports*sizeof(int));
+
+ if ( strcmp(com[0], "all")==0 ) {
+ d=parseBitrate(com[1]);
+ com+=2;
+ nb-=2;
+ }
+
for (i=0; i<sa->ports; ++i) {
- ports[i]=BITRATE_UNSPEC;
+ ports[i]=d;
}
for (i=0; i<nb; i+=2) {
-static bool do_stormfilt_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
+static bool do_stormfilter_show (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga) {
int i, s, ret=true, *ports=NULL;
const struct swi_attr *sa;
}
for (i=0; i<sa->ports; ++i) {
- printf("port %i: ", i+1);
- printBitrate(ports[i]);
+ printf("port %i: %s\n", i+1, bitrates[ports[i]]);
}
end:
+// =============================================================================
+// tree
+
+
+static void display_node (const struct TreeNode *tn, int depth) {
+
+ int i;
+ const struct TreeNode *s;
+
+
+ for (i=0; i<depth; ++i) {
+ putchar('\t');
+ }
+
+ puts(tn->name);
+
+ if ( tn->sub==NULL ) return;
+
+ for (s=tn->sub; s->name!=NULL; ++s) {
+ display_node(s, depth+1);
+ }
+
+
+}
+
+
+static bool do_tree (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+
+
+ display_node(&coms, 0);
+
+
+ return true;
+
+}
+
+
+
// =============================================================================
COM_ROOT_START(coms)
+ COM_START(bitrate)
+ COM_TERM(set, do_bitrate_set, true)
+ COM_TERM(show, do_bitrate_show, false)
+ COM_END
+
+ COM_TERM(cabletest, NULL, true)
+
+ COM_TERM(defaults, NULL, false)
+
COM_START(firmware)
COM_TERM(show, do_firmware_show, false)
COM_TERM(upgrade, do_firmware_upgrade, true)
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)
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
-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;
}
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);
//
#define QOS_PORT 1
#define QOS_DOT 2
+#define PRIO_UNSPEC -1
#define PRIO_HIGH 1
#define PRIO_MED 2
#define PRIO_NORM 3
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;
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
#define CODE_WRITE_REP 4
#define ATTR_PRODUCT 0x0001
-#define ATTR_UNK2 0x0002
+#define ATTR_UNK_0002 0x0002
#define ATTR_NAME 0x0003
#define ATTR_MAC 0x0004
-#define ATTR_UNK5 0x0005
+#define ATTR_UNK_0005 0x0005
#define ATTR_IP 0x0006
#define ATTR_NETMASK 0x0007
#define ATTR_GATEWAY 0x0008
#define ATTR_NEW_PASSWORD 0x0009
#define ATTR_PASSWORD 0x000A
#define ATTR_DHCP 0x000B
-#define ATTR_UNK12 0x000C
+#define ATTR_UNK_000C 0x000C
#define ATTR_FIRM_VER 0x000D
-#define ATTR_UNK14 0x000E
-#define ATTR_UNK15 0x000F
+#define ATTR_UNK_000E 0x000E
+#define ATTR_UNK_000F 0x000F
#define ATTR_RESTART 0x0013
#define ATTR_DEFAULTS 0x0400
#define ATTR_PORT_STATUS 0x0C00
#define ATTR_PORT_STATISTICS 0x1000
#define ATTR_STATS_RESET 0x1400
#define ATTR_VLAN_TYPE 0x2000
-#define ATTR_VLAN_CONFIG 0x2400
+#define ATTR_VLAN_PORT_CONF 0x2400
+#define ATTR_VLAN_DOT_CONF 0x2800
#define ATTR_QOS_TYPE 0x3400
#define ATTR_QOS_CONFIG 0x3800
#define ATTR_BITRATE_INPUT 0x4C00
#define ATTR_STORM_BITRATE 0x5800
#define ATTR_MIRROR 0x5C00
#define ATTR_PORTS_COUNT 0x6000
+#define ATTR_UNK_6800 0x6800
+#define ATTR_UNK_6C00 0x6C00
+#define ATTR_UNK_7000 0x7000
+#define ATTR_UNK_7400 0x7400
#define ATTR_END 0xFFFF
// 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
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));
+// -------------------------------------
+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) {
-// --------------------------------------------------------------------------------------------------------------------------
-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;
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) {
}
}
+ 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");
}
-// ---------------------------------------------------------------------------------------------------------------------------------------------------
-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;
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;
//
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);
+// ---------------------------------------------
+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) {
}
// 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;
// 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);
}
- 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
}
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;
}
+// -----------------------------------------------------------
+int ngadmin_getBitrateLimits (struct ngadmin *nga, int *ports) {
+
+ List *attr;
+ ListNode *ln;
+ struct attr *at;
+ int ret=ERR_OK, i;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_INPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_BITRATE_OUTPUT));
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_READ_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_READ_REP, NULL, NULL))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ for (ln=attr->first; ln!=NULL; ln=ln->next) {
+ at=ln->data;
+ if ( at->attr==ATTR_BITRATE_INPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ ports[i*2+0]=ntohl(*(int*)(1+(char*)at->data));
+ } else if ( at->attr==ATTR_BITRATE_OUTPUT && at->size>=5 && (i=*(char*)(at->data)-1)>=0 && i<nga->current->ports ) {
+ ports[i*2+1]=ntohl(*(int*)(1+(char*)at->data));
+ }
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+
+ end:
+
+ return ret;
+
+}
+
+
+
+// -----------------------------------------------------------------
+int ngadmin_setBitrateLimits (struct ngadmin *nga, const int *ports) {
+
+ List *attr;
+ int ret=ERR_OK, i;
+ char err;
+ unsigned short attr_error;
+ char *p;
+
+
+ if ( nga==NULL || ports==NULL ) {
+ return ERR_INVARG;
+ } else if ( nga->current==NULL ) {
+ return ERR_NOTLOG;
+ }
+
+
+ attr=createEmptyList();
+ pushBackList(attr, newAttr(ATTR_PASSWORD, strlen(nga->password), strdup(nga->password)));
+
+ for (i=0; i<nga->current->ports; ++i) {
+ if ( ports[2*i+0]>=0 && ports[2*i+0]<=11 ) {
+ p=malloc(5);
+ *p=i+1;
+ *(int*)(p+1)=htonl(ports[2*i+0]);
+ pushBackList(attr, newAttr(ATTR_BITRATE_INPUT, 5, p));
+ }
+ if ( ports[2*i+1]>=0 && ports[2*i+1]<=11 ) {
+ p=malloc(5);
+ *p=i+1;
+ *(int*)(p+1)=htonl(ports[2*i+1]);
+ pushBackList(attr, newAttr(ATTR_BITRATE_OUTPUT, 5, p));
+ }
+ }
+
+ pushBackList(attr, newEmptyAttr(ATTR_END));
+ i=sendNgPacket(nga, CODE_WRITE_REQ, attr);
+ destroyList(attr, (void(*)(void*))freeAttr);
+ if ( i<0 || (attr=recvNgPacket(nga, CODE_WRITE_REP, &err, &attr_error))==NULL ) {
+ ret=ERR_NET;
+ goto end;
+ }
+
+ destroyList(attr, (void(*)(void*))freeAttr);
+
+ if ( err==7 && attr_error==ATTR_PASSWORD ) {
+ ret=ERR_BADPASS;
+ goto end;
+ }
+
+
+ end:
+
+ return ret;
+
+}
+
+