1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * TCP protocol commands File: ui_tcpcmds.c 5 * 6 * This file contains commands that make use of the TCP protocol 7 * in CFE, assuming it's configured. 8 * 9 * Author: Mitch Lichtenberg 10 * 11 ********************************************************************* 12 * 13 * Copyright 2000,2001,2002,2003 14 * Broadcom Corporation. All rights reserved. 15 * 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. 22 * 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. 26 * 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. 32 * 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 ********************************************************************* */ 47 48#include "cfe.h" 49#include "ui_command.h" 50 51#if CFG_TCP 52#include "net_ebuf.h" 53#include "net_api.h" 54#endif 55 56 57/* ********************************************************************* 58 * Configuration 59 ********************************************************************* */ 60 61/* ********************************************************************* 62 * prototypes 63 ********************************************************************* */ 64 65#if CFG_TCP 66 67int ui_init_tcpcmds(void); 68 69static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[]); 70static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[]); 71static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[]); 72static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[]); 73static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[]); 74#define isdigit(d) (((d) >= '0') && ((d) <= '9')) 75 76 77/* ********************************************************************* 78 * ui_init_tcpcmds() 79 * 80 * Add TCP-specific commands to the command table 81 * 82 * Input parameters: 83 * nothing 84 * 85 * Return value: 86 * 0 87 ********************************************************************* */ 88 89 90int ui_init_tcpcmds(void) 91{ 92 93 cmd_addcmd("rlogin", 94 ui_cmd_rlogin, 95 NULL, 96 "mini rlogin client.", 97 "rlogin hostname [username]\n\n" 98 "Connects to a remote system using the RLOGIN protocol. The remote" 99 "system must have appropriate permissions in place (usually via the" 100 "file '.rhosts') for CFE to connect. To terminate the session, type" 101 "a tilde (~) character followed by a period (.)", 102 ""); 103 104 cmd_addcmd("tcp connect", 105 ui_cmd_connect, 106 NULL, 107 "TCP connection test.", 108 "tcp connect hostname [portnum]", 109 "-q;sink output, don't display on terminal|" 110 "-d;Send junk data to discard|" 111 "-nodelay;set nodelay option on socket|" 112 "-srcport=*;Specify the source port"); 113 114 cmd_addcmd("tcp listen", 115 ui_cmd_listen, 116 NULL, 117 "port listener.", 118 "tcp listen portnum", 119 "-q;sink output, don't display on terminal|" 120 "-d;Send junk data to discard|" 121 "-nodelay;set nodelay option on socket"); 122 123 124 cmd_addcmd("tcp constest", 125 ui_cmd_tcpconstest, 126 NULL, 127 "tcp console test.", 128 "tcp constest device", 129 ""); 130 131 cmd_addcmd("ttcp", 132 ui_cmd_ttcp, 133 NULL, 134 "TCP test command.", 135 "ttcp -t [-options] host\n" 136 "ttcp -r [-options]\n\n", 137 "-t;Source a pattern to the network|" 138 "-r;Sink (discard) data from the network|" 139 "-D;Don't buffer TCP writes (TCP_NODELAY)|" 140 "-n=*;Number of buffers to send (-t only) (default 2048)|" 141 "-l=*;Size of buffer to send/receive (default 2048)|" 142 "-p=*;Port number to use (default 5001)"); 143 144 return 0; 145} 146 147 148 149 150 151static unsigned long rand(void) 152{ 153 static unsigned long seed = 1; 154 long x, hi, lo, t; 155 156 x = seed; 157 hi = x / 127773; 158 lo = x % 127773; 159 t = 16807 * lo - 2836 * hi; 160 if (t <= 0) t += 0x7fffffff; 161 seed = t; 162 return t; 163} 164 165 166static int ui_cmd_rlogin(ui_cmdline_t *cmd,int argc,char *argv[]) 167{ 168 int s; 169 uint8_t hostaddr[IP_ADDR_LEN]; 170 char *host; 171 int res; 172 int connflag; 173 int rxdata; 174 int sport; 175 uint8_t data[100]; 176 int tilde; 177 char *username; 178 uint8_t *p; 179 180 /* 181 * Process args 182 */ 183 184 host = cmd_getarg(cmd,0); 185 if (!host) return ui_showusage(cmd); 186 187 username = cmd_getarg(cmd,1); 188 if (!username) username = ""; 189 190 /* 191 * Look up remote host 192 */ 193 194 if (isdigit(*host)) { 195 if (parseipaddr(host,hostaddr) < 0) { 196 xprintf("Invalid IP address: %s\n",host); 197 return -1; 198 } 199 } 200 else { 201 res = dns_lookup(host,hostaddr); 202 if (res < 0) { 203 return ui_showerror(res,"Could not resolve IP address of host %s",host); 204 } 205 } 206 207 /* 208 * Create TCP socket and bind to a port number less than 1023 209 * See RFC1282 for more info about this 210 */ 211 212 s = tcp_socket(); 213 214 if (s < 0) { 215 return ui_showerror(s,"Could not create TCP socket"); 216 } 217 218 res = 0; 219 tilde = 0; 220 for (sport = 1023; sport > 513; sport--) { 221 res = tcp_bind(s,sport); 222 if (res == 0) break; 223 } 224 225 if (sport == 513) { 226 ui_showerror(res,"No ports available for RLOGIN"); 227 return res; 228 } 229 230 /* 231 * Establish a connection. Our sockets default to nonblocking 232 * so we want to switch to blocking temporarily to 233 * let the tcp_connect routine do this by itself. 234 */ 235 236 tcp_setflags(s,0); 237 res = tcp_connect(s,hostaddr,513); 238 if (res < 0) { 239 ui_showerror(res,"Could not connect to host %I",hostaddr); 240 tcp_close(s); 241 return res; 242 } 243 244 245 /* 246 * Construct the initial RLOGIN sequence to include 247 * our user name and terminal type 248 */ 249 250 p = data; 251 *p++ = '\0'; 252 p += sprintf((char *)p,"%s",username) + 1; 253 p += sprintf((char *)p,"%s",username) + 1; 254 p += sprintf((char *)p,"vt100/38400") + 1; 255 256 tcp_send(s,PTR2HSADDR(data),p-&data[0]); 257 258 res = tcp_recv(s,PTR2HSADDR(data),1); /* receive result code */ 259 if (res <= 0) { 260 goto remdisc; 261 } 262 263 /* 264 * Switch back to nonblocking I/O for the loop 265 */ 266 267 tcp_setflags(s,TCPFLG_NBIO); 268 269 /* 270 * Begin processing loop 271 */ 272 273 connflag = TRUE; 274 for (;;) { 275 276 /* 277 * Test connection status 278 */ 279 280 tcp_status(s,&connflag,&rxdata,NULL); 281 if (connflag != TCPSTATUS_CONNECTED) { 282 goto remdisc; 283 } 284 285 /* 286 * Process received data 287 */ 288 289 if (rxdata != 0) { 290 res = tcp_recv(s,PTR2HSADDR(data),sizeof(data)); 291 if (res > 0) { 292 console_write(data,res); 293 } 294 if (res < 0) { 295 ui_showerror(res,"TCP read error"); 296 break; 297 } 298 } 299 300 /* 301 * Process transmitted data 302 */ 303 304 if (console_status()) { 305 console_read(data,1); 306 if (tilde == 1) { 307 if (data[0] == '.') break; 308 tilde = 0; 309 tcp_send(s,PTR2HSADDR(data),1); 310 } 311 else { 312 if (data[0] == '~') tilde = 1; 313 else tcp_send(s,PTR2HSADDR(data),1); 314 } 315 } 316 317 /* 318 * Give the background a chance 319 */ 320 321 POLL(); 322 } 323 324 printf("Disconnecting..."); 325 tcp_close(s); 326 printf("done.\n"); 327 return 0; 328 329remdisc: 330 printf("Remote host is no longer connected.\n"); 331 tcp_close(s); 332 return 0; 333} 334 335 336 337static int ui_cmd_connect(ui_cmdline_t *cmd,int argc,char *argv[]) 338{ 339 int s; 340 uint8_t hostaddr[IP_ADDR_LEN]; 341 char *host; 342 char *port; 343 int res; 344 int connflag; 345 int rxdata; 346 uint8_t data[100]; 347 int quiet; 348 int discard; 349 int total = 0; 350 int total2 = 0; 351 char b = 0; 352 cfe_timer_t t; 353 char *bigbuf; 354 int nodelay; 355 char *sport = NULL; 356 357 bigbuf = KMALLOC(4096,0); 358 for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26); 359 360 quiet = cmd_sw_isset(cmd,"-q"); 361 discard = cmd_sw_isset(cmd,"-d"); 362 nodelay = cmd_sw_isset(cmd,"-nodelay"); 363 364 host = cmd_getarg(cmd,0); 365 if (!host) return -1; 366 367 port = cmd_getarg(cmd,1); 368 if (!port) port = "23"; 369 370 if (strcmp(port,"discard") == 0) port = "9"; 371 else if (strcmp(port,"chargen") == 0) port = "19"; 372 else if (strcmp(port,"echo") == 0) port = "7"; 373 374 if (isdigit(*host)) { 375 if (parseipaddr(host,hostaddr) < 0) { 376 xprintf("Invalid IP address: %s\n",host); 377 return -1; 378 } 379 } 380 else { 381 res = dns_lookup(host,hostaddr); 382 if (res < 0) { 383 return ui_showerror(res,"Could not resolve IP address of host %s",host); 384 } 385 } 386 387 388 s = tcp_socket(); 389 390 if (s < 0) { 391 return ui_showerror(s,"Could not create TCP socket"); 392 } 393 394 if (cmd_sw_value(cmd,"-srcport",&sport)) { 395 res = tcp_bind(s,atoi(sport)); 396 if (res < 0) { 397 ui_showerror(res,"Could not bind to port %s",sport); 398 tcp_close(s); 399 return res; 400 } 401 } 402 403 res = tcp_connect(s,hostaddr,atoi(port)); 404 if (res < 0) { 405 ui_showerror(res,"Could not connect to host %I",hostaddr); 406 tcp_close(s); 407 return res; 408 } 409 410 TIMER_SET(t,CFE_HZ*30); 411 connflag = 0; 412 while (!TIMER_EXPIRED(t)) { 413 POLL(); 414 tcp_status(s,&connflag,NULL,NULL); 415 if (connflag == TCPSTATUS_CONNECTING) continue; 416 break; 417 } 418 419 if (connflag != TCPSTATUS_CONNECTED) { 420 printf("Could not connect to remote host\n"); 421 tcp_close(s); 422 return -1; 423 } 424 else { 425 printf("Connected to remote host.\n"); 426 } 427 428 429 if (nodelay) tcp_setflags(s,TCPFLG_NODELAY); 430 431 connflag = TRUE; 432 for (;;) { 433 tcp_status(s,&connflag,&rxdata,NULL); 434 if (connflag != TCPSTATUS_CONNECTED) { 435 printf("Remote host is no longer connected.\n"); 436 break; 437 } 438 if (rxdata != 0) { 439 res = tcp_recv(s,PTR2HSADDR(data),sizeof(data)); 440 if (res > 0) { 441 if (quiet) { 442 total += res; 443 if (total > 1000000) { 444 total -= 1000000; 445 printf("."); 446 } 447 } 448 else { 449 console_write(data,res); 450 } 451 } 452 if (res < 0) { 453 ui_showerror(res,"TCP read error"); 454 } 455 } 456 if (console_status()) { 457 console_read(data,1); 458 if (data[0] == 1) break; 459 else if (data[0] == 3) break; 460 else if (data[0] == 4) { 461 for (res = 0; res < 100; res++) data[res] = 'A'+(res%26); 462 tcp_send(s,PTR2HSADDR(data),100); 463 } 464 else if (data[0] == 5) tcp_send(s,PTR2HSADDR(bigbuf),2048); 465 else if (data[0] == 2) tcp_debug(s,0); 466 else tcp_send(s,PTR2HSADDR(data),1); 467 } 468 if (discard) { 469 res = rand() % sizeof(data); 470 memset(data,b,res); 471 b++; 472 res = tcp_send(s,PTR2HSADDR(data),res); 473 if (res > 0) { 474 total2 += res; 475 if (total2 > 1000000) { 476 total2 -= 1000000; 477 printf("+"); 478 } 479 } 480 481 } 482 483 POLL(); 484 } 485 486 printf("Disconnecting..."); 487 tcp_close(s); 488 printf("done.\n"); 489 490 KFREE(bigbuf); 491 492 return 0; 493} 494 495 496static int ui_cmd_listen(ui_cmdline_t *cmd,int argc,char *argv[]) 497{ 498 int s; 499 char *port; 500 int res; 501 int connflag; 502 int rxdata; 503 uint8_t data[100]; 504 int quiet; 505 int discard; 506 int total = 0; 507 int total2 = 0; 508 char b = 0; 509 char *bigbuf; 510 uint16_t p; 511 uint16_t remport; 512 uint8_t remaddr[IP_ADDR_LEN]; 513 int nodelay; 514 515 bigbuf = KMALLOC(4096,0); 516 for (res = 0; res < 4096; res++) bigbuf[res] = 'A'+(res%26); 517 518 quiet = cmd_sw_isset(cmd,"-q"); 519 discard = cmd_sw_isset(cmd,"-d"); 520 nodelay = cmd_sw_isset(cmd,"-nodelay"); 521 522 port = cmd_getarg(cmd,0); 523 if (!port) port = "1234"; 524 p = atoi(port); 525 526 s = tcp_socket(); 527 528 if (s < 0) { 529 return ui_showerror(s,"Could not create TCP socket"); 530 } 531 532 res = tcp_listen(s,p); 533 if (res < 0) { 534 ui_showerror(res,"Could not set socket to listen"); 535 tcp_close(s); 536 return res; 537 } 538 539 printf("Listening..."); 540 connflag = FALSE; 541 for (;;) { 542 if (console_status()) break; 543 tcp_status(s,&connflag,NULL,NULL); 544 if (connflag == TCPSTATUS_CONNECTED) break; 545 POLL(); 546 } 547 548 if (connflag != TCPSTATUS_CONNECTED) { 549 printf("No connection received from remote host\n"); 550 tcp_close(s); 551 return -1; 552 } 553 554 tcp_peeraddr(s,remaddr,&remport); 555 printf("Connection from port %u on %I\n",remport,remaddr); 556 557 if (nodelay) tcp_setflags(s,TCPFLG_NODELAY); 558 559 connflag = TRUE; 560 for (;;) { 561 tcp_status(s,&connflag,&rxdata,NULL); 562 if (connflag != TCPSTATUS_CONNECTED) { 563 printf("Remote host is no longer connected.\n"); 564 break; 565 } 566 if (rxdata != 0) { 567 res = tcp_recv(s,PTR2HSADDR(data),sizeof(data)); 568 if (res > 0) { 569 if (quiet) { 570 total += res; 571 if (total > 1000000) { 572 total -= 1000000; 573 printf("."); 574 } 575 } 576 else { 577 console_write(data,res); 578 } 579 } 580 if (res < 0) { 581 ui_showerror(res,"TCP read error"); 582 } 583 } 584 if (console_status()) { 585 console_read(data,1); 586 if (data[0] == 1) break; 587 if (data[0] == 3) break; 588 if (data[0] == 4) { 589 for (res = 0; res < 100; res++) data[res] = 'A'+(res%26); 590 tcp_send(s,PTR2HSADDR(data),100); 591 } 592 if (data[0] == 5) tcp_send(s,PTR2HSADDR(bigbuf),2048); 593 if (data[0] == 2) tcp_debug(s,0); 594 else tcp_send(s,PTR2HSADDR(data),1); 595 } 596 if (discard) { 597 res = rand() % sizeof(data); 598 memset(data,b,res); 599 b++; 600 res = tcp_send(s,PTR2HSADDR(data),res); 601 if (res > 0) { 602 total2 += res; 603 if (total2 > 1000000) { 604 total2 -= 1000000; 605 printf("+"); 606 } 607 } 608 609 } 610 611 POLL(); 612 } 613 614 615 printf("Disconnecting..."); 616 tcp_close(s); 617 printf("done.\n"); 618 619 KFREE(bigbuf); 620 621 return 0; 622} 623 624 625static int ui_cmd_tcpconstest(ui_cmdline_t *cmd,int argc,char *argv[]) 626{ 627 char *x; 628 int fh; 629 int res; 630 uint8_t data[100]; 631 632 x = cmd_getarg(cmd,0); 633 if (!x) return ui_showusage(cmd); 634 635 fh = cfe_open(x); 636 if (fh < 0) return ui_showerror(fh,"Could not open device %s",x); 637 638 for (;;) { 639 if (console_status()) break; 640 res = cfe_read(fh,PTR2HSADDR(data),sizeof(data)); 641 if (res < 0) { 642 ui_showerror(res,"could not read data"); 643 break; 644 } 645 console_write(data,res); 646 } 647 648 cfe_close(fh); 649 650 return 0; 651} 652 653static int ui_cmd_ttcp(ui_cmdline_t *cmd,int argc,char *argv[]) 654{ 655 int s; 656 uint8_t hostaddr[IP_ADDR_LEN]; 657 char *host; 658 int res; 659 int totalbytes = 0; 660 int totalbufs = 0; 661 cfe_timer_t start_time; 662 cfe_timer_t stop_time; 663 cfe_timer_t t; 664 int connflag; 665 char *bigbuf; 666 int nodelay; 667 int numbuf; 668 int buflen; 669 int txmode,rxmode; 670 uint16_t port; 671 672 char *x; 673 674 if (cmd_sw_value(cmd,"-n",&x)) numbuf = atoi(x); 675 else numbuf = 2048; 676 677 if (cmd_sw_value(cmd,"-l",&x)) buflen = atoi(x); 678 else buflen = 2048; 679 680 if (cmd_sw_value(cmd,"-p",&x)) port = atoi(x); 681 else port = 5001; 682 683 if ((numbuf == 0) || (buflen == 0)) return ui_showusage(cmd); 684 685 686 bigbuf = KMALLOC(buflen,0); 687 for (res = 0; res < buflen; res++) bigbuf[res] = 'A'+(res%26); 688 689 txmode = cmd_sw_isset(cmd,"-t"); 690 rxmode = cmd_sw_isset(cmd,"-r"); 691 692 if (!(txmode ^ rxmode)) { 693 return ui_showerror(-1,"You must specify one of -t or -r"); 694 } 695 696 nodelay = cmd_sw_isset(cmd,"-D"); 697 698 if (txmode) { 699 host = cmd_getarg(cmd,0); 700 if (!host) return ui_showusage(cmd); 701 702 if (isdigit(*host)) { 703 if (parseipaddr(host,hostaddr) < 0) { 704 return ui_showerror(-1,"Invalid IP address: %s\n",host); 705 } 706 } 707 else { 708 res = dns_lookup(host,hostaddr); 709 if (res < 0) { 710 return ui_showerror(res,"Could not resolve IP address of host %s",host); 711 } 712 } 713 } 714 715 716 s = tcp_socket(); 717 718 if (s < 0) { 719 return ui_showerror(s,"Could not create TCP socket"); 720 } 721 722 723 if (txmode) { 724 res = tcp_connect(s,hostaddr,port); 725 if (res < 0) { 726 ui_showerror(res,"Could not connect to host %I",hostaddr); 727 tcp_close(s); 728 return res; 729 } 730 731 TIMER_SET(t,CFE_HZ*30); 732 connflag = 0; 733 while (!TIMER_EXPIRED(t)) { 734 POLL(); 735 tcp_status(s,&connflag,NULL,NULL); 736 if (connflag == TCPSTATUS_CONNECTING) continue; 737 break; 738 } 739 740 if (connflag != TCPSTATUS_CONNECTED) { 741 printf("Could not connect to remote host\n"); 742 tcp_close(s); 743 return -1; 744 } 745 else { 746 printf("Connected to remote host.\n"); 747 } 748 } 749 750 if (rxmode) { 751 printf("Waiting for connection on port %d: ",port); 752 tcp_listen(s,port); 753 for (;;) { 754 if (console_status()) break; 755 tcp_status(s,&connflag,NULL,NULL); 756 if (connflag == TCPSTATUS_CONNECTED) break; 757 POLL(); 758 } 759 if (connflag != TCPSTATUS_CONNECTED) { 760 printf("No connection received from remote host\n"); 761 tcp_close(s); 762 return -1; 763 } 764 printf("done.\n"); 765 } 766 767 768 if (nodelay) tcp_setflags(s,TCPFLG_NODELAY); /* also sets blocking */ 769 else tcp_setflags(s,0); 770 771 start_time = cfe_ticks; 772 773 if (rxmode) { 774 while (1) { 775 POLL(); 776 res = tcp_recv(s,PTR2HSADDR(bigbuf),buflen); 777 if (res != buflen) break; 778 totalbytes += res; 779 totalbufs++; 780 } 781 } 782 else { 783 while (numbuf > 0) { 784 POLL(); 785 res = tcp_send(s,PTR2HSADDR(bigbuf),buflen); 786 if (res != buflen) break; 787 numbuf--; 788 totalbytes += res; 789 totalbufs++; 790 } 791 } 792 793 stop_time = cfe_ticks; 794 795 tcp_close(s); 796 797 if ((res < 0) && !rxmode) { 798 ui_showerror(res,"Network I/O error"); 799 } 800 else { 801 printf("%d bytes transferred via %d calls in %lld ticks\n", 802 totalbytes,totalbufs,stop_time-start_time); 803 } 804 805 806 KFREE(bigbuf); 807 808 return 0; 809 810} 811 812#endif /* CFG_TCP */ 813