1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * TCP protocol commands File: ui_tcpcmds.c
6 * This file contains commands that make use of the TCP protocol
7 * in CFE, assuming it's configured.
9 * Author: Mitch Lichtenberg (mpl@broadcom.com)
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_string.h"
51 #include "lib_queue.h"
52 #include "lib_malloc.h"
53 #include "lib_printf.h"
55 #include "cfe_timer.h"
57 #include "cfe_error.h"
58 #include "cfe_console.h"
60 #include "ui_command.h"
64 #include "cfe_devfuncs.h"
66 #include "bsp_config.h"
74 /* *********************************************************************
76 ********************************************************************* */
78 /* *********************************************************************
80 ********************************************************************* */
84 int ui_init_tcpcmds(void);
86 static int ui_cmd_rlogin(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
87 static int ui_cmd_connect(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
88 static int ui_cmd_listen(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
89 static int ui_cmd_tcpconstest(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
90 static int ui_cmd_ttcp(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
91 #define isdigit(d) (((d) >= '0') && ((d) <= '9'))
94 /* *********************************************************************
97 * Add TCP-specific commands to the command table
104 ********************************************************************* */
107 int ui_init_tcpcmds(void)
113 "mini rlogin client.",
114 "rlogin hostname [username]\n\n"
115 "Connects to a remote system using the RLOGIN protocol. The remote"
116 "system must have appropriate permissions in place (usually via the"
117 "file '.rhosts') for CFE to connect. To terminate the session, type"
118 "a tilde (~) character followed by a period (.)",
121 cmd_addcmd("tcp connect",
124 "TCP connection test.",
125 "tcp connect hostname [portnum]",
126 "-q;sink output, don't display on terminal|"
127 "-d;Send junk data to discard|"
128 "-nodelay;set nodelay option on socket|"
129 "-srcport=*;Specify the source port");
131 cmd_addcmd("tcp listen",
135 "tcp listen portnum",
136 "-q;sink output, don't display on terminal|"
137 "-d;Send junk data to discard|"
138 "-nodelay;set nodelay option on socket");
141 cmd_addcmd("tcp constest",
145 "tcp constest device",
152 "ttcp -t [-options] host\n"
153 "ttcp -r [-options]\n\n",
154 "-t;Source a pattern to the network|"
155 "-r;Sink (discard) data from the network|"
156 "-D;Don't buffer TCP writes (TCP_NODELAY)|"
157 "-n=*;Number of buffers to send (-t only) (default 2048)|"
158 "-l=*;Size of buffer to send/receive (default 2048)|"
159 "-p=*;Port number to use (default 5001)");
168 static unsigned long rand(void)
170 static unsigned long seed
= 1;
176 t
= 16807 * lo
- 2836 * hi
;
177 if (t
<= 0) t
+= 0x7fffffff;
183 static int ui_cmd_rlogin(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
186 uint8_t hostaddr
[IP_ADDR_LEN
];
201 host
= cmd_getarg(cmd
,0);
202 if (!host
) return ui_showusage(cmd
);
204 username
= cmd_getarg(cmd
,1);
205 if (!username
) username
= "";
208 * Look up remote host
211 if (isdigit(*host
)) {
212 if (parseipaddr(host
,hostaddr
) < 0) {
213 xprintf("Invalid IP address: %s\n",host
);
218 res
= dns_lookup(host
,hostaddr
);
220 return ui_showerror(res
,"Could not resolve IP address of host %s",host
);
225 * Create TCP socket and bind to a port number less than 1023
226 * See RFC1282 for more info about this
232 return ui_showerror(s
,"Could not create TCP socket");
237 for (sport
= 1023; sport
> 513; sport
--) {
238 res
= tcp_bind(s
,sport
);
243 ui_showerror(res
,"No ports available for RLOGIN");
248 * Establish a connection. Our sockets default to nonblocking
249 * so we want to switch to blocking temporarily to
250 * let the tcp_connect routine do this by itself.
254 res
= tcp_connect(s
,hostaddr
,513);
256 ui_showerror(res
,"Could not connect to host %I",hostaddr
);
263 * Construct the initial RLOGIN sequence to include
264 * our user name and terminal type
269 p
+= sprintf(p
,"%s",username
) + 1;
270 p
+= sprintf(p
,"%s",username
) + 1;
271 p
+= sprintf(p
,"vt100/38400") + 1;
273 tcp_send(s
,data
,p
-&data
[0]);
275 res
= tcp_recv(s
,data
,1); /* receive result code */
281 * Switch back to nonblocking I/O for the loop
284 tcp_setflags(s
,TCPFLG_NBIO
);
287 * Begin processing loop
294 * Test connection status
297 tcp_status(s
,&connflag
,&rxdata
,NULL
);
298 if (connflag
!= TCPSTATUS_CONNECTED
) {
303 * Process received data
307 res
= tcp_recv(s
,data
,sizeof(data
));
309 console_write(data
,res
);
312 ui_showerror(res
,"TCP read error");
318 * Process transmitted data
321 if (console_status()) {
322 console_read(data
,1);
324 if (data
[0] == '.') break;
328 if (data
[0] == '~') tilde
= 1;
329 else tcp_send(s
,data
,1);
334 * Give the background a chance
340 printf("Disconnecting...");
346 printf("Remote host is no longer connected.\n");
353 static int ui_cmd_connect(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
356 uint8_t hostaddr
[IP_ADDR_LEN
];
373 bigbuf
= KMALLOC(4096,0);
374 for (res
= 0; res
< 4096; res
++) bigbuf
[res
] = 'A'+(res
%26);
376 quiet
= cmd_sw_isset(cmd
,"-q");
377 discard
= cmd_sw_isset(cmd
,"-d");
378 nodelay
= cmd_sw_isset(cmd
,"-nodelay");
380 host
= cmd_getarg(cmd
,0);
381 if (!host
) return -1;
383 port
= cmd_getarg(cmd
,1);
384 if (!port
) port
= "23";
386 if (strcmp(port
,"discard") == 0) port
= "9";
387 else if (strcmp(port
,"chargen") == 0) port
= "19";
388 else if (strcmp(port
,"echo") == 0) port
= "7";
390 if (isdigit(*host
)) {
391 if (parseipaddr(host
,hostaddr
) < 0) {
392 xprintf("Invalid IP address: %s\n",host
);
397 res
= dns_lookup(host
,hostaddr
);
399 return ui_showerror(res
,"Could not resolve IP address of host %s",host
);
407 return ui_showerror(s
,"Could not create TCP socket");
410 if (cmd_sw_value(cmd
,"-srcport",&sport
)) {
411 res
= tcp_bind(s
,atoi(sport
));
413 ui_showerror(res
,"Could not bind to port %s",sport
);
419 res
= tcp_connect(s
,hostaddr
,atoi(port
));
421 ui_showerror(res
,"Could not connect to host %I",hostaddr
);
426 TIMER_SET(t
,CFE_HZ
*30);
428 while (!TIMER_EXPIRED(t
)) {
430 tcp_status(s
,&connflag
,NULL
,NULL
);
431 if (connflag
== TCPSTATUS_CONNECTING
) continue;
435 if (connflag
!= TCPSTATUS_CONNECTED
) {
436 printf("Could not connect to remote host\n");
441 printf("Connected to remote host.\n");
445 if (nodelay
) tcp_setflags(s
,TCPFLG_NODELAY
);
449 tcp_status(s
,&connflag
,&rxdata
,NULL
);
450 if (connflag
!= TCPSTATUS_CONNECTED
) {
451 printf("Remote host is no longer connected.\n");
455 res
= tcp_recv(s
,data
,sizeof(data
));
459 if (total
> 1000000) {
465 console_write(data
,res
);
469 ui_showerror(res
,"TCP read error");
472 if (console_status()) {
473 console_read(data
,1);
474 if (data
[0] == 1) break;
475 else if (data
[0] == 3) break;
476 else if (data
[0] == 4) {
477 for (res
= 0; res
< 100; res
++) data
[res
] = 'A'+(res
%26);
478 tcp_send(s
,data
,100);
480 else if (data
[0] == 5) tcp_send(s
,bigbuf
,2048);
481 else if (data
[0] == 2) tcp_debug(s
,0);
482 else tcp_send(s
,data
,1);
485 res
= rand() % sizeof(data
);
488 res
= tcp_send(s
,data
,res
);
491 if (total2
> 1000000) {
502 printf("Disconnecting...");
512 static int ui_cmd_listen(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
528 uint8_t remaddr
[IP_ADDR_LEN
];
531 bigbuf
= KMALLOC(4096,0);
532 for (res
= 0; res
< 4096; res
++) bigbuf
[res
] = 'A'+(res
%26);
534 quiet
= cmd_sw_isset(cmd
,"-q");
535 discard
= cmd_sw_isset(cmd
,"-d");
536 nodelay
= cmd_sw_isset(cmd
,"-nodelay");
538 port
= cmd_getarg(cmd
,0);
539 if (!port
) port
= "1234";
545 return ui_showerror(s
,"Could not create TCP socket");
548 res
= tcp_listen(s
,p
);
550 ui_showerror(res
,"Could not set socket to listen");
555 printf("Listening...");
558 if (console_status()) break;
559 tcp_status(s
,&connflag
,NULL
,NULL
);
560 if (connflag
== TCPSTATUS_CONNECTED
) break;
564 if (connflag
!= TCPSTATUS_CONNECTED
) {
565 printf("No connection received from remote host\n");
570 tcp_peeraddr(s
,remaddr
,&remport
);
571 printf("Connection from port %u on %I\n",remport
,remaddr
);
573 if (nodelay
) tcp_setflags(s
,TCPFLG_NODELAY
);
577 tcp_status(s
,&connflag
,&rxdata
,NULL
);
578 if (connflag
!= TCPSTATUS_CONNECTED
) {
579 printf("Remote host is no longer connected.\n");
583 res
= tcp_recv(s
,data
,sizeof(data
));
587 if (total
> 1000000) {
593 console_write(data
,res
);
597 ui_showerror(res
,"TCP read error");
600 if (console_status()) {
601 console_read(data
,1);
602 if (data
[0] == 1) break;
603 if (data
[0] == 3) break;
605 for (res
= 0; res
< 100; res
++) data
[res
] = 'A'+(res
%26);
606 tcp_send(s
,data
,100);
608 if (data
[0] == 5) tcp_send(s
,bigbuf
,2048);
609 if (data
[0] == 2) tcp_debug(s
,0);
610 else tcp_send(s
,data
,1);
613 res
= rand() % sizeof(data
);
616 res
= tcp_send(s
,data
,res
);
619 if (total2
> 1000000) {
631 printf("Disconnecting...");
641 static int ui_cmd_tcpconstest(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
648 x
= cmd_getarg(cmd
,0);
649 if (!x
) return ui_showusage(cmd
);
652 if (fh
< 0) return ui_showerror(fh
,"Could not open device %s",x
);
655 if (console_status()) break;
656 res
= cfe_read(fh
,data
,sizeof(data
));
658 ui_showerror(res
,"could not read data");
661 console_write(data
,res
);
669 static int ui_cmd_ttcp(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
672 uint8_t hostaddr
[IP_ADDR_LEN
];
677 cfe_timer_t start_time
;
678 cfe_timer_t stop_time
;
690 if (cmd_sw_value(cmd
,"-n",&x
)) numbuf
= atoi(x
);
693 if (cmd_sw_value(cmd
,"-l",&x
)) buflen
= atoi(x
);
696 if (cmd_sw_value(cmd
,"-p",&x
)) port
= atoi(x
);
699 if ((numbuf
== 0) || (buflen
== 0)) return ui_showusage(cmd
);
702 bigbuf
= KMALLOC(buflen
,0);
703 for (res
= 0; res
< buflen
; res
++) bigbuf
[res
] = 'A'+(res
%26);
705 txmode
= cmd_sw_isset(cmd
,"-t");
706 rxmode
= cmd_sw_isset(cmd
,"-r");
708 if (!(txmode
^ rxmode
)) {
709 return ui_showerror(-1,"You must specify one of -t or -r");
712 nodelay
= cmd_sw_isset(cmd
,"-D");
715 host
= cmd_getarg(cmd
,0);
716 if (!host
) return ui_showusage(cmd
);
718 if (isdigit(*host
)) {
719 if (parseipaddr(host
,hostaddr
) < 0) {
720 return ui_showerror(-1,"Invalid IP address: %s\n",host
);
724 res
= dns_lookup(host
,hostaddr
);
726 return ui_showerror(res
,"Could not resolve IP address of host %s",host
);
735 return ui_showerror(s
,"Could not create TCP socket");
740 res
= tcp_connect(s
,hostaddr
,port
);
742 ui_showerror(res
,"Could not connect to host %I",hostaddr
);
747 TIMER_SET(t
,CFE_HZ
*30);
749 while (!TIMER_EXPIRED(t
)) {
751 tcp_status(s
,&connflag
,NULL
,NULL
);
752 if (connflag
== TCPSTATUS_CONNECTING
) continue;
756 if (connflag
!= TCPSTATUS_CONNECTED
) {
757 printf("Could not connect to remote host\n");
762 printf("Connected to remote host.\n");
767 printf("Waiting for connection on port %d: ",port
);
770 if (console_status()) break;
771 tcp_status(s
,&connflag
,NULL
,NULL
);
772 if (connflag
== TCPSTATUS_CONNECTED
) break;
775 if (connflag
!= TCPSTATUS_CONNECTED
) {
776 printf("No connection received from remote host\n");
784 if (nodelay
) tcp_setflags(s
,TCPFLG_NODELAY
); /* also sets blocking */
785 else tcp_setflags(s
,0);
787 start_time
= cfe_ticks
;
792 res
= tcp_recv(s
,bigbuf
,buflen
);
793 if (res
!= buflen
) break;
801 res
= tcp_send(s
,bigbuf
,buflen
);
802 if (res
!= buflen
) break;
809 stop_time
= cfe_ticks
;
813 if ((res
< 0) && !rxmode
) {
814 ui_showerror(res
,"Network I/O error");
817 printf("%d bytes transferred via %d calls in %lld ticks\n",
818 totalbytes
,totalbufs
,stop_time
-start_time
);