1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Network commands File: ui_netcmds.c 5 * 6 * Network user interface 7 * 8 * Author: Mitch Lichtenberg 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 15 * This software is furnished under license and may be used and 16 * copied only in accordance with the following terms and 17 * conditions. Subject to these conditions, you may download, 18 * copy, install, use, modify and distribute modified or unmodified 19 * copies of this software in source and/or binary form. No title 20 * or ownership is transferred hereby. 21 * 22 * 1) Any source code used, modified or distributed must reproduce 23 * and retain this copyright notice and list of conditions 24 * as they appear in the source file. 25 * 26 * 2) No right is granted to use any trade name, trademark, or 27 * logo of Broadcom Corporation. The "Broadcom Corporation" 28 * name may not be used to endorse or promote products derived 29 * from this software without the prior written permission of 30 * Broadcom Corporation. 31 * 32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR 33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED 34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT 36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN 37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, 38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF 44 * THE POSSIBILITY OF SUCH DAMAGE. 45 ********************************************************************* */ 46 47 48#include "cfe.h" 49 50#include "env_subr.h" 51#include "ui_command.h" 52 53#include "net_enet.h" 54#include "net_ebuf.h" 55#include "net_ether.h" 56 57#include "net_api.h" 58 59#include "cfe_fileops.h" 60 61#define ip_addriszero(a) (((a)[0]|(a)[1]|(a)[2]|(a)[3]) == 0) 62#define isdigit(d) (((d) >= '0') && ((d) <= '9')) 63 64int ui_init_netcmds(void); 65 66#if CFG_NETWORK 67static int ui_cmd_ifconfig(ui_cmdline_t *cmd,int argc,char *argv[]); 68static int ui_cmd_arp(ui_cmdline_t *cmd,int argc,char *argv[]); 69static int ui_cmd_ping(ui_cmdline_t *cmd,int argc,char *argv[]); 70#if CFG_TCP 71extern int ui_init_tcpcmds(void); 72#endif 73#endif 74 75typedef struct netparam_s { 76 const char *str; 77 int num; 78} netparam_t; 79 80#if CFG_NETWORK 81static int ui_ifconfig_lookup(char *name,char *val,const netparam_t *list) ; 82#endif 83 84const static netparam_t loopbacktypes[] = { 85 {"off",ETHER_LOOPBACK_OFF}, 86 {"internal",ETHER_LOOPBACK_INT}, 87 {"external",ETHER_LOOPBACK_EXT}, 88 {0,NULL}}; 89 90const static netparam_t speedtypes[] = { 91 {"auto",ETHER_SPEED_AUTO}, 92 {"10hdx",ETHER_SPEED_10HDX}, 93 {"10fdx",ETHER_SPEED_10FDX}, 94 {"100hdx",ETHER_SPEED_100HDX}, 95 {"100fdx",ETHER_SPEED_100FDX}, 96 {"1000hdx",ETHER_SPEED_1000HDX}, 97 {"1000fdx",ETHER_SPEED_1000FDX}, 98 {0,NULL}}; 99 100 101int ui_init_netcmds(void) 102{ 103#if CFG_NETWORK 104 cmd_addcmd("ifconfig", 105 ui_cmd_ifconfig, 106 NULL, 107 "Configure the Ethernet interface", 108 "ifconfig device [options..]\n\n" 109 "Activates and configures the specified Ethernet interface and sets its\n" 110 "IP address, netmask, and other parameters. The -auto switch can be used\n" 111 "to set this information via DHCP.", 112 "-auto;Configure interface automatically via DHCP|" 113 "-off;Deactivate the specified interface|" 114 "-addr=*;Specifies the IP address of the interface|" 115 "-mask=*;Specifies the subnet mask for the interface|" 116 "-gw=*;Specifies the gateway address for the interface|" 117 "-dns=*;Specifies the name server address for the interface|" 118 "-domain=*;Specifies the default domain for name service queries|" 119 "-speed=*;Sets the interface speed (auto,10fdx,10hdx,100fdx,\n" 120 "100hdx,1000fdx,1000hdx)|" 121 "-loopback=*;Sets the loopback mode (off,internal,external) " 122 "External\nloopback causes the phy to be placed in loopback mode|" 123 "-hwaddr=*;Sets the hardware address (overrides environment)"); 124 125 cmd_addcmd("arp", 126 ui_cmd_arp, 127 NULL, 128 "Display or modify the ARP Table", 129 "arp [-d] [ip-address] [dest-address]\n\n" 130 "Without any parameters, the arp command will display the contents of the\n" 131 "arp table. With two parameters, arp can be used to add permanent arp\n" 132 "entries to the table (permanent arp entries do not time out)", 133 "-d;Delete the specified ARP entry. If specified, ip-address\n" 134 "may be * to delete all entries."); 135 136 cmd_addcmd("ping", 137 ui_cmd_ping, 138 NULL, 139 "Ping a remote IP host.", 140 "ping [-t] remote-host\n\n" 141 "This command sends an ICMP ECHO message to a remote host and waits for \n" 142 "a reply. The network interface must be configured and operational for\n" 143 "this command to work. If the interface is configured for loopback mode\n" 144 "the packet will be sent through the network interface, so this command\n" 145 "can be used for a simple network test.", 146 "-t;Ping forever, or until the ENTER key is struck|" 147 "-x;Exit immediately on first error (use with -f or -t)|" 148 "-f;Flood ping (use carefully!) - ping as fast as possible|" 149 "-s=*;Specify the number of ICMP data bytes|" 150 "-c=*;Specify number of packets to echo|" 151 "-A;don't abort even if key is pressed|" 152 "-E;Require all packets sent to be returned, for successful return status"); 153 154#if CFG_TCP 155 ui_init_tcpcmds(); 156#endif 157 158 159#endif 160 161 return 0; 162} 163 164 165#if CFG_NETWORK 166static int ui_ifdown(void) 167{ 168 char *devname; 169 170 devname = (char *) net_getparam(NET_DEVNAME); 171 if (devname) { 172 xprintf("Device %s has been deactivated.\n",devname); 173 net_uninit(); 174 net_setnetvars(); 175 } 176 177 return 0; 178} 179 180static void ui_showifconfig(void) 181{ 182 char *devname; 183 uint8_t *addr; 184 185 devname = (char *) net_getparam(NET_DEVNAME); 186 if (devname == NULL) { 187 xprintf("Network interface has not been configured\n"); 188 return; 189 } 190 191 xprintf("Device %s: ",devname); 192 193 addr = net_getparam(NET_HWADDR); 194 if (addr) xprintf(" hwaddr %a",addr); 195 196 addr = net_getparam(NET_IPADDR); 197 if (addr) { 198 if (ip_addriszero(addr)) xprintf(", ipaddr not set"); 199 else xprintf(", ipaddr %I",addr); 200 } 201 202 addr = net_getparam(NET_NETMASK); 203 if (addr) { 204 if (ip_addriszero(addr)) xprintf(", mask not set"); 205 else xprintf(", mask %I",addr); 206 } 207 208 xprintf("\n"); 209 xprintf(" "); 210 211 addr = net_getparam(NET_GATEWAY); 212 if (addr) { 213 if (ip_addriszero(addr)) xprintf("gateway not set"); 214 else xprintf("gateway %I",addr); 215 } 216 217 addr = net_getparam(NET_NAMESERVER); 218 if (addr) { 219 if (ip_addriszero(addr)) xprintf(", nameserver not set"); 220 else xprintf(", nameserver %I",addr); 221 } 222 223 addr = net_getparam(NET_DOMAIN); 224 if (addr) { 225 xprintf(", domain %s",addr); 226 } 227 228 xprintf("\n"); 229} 230 231static int ui_ifconfig_auto(ui_cmdline_t *cmd,char *devname) 232{ 233 int err; 234 dhcpreply_t *reply = NULL; 235 char *x; 236 uint8_t hwaddr[ENET_ADDR_LEN]; 237 int speed = ETHER_SPEED_AUTO; 238 239 net_uninit(); 240 241 err = net_init(devname); 242 if (err < 0) { 243 xprintf("Could not activate device %s: %s\n", 244 devname,cfe_errortext(err)); 245 return err; 246 } 247 248 if (cmd_sw_value(cmd,"-hwaddr",&x)) { 249 if (enet_parse_hwaddr(x,hwaddr) != 0) { 250 xprintf("Invalid hardware address: %s\n",x); 251 net_uninit(); 252 return CFE_ERR_INV_PARAM; 253 } 254 else { 255 net_setparam(NET_HWADDR,hwaddr); 256 } 257 } 258 259 if (cmd_sw_value(cmd,"-speed",&x)) { 260 speed = ui_ifconfig_lookup("-speed",x,speedtypes); 261 if (speed >= 0) { 262 net_setparam(NET_SPEED,(uint8_t *) &speed); 263 } 264 else return CFE_ERR_INV_PARAM; 265 } 266 267 err = dhcp_bootrequest(&reply); 268 269 if (err < 0) { 270 xprintf("DHCP registration failed on device %s\n",devname); 271 net_uninit(); 272 return CFE_ERR_NETDOWN; 273 } 274 275 net_setparam(NET_IPADDR,reply->dr_ipaddr); 276 net_setparam(NET_NETMASK,reply->dr_netmask); 277 net_setparam(NET_GATEWAY,reply->dr_gateway); 278 net_setparam(NET_NAMESERVER,reply->dr_nameserver); 279 net_setparam(NET_DOMAIN,(uint8_t *)reply->dr_domainname); 280 281 dhcp_set_envvars(reply); 282 283 if (reply) dhcp_free_reply(reply); 284 285 ui_showifconfig(); 286 net_setnetvars(); 287 return 0; 288} 289 290static int ui_ifconfig_getsw(ui_cmdline_t *cmd,char *swname,char *descr,uint8_t *addr) 291{ 292 char *x; 293 294 x = NULL; 295 296 if (cmd_sw_value(cmd,swname,&x) == 0) return 0; 297 298 if ((x == NULL) || (parseipaddr(x,addr) < 0)) { 299 xprintf("Invalid %s: %s\n",descr,x ? x : "(none)"); 300 return -1; 301 } 302 303 return 1; 304} 305 306static int ui_ifconfig_lookup(char *name,char *val,const netparam_t *list) 307{ 308 const netparam_t *p = list; 309 310 while (p->str) { 311 if (strcmp(p->str,val) == 0) return p->num; 312 p++; 313 } 314 315 xprintf("Invalid parameter for %s: Valid options are: "); 316 317 p = list; 318 while (p->str) { 319 xprintf("%s ",p->str); 320 p++; 321 } 322 323 xprintf("\n"); 324 return -1; 325} 326 327 328#define FLG_IPADDR 1 329#define FLG_NETMASK 2 330#define FLG_GATEWAY 4 331#define FLG_NAMESERVER 8 332#define FLG_DOMAIN 16 333#define FLG_LOOPBACK 32 334#define FLG_SPEED 64 335#define FLG_HWADDR 128 336 337static int ui_cmd_ifconfig(ui_cmdline_t *cmd,int argc,char *argv[]) 338{ 339 char *devname; 340 int flags = 0; 341 uint8_t ipaddr[IP_ADDR_LEN]; 342 uint8_t netmask[IP_ADDR_LEN]; 343 uint8_t gateway[IP_ADDR_LEN]; 344 uint8_t nameserver[IP_ADDR_LEN]; 345 uint8_t hwaddr[ENET_ADDR_LEN]; 346 int speed = ETHER_SPEED_AUTO; 347 int loopback = ETHER_LOOPBACK_OFF; 348 char *domain = NULL; 349 int res; 350 char *x; 351 352 if (argc < 1) { 353 ui_showifconfig(); 354 return 0; 355 } 356 357 devname = cmd_getarg(cmd,0); 358 359 if (cmd_sw_isset(cmd,"-off")) { 360 return ui_ifdown(); 361 } 362 363 if (cmd_sw_isset(cmd,"-auto")) { 364 return ui_ifconfig_auto(cmd,devname); 365 } 366 367 res = ui_ifconfig_getsw(cmd,"-addr","interface IP address",ipaddr); 368 if (res < 0) return CFE_ERR_INV_PARAM; 369 if (res > 0) { 370 flags |= FLG_IPADDR; 371 } 372 373 res = ui_ifconfig_getsw(cmd,"-mask","netmask",netmask); 374 if (res < 0) return CFE_ERR_INV_PARAM; 375 if (res > 0) { 376 flags |= FLG_NETMASK; 377 } 378 379 res = ui_ifconfig_getsw(cmd,"-gw","gateway IP address",gateway); 380 if (res < 0) return CFE_ERR_INV_PARAM; 381 if (res > 0) { 382 flags |= FLG_GATEWAY; 383 } 384 385 res = ui_ifconfig_getsw(cmd,"-dns","name server IP address",nameserver); 386 if (res < 0) return CFE_ERR_INV_PARAM; 387 if (res > 0) { 388 flags |= FLG_NAMESERVER; 389 } 390 391 if (cmd_sw_value(cmd,"-domain",&domain)) { 392 if (domain) flags |= FLG_DOMAIN; 393 } 394 395 if (cmd_sw_value(cmd,"-speed",&x)) { 396 speed = ui_ifconfig_lookup("-speed",x,speedtypes); 397 if (speed >= 0) flags |= FLG_SPEED; 398 else return CFE_ERR_INV_PARAM; 399 } 400 401 if (cmd_sw_value(cmd,"-loopback",&x)) { 402 loopback = ui_ifconfig_lookup("-loopback",x,loopbacktypes); 403 if (loopback >= 0) flags |= FLG_LOOPBACK; 404 else return CFE_ERR_INV_PARAM; 405 } 406 407 if (cmd_sw_value(cmd,"-hwaddr",&x)) { 408 if (enet_parse_hwaddr(x,hwaddr) != 0) { 409 xprintf("Invalid hardware address: %s\n",x); 410 return CFE_ERR_INV_PARAM; 411 } 412 else { 413 flags |= FLG_HWADDR; 414 } 415 } 416 417 /* 418 * If the network is running and the device name is 419 * different, uninit the net first. 420 */ 421 422 x = (char *) net_getparam(NET_DEVNAME); 423 424 if ((x != NULL) && (strcmp(x,devname) != 0)) { 425 net_uninit(); 426 } 427 428 /* 429 * Okay, initialize the network if it is not already on. If it 430 * is OFF, the "net_devname" parameter will be NULL. 431 */ 432 433 if (x == NULL) { 434 res = net_init(devname); /* turn interface on */ 435 if (res < 0) { 436 ui_showerror(res,"Could not activate network interface '%s'",devname); 437 return res; 438 } 439 } 440 441 /* 442 * Set the parameters 443 */ 444 445 if (flags & FLG_HWADDR) net_setparam(NET_HWADDR,hwaddr); 446 if (flags & FLG_IPADDR) net_setparam(NET_IPADDR,ipaddr); 447 if (flags & FLG_NETMASK) net_setparam(NET_NETMASK,netmask); 448 if (flags & FLG_GATEWAY) net_setparam(NET_GATEWAY,gateway); 449 if (flags & FLG_NAMESERVER) net_setparam(NET_NAMESERVER,nameserver); 450 if (flags & FLG_DOMAIN) net_setparam(NET_DOMAIN,(uint8_t *)domain); 451 if (flags & FLG_SPEED) net_setparam(NET_SPEED,(uint8_t *) &speed); 452 if (flags & FLG_LOOPBACK) net_setparam(NET_LOOPBACK,(uint8_t *) &loopback); 453 454 ui_showifconfig(); 455 net_setnetvars(); 456 457 return 0; 458} 459 460 461static int ui_cmd_arp(ui_cmdline_t *cmd,int argc,char *argv[]) 462{ 463 int idx; 464 uint8_t ipaddr[IP_ADDR_LEN]; 465 uint8_t hwaddr[ENET_ADDR_LEN]; 466 char *x; 467 int once = 0; 468 469 if (cmd_sw_isset(cmd,"-d")) { 470 if ((x = cmd_getarg(cmd,0)) == NULL) { 471 return ui_showusage(cmd); 472 } 473 474 if (strcmp(x,"*") == 0) { 475 while (arp_enumerate(0,ipaddr,hwaddr) >= 0) { 476 arp_delete(ipaddr); 477 } 478 } 479 else { 480 if (parseipaddr(x,ipaddr) < 0) { 481 xprintf("Invalid IP address: %s\n",x); 482 return CFE_ERR_INV_PARAM; 483 } 484 arp_delete(ipaddr); 485 } 486 return 0; 487 } 488 489 /* 490 * Get the IP address. If NULL, display the table. 491 */ 492 493 x = cmd_getarg(cmd,0); 494 if (x == NULL) { 495 idx = 0; 496 while (arp_enumerate(idx,ipaddr,hwaddr) >= 0) { 497 if (once == 0) { 498 xprintf("Hardware Address IP Address\n"); 499 xprintf("----------------- ---------------\n"); 500 once = 1; 501 } 502 xprintf("%a %I\n",hwaddr,ipaddr); 503 idx++; 504 } 505 if (idx == 0) xprintf("No ARP entries.\n"); 506 return 0; 507 } 508 509 if (parseipaddr(x,ipaddr) < 0) { 510 xprintf("Invalid IP address: %s\n",x); 511 return CFE_ERR_INV_PARAM; 512 } 513 514 /* 515 * Get the hardware address. 516 */ 517 518 x = cmd_getarg(cmd,1); 519 if (x == NULL) { 520 return ui_showusage(cmd); 521 } 522 523 if (enet_parse_hwaddr(x,hwaddr) < 0) { 524 xprintf("Invalid hardware address: %s\n",x); 525 return CFE_ERR_INV_PARAM; 526 } 527 528 arp_add(ipaddr,hwaddr); 529 530 return 0; 531} 532 533#define IP_HDR_LENGTH 20 534#define ICMP_HDR_LENGTH 8 535#define PING_HDR_LENGTH (IP_HDR_LENGTH+ICMP_HDR_LENGTH) 536#define MAX_PKT_LENGTH 1500 537 538static int ui_cmd_ping(ui_cmdline_t *cmd,int argc,char *argv[]) 539{ 540 char *host; 541 uint8_t hostaddr[IP_ADDR_LEN]; 542 int res; 543 int seq = 0; 544 int forever = 0; 545 int count = 1; 546 int ttlcount = 1; 547 int countreturned = 0; 548 int size = 56; 549 int flood = 0; 550 int retval = 0; 551 int exitonerror = 0; 552 int needexact = 0; 553 int noabort = 0; 554 char *x; 555 556 host = cmd_getarg(cmd,0); 557 if (!host) return -1; 558 559 if (cmd_sw_isset(cmd,"-t")) { 560 forever = 1; 561 } 562 563 /* Per traditional Unix usage, the size argument to ping is 564 the number of ICMP data bytes. The frame on the wire will also 565 include the ethernet, IP and ICMP headers (14, 20, and 566 8 bytes respectively) and ethernet trailer (CRC, 4 bytes). */ 567 if (cmd_sw_value(cmd,"-s",&x)) { 568 size = atoi(x); 569 if (size < 0) 570 size = 0; 571 if (size > MAX_PKT_LENGTH - PING_HDR_LENGTH) 572 size = MAX_PKT_LENGTH - PING_HDR_LENGTH; 573 } 574 575 if (cmd_sw_isset(cmd,"-f")) { 576 flood = 1; 577 forever = 1; 578 } 579 580 if (cmd_sw_isset(cmd,"-x")) { 581 exitonerror = 1; 582 } 583 584 if (cmd_sw_value(cmd,"-c",&x)) { 585 count = atoi(x); 586 ttlcount = count; 587 forever = 0; 588 } 589 590 if (cmd_sw_isset(cmd,"-A")) { 591 noabort = 1; 592 } 593 594 if (cmd_sw_isset(cmd,"-E")) { 595 needexact = 1; 596 } 597 598 if (isdigit(*host)) { 599 if (parseipaddr(host,hostaddr) < 0) { 600 xprintf("Invalid IP address: %s\n",host); 601 return -1; 602 } 603 } 604 else { 605 res = dns_lookup(host,hostaddr); 606 if (res < 0) { 607 return ui_showerror(res,"Could not resolve IP address of host %s",host); 608 } 609 } 610 611 if (forever) xprintf("Press ENTER to stop pinging\n"); 612 613 do { 614 res = icmp_ping(hostaddr,seq,size); 615 616 if (res < 0) { 617 xprintf("Could not transmit echo request\n"); 618 retval = CFE_ERR_IOERR; 619 break; 620 } 621 else if (res == 0) { 622 xprintf("%s (%I) is not responding (seq=%d)\n",host,hostaddr,seq); 623 retval = CFE_ERR_TIMEOUT; 624 if (exitonerror) break; 625 } 626 else { 627 countreturned++; 628 if (!flood || ((seq % 10000) == 0)) { 629 if (forever || (ttlcount > 1)) { 630 xprintf("%s (%I) is alive (seq=%d)\n",host,hostaddr,seq); 631 } 632 else xprintf("%s (%I) is alive\n",host,hostaddr); 633 } 634 } 635 636 if ((forever || (count > 1)) && !flood) { 637 if (res > 0) cfe_sleep(CFE_HZ); 638 } 639 640 seq++; 641 count--; 642 643 } while ((forever || (count > 0)) && (noabort || !console_status())); 644 645 xprintf("%s (%I): %d packets sent, %d received\n",host,hostaddr, 646 ttlcount-count,countreturned); 647 return (needexact ? (countreturned != ttlcount) : (countreturned == 0)); 648} 649 650#endif 651