From: darkcoven Date: Fri, 11 Oct 2013 19:48:29 +0000 (+0200) Subject: Merge branch 'autotools' X-Git-Url: https://git.sur5r.net/?p=ngadmin;a=commitdiff_plain;h=ce846b1344839e09f7c272c2ba2d5259a891892a Merge branch 'autotools' Conflicts: cli/src/admin.c --- ce846b1344839e09f7c272c2ba2d5259a891892a diff --cc cli/src/admin.c index 0000000,dbd30bb..73ea79c mode 000000,100644..100644 --- a/cli/src/admin.c +++ b/cli/src/admin.c @@@ -1,0 -1,407 +1,411 @@@ + + #ifdef HAVE_CONFIG_H + #include "config.h" + #endif + + #include + #include + #include + #include + + #include + #ifdef HAVE_LIBREADLINE + #include + #include + #endif + + #include "common.h" + #include "commands.h" + + + #define MAXCOM 32 + + -int main_loop_continue; - + + static const struct TreeNode* getSubCom (char **com, int n, int *t) + { + int i; + const struct TreeNode *cur, *next; + + + cur = &commands; + for (i = 0; i < n; i++) { + /* we have reached a terminal command, exit */ + if (cur->sub == NULL) + break; + + /* search sub command in sub command array */ + for (next = cur->sub; next->name != NULL && strcmp(next->name, com[i]) != 0; next++); + + /* sub command not found, exit */ + if (next->name == NULL) + break; + + /* next command is now the current one */ + cur = next; + } + + *t = i; + + + return cur; + } + + + #ifdef HAVE_LIBREADLINE + static const struct TreeNode *compcur; + + + static char* my_generator (const char* text, int state) + { + static int len; + static const struct TreeNode *tn; + const char *name; + + + if (compcur == NULL) { + /* sub command not found */ + return NULL; + } else if (state == 0) { + tn = compcur->sub; + len = strlen(text); + } + + if (tn == NULL) /* terminal command */ + return NULL; + + while ((name = tn++->name) != NULL) { + if (strncmp(name, text, len) == 0) + return strdup(name); + } + + + return NULL; + } + + + static char** my_completion (const char *text, int start, int end UNUSED) + { + char **matches = NULL; + char *line, *com[MAXCOM]; + int i, n; + + + memset(com, 0, MAXCOM * sizeof(char*)); + line = strdup(rl_line_buffer); + line[start] = '\0'; + trim(line, start); + n = explode(line, com, MAXCOM); + free(line); + + compcur = getSubCom(com, n, &i); + + if (i < n) + compcur = NULL; + matches = rl_completion_matches(text, my_generator); + + for (i = 0; com[i] != NULL; i++) + free(com[i]); + + + return matches; + } + #endif /* HAVE_LIBREADLINE */ + + ++int main_loop_continue; + static struct ngadmin *nga; + static sigjmp_buf jmpbuf; + static struct termios orig_term; + struct termios current_term; + static bool batch; + + + 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); + - if (!batch) ++ if (!batch && main_loop_continue) + siglongjmp(jmpbuf, 1); + + default: + ngadmin_close(nga); + + tcsetattr(STDIN_FILENO, TCSANOW, &orig_term); + + exit(0); + } + } + + + static int pre_login (const struct ether_addr *mac, int retries) + { + const struct swi_attr *sa; + int i, n, err; + + + for (i = 1; retries <= 0 || i <= retries; i++) { + /* scan */ + printf("scan... "); + fflush(stdout); + err = ngadmin_scan(nga); + if (err < 0) { + printErrCode(err); - continue; ++ return err; + } + + /* search switch with requested MAC */ + sa = ngadmin_getSwitchTab(nga, &n); + while (--n >= 0) { + if (memcmp(mac, &sa[n].mac, ETH_ALEN) == 0) + break; + } + + if (n < 0) { + printf("no switch found\n"); + } else { + printf("done\n"); + break; + } + } + + if (n < 0) + return 1; + + /* login */ + printf("login... "); + fflush(stdout); + err = ngadmin_login(nga, n); + if (err < 0) + printErrCode(err); + else + printf("done\n"); + + return err; + } + + + int main (int argc, char **argv) + { + static const struct option opts[] = { + {"batch", no_argument, NULL, 'a'}, + {"keep-broadcasting", no_argument, NULL, 'b'}, + {"force-interface", no_argument, NULL, 'f'}, - {"global-broadcast", no_argument, NULL, 'g'}, + {"help", no_argument, NULL, 'h'}, + {"interface", required_argument, NULL, 'i'}, ++ {"local-broadcast", no_argument, NULL, 'l'}, + {"mac", required_argument, NULL, 'm'}, + {"password", required_argument, NULL, 'p'}, + {"retries", required_argument, NULL, 'r'}, + {"timeout", required_argument, NULL, 't'}, + {0, 0, 0, 0} + }; + char *line, *com[MAXCOM]; + const char *iface = "eth0", *password = NULL; + float timeout = 0.f; - bool kb = false, force = false, global = false; ++ bool kb = false, force = false, global = true; + struct timeval tv; + const struct TreeNode *cur, *next; + struct ether_addr *mac = NULL; + int i, n, retries = 3; + + + tcgetattr(STDIN_FILENO, &orig_term); + current_term = orig_term; + #ifdef HAVE_LIBREADLINE + batch = false; + #else + batch = true; + #endif + + opterr = 0; + - while ((n = getopt_long(argc, argv, "abfghi:m:p:r:t:", opts, NULL)) != -1) { ++ while ((n = getopt_long(argc, argv, "abfhi:lm:p:r:t:", opts, NULL)) != -1) { + switch (n) { + + case 'a': + batch = true; + break; + + case 'b': + kb = true; + break; + + case 'f': + force = true; + break; + - case 'g': - global = true; - break; - + case 'h': + printf("usage: %s [-a] [-b] [-f] [-g] [-i ] [-m ] [-p ]\n", argv[0]); + goto end; + + case 'i': + iface = optarg; + break; + ++ case 'l': ++ global = false; ++ break; ++ + case 'm': + mac = ether_aton(optarg); + if (mac == NULL) { + printf("invalid MAC\n"); + goto end; + } + break; + + case 'p': + password = optarg; + break; + + case 'r': + retries = strtol(optarg, NULL, 0); + break; + + case 't': + timeout = strtof(optarg, NULL); + break; + + 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*)); + + nga = ngadmin_init(iface); + if (nga == NULL) { + fprintf(stderr, "initialization error\n"); + goto end; + } + + /* set timeout */ + if (timeout > 0.f) { + tv.tv_sec = (int)timeout; + tv.tv_usec = (int)((timeout - (float)tv.tv_sec) * 1.e6f); + ngadmin_setTimeout(nga, &tv); + } + + - if (kb && ngadmin_setKeepBroadcasting(nga, true) != ERR_OK) ++ if (ngadmin_setKeepBroadcasting(nga, kb) != ERR_OK) + goto end; + + if (force && ngadmin_forceInterface(nga) != ERR_OK) + goto end; + - if (global && ngadmin_useGlobalBroadcast(nga, true) != ERR_OK) ++ if (ngadmin_useGlobalBroadcast(nga, global) != ERR_OK) + goto end; + + /* non-TTY inputs are automatically set to batch mode */ + if (!isatty(STDIN_FILENO)) + batch = true; + + if (password != NULL) + ngadmin_setPassword(nga, password); + + signal(SIGTERM, handler); + signal(SIGINT, handler); + + /* automatic scan & login when switch MAC is specified on the command line */ + if (mac != NULL && pre_login(mac, retries) != 0) + goto end; + - if (!batch) { ++ if (batch) { ++ /* in batch mode, we must be logged to continue */ ++ if (ngadmin_getCurrentSwitch(nga) == NULL) { ++ printf("must be logged\n"); ++ goto end; ++ } ++ } else { + #ifdef HAVE_LIBREADLINE + /* initialize readline functions */ + rl_attempted_completion_function = my_completion; + rl_completion_entry_function = my_generator; + + sigsetjmp(jmpbuf, 1); + #endif + } + + main_loop_continue = 1; - + while (main_loop_continue) { + /* read user input */ + line = NULL; + n = 0; + if (batch) + n = getline(&line, (size_t*)&i, stdin); + #ifdef HAVE_LIBREADLINE + else + line = readline("> "); + #endif + if (n < 0 || line == NULL) + goto end; + + /* split string into words */ + trim(line, strlen(line)); + n = explode(line, com, MAXCOM); + + if (n == 0) { + free(line); + continue; + } else { + #ifdef HAVE_LIBREADLINE + if (!batch) + add_history(line); + #endif + free(line); + } + + cur = getSubCom(com, n, &i); + + if (cur->sub != NULL) { + /* not terminal command */ + if (i == 0) { + /* root command */ + printf("unknown command: %s\n", com[i]); + } else if (i < n) { + /* intermediate command, remaining string */ + printf("unknown %s subcommand: %s\n", com[i - 1], com[i]); + } else { + /* intermediate command, no remaining string */ + /* print available subcommands */ + for (next = cur->sub; next->name != NULL; next++) + printf("%s ", next->name); + putchar('\n'); + } + } else if (cur->comfunc == NULL) { + /* erroneous terminal command without function */ + printf("terminal command without function\n"); + } else { + /* execute terminal command */ + cur->comfunc(n - i, (const char**)&com[i], nga); + } + + for (i = 0; com[i] != NULL; i++) { + free(com[i]); + com[i] = NULL; + } + } + + end: + handler(0); + } + + diff --cc cli/src/com_vlan.c index 0000000,3496815..0baa1d5 mode 000000,100644..100644 --- a/cli/src/com_vlan.c +++ b/cli/src/com_vlan.c @@@ -1,0 -1,510 +1,511 @@@ + + #include "commands.h" + + + + static char vlan_char (int t) + { + switch (t) { + + case VLAN_TAGGED: + return 'T'; + + case VLAN_UNTAGGED: + return 'U'; + + case VLAN_NO: + return ' '; + + default: + return '?'; + } + } + + + int do_vlan_8021q_del (int argc, const char **argv, struct ngadmin *nga) + { + const struct swi_attr *sa; + unsigned short vlan; + int i; + + + if (argc != 1) { + printf("usage: vlan 8021q del \n"); + return 1; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + return 1; + } + + vlan=strtoul(argv[0], NULL, 0); + if (vlan < VLAN_MIN || vlan > VLAN_DOT_MAX) { + printf("vlan out of range\n"); + return 1; + } + + i = ngadmin_VLANDestroy(nga, vlan); + printErrCode(i); + + + return 0; + } + + + int do_vlan_port_set (int argc, const char **argv, struct ngadmin *nga) + { + unsigned char vlan, port, *ports = NULL; + const struct swi_attr *sa; + int i, k = 0, ret = 0; + + + if (argc < 2) { + printf("usage: vlan port set [all ] [ ] [ ] [...]\n"); + ret = 1; + goto end; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + ports = malloc(sa->ports * sizeof(unsigned char)); + + /* read defaults */ + vlan = 0; + if (strcmp(argv[k], "all") == 0) { + k++; + vlan = strtoul(argv[k++], NULL, 0); + /* VLAN 0 is allowed and means no change */ + if (vlan > VLAN_PORT_MAX) { + printf("vlan out of range\n"); + ret = 1; + goto end; + } + } + + /* apply defaults */ + memset(ports, vlan, sa->ports); + + /* read and apply port specifics */ + while (k < argc - 1) { + /* read port */ + port = strtoul(argv[k++], NULL, 0); + if (port < 1 || port > sa->ports) { + printf("port out of range\n"); + ret = 1; + goto end; + } + + /* read vlan */ + vlan = strtoul(argv[k++], NULL, 0); + /* VLAN 0 is allowed and means no change */ + if (vlan > VLAN_PORT_MAX) { + printf("vlan out of range\n"); + ret = 1; + goto end; + } + + ports[port - 1] = vlan; + } + + /* set conf */ + i = ngadmin_setVLANPortConf(nga, ports); + printErrCode(i); + + end: + free(ports); + + return ret; + } + + + int do_vlan_port_show (int argc, const char **argv UNUSED, struct ngadmin *nga) + { + unsigned char *ports = NULL; + const struct swi_attr *sa; + int i, ret = 0; + + + if (argc > 0) { + printf("this command takes no argument\n"); + ret = 1; + goto end; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + ports = malloc(sa->ports * sizeof(unsigned char)); + + /* request all VLANs config */ + i = ngadmin_getVLANPortConf(nga, ports); + + if (i != ERR_OK) { + printErrCode(i); + ret = 1; + goto end; + } + + printf("Ports configuration: \n"); + printf("Port\t"); + for (i = 1; i <= sa->ports; i++) + printf("%i\t", i); + putchar('\n'); + + /* show all VLANs */ + printf("VLAN\t"); + for (i = 0; i < sa->ports; i++) + printf("%u\t", ports[i]); + putchar('\n'); + + end: + free(ports); + + return ret; + } + + + int do_vlan_8021q_set (int argc, const char **argv, struct ngadmin *nga) + { + unsigned char *ports = NULL, p, def = VLAN_UNSPEC; + const struct swi_attr *sa; + unsigned short vlan; + int i, k = 0, ret = 0; + + + if (argc == 0) { + printf("usage: vlan 802.1q set [all unspec|no|untagged|tagged] [ unspec|no|untagged|tagged ...]\n"); + ret = 1; + goto end; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + /* read vlan */ + vlan = strtoul(argv[k++], NULL, 0); + + if (vlan < VLAN_MIN || vlan > VLAN_DOT_MAX) { + printf("vlan out of range\n"); + ret = 1; + goto end; + } + + /* read defaults */ + if (k < argc - 1 && strcasecmp(argv[k], "all") == 0) { + k++; + if (strcasecmp(argv[k], "tagged") == 0) { + def = VLAN_TAGGED; + } else if (strcasecmp(argv[k], "untagged") == 0) { + def = VLAN_UNTAGGED; + } else if (strcasecmp(argv[k], "no") == 0) { + def = VLAN_NO; + } else if (strcasecmp(argv[k], "unspec") == 0) { + def = VLAN_UNSPEC; + } else { + printf("incorrect type\n"); + ret = 1; + goto end; + } + k++; + } + + ports = malloc(sa->ports * sizeof(unsigned char)); + + /* apply defaults */ + memset(ports, def, sa->ports); + + /* read and apply port specifics */ + while (k < argc - 1) { + p = strtoul(argv[k++], NULL, 0) - 1; + if (p >= sa->ports) { + printf("port out of range\n"); + ret = 1; + goto end; + } + if (strcasecmp(argv[k], "tagged") ==0) { + ports[p] = VLAN_TAGGED; + } else if (strcasecmp(argv[k], "untagged") == 0) { + ports[p] = VLAN_UNTAGGED; + } else if (strcasecmp(argv[k], "no") == 0) { + ports[p] = VLAN_NO; + } else if (strcasecmp(argv[k], "unspec") == 0) { + ports[p] = VLAN_UNSPEC; + } else { + printf("incorrect type\n"); + ret = 1; + goto end; + } + k++; + } + + /* set conf */ + i = ngadmin_setVLANDotConf(nga, vlan, ports); + printErrCode(i); + + end: + free(ports); + + return ret; + } + + + int do_vlan_8021q_show (int argc, const char **argv, struct ngadmin *nga) + { + unsigned short vl = 0, *vlans = NULL; + unsigned char *ports = NULL; + const struct swi_attr *sa; + int i, j, n = 16, ret = 0; + + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + if (argc > 0) + vl = strtoul(argv[0], NULL, 0); + + ports = malloc(sa->ports * n * sizeof(unsigned char)); + + if (vl == 0) { + /* request all VLANs config */ + vlans = malloc(n * sizeof(unsigned short)); + ports = malloc(sa->ports * n * sizeof(unsigned char)); + i = ngadmin_getVLANDotAllConf(nga, vlans, ports, &n); + } else { + /* request single VLAN config */ + ports = malloc(sa->ports * sizeof(unsigned char)); + i = ngadmin_getVLANDotConf(nga, vl, ports); + } + + if (i != ERR_OK) { + printErrCode(i); + ret = 1; + goto end; + } + + printf("Ports configuration: \n"); + printf("VLAN\t"); + for (i = 1; i <= sa->ports; i++) + printf("%i\t", i); + putchar('\n'); + + if (vl == 0) { + /* show all VLANs */ + for (i = 0; i < n; i++) { + printf("%u\t", vlans[i]); + for (j = 0; j < sa->ports; j++) + printf("%c\t", vlan_char(ports[i * sa->ports + j])); + putchar('\n'); + } + } else { + /* show single VLAN config */ + printf("%u\t", vl); + for (j = 0; j < sa->ports; j++) + printf("%c\t", vlan_char(ports[j])); + putchar('\n'); + } + + end: + free(vlans); + free(ports); + + return ret; + } + + + int do_vlan_mode_set (int argc, const char **argv, struct ngadmin *nga) + { + int mode, i; + + + if (argc == 0) { + printf( + "usage: vlan mode set \n" ++ "0 - disabled\n" + "1 - basic port based\n" + "2 - advanced port based\n" + "3 - basic 802.1Q\n" + "4 - advanced 802.1Q\n" + ); + return 0; + } + + if (ngadmin_getCurrentSwitch(nga) == NULL) { + printf("must be logged\n"); + return 1; + } + + mode = strtoul(argv[0], NULL, 0); - if (mode < 1 || mode > 4) { ++ if (mode < VLAN_DISABLED || mode > VLAN_DOT_ADV) { + printf("mode out of range\n"); + return 1; + } + + i = ngadmin_setVLANType(nga, mode); + printErrCode(i); + + + return 0; + } + + + int do_vlan_mode_show (int argc, const char **argv UNUSED, struct ngadmin *nga) + { + int i, t, ret = 0; + + + if (argc > 0) { + printf("this command takes no argument\n"); + ret = 1; + goto end; + } + + if (ngadmin_getCurrentSwitch(nga) == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + i = ngadmin_getVLANType(nga, &t); + if (i != ERR_OK) { + printErrCode(i); + ret = 1; + goto end; + } + + printf("VLAN type: "); + switch (t) { + + case VLAN_DISABLED: + printf("disabled\n"); + break; + + case VLAN_PORT_BASIC: + printf("port basic\n"); + break; + + case VLAN_PORT_ADV: + printf("port advanced\n"); + break; + + case VLAN_DOT_BASIC: + printf("802.1Q basic\n"); + break; + + case VLAN_DOT_ADV: + printf("802.1Q advanced\n"); + break; + + default: + printf("unknown (%i)\n", t); + } + + end: + + return ret; + } + + + int do_vlan_pvid_set (int argc, const char **argv, struct ngadmin *nga) + { + const struct swi_attr *sa; + unsigned char port; + unsigned short vlan; + int i; + + + if (argc != 2) { + printf("usage: vlan pvid set \n"); + return 1; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + return 1; + } + + port = strtoul(argv[0], NULL, 0); + vlan = strtoul(argv[1], NULL, 0); + + if (port < 1 || port > sa->ports) { + printf("port out of range\n"); + return 1; + } + + if (vlan < VLAN_MIN || vlan > VLAN_DOT_MAX) { + printf("vlan out of range\n"); + return 1; + } + + i = ngadmin_setPVID(nga, port, vlan); + printErrCode(i); + + + return 0; + } + + + int do_vlan_pvid_show (int argc, const char **argv UNUSED, struct ngadmin *nga) + { + unsigned short *ports = NULL; + const struct swi_attr *sa; + int i, ret = 0; + + + if (argc > 0) { + printf("this command takes no argument\n"); + ret = 1; + goto end; + } + + sa = ngadmin_getCurrentSwitch(nga); + if (sa == NULL) { + printf("must be logged\n"); + ret = 1; + goto end; + } + + ports = malloc(sa->ports * sizeof(unsigned short)); + i = ngadmin_getAllPVID(nga, ports); + if (i != ERR_OK) { + printErrCode(i); + ret = 1; + goto end; + } + + printf("Port\t"); + for (i = 1; i <= sa->ports; i++) + printf("%i\t", i); + putchar('\n'); + + printf("VLAN\t"); + for (i = 0; i < sa->ports; i++) + printf("%u\t", ports[i]); + putchar('\n'); + + end: + free(ports); + + return ret; + } + +