summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/ui/ui_tcpcmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/ui/ui_tcpcmds.c')
-rw-r--r--cfe/cfe/ui/ui_tcpcmds.c828
1 files changed, 828 insertions, 0 deletions
diff --git a/cfe/cfe/ui/ui_tcpcmds.c b/cfe/cfe/ui/ui_tcpcmds.c
new file mode 100644
index 0000000..e092021
--- /dev/null
+++ b/cfe/cfe/ui/ui_tcpcmds.c
@@ -0,0 +1,828 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * TCP protocol commands File: ui_tcpcmds.c
+ *
+ * This file contains commands that make use of the TCP protocol
+ * in CFE, assuming it's configured.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_timer.h"
+
+#include "cfe_error.h"
+#include "cfe_console.h"
+
+#include "ui_command.h"
+#include "cfe.h"
+
+#include "cfe_iocb.h"
+#include "cfe_devfuncs.h"
+
+#include "bsp_config.h"
+
+#if CFG_TCP
+#include "net_ebuf.h"
+#include "net_api.h"
+#endif
+
+
+/* *********************************************************************
+ * Configuration
+ ********************************************************************* */
+
+/* *********************************************************************
+ * prototypes
+ ********************************************************************* */
+
+#if CFG_TCP
+
+int ui_init_tcpcmds(void);
+
+static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[]);
+static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[]);
+#define isdigit(d) (((d) >= '0') && ((d) <= '9'))
+
+
+/* *********************************************************************
+ * ui_init_tcpcmds()
+ *
+ * Add TCP-specific commands to the command table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+
+int ui_init_tcpcmds(void)
+{
+
+ cmd_addcmd("rlogin",
+ ui_cmd_rlogin,
+ NULL,
+ "mini rlogin client.",
+ "rlogin hostname [username]\n\n"
+ "Connects to a remote system using the RLOGIN protocol. The remote"
+ "system must have appropriate permissions in place (usually via the"
+ "file '.rhosts') for CFE to connect. To terminate the session, type"
+ "a tilde (~) character followed by a period (.)",
+ "");
+
+ cmd_addcmd("tcp connect",
+ ui_cmd_connect,
+ NULL,
+ "TCP connection test.",
+ "tcp connect hostname [portnum]",
+ "-q;sink output, don't display on terminal|"
+ "-d;Send junk data to discard|"
+ "-nodelay;set nodelay option on socket|"
+ "-srcport=*;Specify the source port");
+
+ cmd_addcmd("tcp listen",
+ ui_cmd_listen,
+ NULL,
+ "port listener.",
+ "tcp listen portnum",
+ "-q;sink output, don't display on terminal|"
+ "-d;Send junk data to discard|"
+ "-nodelay;set nodelay option on socket");
+
+
+ cmd_addcmd("tcp constest",
+ ui_cmd_tcpconstest,
+ NULL,
+ "tcp console test.",
+ "tcp constest device",
+ "");
+
+ cmd_addcmd("ttcp",
+ ui_cmd_ttcp,
+ NULL,
+ "TCP test command.",
+ "ttcp -t [-options] host\n"
+ "ttcp -r [-options]\n\n",
+ "-t;Source a pattern to the network|"
+ "-r;Sink (discard) data from the network|"
+ "-D;Don't buffer TCP writes (TCP_NODELAY)|"
+ "-n=*;Number of buffers to send (-t only) (default 2048)|"
+ "-l=*;Size of buffer to send/receive (default 2048)|"
+ "-p=*;Port number to use (default 5001)");
+
+ return 0;
+}
+
+
+
+
+
+static unsigned long rand(void)
+{
+ static unsigned long seed = 1;
+ long x, hi, lo, t;
+
+ x = seed;
+ hi = x / 127773;
+ lo = x % 127773;
+ t = 16807 * lo - 2836 * hi;
+ if (t <= 0) t += 0x7fffffff;
+ seed = t;
+ return t;
+}
+
+
+static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ int res;
+ int connflag;
+ int rxdata;
+ int sport;
+ uint8_t data[100];
+ int tilde;
+ char *username;
+ uint8_t *p;
+
+ /*
+ * Process args
+ */
+
+ host = cmd_getarg(cmd,0);
+ if (!host) return ui_showusage(cmd);
+
+ username = cmd_getarg(cmd,1);
+ if (!username) username = "";
+
+ /*
+ * Look up remote host
+ */
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",host);
+ return -1;
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+
+ /*
+ * Create TCP socket and bind to a port number less than 1023
+ * See RFC1282 for more info about this
+ */
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ res = 0;
+ tilde = 0;
+ for (sport = 1023; sport > 513; sport--) {
+ res = tcp_bind(s,sport);
+ if (res == 0) break;
+ }
+
+ if (sport == 513) {
+ ui_showerror(res,"No ports available for RLOGIN");
+ return res;
+ }
+
+ /*
+ * Establish a connection. Our sockets default to nonblocking
+ * so we want to switch to blocking temporarily to
+ * let the tcp_connect routine do this by itself.
+ */
+
+ tcp_setflags(s,0);
+ res = tcp_connect(s,hostaddr,513);
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+
+ /*
+ * Construct the initial RLOGIN sequence to include
+ * our user name and terminal type
+ */
+
+ p = data;
+ *p++ = '\0';
+ p += sprintf(p,"%s",username) + 1;
+ p += sprintf(p,"%s",username) + 1;
+ p += sprintf(p,"vt100/38400") + 1;
+
+ tcp_send(s,data,p-&data[0]);
+
+ res = tcp_recv(s,data,1); /* receive result code */
+ if (res <= 0) {
+ goto remdisc;
+ }
+
+ /*
+ * Switch back to nonblocking I/O for the loop
+ */
+
+ tcp_setflags(s,TCPFLG_NBIO);
+
+ /*
+ * Begin processing loop
+ */
+
+ connflag = TRUE;
+ for (;;) {
+
+ /*
+ * Test connection status
+ */
+
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ goto remdisc;
+ }
+
+ /*
+ * Process received data
+ */
+
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ console_write(data,res);
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ break;
+ }
+ }
+
+ /*
+ * Process transmitted data
+ */
+
+ if (console_status()) {
+ console_read(data,1);
+ if (tilde == 1) {
+ if (data[0] == '.') break;
+ tcp_send(s,data,1);
+ }
+ else {
+ if (data[0] == '~') tilde = 1;
+ else tcp_send(s,data,1);
+ }
+ }
+
+ /*
+ * Give the background a chance
+ */
+
+ POLL();
+ }
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+ return 0;
+
+remdisc:
+ printf("Remote host is no longer connected.\n");
+ tcp_close(s);
+ return 0;
+}
+
+
+
+static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ char *port;
+ int res;
+ int connflag;
+ int rxdata;
+ uint8_t data[100];
+ int quiet;
+ int discard;
+ int total = 0;
+ int total2 = 0;
+ char b = 0;
+ cfe_timer_t t;
+ char *bigbuf;
+ int nodelay;
+ char *sport = NULL;
+
+ bigbuf = KMALLOC(4096,0);
+ for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26);
+
+ quiet = cmd_sw_isset(cmd,"-q");
+ discard = cmd_sw_isset(cmd,"-d");
+ nodelay = cmd_sw_isset(cmd,"-nodelay");
+
+ host = cmd_getarg(cmd,0);
+ if (!host) return -1;
+
+ port = cmd_getarg(cmd,1);
+ if (!port) port = "23";
+
+ if (strcmp(port,"discard") == 0) port = "9";
+ else if (strcmp(port,"chargen") == 0) port = "19";
+ else if (strcmp(port,"echo") == 0) port = "7";
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ xprintf("Invalid IP address: %s\n",host);
+ return -1;
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ if (cmd_sw_value(cmd,"-srcport",&sport)) {
+ res = tcp_bind(s,atoi(sport));
+ if (res < 0) {
+ ui_showerror(res,"Could not bind to port %s",sport);
+ tcp_close(s);
+ return res;
+ }
+ }
+
+ res = tcp_connect(s,hostaddr,atoi(port));
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+ TIMER_SET(t,CFE_HZ*30);
+ connflag = 0;
+ while (!TIMER_EXPIRED(t)) {
+ POLL();
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTING) continue;
+ break;
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Could not connect to remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ else {
+ printf("Connected to remote host.\n");
+ }
+
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY);
+
+ connflag = TRUE;
+ for (;;) {
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Remote host is no longer connected.\n");
+ break;
+ }
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ if (quiet) {
+ total += res;
+ if (total > 1000000) {
+ total -= 1000000;
+ printf(".");
+ }
+ }
+ else {
+ console_write(data,res);
+ }
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ }
+ }
+ if (console_status()) {
+ console_read(data,1);
+ if (data[0] == 1) break;
+ else if (data[0] == 3) break;
+ else if (data[0] == 4) {
+ for (res = 0; res < 100; res++) data[res] = 'A'+(res%26);
+ tcp_send(s,data,100);
+ }
+ else if (data[0] == 5) tcp_send(s,bigbuf,2048);
+ else if (data[0] == 2) tcp_debug(s,0);
+ else tcp_send(s,data,1);
+ }
+ if (discard) {
+ res = rand() % sizeof(data);
+ memset(data,b,res);
+ b++;
+ res = tcp_send(s,data,res);
+ if (res > 0) {
+ total2 += res;
+ if (total2 > 1000000) {
+ total2 -= 1000000;
+ printf("+");
+ }
+ }
+
+ }
+
+ POLL();
+ }
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+
+ KFREE(bigbuf);
+
+ return 0;
+}
+
+
+static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ char *port;
+ int res;
+ int connflag;
+ int rxdata;
+ uint8_t data[100];
+ int quiet;
+ int discard;
+ int total = 0;
+ int total2 = 0;
+ char b = 0;
+ char *bigbuf;
+ uint16_t p;
+ uint16_t remport;
+ uint8_t remaddr[IP_ADDR_LEN];
+ int nodelay;
+
+ bigbuf = KMALLOC(4096,0);
+ for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26);
+
+ quiet = cmd_sw_isset(cmd,"-q");
+ discard = cmd_sw_isset(cmd,"-d");
+ nodelay = cmd_sw_isset(cmd,"-nodelay");
+
+ port = cmd_getarg(cmd,0);
+ if (!port) port = "1234";
+ p = atoi(port);
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+ res = tcp_listen(s,p);
+ if (res < 0) {
+ ui_showerror(res,"Could not set socket to listen");
+ tcp_close(s);
+ return res;
+ }
+
+ printf("Listening...");
+ connflag = FALSE;
+ for (;;) {
+ if (console_status()) break;
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTED) break;
+ POLL();
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("No connection received from remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+
+ tcp_peeraddr(s,remaddr,&remport);
+ printf("Connection from port %u on %I\n",remport,remaddr);
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY);
+
+ connflag = TRUE;
+ for (;;) {
+ tcp_status(s,&connflag,&rxdata,NULL);
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Remote host is no longer connected.\n");
+ break;
+ }
+ if (rxdata != 0) {
+ res = tcp_recv(s,data,sizeof(data));
+ if (res > 0) {
+ if (quiet) {
+ total += res;
+ if (total > 1000000) {
+ total -= 1000000;
+ printf(".");
+ }
+ }
+ else {
+ console_write(data,res);
+ }
+ }
+ if (res < 0) {
+ ui_showerror(res,"TCP read error");
+ }
+ }
+ if (console_status()) {
+ console_read(data,1);
+ if (data[0] == 1) break;
+ if (data[0] == 3) break;
+ if (data[0] == 4) {
+ for (res = 0; res < 100; res++) data[res] = 'A'+(res%26);
+ tcp_send(s,data,100);
+ }
+ if (data[0] == 5) tcp_send(s,bigbuf,2048);
+ if (data[0] == 2) tcp_debug(s,0);
+ else tcp_send(s,data,1);
+ }
+ if (discard) {
+ res = rand() % sizeof(data);
+ memset(data,b,res);
+ b++;
+ res = tcp_send(s,data,res);
+ if (res > 0) {
+ total2 += res;
+ if (total2 > 1000000) {
+ total2 -= 1000000;
+ printf("+");
+ }
+ }
+
+ }
+
+ POLL();
+ }
+
+
+ printf("Disconnecting...");
+ tcp_close(s);
+ printf("done.\n");
+
+ KFREE(bigbuf);
+
+ return 0;
+}
+
+
+static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ char *x;
+ int fh;
+ int res;
+ uint8_t data[100];
+
+ x = cmd_getarg(cmd,0);
+ if (!x) return ui_showusage(cmd);
+
+ fh = cfe_open(x);
+ if (fh < 0) return ui_showerror(fh,"Could not open device %s",x);
+
+ for (;;) {
+ if (console_status()) break;
+ res = cfe_read(fh,data,sizeof(data));
+ if (res < 0) {
+ ui_showerror(res,"could not read data");
+ break;
+ }
+ console_write(data,res);
+ }
+
+ cfe_close(fh);
+
+ return 0;
+}
+
+static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[])
+{
+ int s;
+ uint8_t hostaddr[IP_ADDR_LEN];
+ char *host;
+ int res;
+ int totalbytes = 0;
+ int totalbufs = 0;
+ cfe_timer_t start_time;
+ cfe_timer_t stop_time;
+ cfe_timer_t t;
+ int connflag;
+ char *bigbuf;
+ int nodelay;
+ int numbuf;
+ int buflen;
+ int txmode,rxmode;
+ uint16_t port;
+
+ char *x;
+
+ if (cmd_sw_value(cmd,"-n",&x)) numbuf = atoi(x);
+ else numbuf = 2048;
+
+ if (cmd_sw_value(cmd,"-l",&x)) buflen = atoi(x);
+ else buflen = 2048;
+
+ if (cmd_sw_value(cmd,"-p",&x)) port = atoi(x);
+ else port = 5001;
+
+ if ((numbuf == 0) || (buflen == 0)) return ui_showusage(cmd);
+
+
+ bigbuf = KMALLOC(buflen,0);
+ for (res = 0; res < buflen; res++) bigbuf[res] = 'A'+(res%26);
+
+ txmode = cmd_sw_isset(cmd,"-t");
+ rxmode = cmd_sw_isset(cmd,"-r");
+
+ if (!(txmode ^ rxmode)) {
+ return ui_showerror(-1,"You must specify one of -t or -r");
+ }
+
+ nodelay = cmd_sw_isset(cmd,"-D");
+
+ if (txmode) {
+ host = cmd_getarg(cmd,0);
+ if (!host) return ui_showusage(cmd);
+
+ if (isdigit(*host)) {
+ if (parseipaddr(host,hostaddr) < 0) {
+ return ui_showerror(-1,"Invalid IP address: %s\n",host);
+ }
+ }
+ else {
+ res = dns_lookup(host,hostaddr);
+ if (res < 0) {
+ return ui_showerror(res,"Could not resolve IP address of host %s",host);
+ }
+ }
+ }
+
+
+ s = tcp_socket();
+
+ if (s < 0) {
+ return ui_showerror(s,"Could not create TCP socket");
+ }
+
+
+ if (txmode) {
+ res = tcp_connect(s,hostaddr,port);
+ if (res < 0) {
+ ui_showerror(res,"Could not connect to host %I",hostaddr);
+ tcp_close(s);
+ return res;
+ }
+
+ TIMER_SET(t,CFE_HZ*30);
+ connflag = 0;
+ while (!TIMER_EXPIRED(t)) {
+ POLL();
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTING) continue;
+ break;
+ }
+
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("Could not connect to remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ else {
+ printf("Connected to remote host.\n");
+ }
+ }
+
+ if (rxmode) {
+ printf("Waiting for connection on port %d: ",port);
+ tcp_listen(s,port);
+ for (;;) {
+ if (console_status()) break;
+ tcp_status(s,&connflag,NULL,NULL);
+ if (connflag == TCPSTATUS_CONNECTED) break;
+ POLL();
+ }
+ if (connflag != TCPSTATUS_CONNECTED) {
+ printf("No connection received from remote host\n");
+ tcp_close(s);
+ return -1;
+ }
+ printf("done.\n");
+ }
+
+
+ if (nodelay) tcp_setflags(s,TCPFLG_NODELAY); /* also sets blocking */
+ else tcp_setflags(s,0);
+
+ start_time = cfe_ticks;
+
+ if (rxmode) {
+ while (1) {
+ POLL();
+ res = tcp_recv(s,bigbuf,buflen);
+ if (res != buflen) break;
+ totalbytes += res;
+ totalbufs++;
+ }
+ }
+ else {
+ while (numbuf > 0) {
+ POLL();
+ res = tcp_send(s,bigbuf,buflen);
+ if (res != buflen) break;
+ numbuf--;
+ totalbytes += res;
+ totalbufs++;
+ }
+ }
+
+ stop_time = cfe_ticks;
+
+ tcp_close(s);
+
+ if ((res < 0) && !rxmode) {
+ ui_showerror(res,"Network I/O error");
+ }
+ else {
+ printf("%d bytes transferred via %d calls in %lld ticks\n",
+ totalbytes,totalbufs,stop_time-start_time);
+ }
+
+
+ KFREE(bigbuf);
+
+ return 0;
+
+}
+
+#endif /* CFG_TCP */