diff options
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | amtterm.c | 28 | ||||
-rw-r--r-- | gamt.c | 103 | ||||
-rw-r--r-- | redir.c | 69 | ||||
-rw-r--r-- | redir.h | 17 |
5 files changed, 176 insertions, 43 deletions
diff --git a/GNUmakefile b/GNUmakefile index aec0067..cd65580 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -52,7 +52,7 @@ distclean: clean ################################################################# amtterm: amtterm.o redir.o tcp.o -gamt: gamt.o +gamt: gamt.o redir.o tcp.o ################################################################# @@ -8,7 +8,6 @@ #include <signal.h> #include <sys/ioctl.h> -#include "tcp.h" #include "redir.h" #define APPNAME "amtterm" @@ -30,10 +29,11 @@ static void state_tty(void *cb_data, enum redir_state old, enum redir_state new) if (!r->verbose) return; - fprintf(stderr, APPNAME " state: %s -> %s\n", - redir_strstate(old), redir_strstate(new)); + fprintf(stderr, APPNAME ": %s -> %s (%s)\n", + redir_state_name(old), redir_state_name(new), + redir_state_desc(new)); switch (new) { - case REDIR_CONN_SOL: + case REDIR_RUN_SOL: fprintf(stderr, "serial-over-lan redirection ok\n"); fprintf(stderr, "connected now, use ^] to escape\n"); break; @@ -55,7 +55,7 @@ static int redir_loop(struct redir *r) break; FD_ZERO(&set); - if (r->state == REDIR_CONN_SOL) + if (r->state == REDIR_RUN_SOL) FD_SET(0,&set); FD_SET(r->sock,&set); tv.tv_sec = HEARTBEAT_INTERVAL * 4 / 1000; @@ -164,10 +164,7 @@ static void usage(FILE *fp) int main(int argc, char *argv[]) { - struct addrinfo ai; struct redir r; - char *port = "16994"; - char *host = NULL; char *h; int c; @@ -211,10 +208,10 @@ int main(int argc, char *argv[]) } if (optind < argc) - host = argv[optind]; + snprintf(r.host, sizeof(r.host), "%s", argv[optind]); if (optind+1 < argc) - port = argv[optind+1]; - if (NULL == host) { + snprintf(r.port, sizeof(r.port), "%s", argv[optind+1]); + if (0 == strlen(r.host)) { usage(stderr); exit(1); } @@ -222,7 +219,7 @@ int main(int argc, char *argv[]) tty_save(); if (0 == strlen(r.pass)) { tty_noecho(); - fprintf(stderr, "AMT password for host %s: ", host); + fprintf(stderr, "AMT password for host %s: ", r.host); fgets(r.pass, sizeof(r.pass), stdin); fprintf(stderr, "\n"); if (NULL != (h = strchr(r.pass, '\r'))) @@ -231,12 +228,7 @@ int main(int argc, char *argv[]) *h = 0; } - memset(&ai, 0, sizeof(ai)); - ai.ai_socktype = SOCK_STREAM; - ai.ai_family = PF_UNSPEC; - tcp_verbose = r.verbose; - r.sock = tcp_connect(&ai, NULL, NULL, host, port); - if (-1 == r.sock) { + if (-1 == redir_connect(&r)) { tty_restore(); exit(1); } @@ -10,6 +10,8 @@ #include <gtk/gtk.h> #include <vte/vte.h> +#include "redir.h" + struct gamt_window { /* gtk stuff */ GtkActionGroup *ag; @@ -17,6 +19,11 @@ struct gamt_window { GtkWidget *win; GtkWidget *vte; GtkWidget *status; + + /* sol stuff */ + struct redir redir; + GIOChannel *ch; + guint id; }; /* ------------------------------------------------------------------ */ @@ -38,6 +45,41 @@ static void destroy_cb(GtkWidget *widget, gpointer data) /* ------------------------------------------------------------------ */ +static int recv_gtk(void *cb_data, unsigned char *buf, int len) +{ + struct gamt_window *gamt = cb_data; + vte_terminal_feed(VTE_TERMINAL(gamt->vte), buf, len); + return 0; +} + +static void state_gtk(void *cb_data, enum redir_state old, enum redir_state new) +{ + struct gamt_window *gamt = cb_data; + unsigned char buf[128]; + + switch (new) { + case REDIR_ERROR: + snprintf(buf, sizeof(buf), "%s: %s FAILED", gamt->redir.host, + redir_state_desc(old)); + break; + default: + snprintf(buf, sizeof(buf), "%s: %s", gamt->redir.host, + redir_state_desc(new)); + break; + } + gtk_label_set_text(GTK_LABEL(gamt->status), buf); +} + +static void user_input(VteTerminal *vte, gchar *buf, guint len, + gpointer data) +{ + struct gamt_window *gamt = data; + + redir_sol_send(&gamt->redir, buf, len); +} + +/* ------------------------------------------------------------------ */ + static const GtkActionEntry entries[] = { { .name = "FileMenu", @@ -66,6 +108,51 @@ static char ui_xml[] = /* ------------------------------------------------------------------ */ +static gboolean gamt_data(GIOChannel *source, GIOCondition condition, + gpointer data) +{ + struct gamt_window *gamt = data; + + redir_data(&gamt->redir); + + if (gamt->redir.state == REDIR_CLOSED || + gamt->redir.state == REDIR_ERROR) { + g_source_destroy(g_main_context_find_source_by_id + (g_main_context_default(), gamt->id)); + gamt->id = 0; + gamt->ch = NULL; + } + return TRUE; +} + +static int gamt_connect(struct gamt_window *gamt, char *host, char *port) +{ + char *h; + + memset(&gamt->redir, 0, sizeof(gamt->redir)); + memcpy(&gamt->redir.type, "SOL ", 4); + strcpy(gamt->redir.user, "admin"); + if (NULL != (h = getenv("AMT_PASSWORD"))) + snprintf(gamt->redir.pass, sizeof(gamt->redir.pass), "%s", h); + + snprintf(gamt->redir.host, sizeof(gamt->redir.host), "%s", host); + if (port) + snprintf(gamt->redir.port, sizeof(gamt->redir.port), "%s", port); + + gamt->redir.verbose = 1; + gamt->redir.cb_data = gamt; + gamt->redir.cb_recv = recv_gtk; + gamt->redir.cb_state = state_gtk; + + if (-1 == redir_connect(&gamt->redir)) + return -1; + + gamt->ch = g_io_channel_unix_new(gamt->redir.sock); + gamt->id = g_io_add_watch(gamt->ch, G_IO_IN, gamt_data, gamt); + redir_start(&gamt->redir); + return 0; +} + static struct gamt_window *gamt_window() { GtkWidget *vbox, *frame, *item; @@ -100,9 +187,11 @@ static struct gamt_window *gamt_window() /* vte terminal */ gamt->vte = vte_terminal_new(); + g_signal_connect(gamt->vte, "commit", G_CALLBACK(user_input), gamt); + /* other widgets */ - gamt->status = gtk_label_new("status line"); + gamt->status = gtk_label_new("idle"); gtk_misc_set_alignment(GTK_MISC(gamt->status), 0, 0.5); gtk_misc_set_padding(GTK_MISC(gamt->status), 3, 1); @@ -141,6 +230,7 @@ static void usage(FILE *fp) int main(int argc, char *argv[]) { + struct gamt_window *gamt; int debug = 0; int c; @@ -161,15 +251,12 @@ main(int argc, char *argv[]) } } -#if 0 - if (optind+1 > argc) { - usage(stderr); + gamt = gamt_window(); + if (NULL == gamt) exit(1); - } -#endif - if (NULL == gamt_window()) - exit(1); + if (optind+1 <= argc) + gamt_connect(gamt, argv[optind], NULL); gtk_main(); exit(0); @@ -3,21 +3,37 @@ #include <unistd.h> #include <string.h> +#include "tcp.h" #include "redir.h" -static const char *state_names[] = { +static const char *state_name[] = { [ REDIR_NONE ] = "NONE", + [ REDIR_CONNECT ] = "CONNECT", [ REDIR_INIT ] = "INIT", [ REDIR_AUTH ] = "AUTH", [ REDIR_INIT_SOL ] = "INIT_SOL", - [ REDIR_CONN_SOL ] = "CONN_SOL", + [ REDIR_RUN_SOL ] = "RUN_SOL", [ REDIR_INIT_IDER ] = "INIT_IDER", - [ REDIR_CONN_IDER ] = "CONN_IDER", + [ REDIR_RUN_IDER ] = "RUN_IDER", [ REDIR_CLOSING ] = "CLOSING", [ REDIR_CLOSED ] = "CLOSED", [ REDIR_ERROR ] = "ERROR", }; +static const char *state_desc[] = { + [ REDIR_NONE ] = "disconnected", + [ REDIR_CONNECT ] = "connection to host", + [ REDIR_INIT ] = "redirection initialization", + [ REDIR_AUTH ] = "session authentication", + [ REDIR_INIT_SOL ] = "serial-over-lan initialization", + [ REDIR_RUN_SOL ] = "serial-over-lan active", + [ REDIR_INIT_IDER ] = "IDE redirect initialization", + [ REDIR_RUN_IDER ] = "IDE redirect active", + [ REDIR_CLOSING ] = "redirection shutdown", + [ REDIR_CLOSED ] = "connection closed", + [ REDIR_ERROR ] = "failure", +}; + /* ------------------------------------------------------------------ */ static void redir_state(struct redir *r, enum redir_state new) @@ -31,17 +47,47 @@ static void redir_state(struct redir *r, enum redir_state new) /* ------------------------------------------------------------------ */ -const char *redir_strstate(enum redir_state state) +const char *redir_state_name(enum redir_state state) { const char *name = NULL; - if (state < sizeof(state_names)/sizeof(state_names[0])) - name = state_names[state]; + if (state < sizeof(state_name)/sizeof(state_name[0])) + name = state_name[state]; if (NULL == name) name = "unknown"; return name; } +const char *redir_state_desc(enum redir_state state) +{ + const char *desc = NULL; + + if (state < sizeof(state_desc)/sizeof(state_desc[0])) + desc = state_desc[state]; + if (NULL == desc) + desc = "unknown"; + return desc; +} + +int redir_connect(struct redir *r) +{ + static unsigned char *defport = "16994"; + struct addrinfo ai; + + memset(&ai, 0, sizeof(ai)); + ai.ai_socktype = SOCK_STREAM; + ai.ai_family = PF_UNSPEC; + tcp_verbose = r->verbose; + redir_state(r, REDIR_CONNECT); + r->sock = tcp_connect(&ai, NULL, NULL, r->host, + strlen(r->port) ? r->port : defport); + if (-1 == r->sock) { + redir_state(r, REDIR_ERROR); + return -1; + } + return 0; +} + int redir_start(struct redir *r) { unsigned char request[START_REDIRECTION_SESSION_LENGTH] = { @@ -60,7 +106,9 @@ int redir_stop(struct redir *r) }; redir_state(r, REDIR_CLOSED); - return write(r->sock, request, sizeof(request)); + write(r->sock, request, sizeof(request)); + close(r->sock); + return 0; } int redir_auth(struct redir *r) @@ -172,8 +220,9 @@ int redir_data(struct redir *r) int rc; rc = read(r->sock, request, sizeof(request)); - if (rc < 4) + if (rc != 4) goto err; + switch (request[0]) { case START_REDIRECTION_SESSION_REPLY: if (rc != START_REDIRECTION_SESSION_REPLY_LENGTH) { @@ -197,13 +246,13 @@ int redir_data(struct redir *r) fprintf(stderr, "serial-over-lan redirection failed\n"); goto err; } - redir_state(r, REDIR_CONN_SOL); + redir_state(r, REDIR_RUN_SOL); return 0; case SOL_HEARTBEAT: case SOL_KEEP_ALIVE_PING: case IDER_HEARTBEAT: case IDER_KEEP_ALIVE_PING: - if (rc != HEARTBEAT_LENGTH) { + if (rc < HEARTBEAT_LENGTH) { fprintf(stderr,"HEARTBEAT: got %d, expected %d bytes\n", rc, HEARTBEAT_LENGTH); goto err; @@ -2,20 +2,23 @@ enum redir_state { REDIR_NONE = 0, - REDIR_INIT = 1, - REDIR_AUTH = 2, + REDIR_CONNECT = 1, + REDIR_INIT = 2, + REDIR_AUTH = 3, REDIR_INIT_SOL = 10, - REDIR_CONN_SOL = 11, + REDIR_RUN_SOL = 11, REDIR_INIT_IDER = 20, - REDIR_CONN_IDER = 21, + REDIR_RUN_IDER = 21, REDIR_CLOSING = 30, REDIR_CLOSED = 31, - REDIR_ERROR = 99, + REDIR_ERROR = 40, }; struct redir { int sock; int verbose; + unsigned char host[64]; + unsigned char port[16]; unsigned char type[4]; unsigned char user[16]; unsigned char pass[16]; @@ -27,8 +30,10 @@ struct redir { int (*cb_recv)(void *cb_data, unsigned char *buf, int len); }; -const char *redir_strstate(enum redir_state state); +const char *redir_state_name(enum redir_state state); +const char *redir_state_desc(enum redir_state state); +int redir_connect(struct redir *r); int redir_start(struct redir *r); int redir_stop(struct redir *r); int redir_auth(struct redir *r); |