From 1f4248859d9d0f51d628df6686d09c3aef09bc90 Mon Sep 17 00:00:00 2001 From: darkcoven Date: Sun, 25 Dec 2011 12:00:00 +0100 Subject: [PATCH] CLI: added the possibility to interrupt hanging commands with CTRL+C. CLI: added the possiblity to enter password without displaying it. CLI: added help command. Lib: added check on packet extraction. --- cli/admin.c | 56 +++++++++++++++++++++++++++++++---- cli/com_help.c | 26 ++++++++++++++++ cli/com_password.c | 29 +++++++++++++++--- cli/commands.c | 6 ++++ cli/common.h | 6 +++- lib/src/network.c | 74 ++++++++++++++++++++++++++++++++++++++-------- lib/src/network.h | 2 ++ lib/src/protocol.c | 21 +++++++++---- lib/src/protocol.h | 2 +- 9 files changed, 193 insertions(+), 29 deletions(-) create mode 100644 cli/com_help.c diff --git a/cli/admin.c b/cli/admin.c index beb40f2..eddbf83 100644 --- a/cli/admin.c +++ b/cli/admin.c @@ -1,5 +1,7 @@ #include +#include +#include #include #include @@ -121,6 +123,39 @@ char** my_completion (const char *text, int start, int end UNUSED) { +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) { @@ -137,7 +172,6 @@ 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; @@ -212,12 +246,27 @@ int main (int argc, char **argv) { 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; @@ -274,10 +323,7 @@ int main (int argc, char **argv) { end: - ngadmin_close(nga); - - - return 0; + handler(0); } diff --git a/cli/com_help.c b/cli/com_help.c new file mode 100644 index 0000000..5bf84ee --- /dev/null +++ b/cli/com_help.c @@ -0,0 +1,26 @@ + +#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; + +} + + + + diff --git a/cli/com_password.c b/cli/com_password.c index f93412e..92e96c6 100644 --- a/cli/com_password.c +++ b/cli/com_password.c @@ -32,15 +32,36 @@ bool do_password_change (int nb, const char **com, struct ngadmin *nga) { 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 \n"); + if ( nb>1 ) { + printf("Usage: password set []\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; diff --git a/cli/commands.c b/cli/commands.c index 2d5e9cc..df13a58 100644 --- a/cli/commands.c +++ b/cli/commands.c @@ -22,6 +22,10 @@ bool do_firmware_show (int nb, const char **com, struct ngadmin *nga); 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); @@ -119,6 +123,8 @@ COM_ROOT_START(coms) 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) diff --git a/cli/common.h b/cli/common.h index d746977..c0e6cb8 100644 --- a/cli/common.h +++ b/cli/common.h @@ -6,15 +6,19 @@ #include #include #include +#include +#include #include -#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[]; diff --git a/lib/src/network.c b/lib/src/network.c index d548b58..4f4b3ff 100644 --- a/lib/src/network.c +++ b/lib/src/network.c @@ -191,6 +191,38 @@ int sendNgPacket (struct ngadmin *nga, char code, const List *attr) { } +/* +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) { @@ -200,29 +232,45 @@ int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned 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; } @@ -233,7 +281,7 @@ int recvNgPacket (struct ngadmin *nga, char code, unsigned char *error, unsigned -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 ) { diff --git a/lib/src/network.h b/lib/src/network.h index 6ed3cde..534ae31 100644 --- a/lib/src/network.h +++ b/lib/src/network.h @@ -5,10 +5,12 @@ #include #include +//#include #include #include #include #include +//#include #include "list.h" #include "lib.h" diff --git a/lib/src/protocol.c b/lib/src/protocol.c index 5f99da2..05677a8 100644 --- a/lib/src/protocol.c +++ b/lib/src/protocol.c @@ -256,9 +256,10 @@ 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) { struct attr *at; + int ret=0; if ( error!=NULL ) *error=np->nh->error; @@ -266,12 +267,20 @@ void extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsign while ( getPacketTotalSize(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; } @@ -284,15 +293,17 @@ void extractPacketAttributes (struct ng_packet *np, unsigned char *error, unsign 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; + } diff --git a/lib/src/protocol.h b/lib/src/protocol.h index 24fbbfe..cec182b 100644 --- a/lib/src/protocol.h +++ b/lib/src/protocol.h @@ -110,7 +110,7 @@ struct attr* newAddrAttr (unsigned short attr, struct in_addr value); 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); -- 2.39.5