CLI: added the possiblity to enter password without displaying it.
CLI: added help command.
Lib: added check on packet extraction.
#include <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
#include <getopt.h>
#include <readline/readline.h>
+static struct ngadmin *nga=NULL;
+static sigjmp_buf jmpbuf;
+struct termios orig_term, current_term;
+
+
+
+NORET static void handler (int sig) {
+
+
+ switch ( sig ) {
+
+ case SIGTERM:
+ case SIGINT:
+ printf("interrupt\n");
+
+ current_term.c_lflag|=ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
+
+ siglongjmp(jmpbuf, 1);
+
+ default:
+ ngadmin_close(nga);
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
+
+ exit(0);
+
+ }
+
+
+}
+
+
int main (int argc, char **argv) {
const char *iface="eth0";
float timeout=0.f;
bool kb=false, force=false, global=false;
- struct ngadmin *nga=NULL;
struct timeval tv;
const struct TreeNode *cur, *next;
int i, n;
if ( global && ngadmin_useGlobalBroadcast(nga, true)!=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;
+ tcgetattr(STDIN_FILENO, &orig_term);
+ current_term=orig_term;
+ /*
+ current_term.c_lflag&=~ECHOCTL;
+ tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
+ */
+
+
+ signal(SIGTERM, handler);
+ signal(SIGINT, handler);
+
+ sigsetjmp(jmpbuf, 1);
+
+
while ( cont ) {
if ( (line=readline("> "))==NULL ) goto end;
end:
- ngadmin_close(nga);
-
-
- return 0;
+ handler(0);
}
--- /dev/null
+
+#include "commands.h"
+
+
+
+
+bool do_help (int nb UNUSED, const char **com UNUSED, struct ngadmin *nga UNUSED) {
+
+ const struct TreeNode *s;
+
+
+ printf("Available commands: \n");
+
+ for (s=coms.sub; s->name!=NULL; ++s) {
+ printf("%s ", s->name);
+ }
+ putchar('\n');
+
+
+ return true;
+
+}
+
+
+
+
bool do_password_set (int nb, const char **com, struct ngadmin *nga) {
int i;
+ char buf[64];
+ const char *pass;
- if ( nb!=1 ) {
- printf("Usage: password set <value>\n");
+ if ( nb>1 ) {
+ printf("Usage: password set [<value>]\n");
return false;
}
- i=ngadmin_setPassword(nga, com[0]);
- printErrCode(i);
+
+ if ( nb==0 ) {
+ printf("Enter password: ");
+ fflush(stdout);
+ current_term.c_lflag&=~ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
+ pass=fgets(buf, sizeof(buf), stdin);
+ trim(buf, strlen(buf));
+ current_term.c_lflag|=ECHO;
+ tcsetattr(STDIN_FILENO, TCSANOW, ¤t_term);
+ putchar('\n');
+ } else {
+ pass=com[0];
+ }
+
+
+ if ( pass!=NULL ) {
+ i=ngadmin_setPassword(nga, pass);
+ printErrCode(i);
+ }
+
return true;
bool do_firmware_upgrade (int nb, const char **com, struct ngadmin *nga);
+// help
+bool do_help (int nb, const char **com, struct ngadmin *nga);
+
+
// igmp
bool do_igmp_set (int nb, const char **com, struct ngadmin *nga);
bool do_igmp_show (int nb, const char **com, struct ngadmin *nga);
COM_TERM(upgrade, do_firmware_upgrade, true)
COM_END
+ COM_TERM(help, do_help, false)
+
COM_START(igmp)
COM_TERM(set, do_igmp_set, true)
COM_TERM(show, do_igmp_show, false)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <termios.h>
+#include <unistd.h>
#include <ngadmin.h>
-#define UNUSED __attribute__((unused))
+#define UNUSED __attribute__((unused))
+#define NORET __attribute__((noreturn))
extern int cont;
+extern struct termios current_term;
extern const char *bitrates[], *prio[];
}
+/*
+static int my_poll (struct pollfd *fds, nfds_t nfds, struct timeval *timeout) {
+
+ int ret, rem=-1;
+ struct timeval start, stop;
+
+
+ if ( timeout!=NULL ) {
+ if ( timeout->tv_sec<0 || timeout->tv_usec<0 ) rem=0;
+ else rem=timeout->tv_sec*1000+timeout->tv_usec/1000;
+ }
+
+ gettimeofday(&start, NULL);
+ ret=poll(fds, nfds, rem);
+ gettimeofday(&stop, NULL);
+
+ if ( timeout!=NULL ) {
+ rem-=(stop.tv_sec-start.tv_sec)*1000+(stop.tv_usec-start.tv_usec)/1000;
+ if ( ret<=0 || rem<0 ) rem=0;
+ printf("tv_sec = %i, tv_usec = %i\n", start.tv_sec, start.tv_usec);
+ printf("tv_sec = %i, tv_usec = %i\n", stop.tv_sec, stop.tv_usec);
+ printf("rem = %i\n", rem);
+ timeout->tv_sec=rem/1000;
+ timeout->tv_usec=(rem%1000)*1000;
+ }
+
+
+ return ret;
+
+}
+*/
+
// ------------------------------------------------------------------------------------------------------------
int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned short *attr_error, List *attr) {
struct sockaddr_in remote;
socklen_t slen=sizeof(struct sockaddr_in);
const struct swi_attr *sa=nga->current;
- int len;
+ struct timeval rem;
+ //struct pollfd fds;
+ fd_set fs;
+ int len=-1;
np.buffer=buffer;
- np.maxlen=sizeof(buffer);
memset(&remote, 0, sizeof(struct sockaddr_in));
remote.sin_family=AF_INET;
+ rem=nga->timeout;
+
+ //fds.fd=nga->sock;
+ //fds.events=POLLIN;
+
while ( 1 ) {
- len=recvfrom(nga->sock, buffer, sizeof(buffer), 0, (struct sockaddr*)&remote, &slen);
+ //my_poll(&fds, 1, &rem);
+ FD_ZERO(&fs);
+ FD_SET(nga->sock, &fs);
+ select(nga->sock+1, &fs, NULL, NULL, &rem);
- if ( len<0 ) {
- break;
- }
+ len=recvfrom(nga->sock, buffer, sizeof(buffer), MSG_DONTWAIT, (struct sockaddr*)&remote, &slen);
- if ( ntohs(remote.sin_port)==SWITCH_PORT && len>=(int)sizeof(struct ng_header) && validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ) {
- initNgPacket(&np);
- extractPacketAttributes(&np, error, attr_error, attr);
- len=0;
- break;
- }
+ if ( len<0 ) break;
+
+ np.maxlen=len;
+ initNgPacket(&np);
+
+ if (
+ ntohs(remote.sin_port)!=SWITCH_PORT ||
+ len<(int)sizeof(struct ng_header) ||
+ !validateNgHeader(np.nh, code, &nga->localmac, sa==NULL ? NULL : &sa->mac , nga->seq) ||
+ extractPacketAttributes(&np, error, attr_error, attr)<0
+ ) continue;
+
+ len=0;
+ break;
}
-int checkErrorCode (unsigned char err, unsigned short attr_error) {
+static int checkErrorCode (unsigned char err, unsigned short attr_error) {
if ( err==ERROR_INVALID_PASSWORD && attr_error==ATTR_PASSWORD ) {
#include <string.h>
#include <unistd.h>
+//#include <poll.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <sys/ioctl.h>
+//#include <sys/time.h>
#include "list.h"
#include "lib.h"
// --------------------------------------------------------------------------------------------------------------
-void extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr) {
+int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr) {
struct attr *at;
+ int ret=0;
if ( error!=NULL ) *error=np->nh->error;
while ( getPacketTotalSize(np)<np->maxlen ) {
+ // no room for an attribute header: error
+ if ( getPacketTotalSize(np)+(int)sizeof(struct attr_header)>np->maxlen ) {
+ ret=-1;
+ break;
+ }
+
at=malloc(sizeof(struct attr));
at->attr=ntohs(np->ah->attr);
at->size=ntohs(np->ah->size);
- if ( getPacketTotalSize(np)+at->size>np->maxlen ) {
+ // attribute data bigger than the remaining size: error
+ if ( getPacketTotalSize(np)+(int)sizeof(struct attr_header)+at->size>np->maxlen ) {
free(at);
+ ret=-1;
break;
}
pushBackList(attr, at);
- if ( at->attr==ATTR_END ) {
- break;
- }
+ // stop on an END attribute
+ if ( at->attr==ATTR_END ) break;
+ // move to next attribute
np->ah=(struct attr_header*)(np->ah->data+at->size);
}
+ return ret;
+
}
void freeAttr (struct attr *at);
//
-void extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr);
+int extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsigned short *attr_error, List *attr);
//
void extractSwitchAttributes (struct swi_attr *sa, const List *l);